Sindbad~EG File Manager
/* chmd_order: test that extracting a CHM file in different ways works
* and all give the same results:
* - extracting files in the order they're listed (generally alphabetical)
* - extracting files ordered by their content section offset
* - extracting files using fast_find() to find them
* - extracting files from two chms at the same time with one decompressor
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mspack.h>
#include <md5_fh.h>
#include <error.h>
struct my_file {
struct mschmd_file *file;
struct mschmd_file result;
char ordered[32], sorted[32], fast_find[32], mixed[32];
};
static int sortfunc(const void *a, const void *b) {
off_t diff =
((struct my_file *) a)->file->offset -
((struct my_file *) b)->file->offset;
return (diff < 0) ? -1 : ((diff > 0) ? 1 : 0);
}
int main(int argc, char *argv[]) {
struct mschm_decompressor *chmd;
struct mschmd_header *chm, *chm2;
struct mschmd_file *file;
struct my_file *f;
unsigned int N, i;
MSPACK_SYS_SELFTEST(i);
if (i) return 0;
if ((chmd = mspack_create_chm_decompressor(&read_files_write_md5))) {
for (argv++; *argv; argv++) {
printf("%s\n", *argv);
if ((chm = chmd->open(chmd, *argv))) {
if ((chm2 = chmd->fast_open(chmd, *argv))) {
/* count the number of files, allocate a results structure */
for (N=0, file = chm->files; file; file = file->next) N++;
if ((f = (struct my_file *) calloc(N, sizeof(struct my_file)))) {
/* fill out results structure while doing ordered extraction */
for (i = 0, file = chm->files; file; file = file->next, i++) {
printf("OX %s\n", file->filename);
f[i].file = file;
if (chmd->extract(chmd, file, NULL)) {
fprintf(stderr, "%s: O extract error on \"%s\": %s\n",
*argv, file->filename, ERROR(chmd));
continue;
}
memcpy(&f[i].ordered[0], md5_string, 32);
}
/* sort the list into offset order */
qsort(f, N, sizeof(struct my_file), &sortfunc);
/* extract in offset order */
for (i = 0; i < N; i++) {
printf("SX %s\n", f[i].file->filename);
if (chmd->extract(chmd, f[i].file, NULL)) {
fprintf(stderr, "%s: S extract error on \"%s\": %s\n",
*argv, f[i].file->filename, ERROR(chmd));
continue;
}
memcpy(&f[i].sorted[0], md5_string, 32);
}
/* extract using fast_find */
for (i = 0; i < N; i++) {
printf("FX %s\n", f[i].file->filename);
if (chmd->fast_find(chmd, chm2,
f[i].file->filename,
&f[i].result, sizeof(struct mschmd_file)))
{
fprintf(stderr, "%s: find error on \"%s\": %s\n",
*argv, f[i].file->filename, ERROR(chmd));
continue;
}
if (!f[i].result.section) {
fprintf(stderr, "%s: can't find file \"%s\"\n",
*argv, f[i].file->filename);
continue;
}
if (chmd->extract(chmd, &f[i].result, NULL)) {
fprintf(stderr, "%s: F extract error on \"%s\": %s\n",
*argv, f[i].file->filename, ERROR(chmd));
continue;
}
memcpy(&f[i].fast_find[0], md5_string, 32);
}
/* extract two chms at once */
for (i = 0; i < N; i++) {
printf("MX %s\n", f[i].file->filename);
chmd->extract(chmd, f[i].file, NULL);
if (chmd->extract(chmd, &f[i].result, NULL)) {
fprintf(stderr, "%s: M extract error on \"%s\": %s\n",
*argv, f[i].file->filename, ERROR(chmd));
continue;
}
memcpy(&f[i].mixed[0], md5_string, 32);
}
/* check all the MD5 sums match */
for (i = 0; i < N; i++) {
if (memcmp(&f[i].ordered, &f[i].sorted, 32) ||
memcmp(&f[i].ordered, &f[i].fast_find, 32) ||
memcmp(&f[i].ordered, &f[i].mixed, 32))
{
fprintf(stderr, "%s: sums mismatch on %s "
"(O=%32.32s,S=%32.32s,F=%32.32s,M=%32.32s)\n",
*argv, f[i].file->filename,
&f[i].ordered[0], &f[i].sorted[0],
&f[i].fast_find[0], &f[i].mixed[0]);
}
}
free(f);
}
chmd->close(chmd, chm2);
}
chmd->close(chmd, chm);
}
else {
printf("%s: can't open -- %s\n", *argv, ERROR(chmd));
}
}
mspack_destroy_chm_decompressor(chmd);
}
return 0;
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists