1 /* chmd_order: test that extracting a CHM file in different ways works
2 * and all give the same results:
3 * - extracting files in the order they're listed (generally alphabetical)
4 * - extracting files ordered by their content section offset
5 * - extracting files using fast_find() to find them
6 * - extracting files from two chms at the same time with one decompressor
7 */
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <mspack.h>
16
17 #include <md5_fh.h>
18 #include <error.h>
19
20 struct my_file {
21 struct mschmd_file *file;
22 struct mschmd_file result;
23 char ordered[32], sorted[32], fast_find[32], mixed[32];
24 };
25
sortfunc(const void * a,const void * b)26 static int sortfunc(const void *a, const void *b) {
27 off_t diff =
28 ((struct my_file *) a)->file->offset -
29 ((struct my_file *) b)->file->offset;
30 return (diff < 0) ? -1 : ((diff > 0) ? 1 : 0);
31 }
32
main(int argc,char * argv[])33 int main(int argc, char *argv[]) {
34 struct mschm_decompressor *chmd;
35 struct mschmd_header *chm, *chm2;
36 struct mschmd_file *file;
37 struct my_file *f;
38 unsigned int N, i;
39
40 MSPACK_SYS_SELFTEST(i);
41 if (i) return 0;
42
43 if ((chmd = mspack_create_chm_decompressor(&read_files_write_md5))) {
44 for (argv++; *argv; argv++) {
45 printf("%s\n", *argv);
46
47 if ((chm = chmd->open(chmd, *argv))) {
48 if ((chm2 = chmd->fast_open(chmd, *argv))) {
49
50 /* count the number of files, allocate a results structure */
51 for (N=0, file = chm->files; file; file = file->next) N++;
52 if ((f = (struct my_file *) calloc(N, sizeof(struct my_file)))) {
53
54 /* fill out results structure while doing ordered extraction */
55 for (i = 0, file = chm->files; file; file = file->next, i++) {
56 printf("OX %s\n", file->filename);
57 f[i].file = file;
58 if (chmd->extract(chmd, file, NULL)) {
59 fprintf(stderr, "%s: O extract error on \"%s\": %s\n",
60 *argv, file->filename, ERROR(chmd));
61 continue;
62 }
63 memcpy(&f[i].ordered[0], md5_string, 32);
64 }
65
66 /* sort the list into offset order */
67 qsort(f, N, sizeof(struct my_file), &sortfunc);
68
69 /* extract in offset order */
70 for (i = 0; i < N; i++) {
71 printf("SX %s\n", f[i].file->filename);
72 if (chmd->extract(chmd, f[i].file, NULL)) {
73 fprintf(stderr, "%s: S extract error on \"%s\": %s\n",
74 *argv, f[i].file->filename, ERROR(chmd));
75 continue;
76 }
77 memcpy(&f[i].sorted[0], md5_string, 32);
78 }
79
80 /* extract using fast_find */
81 for (i = 0; i < N; i++) {
82 printf("FX %s\n", f[i].file->filename);
83
84 if (chmd->fast_find(chmd, chm2,
85 f[i].file->filename,
86 &f[i].result, sizeof(struct mschmd_file)))
87 {
88 fprintf(stderr, "%s: find error on \"%s\": %s\n",
89 *argv, f[i].file->filename, ERROR(chmd));
90 continue;
91 }
92 if (!f[i].result.section) {
93 fprintf(stderr, "%s: can't find file \"%s\"\n",
94 *argv, f[i].file->filename);
95 continue;
96 }
97 if (chmd->extract(chmd, &f[i].result, NULL)) {
98 fprintf(stderr, "%s: F extract error on \"%s\": %s\n",
99 *argv, f[i].file->filename, ERROR(chmd));
100 continue;
101 }
102 memcpy(&f[i].fast_find[0], md5_string, 32);
103 }
104
105 /* extract two chms at once */
106 for (i = 0; i < N; i++) {
107 printf("MX %s\n", f[i].file->filename);
108 chmd->extract(chmd, f[i].file, NULL);
109 if (chmd->extract(chmd, &f[i].result, NULL)) {
110 fprintf(stderr, "%s: M extract error on \"%s\": %s\n",
111 *argv, f[i].file->filename, ERROR(chmd));
112 continue;
113 }
114 memcpy(&f[i].mixed[0], md5_string, 32);
115 }
116
117 /* check all the MD5 sums match */
118 for (i = 0; i < N; i++) {
119 if (memcmp(&f[i].ordered, &f[i].sorted, 32) ||
120 memcmp(&f[i].ordered, &f[i].fast_find, 32) ||
121 memcmp(&f[i].ordered, &f[i].mixed, 32))
122 {
123 fprintf(stderr, "%s: sums mismatch on %s "
124 "(O=%32.32s,S=%32.32s,F=%32.32s,M=%32.32s)\n",
125 *argv, f[i].file->filename,
126 &f[i].ordered[0], &f[i].sorted[0],
127 &f[i].fast_find[0], &f[i].mixed[0]);
128 }
129 }
130
131 free(f);
132 }
133 chmd->close(chmd, chm2);
134 }
135 chmd->close(chmd, chm);
136 }
137 else {
138 printf("%s: can't open -- %s\n", *argv, ERROR(chmd));
139 }
140 }
141 mspack_destroy_chm_decompressor(chmd);
142 }
143 return 0;
144 }
145