2 * Copyright (c) 2003 Guido Draheim <guidod@gmx.de>
3 * Use freely under the restrictions of the ZLIB license.
5 * This file is used as an example to clarify zzipmmap api usage.
8 #include <zlib.h> /* crc32 */
10 #include <zzip/memdisk.h>
15 #ifdef ZZIP_HAVE_UNISTD_H
24 #ifdef ZZIP_HAVE_FNMATCH_H
27 #define fnmatch(x,y,z) strcmp(x,y)
37 #define EXIT_SUCCESS 0
38 #define EXIT_WARNINGS 1
40 #define EXIT_EFORMAT 3
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
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" */
67 static const char usage
[] =
69 "unzzip-mem <zip> [names].. \n"
70 " - unzzip a zip archive.\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"
86 static void zzip_mem_entry_pipe(ZZIP_MEM_DISK
* disk
,
87 ZZIP_MEM_ENTRY
* entry
, FILE* out
)
89 ZZIP_DISK_FILE
* file
= zzip_mem_entry_fopen (disk
, entry
);
92 char buffer
[1024]; int len
;
93 while ((len
= zzip_mem_disk_fread (buffer
, 1024, 1, file
)))
94 fwrite (buffer
, len
, 1, out
);
96 zzip_mem_disk_fclose (file
);
100 static void zzip_mem_entry_make(ZZIP_MEM_DISK
* disk
,
101 ZZIP_MEM_ENTRY
* entry
)
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
;
109 /* ------------------------- test ------------------------------------ */
111 static char* archive
= 0;
112 static int test_errors
= 0;
114 static void zzip_mem_entry_test(ZZIP_MEM_DISK
* disk
,
115 ZZIP_MEM_ENTRY
* entry
)
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
),
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
);
131 zzip_mem_disk_fclose (file
);
132 if (crc
== (unsigned long) entry
->zz_crc32
) {
135 printf ("BAD %lx (should be %lx)\n", crc
, entry
->zz_crc32
);
139 printf ("ERROR (no such file)\n");
144 static void zzip_mem_entry_test_start(void)
147 printf ("Archive: %s\n", archive
);
150 static void zzip_mem_entry_test_done(void)
152 if (test_errors
== 0) {
153 printf ("No errors detected in compressed data of %s\n", archive
);
155 printf ("%i errors detected in compressed data of %s\n",
156 test_errors
, archive
);
160 /* ------------------------- list ------------------------------------ */
162 static char _zzip_time_
[30];
163 static char* _zzip_ctime (const time_t* timeval
)
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
);
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" };
176 zzip_off_t sum_usize
= 0;
177 zzip_off_t sum_csize
= 0;
178 zzip_off_t sum_files
= 0;
181 static void zzip_mem_entry_direntry_start (void)
186 if (option_verbose
) goto verbose
;
187 printf(" Length Date & Time Name\n");
188 printf(" -------- ---- ---- ----\n");
191 printf(" Length Method Size Ratio Date Time CRC-32 Name\n");
192 printf("-------- ------ ------- ----- ---- ---- ------ ----\n");
195 static void zzip_mem_entry_direntry_done (void)
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");
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");
217 static void zzip_mem_entry_direntry(ZZIP_MEM_ENTRY
* entry
)
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 time_t mtime
= entry
->zz_mktime
;
224 long crc32
= entry
->zz_crc32
;
225 const char* comment
= zzip_mem_entry_to_comment (entry
);
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; }
239 if (! comment
) comment
= "";
240 if (*name
== '\n') name
++;
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
);
248 printf(" %8li%c %s %s %s\n",
249 L usize
, exp
, _zzip_ctime(&mtime
), name
, comment
);
253 static void zzip_mem_entry_listfiles(ZZIP_MEM_DISK
* disk
, char* filespec
)
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 ();
262 static void zzip_mem_entry_listall(ZZIP_MEM_DISK
* disk
)
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 ();
271 static void zzip_mem_entry_testfiles(ZZIP_MEM_DISK
* disk
, char* filespec
)
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 ();
280 static void zzip_mem_entry_testall(ZZIP_MEM_DISK
* disk
)
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 ();
289 static void zzip_mem_entry_pipefiles(ZZIP_MEM_DISK
* disk
, char* filespec
)
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
);
296 static void zzip_mem_entry_pipeall(ZZIP_MEM_DISK
* disk
)
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
);
303 static void zzip_mem_entry_makefiles(ZZIP_MEM_DISK
* disk
, char* filespec
)
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
);
310 static void zzip_mem_entry_makeall(ZZIP_MEM_DISK
* disk
)
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
);
318 main (int argc
, char ** argv
)
320 int argn
; int archname
= 0; int filespec
= 0;
322 if (argc
<= 1 || ! strcmp (argv
[1], "--help"))
327 if (! strcmp (argv
[1], "--version"))
329 printf (__FILE__
" version "ZZIP_PACKAGE
" "ZZIP_VERSION
"\n");
333 for (argn
=1; argn
< argc
; argn
++) {
334 if ((argv
[argn
])[0] == '-') {
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;
355 if (! archname
) { archname
= argn
; continue; }
356 if (! filespec
) { filespec
= argn
; continue; }
363 } else archive
= argv
[archname
];
365 disk
= zzip_mem_disk_open (argv
[archname
]);
367 perror(argv
[archname
]);
371 if (option_list
|| option_verbose
) {
373 zzip_mem_entry_listall (disk
);
375 for (argn
=filespec
; argn
< argc
; argn
++) {
377 zzip_mem_entry_listfiles (disk
, argv
[argn
]);
381 } else if (option_pipe
) {
383 zzip_mem_entry_pipeall (disk
);
385 for (argn
=filespec
; argn
< argc
; argn
++) {
387 zzip_mem_entry_pipefiles (disk
, argv
[argn
]);
391 } else if (option_testcrc
) {
393 zzip_mem_entry_testall (disk
);
395 for (argn
=filespec
; argn
< argc
; argn
++) {
397 zzip_mem_entry_testfiles (disk
, argv
[argn
]);
403 zzip_mem_entry_makeall (disk
);
405 for (argn
=filespec
; argn
< argc
; argn
++) {
407 zzip_mem_entry_makefiles (disk
, argv
[argn
]);
418 * c-file-style: "stroustrup"