I have the following program, which was written with great help. It will blow up the compressed PKWare DCL.vol archives (file identifier RESLIST) and extract the files to the specified output folder, giving the extracted files the date the original .vol file was modified. It is intended for use in the Inno Setup installer, and I would like to see if I can compile it as a .dll library that can be imported into my .iss script, that is:
function VolEx( filename, outputpath: String ): Integer; external ' VolExA@volex.dll stdcall';
I read http://www.mingw.org/wiki/sampleDLL , but it was hard for me to understand all ifdefs and extern "C".
Also, I would like it to be able to modify the WizardForm.FilenameLabel.Caption in my installer so that it matches the file currently being extracted (I understand that this requires InnoTools InnoCallback http://www.sherlocksoftware.org/page. php? id = 54 ; something similar was done with FreeArc http://freearc.org/InnoSetup.aspx )
Volex.c (including blast.c and blast.h from here: https://github.com/madler/zlib/tree/master/contrib/blast )
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <sys/stat.h> #include <time.h> #include <utime.h> #include "blast.h" #define local static #define VOLID "RESLIST" struct inbuf { unsigned long left; unsigned char *buf; unsigned size; FILE *in; }; struct stat statbuf; time_t mtime; time_t voltime; struct utimbuf new_times; local unsigned inf(void *how, unsigned char **buf) { unsigned len; struct inbuf *inb = how; len = inb->size > inb->left ? inb->left : inb->size; len = fread(inb->buf, 1, len, inb->in); inb->left -= len; *buf = inb->buf; return len; } local int outf(void *how, unsigned char *buf, unsigned len) { return fwrite(buf, 1, len, (FILE *)how) != len; } #define BUFSIZE 16384 /* must fit in unsigned */ local int extract(char *name, unsigned long len, FILE *in, char *path, time_t prevtime) { int err; FILE *out; struct inbuf inb; unsigned char buf[BUFSIZE]; inb.left = len; inb.buf = buf; inb.size = BUFSIZE; inb.in = in; mkdir(path); char outPath[strlen(path) + 20]; strcpy(outPath, path); strcat(outPath, "\\"); strcat(outPath, name); out = fopen(outPath, "wb"); if (out == NULL) return 2; err = blast(inf, &inb, outf, out); fclose(out); if (stat(outPath, &statbuf) < 0) { perror(outPath); return 1; } mtime = statbuf.st_mtime; /* seconds since the epoch */ new_times.actime = statbuf.st_atime; /* keep atime unchanged */ new_times.modtime = prevtime; /* set mtime to current time */ if (utime(outPath, &new_times) < 0) { perror(outPath); return 1; } return err; } int main(int argc, char *argv[]) { if ( argc != 3 ) { printf( "Usage: %s <vol> <output path>", argv[0] ); return 1; } else { FILE *in = fopen(argv[1],"rb"); unsigned long off, next; int err; unsigned char head[24]; if (stat(argv[1], &statbuf) < 0) { perror(argv[1]); return 1; } voltime = statbuf.st_mtime; /* seconds since the epoch */ if (fread(head, 1, 8, in) != 8 || memcmp(head, VOLID, 8)) { fprintf(stderr, "not the expected .vol format\n"); return 1; } off = 8; while ((next = fread(head, 1, 24, in)) == 24) { off += 24; next = head[20] + (head[21] << 8) + ((unsigned long)(head[22]) << 16) + ((unsigned long)(head[23]) << 24); head[20] = 0; err = extract((char *)head, next - off, in, argv[2], voltime); if (err) { fprintf(stderr, "extraction error %d on %s\n", err, head); return 1; } off = next; } if (next) fprintf(stderr, "%lu bytes ignored at the end\n", next); return 0; } }