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