/StormLib/stormlib/zlib/contrib/minizip/miniunz.c

http://ghostcb.googlecode.com/ · C · 585 lines · 491 code · 70 blank · 24 comment · 115 complexity · 6da0720d7ef48b92c64b83d85d1da19d MD5 · raw file

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