Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
8614 | maxcodehac | 1 | /* |
2 | miniunz.c |
||
3 | Version 1.01e, February 12th, 2005 |
||
4 | |||
5 | Copyright (C) 1998-2005 Gilles Vollant |
||
6 | */ |
||
7 | |||
8 | |||
9 | #include |
||
10 | #include |
||
11 | #include |
||
12 | #include |
||
13 | #include |
||
14 | #include |
||
15 | |||
16 | #ifdef unix |
||
17 | # include |
||
18 | # include |
||
19 | #else |
||
20 | # include |
||
21 | # include |
||
22 | #endif |
||
23 | |||
24 | #include "unzip.h" |
||
25 | |||
26 | #define CASESENSITIVITY (0) |
||
27 | #define WRITEBUFFERSIZE (8192) |
||
28 | #define MAXFILENAME (256) |
||
29 | |||
30 | #ifdef WIN32 |
||
31 | #define USEWIN32IOAPI |
||
32 | #include "iowin32.h" |
||
33 | #endif |
||
34 | /* |
||
35 | mini unzip, demo of unzip package |
||
36 | |||
37 | usage : |
||
38 | Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir] |
||
39 | |||
40 | list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT |
||
41 | if it exists |
||
42 | */ |
||
43 | |||
44 | |||
45 | /* change_file_date : change the date/time of a file |
||
46 | filename : the filename of the file where date/time must be modified |
||
47 | dosdate : the new date at the MSDos format (4 bytes) |
||
48 | tmu_date : the SAME new date at the tm_unz format */ |
||
49 | void change_file_date(filename,dosdate,tmu_date) |
||
50 | const char *filename; |
||
51 | uLong dosdate; |
||
52 | tm_unz tmu_date; |
||
53 | { |
||
54 | #ifdef WIN32 |
||
55 | HANDLE hFile; |
||
56 | FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; |
||
57 | |||
58 | hFile = CreateFile(filename,GENERIC_READ | GENERIC_WRITE, |
||
59 | 0,NULL,OPEN_EXISTING,0,NULL); |
||
60 | GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite); |
||
61 | DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal); |
||
62 | LocalFileTimeToFileTime(&ftLocal,&ftm); |
||
63 | SetFileTime(hFile,&ftm,&ftLastAcc,&ftm); |
||
64 | CloseHandle(hFile); |
||
65 | #else |
||
66 | #ifdef unix |
||
67 | struct utimbuf ut; |
||
68 | struct tm newdate; |
||
69 | newdate.tm_sec = tmu_date.tm_sec; |
||
70 | newdate.tm_min=tmu_date.tm_min; |
||
71 | newdate.tm_hour=tmu_date.tm_hour; |
||
72 | newdate.tm_mday=tmu_date.tm_mday; |
||
73 | newdate.tm_mon=tmu_date.tm_mon; |
||
74 | if (tmu_date.tm_year > 1900) |
||
75 | newdate.tm_year=tmu_date.tm_year - 1900; |
||
76 | else |
||
77 | newdate.tm_year=tmu_date.tm_year ; |
||
78 | newdate.tm_isdst=-1; |
||
79 | |||
80 | ut.actime=ut.modtime=mktime(&newdate); |
||
81 | // utime(filename,&ut); |
||
82 | #endif |
||
83 | #endif |
||
84 | } |
||
85 | |||
86 | |||
87 | /* mymkdir and change_file_date are not 100 % portable |
||
88 | As I don't know well Unix, I wait feedback for the unix portion */ |
||
89 | |||
90 | int mymkdir(dirname) |
||
91 | const char* dirname; |
||
92 | { |
||
93 | int ret=0; |
||
94 | #ifdef WIN32 |
||
95 | ret = mkdir(dirname); |
||
96 | #else |
||
97 | #ifdef unix |
||
98 | ret = mkdir (dirname,0775); |
||
99 | #endif |
||
100 | #endif |
||
101 | return ret; |
||
102 | } |
||
103 | |||
104 | int makedir (newdir) |
||
105 | char *newdir; |
||
106 | { |
||
107 | char *buffer ; |
||
108 | char *p; |
||
109 | int len = (int)strlen(newdir); |
||
110 | |||
111 | if (len <= 0) |
||
112 | return 0; |
||
113 | |||
114 | buffer = (char*)malloc(len+1); |
||
115 | strcpy(buffer,newdir); |
||
116 | |||
117 | if (buffer[len-1] == '/') { |
||
118 | buffer[len-1] = '\0'; |
||
119 | } |
||
120 | if (mymkdir(buffer) == 0) |
||
121 | { |
||
122 | free(buffer); |
||
123 | return 1; |
||
124 | } |
||
125 | |||
126 | p = buffer+1; |
||
127 | while (1) |
||
128 | { |
||
129 | char hold; |
||
130 | |||
131 | while(*p && *p != '\\' && *p != '/') |
||
132 | p++; |
||
133 | hold = *p; |
||
134 | *p = 0; |
||
135 | if ((mymkdir(buffer) == -1) && (errno == ENOENT)) |
||
136 | { |
||
137 | printf("couldn't create directory %s\n",buffer); |
||
138 | free(buffer); |
||
139 | return 0; |
||
140 | } |
||
141 | if (hold == 0) |
||
142 | break; |
||
143 | *p++ = hold; |
||
144 | } |
||
145 | free(buffer); |
||
146 | return 1; |
||
147 | } |
||
148 | |||
149 | void do_banner() |
||
150 | { |
||
151 | printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n"); |
||
152 | printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n"); |
||
153 | } |
||
154 | |||
155 | void do_help() |
||
156 | { |
||
157 | printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \ |
||
158 | " -e Extract without pathname (junk paths)\n" \ |
||
159 | " -x Extract with pathname\n" \ |
||
160 | " -v list files\n" \ |
||
161 | " -l list files\n" \ |
||
162 | " -d directory to extract into\n" \ |
||
163 | " -o overwrite files without prompting\n" \ |
||
164 | " -p extract crypted file using password\n\n"); |
||
165 | } |
||
166 | |||
167 | |||
168 | int do_list(uf) |
||
169 | unzFile uf; |
||
170 | { |
||
171 | uLong i; |
||
172 | unz_global_info gi; |
||
173 | int err; |
||
174 | |||
175 | err = unzGetGlobalInfo (uf,&gi); |
||
176 | if (err!=UNZ_OK) |
||
177 | printf("error %d with zipfile in unzGetGlobalInfo \n",err); |
||
178 | printf(" Length Method Size Ratio Date Time CRC-32 Name\n"); |
||
179 | printf(" ------ ------ ---- ----- ---- ---- ------ ----\n"); |
||
180 | for (i=0;i |
||
181 | { |
||
182 | char filename_inzip[256]; |
||
183 | unz_file_info file_info; |
||
184 | uLong ratio=0; |
||
185 | const char *string_method; |
||
186 | char charCrypt=' '; |
||
187 | err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0); |
||
188 | if (err!=UNZ_OK) |
||
189 | { |
||
190 | printf("error %d with zipfile in unzGetCurrentFileInfo\n",err); |
||
191 | break; |
||
192 | } |
||
193 | if (file_info.uncompressed_size>0) |
||
194 | ratio = (file_info.compressed_size*100)/file_info.uncompressed_size; |
||
195 | |||
196 | /* display a '*' if the file is crypted */ |
||
197 | if ((file_info.flag & 1) != 0) |
||
198 | charCrypt='*'; |
||
199 | |||
200 | if (file_info.compression_method==0) |
||
201 | string_method="Stored"; |
||
202 | else |
||
203 | if (file_info.compression_method==Z_DEFLATED) |
||
204 | { |
||
205 | uInt iLevel=(uInt)((file_info.flag & 0x6)/2); |
||
206 | if (iLevel==0) |
||
207 | string_method="Defl:N"; |
||
208 | else if (iLevel==1) |
||
209 | string_method="Defl:X"; |
||
210 | else if ((iLevel==2) || (iLevel==3)) |
||
211 | string_method="Defl:F"; /* 2:fast , 3 : extra fast*/ |
||
212 | } |
||
213 | else |
||
214 | string_method="Unkn. "; |
||
215 | |||
216 | printf("%7lu %6s%c%7lu %3lu%% %2.2lu-%2.2lu-%2.2lu %2.2lu:%2.2lu %8.8lx %s\n", |
||
217 | file_info.uncompressed_size,string_method, |
||
218 | charCrypt, |
||
219 | file_info.compressed_size, |
||
220 | ratio, |
||
221 | (uLong)file_info.tmu_date.tm_mon + 1, |
||
222 | (uLong)file_info.tmu_date.tm_mday, |
||
223 | (uLong)file_info.tmu_date.tm_year % 100, |
||
224 | (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min, |
||
225 | (uLong)file_info.crc,filename_inzip); |
||
226 | if ((i+1) |
||
227 | { |
||
228 | err = unzGoToNextFile(uf); |
||
229 | if (err!=UNZ_OK) |
||
230 | { |
||
231 | printf("error %d with zipfile in unzGoToNextFile\n",err); |
||
232 | break; |
||
233 | } |
||
234 | } |
||
235 | } |
||
236 | |||
237 | return 0; |
||
238 | } |
||
239 | |||
240 | |||
241 | int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,password) |
||
242 | unzFile uf; |
||
243 | const int* popt_extract_without_path; |
||
244 | int* popt_overwrite; |
||
245 | const char* password; |
||
246 | { |
||
247 | char filename_inzip[256]; |
||
248 | char* filename_withoutpath; |
||
249 | char* p; |
||
250 | int err=UNZ_OK; |
||
251 | FILE *fout=NULL; |
||
252 | void* buf; |
||
253 | uInt size_buf; |
||
254 | |||
255 | unz_file_info file_info; |
||
256 | uLong ratio=0; |
||
257 | err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0); |
||
258 | |||
259 | if (err!=UNZ_OK) |
||
260 | { |
||
261 | printf("error %d with zipfile in unzGetCurrentFileInfo\n",err); |
||
262 | return err; |
||
263 | } |
||
264 | |||
265 | size_buf = WRITEBUFFERSIZE; |
||
266 | buf = (void*)malloc(size_buf); |
||
267 | if (buf==NULL) |
||
268 | { |
||
269 | printf("Error allocating memory\n"); |
||
270 | return UNZ_INTERNALERROR; |
||
271 | } |
||
272 | |||
273 | p = filename_withoutpath = filename_inzip; |
||
274 | while ((*p) != '\0') |
||
275 | { |
||
276 | if (((*p)=='/') || ((*p)=='\\')) |
||
277 | filename_withoutpath = p+1; |
||
278 | p++; |
||
279 | } |
||
280 | |||
281 | if ((*filename_withoutpath)=='\0') |
||
282 | { |
||
283 | if ((*popt_extract_without_path)==0) |
||
284 | { |
||
285 | printf("creating directory: %s\n",filename_inzip); |
||
286 | mymkdir(filename_inzip); |
||
287 | } |
||
288 | } |
||
289 | else |
||
290 | { |
||
291 | const char* write_filename; |
||
292 | int skip=0; |
||
293 | |||
294 | if ((*popt_extract_without_path)==0) |
||
295 | write_filename = filename_inzip; |
||
296 | else |
||
297 | write_filename = filename_withoutpath; |
||
298 | |||
299 | err = unzOpenCurrentFilePassword(uf,password); |
||
300 | if (err!=UNZ_OK) |
||
301 | { |
||
302 | printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err); |
||
303 | } |
||
304 | |||
305 | if (((*popt_overwrite)==0) && (err==UNZ_OK)) |
||
306 | { |
||
307 | char rep=0; |
||
308 | FILE* ftestexist; |
||
309 | ftestexist = fopen(write_filename,"rb"); |
||
310 | if (ftestexist!=NULL) |
||
311 | { |
||
312 | fclose(ftestexist); |
||
313 | do |
||
314 | { |
||
315 | char answer[128]; |
||
316 | int ret; |
||
317 | |||
318 | printf("The file %s exists. Overwrite ? [y]es, [n]o, [A]ll: ",write_filename); |
||
319 | ret = scanf("%1s",answer); |
||
320 | if (ret != 1) |
||
321 | { |
||
322 | exit(EXIT_FAILURE); |
||
323 | } |
||
324 | rep = answer[0] ; |
||
325 | if ((rep>='a') && (rep<='z')) |
||
326 | rep -= 0x20; |
||
327 | } |
||
328 | while ((rep!='Y') && (rep!='N') && (rep!='A')); |
||
329 | } |
||
330 | |||
331 | if (rep == 'N') |
||
332 | skip = 1; |
||
333 | |||
334 | if (rep == 'A') |
||
335 | *popt_overwrite=1; |
||
336 | } |
||
337 | |||
338 | if ((skip==0) && (err==UNZ_OK)) |
||
339 | { |
||
340 | fout=fopen(write_filename,"wb"); |
||
341 | |||
342 | /* some zipfile don't contain directory alone before file */ |
||
343 | if ((fout==NULL) && ((*popt_extract_without_path)==0) && |
||
344 | (filename_withoutpath!=(char*)filename_inzip)) |
||
345 | { |
||
346 | char c=*(filename_withoutpath-1); |
||
347 | *(filename_withoutpath-1)='\0'; |
||
348 | makedir(write_filename); |
||
349 | *(filename_withoutpath-1)=c; |
||
350 | fout=fopen(write_filename,"wb"); |
||
351 | } |
||
352 | |||
353 | if (fout==NULL) |
||
354 | { |
||
355 | printf("error opening %s\n",write_filename); |
||
356 | } |
||
357 | } |
||
358 | |||
359 | if (fout!=NULL) |
||
360 | { |
||
361 | printf(" extracting: %s\n",write_filename); |
||
362 | |||
363 | do |
||
364 | { |
||
365 | err = unzReadCurrentFile(uf,buf,size_buf); |
||
366 | if (err<0) |
||
367 | { |
||
368 | printf("error %d with zipfile in unzReadCurrentFile\n",err); |
||
369 | break; |
||
370 | } |
||
371 | if (err>0) |
||
372 | if (fwrite(buf,err,1,fout)!=1) |
||
373 | { |
||
374 | printf("error in writing extracted file\n"); |
||
375 | err=UNZ_ERRNO; |
||
376 | break; |
||
377 | } |
||
378 | } |
||
379 | while (err>0); |
||
380 | if (fout) |
||
381 | fclose(fout); |
||
382 | |||
383 | if (err==0) |
||
384 | change_file_date(write_filename,file_info.dosDate, |
||
385 | file_info.tmu_date); |
||
386 | } |
||
387 | |||
388 | if (err==UNZ_OK) |
||
389 | { |
||
390 | err = unzCloseCurrentFile (uf); |
||
391 | if (err!=UNZ_OK) |
||
392 | { |
||
393 | printf("error %d with zipfile in unzCloseCurrentFile\n",err); |
||
394 | } |
||
395 | } |
||
396 | else |
||
397 | unzCloseCurrentFile(uf); /* don't lose the error */ |
||
398 | } |
||
399 | |||
400 | free(buf); |
||
401 | return err; |
||
402 | } |
||
403 | |||
404 | |||
405 | int do_extract(uf,opt_extract_without_path,opt_overwrite,password) |
||
406 | unzFile uf; |
||
407 | int opt_extract_without_path; |
||
408 | int opt_overwrite; |
||
409 | const char* password; |
||
410 | { |
||
411 | uLong i; |
||
412 | unz_global_info gi; |
||
413 | int err; |
||
414 | FILE* fout=NULL; |
||
415 | |||
416 | err = unzGetGlobalInfo (uf,&gi); |
||
417 | if (err!=UNZ_OK) |
||
418 | printf("error %d with zipfile in unzGetGlobalInfo \n",err); |
||
419 | |||
420 | for (i=0;i |
||
421 | { |
||
422 | if (do_extract_currentfile(uf,&opt_extract_without_path, |
||
423 | &opt_overwrite, |
||
424 | password) != UNZ_OK) |
||
425 | break; |
||
426 | |||
427 | if ((i+1) |
||
428 | { |
||
429 | err = unzGoToNextFile(uf); |
||
430 | if (err!=UNZ_OK) |
||
431 | { |
||
432 | printf("error %d with zipfile in unzGoToNextFile\n",err); |
||
433 | break; |
||
434 | } |
||
435 | } |
||
436 | } |
||
437 | |||
438 | return 0; |
||
439 | } |
||
440 | |||
441 | int do_extract_onefile(uf,filename,opt_extract_without_path,opt_overwrite,password) |
||
442 | unzFile uf; |
||
443 | const char* filename; |
||
444 | int opt_extract_without_path; |
||
445 | int opt_overwrite; |
||
446 | const char* password; |
||
447 | { |
||
448 | int err = UNZ_OK; |
||
449 | if (unzLocateFile(uf,filename,CASESENSITIVITY)!=UNZ_OK) |
||
450 | { |
||
451 | printf("file %s not found in the zipfile\n",filename); |
||
452 | return 2; |
||
453 | } |
||
454 | |||
455 | if (do_extract_currentfile(uf,&opt_extract_without_path, |
||
456 | &opt_overwrite, |
||
457 | password) == UNZ_OK) |
||
458 | return 0; |
||
459 | else |
||
460 | return 1; |
||
461 | } |
||
462 | |||
463 | |||
464 | int main(argc,argv) |
||
465 | int argc; |
||
466 | char *argv[]; |
||
467 | { |
||
468 | const char *zipfilename=NULL; |
||
469 | const char *filename_to_extract=NULL; |
||
470 | const char *password=NULL; |
||
471 | char filename_try[MAXFILENAME+16] = ""; |
||
472 | int i; |
||
473 | int opt_do_list=0; |
||
474 | int opt_do_extract=1; |
||
475 | int opt_do_extract_withoutpath=0; |
||
476 | int opt_overwrite=0; |
||
477 | int opt_extractdir=0; |
||
478 | const char *dirname=NULL; |
||
479 | unzFile uf=NULL; |
||
480 | |||
481 | do_banner(); |
||
482 | if (argc==1) |
||
483 | { |
||
484 | do_help(); |
||
485 | return 0; |
||
486 | } |
||
487 | else |
||
488 | { |
||
489 | for (i=1;i |
||
490 | { |
||
491 | if ((*argv[i])=='-') |
||
492 | { |
||
493 | const char *p=argv[i]+1; |
||
494 | |||
495 | while ((*p)!='\0') |
||
496 | { |
||
497 | char c=*(p++);; |
||
498 | if ((c=='l') || (c=='L')) |
||
499 | opt_do_list = 1; |
||
500 | if ((c=='v') || (c=='V')) |
||
501 | opt_do_list = 1; |
||
502 | if ((c=='x') || (c=='X')) |
||
503 | opt_do_extract = 1; |
||
504 | if ((c=='e') || (c=='E')) |
||
505 | opt_do_extract = opt_do_extract_withoutpath = 1; |
||
506 | if ((c=='o') || (c=='O')) |
||
507 | opt_overwrite=1; |
||
508 | if ((c=='d') || (c=='D')) |
||
509 | { |
||
510 | opt_extractdir=1; |
||
511 | dirname=argv[i+1]; |
||
512 | } |
||
513 | |||
514 | if (((c=='p') || (c=='P')) && (i+1 |
||
515 | { |
||
516 | password=argv[i+1]; |
||
517 | i++; |
||
518 | } |
||
519 | } |
||
520 | } |
||
521 | else |
||
522 | { |
||
523 | if (zipfilename == NULL) |
||
524 | zipfilename = argv[i]; |
||
525 | else if ((filename_to_extract==NULL) && (!opt_extractdir)) |
||
526 | filename_to_extract = argv[i] ; |
||
527 | } |
||
528 | } |
||
529 | } |
||
530 | |||
531 | if (zipfilename!=NULL) |
||
532 | { |
||
533 | |||
534 | # ifdef USEWIN32IOAPI |
||
535 | zlib_filefunc_def ffunc; |
||
536 | # endif |
||
537 | |||
538 | strncpy(filename_try, zipfilename,MAXFILENAME-1); |
||
539 | /* strncpy doesnt append the trailing NULL, of the string is too long. */ |
||
540 | filename_try[ MAXFILENAME ] = '\0'; |
||
541 | |||
542 | # ifdef USEWIN32IOAPI |
||
543 | fill_win32_filefunc(&ffunc); |
||
544 | uf = unzOpen2(zipfilename,&ffunc); |
||
545 | # else |
||
546 | uf = unzOpen(zipfilename); |
||
547 | # endif |
||
548 | if (uf==NULL) |
||
549 | { |
||
550 | strcat(filename_try,".zip"); |
||
551 | # ifdef USEWIN32IOAPI |
||
552 | uf = unzOpen2(filename_try,&ffunc); |
||
553 | # else |
||
554 | uf = unzOpen(filename_try); |
||
555 | # endif |
||
556 | } |
||
557 | } |
||
558 | |||
559 | if (uf==NULL) |
||
560 | { |
||
561 | printf("Cannot open %s or %s.zip\n",zipfilename,zipfilename); |
||
562 | return 1; |
||
563 | } |
||
564 | printf("%s opened\n",filename_try); |
||
565 | |||
566 | if (opt_do_list==1) |
||
567 | return do_list(uf); |
||
568 | else if (opt_do_extract==1) |
||
569 | { |
||
570 | if (opt_extractdir && chdir(dirname)) |
||
571 | { |
||
572 | printf("Error changing into %s, aborting\n", dirname); |
||
573 | exit(-1); |
||
574 | } |
||
575 | |||
576 | if (filename_to_extract == NULL) |
||
577 | return do_extract(uf,opt_do_extract_withoutpath,opt_overwrite,password); |
||
578 | else |
||
579 | return do_extract_onefile(uf,filename_to_extract, |
||
580 | opt_do_extract_withoutpath,opt_overwrite,password); |
||
581 | } |
||
582 | unzCloseCurrentFile(uf); |
||
583 | |||
584 | return 0; |
||
585 | } |