]> granicus.if.org Git - zziplib/blob - bins/unzip-mem.c
msvc8
[zziplib] / bins / unzip-mem.c
1 /*
2  *      Copyright (c) 2003 Guido Draheim <guidod@gmx.de>
3  *      Use freely under the restrictions of the ZLIB license.
4  *
5  *      This file is used as an example to clarify zzipmmap api usage.
6  */
7
8 #include <zlib.h> /* crc32 */
9
10 #include <zzip/memdisk.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #ifdef ZZIP_HAVE_UNISTD_H
16 #include <unistd.h>
17 #endif
18 #ifdef ZZIP_HAVE_IO_H
19 #include <io.h>
20 #endif
21
22 #include <time.h>
23
24 #ifdef ZZIP_HAVE_FNMATCH_H
25 #include <fnmatch.h>
26 #else
27 #define fnmatch(x,y,z) strcmp(x,y)
28 #endif
29
30 #ifndef O_BINARY
31 #define O_BINARY 0
32 #endif
33
34 #define ___ {
35 #define ____ }
36
37 #define EXIT_SUCCESS 0
38 #define EXIT_WARNINGS 1
39 #define EXIT_ERRORS 2
40 #define EXIT_EFORMAT 3
41 #define EXIT_ENOMEM 4
42 #define EXIT_ENOTTY 5
43 #define EXIT_EINFLATE 6
44 #define EXIT_ENOARCH 9
45 #define EXIT_EOPTION 10
46 #define EXIT_ENOFILE 11
47 #define EXIT_EDISKFULL 50
48 #define EXIT_EPREMATURE 51
49 #define EXIT_USERABORT 80
50 #define EXIT_BADCOMPRESSION 81
51 #define EXIT_BADPASSWORD 82
52
53 static int status = EXIT_SUCCESS;
54 static int option_list = 0;        /* "-l" */
55 static int option_pipe = 0;        /* "-p" */
56 static int option_verbose = 0;     /* "-v" */
57 static int option_testcrc = 0;     /* "-t" */
58 static int option_binary = 0;      /* "-b" */
59 static int option_nocase = 0;      /* "-C" */
60 static int option_junkpaths = 0;   /* "-j" */
61 static int option_dosfiles = 0;    /* "-L" */
62 static int option_keepold = 0;     /* "-n" */
63 static int option_overwrite = 0;   /* "-o" */
64 static int option_quiet = 0;       /* "-q" */
65 static int option_permbits = 0;    /* "-X" */
66
67 static const char usage[] = 
68 {
69     "unzzip-mem <zip> [names].. \n"
70     "  - unzzip a zip archive.\n"
71     "options:\n"
72     "  -l list archive files (name, usize, mtime, comments)\n" /* +totals */
73     "  -p extract archive files to pipe, i.e. stdout (binary mode)\n"
74     "  -t test archive files (check the crc values)\n"
75     "  -v verbose list of archive files\n"
76     "  -b accept and ignore (force binary extract)\n"
77     "  -C match filenames case-insensitively\n"
78     "  -j junk paths (do not recreate directory structure)\n"
79     "  -L convert dos filenames to lowercase upon extract\n"
80     "  -n never overwrite existing files\n"
81     "  -o always overwrite existing files\n"
82     "  -q quite operation\n"
83     "  -X restore user/owner attributes of files\n"
84 };
85
86 static void zzip_mem_entry_pipe(ZZIP_MEM_DISK* disk, 
87                                 ZZIP_MEM_ENTRY* entry, FILE* out)
88 {
89     ZZIP_DISK_FILE* file = zzip_mem_entry_fopen (disk, entry);
90     if (file) 
91     {
92         char buffer[1024]; int len;
93         while ((len = zzip_mem_disk_fread (buffer, 1024, 1, file)))
94             fwrite (buffer, len, 1, out);
95         
96         zzip_mem_disk_fclose (file);
97     }
98 }
99
100 static void zzip_mem_entry_make(ZZIP_MEM_DISK* disk, 
101                                 ZZIP_MEM_ENTRY* entry)
102 {
103     FILE* file = fopen (entry->zz_name, "w");
104     if (file) { zzip_mem_entry_pipe (disk, entry, file); fclose (file); }
105     perror (entry->zz_name);
106     if (status < EXIT_WARNINGS) status = EXIT_WARNINGS;
107 }
108
109 /* ------------------------- test ------------------------------------ */
110
111 static char* archive = 0;
112 static int test_errors = 0;
113
114 static void zzip_mem_entry_test(ZZIP_MEM_DISK* disk, 
115                                 ZZIP_MEM_ENTRY* entry)
116 {
117     ZZIP_DISK_FILE* file = zzip_mem_entry_fopen (disk, entry);
118     printf ("    testing: %s ", entry->zz_name);
119     if (strlen (entry->zz_name) < 24) {
120         printf ("%.*s", 24 - (int) strlen (entry->zz_name),
121                 "                        ");
122     }
123     if (file) 
124     {
125         unsigned long crc = crc32 (0L, NULL, 0);
126         unsigned char buffer[1024]; int len; 
127         while ((len = zzip_mem_disk_fread (buffer, 1024, 1, file))) {
128             crc = crc32 (crc, buffer, len);
129         }
130         
131         zzip_mem_disk_fclose (file);
132         if (crc == (unsigned long) entry->zz_crc32) {
133             printf ("OK\n");
134         } else {
135             printf ("BAD %lx (should be %lx)\n", crc, entry->zz_crc32);
136             test_errors ++;
137         } 
138     } else {
139         printf ("ERROR (no such file)\n");
140         test_errors ++;
141     }
142 }
143
144 static void zzip_mem_entry_test_start(void)
145 {
146     test_errors = 0;
147     printf ("Archive: %s\n", archive);
148 }
149
150 static void zzip_mem_entry_test_done(void)
151 {
152     if (test_errors == 0) {
153         printf ("No errors detected in compressed data of %s\n", archive);
154     } else {
155         printf ("%i errors detected in compressed data of %s\n", 
156                 test_errors, archive);
157     }
158 }
159
160 /* ------------------------- list ------------------------------------ */
161
162 static char _zzip_time_[30];
163 static char* _zzip_ctime (long* timeval) 
164 {
165     struct tm* date = localtime (timeval);
166     sprintf (_zzip_time_, "%02i-%02i-%02i %02i:%02i",
167              date->tm_mon, date->tm_mday, date->tm_year%100,
168              date->tm_hour, date->tm_min);
169     return _zzip_time_;
170 }
171
172 static const char* comprlevel[] = {
173     "stored",   "shrunk",   "redu:1",   "redu:2",   "redu:3",   "redu:4",
174     "impl:N",   "toknze",   "defl:N",   "defl:B",   "impl:B" };
175
176 zzip_off_t sum_usize = 0;
177 zzip_off_t sum_csize = 0;
178 zzip_off_t sum_files = 0;
179 #define L (long)
180
181 static void zzip_mem_entry_direntry_start (void)
182 {
183     sum_usize = 0;
184     sum_csize = 0;
185     sum_files = 0;
186     if (option_verbose) goto verbose;
187     printf("  Length    Date & Time     Name\n");
188     printf(" --------    ----   ----    ----\n");
189     return;
190  verbose:
191     printf(" Length   Method    Size  Ratio   Date   Time   CRC-32    Name\n");
192     printf("--------  ------  ------- -----   ----   ----   ------    ----\n");
193 }
194
195 static void zzip_mem_entry_direntry_done (void)
196 {
197     char exp = ' ';
198     if (sum_usize / 1024 > 1024*1024*1024) { exp = 'G';
199         sum_usize /= 1024*1024*1024; sum_usize /= 1024*1024*1024; }
200     if (sum_usize > 1024*1024*1024) { exp = 'M';
201         sum_usize /= 1024*1024; sum_csize /= 1024*1024; }
202     if (sum_usize > 1024*1024) { exp = 'K';
203         sum_usize /= 1024; sum_csize /= 1024; }
204     if (option_verbose) goto verbose;
205     printf(" --------                   ----\n");
206     printf(" %8li%c           %8li %s\n", L sum_usize, exp, L sum_files,
207            sum_files == 1 ? "file" : "files");
208     return;
209  verbose:
210     printf("--------  ------  ------- -----                           ----\n");
211     printf("%8li%c       %8li%c %3li%%                     %8li %s\n",
212            L sum_usize, exp, L sum_csize, exp, 
213            L (100 - (sum_csize*100/sum_usize)), L sum_files, 
214            sum_files == 1 ? "file" : "files");
215 }
216
217 static void zzip_mem_entry_direntry(ZZIP_MEM_ENTRY* entry)
218 {
219     char* name = zzip_mem_entry_to_name (entry);
220     zzip_off_t usize = zzip_mem_entry_usize (entry);
221     zzip_off_t csize = zzip_mem_entry_csize (entry);
222     int compr = zzip_mem_entry_data_comprlevel (entry);
223     long mtime = entry->zz_mktime;
224     long crc32 = entry->zz_crc32;
225     const char* comment = zzip_mem_entry_to_comment (entry);
226     char exp = ' ';
227
228     sum_usize += usize;
229     sum_csize += csize;
230     sum_files += 1;
231
232     if (usize / 1024 > 1024*1024*1024) { exp = 'G';
233         usize /= 1024*1024*1024; usize /= 1024*1024*1024; }
234     if (usize > 1024*1024*1024) { exp = 'M';
235         usize /= 1024*1024; csize /= 1024*1024; }
236     if (usize > 1024*1024) { exp = 'K';
237         usize /= 1024; csize /= 1024; }
238    
239     if (! comment) comment = "";
240     if (*name == '\n') name++;
241
242     if (option_verbose) {
243         printf("%8li%c %s %8li%c%3li%%  %s  %8lx  %s %s\n", 
244                L usize, exp, comprlevel[compr], L csize, exp, 
245                L (100 - (csize*100/usize)),
246                _zzip_ctime(&mtime), crc32, name, comment);
247     } else {
248         printf(" %8li%c %s   %s %s\n", 
249                L usize, exp, _zzip_ctime(&mtime), name, comment);
250     }    
251 }
252
253 static void zzip_mem_entry_listfiles(ZZIP_MEM_DISK* disk, char* filespec)
254 {
255     zzip_mem_entry_direntry_start ();
256     ___ ZZIP_MEM_ENTRY* entry = 0;
257     while ((entry = zzip_mem_disk_findmatch(disk, filespec, entry, 0, 0)))
258         zzip_mem_entry_direntry (entry); ____;
259     zzip_mem_entry_direntry_done ();
260 }
261
262 static void zzip_mem_entry_listall(ZZIP_MEM_DISK* disk)
263 {
264     zzip_mem_entry_direntry_start ();
265     ___ ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
266     for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
267         zzip_mem_entry_direntry (entry); ____;
268     zzip_mem_entry_direntry_done ();
269 }
270
271 static void zzip_mem_entry_testfiles(ZZIP_MEM_DISK* disk, char* filespec)
272 {
273     zzip_mem_entry_test_start ();
274     ___ ZZIP_MEM_ENTRY* entry = 0;
275     while ((entry = zzip_mem_disk_findmatch(disk, filespec, entry, 0, 0)))
276         zzip_mem_entry_test (disk, entry); ____;
277     zzip_mem_entry_test_done ();
278 }
279
280 static void zzip_mem_entry_testall(ZZIP_MEM_DISK* disk)
281 {
282     zzip_mem_entry_test_start ();
283     ___ ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
284     for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
285         zzip_mem_entry_test (disk, entry); ____;
286     zzip_mem_entry_test_done ();
287 }
288
289 static void zzip_mem_entry_pipefiles(ZZIP_MEM_DISK* disk, char* filespec)
290 {
291     ZZIP_MEM_ENTRY* entry = 0;
292     while ((entry = zzip_mem_disk_findmatch(disk, filespec, entry, 0, 0)))
293         zzip_mem_entry_pipe (disk, entry, stdout);
294 }
295
296 static void zzip_mem_entry_pipeall(ZZIP_MEM_DISK* disk)
297 {
298     ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
299     for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
300         zzip_mem_entry_pipe (disk, entry, stdout);
301 }
302
303 static void zzip_mem_entry_makefiles(ZZIP_MEM_DISK* disk, char* filespec)
304 {
305     ZZIP_MEM_ENTRY* entry = 0;
306     while ((entry = zzip_mem_disk_findmatch(disk, filespec, entry, 0, 0)))
307         zzip_mem_entry_make (disk, entry);
308 }
309
310 static void zzip_mem_entry_makeall(ZZIP_MEM_DISK* disk)
311 {
312     ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
313     for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
314         zzip_mem_entry_make (disk, entry);
315 }
316
317 int 
318 main (int argc, char ** argv)
319 {
320     int argn; int archname = 0; int filespec = 0;
321     ZZIP_MEM_DISK* disk;
322     if (argc <= 1 || ! strcmp (argv[1], "--help"))
323     {
324         printf (usage);
325         return 0;
326     }
327     if (! strcmp (argv[1], "--version"))
328     {
329         printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
330         return 0;
331     }
332
333     for (argn=1; argn < argc; argn++) {
334         if ((argv[argn])[0] == '-') {
335             int x = 1;
336             while ((argv[argn])[x]) {
337                 switch (argv[argn][x]) {
338                 case 'l': option_list++; break;
339                 case 'p': option_pipe++; break;
340                 case 't': option_testcrc++; break;
341                 case 'v': option_verbose++; break;
342                 case 'b': option_binary++; break;
343                 case 'C': option_nocase++; break;
344                 case 'j': option_junkpaths++; break;
345                 case 'L': option_dosfiles++; break;
346                 case 'n': option_keepold++; break;
347                 case 'o': option_overwrite++; break;
348                 case 'q': option_quiet++; break;
349                 case 'X': option_permbits++; break;
350                 }
351                 x++;
352             }
353             (argv[argn])[0] = 0;
354         } else {
355             if (! archname) { archname = argn; continue; }
356             if (! filespec) { filespec = argn; continue; }
357         }
358     }
359
360     if (! archname) {
361         printf (usage);
362         return 0;
363     } else archive = argv[archname];
364
365     disk = zzip_mem_disk_open (argv[archname]);
366     if (! disk) {
367         perror(argv[archname]);
368         return -1;
369     }
370
371     if (option_list || option_verbose) {
372         if (! filespec) {
373             zzip_mem_entry_listall (disk);
374         } else {
375             for (argn=filespec; argn < argc; argn++) {
376                 if (argv[argn][0]) {
377                     zzip_mem_entry_listfiles (disk, argv[argn]);
378                 }
379             }
380         }
381     } else if (option_pipe) {
382         if (! filespec) {
383             zzip_mem_entry_pipeall (disk);
384         } else {
385             for (argn=filespec; argn < argc; argn++) {
386                 if (argv[argn][0]) {
387                     zzip_mem_entry_pipefiles (disk, argv[argn]);
388                 }
389             }
390         }
391     } else if (option_testcrc) {
392         if (! filespec) {
393             zzip_mem_entry_testall (disk);
394         } else {
395             for (argn=filespec; argn < argc; argn++) {
396                 if (argv[argn][0]) {
397                     zzip_mem_entry_testfiles (disk, argv[argn]);
398                 }
399             }
400         }
401     } else {
402         if (! filespec) {
403             zzip_mem_entry_makeall (disk);
404         } else {
405             for (argn=filespec; argn < argc; argn++) {
406                 if (argv[argn][0]) {
407                     zzip_mem_entry_makefiles (disk, argv[argn]);
408                 }
409             }
410         }
411     }
412
413     return status;
414
415
416 /* 
417  * Local variables:
418  * c-file-style: "stroustrup"
419  * End:
420  */