minizip.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. /*
  2. minizip.c
  3. Version 1.1, February 14h, 2010
  4. sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
  5. Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
  6. Modifications of Unzip for Zip64
  7. Copyright (C) 2007-2008 Even Rouault
  8. Modifications for Zip64 support on both zip and unzip
  9. Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
  10. */
  11. #ifndef _WIN32
  12. #ifndef __USE_FILE_OFFSET64
  13. #define __USE_FILE_OFFSET64
  14. #endif
  15. #ifndef __USE_LARGEFILE64
  16. #define __USE_LARGEFILE64
  17. #endif
  18. #ifndef _LARGEFILE64_SOURCE
  19. #define _LARGEFILE64_SOURCE
  20. #endif
  21. #ifndef _FILE_OFFSET_BIT
  22. #define _FILE_OFFSET_BIT 64
  23. #endif
  24. #endif
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <time.h>
  29. #include <errno.h>
  30. #include <fcntl.h>
  31. #ifdef unix
  32. # include <unistd.h>
  33. # include <utime.h>
  34. # include <sys/types.h>
  35. # include <sys/stat.h>
  36. #else
  37. # include <direct.h>
  38. # include <io.h>
  39. #endif
  40. #include "zip.h"
  41. #ifdef _WIN32
  42. #define USEWIN32IOAPI
  43. #include "iowin32.h"
  44. #endif
  45. #define WRITEBUFFERSIZE (16384)
  46. #define MAXFILENAME (256)
  47. #ifdef _WIN32
  48. uLong filetime(f, tmzip, dt)
  49. char *f; /* name of file to get info on */
  50. tm_zip *tmzip; /* return value: access, modific. and creation times */
  51. uLong *dt; /* dostime */
  52. {
  53. int ret = 0;
  54. {
  55. FILETIME ftLocal;
  56. HANDLE hFind;
  57. WIN32_FIND_DATAA ff32;
  58. hFind = FindFirstFileA(f,&ff32);
  59. if (hFind != INVALID_HANDLE_VALUE)
  60. {
  61. FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
  62. FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
  63. FindClose(hFind);
  64. ret = 1;
  65. }
  66. }
  67. return ret;
  68. }
  69. #else
  70. #ifdef unix
  71. uLong filetime(f, tmzip, dt)
  72. char *f; /* name of file to get info on */
  73. tm_zip *tmzip; /* return value: access, modific. and creation times */
  74. uLong *dt; /* dostime */
  75. {
  76. int ret=0;
  77. struct stat s; /* results of stat() */
  78. struct tm* filedate;
  79. time_t tm_t=0;
  80. if (strcmp(f,"-")!=0)
  81. {
  82. char name[MAXFILENAME+1];
  83. int len = strlen(f);
  84. if (len > MAXFILENAME)
  85. len = MAXFILENAME;
  86. strncpy(name, f,MAXFILENAME-1);
  87. /* strncpy doesnt append the trailing NULL, of the string is too long. */
  88. name[ MAXFILENAME ] = '\0';
  89. if (name[len - 1] == '/')
  90. name[len - 1] = '\0';
  91. /* not all systems allow stat'ing a file with / appended */
  92. if (stat(name,&s)==0)
  93. {
  94. tm_t = s.st_mtime;
  95. ret = 1;
  96. }
  97. }
  98. filedate = localtime(&tm_t);
  99. tmzip->tm_sec = filedate->tm_sec;
  100. tmzip->tm_min = filedate->tm_min;
  101. tmzip->tm_hour = filedate->tm_hour;
  102. tmzip->tm_mday = filedate->tm_mday;
  103. tmzip->tm_mon = filedate->tm_mon ;
  104. tmzip->tm_year = filedate->tm_year;
  105. return ret;
  106. }
  107. #else
  108. uLong filetime(f, tmzip, dt)
  109. char *f; /* name of file to get info on */
  110. tm_zip *tmzip; /* return value: access, modific. and creation times */
  111. uLong *dt; /* dostime */
  112. {
  113. return 0;
  114. }
  115. #endif
  116. #endif
  117. int check_exist_file(filename)
  118. const char* filename;
  119. {
  120. FILE* ftestexist;
  121. int ret = 1;
  122. ftestexist = fopen64(filename,"rb");
  123. if (ftestexist==NULL)
  124. ret = 0;
  125. else
  126. fclose(ftestexist);
  127. return ret;
  128. }
  129. void do_banner()
  130. {
  131. printf("MiniZip 1.1, demo of zLib + MiniZip64 package, written by Gilles Vollant\n");
  132. printf("more info on MiniZip at http://www.winimage.com/zLibDll/minizip.html\n\n");
  133. }
  134. void do_help()
  135. {
  136. printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] [-j] file.zip [files_to_add]\n\n" \
  137. " -o Overwrite existing file.zip\n" \
  138. " -a Append to existing file.zip\n" \
  139. " -0 Store only\n" \
  140. " -1 Compress faster\n" \
  141. " -9 Compress better\n\n" \
  142. " -j exclude path. store only the file name.\n\n");
  143. }
  144. /* calculate the CRC32 of a file,
  145. because to encrypt a file, we need known the CRC32 of the file before */
  146. int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc)
  147. {
  148. unsigned long calculate_crc=0;
  149. int err=ZIP_OK;
  150. FILE * fin = fopen64(filenameinzip,"rb");
  151. unsigned long size_read = 0;
  152. unsigned long total_read = 0;
  153. if (fin==NULL)
  154. {
  155. err = ZIP_ERRNO;
  156. }
  157. if (err == ZIP_OK)
  158. do
  159. {
  160. err = ZIP_OK;
  161. size_read = (int)fread(buf,1,size_buf,fin);
  162. if (size_read < size_buf)
  163. if (feof(fin)==0)
  164. {
  165. printf("error in reading %s\n",filenameinzip);
  166. err = ZIP_ERRNO;
  167. }
  168. if (size_read>0)
  169. calculate_crc = crc32(calculate_crc,buf,size_read);
  170. total_read += size_read;
  171. } while ((err == ZIP_OK) && (size_read>0));
  172. if (fin)
  173. fclose(fin);
  174. *result_crc=calculate_crc;
  175. printf("file %s crc %lx\n", filenameinzip, calculate_crc);
  176. return err;
  177. }
  178. int isLargeFile(const char* filename)
  179. {
  180. int largeFile = 0;
  181. ZPOS64_T pos = 0;
  182. FILE* pFile = fopen64(filename, "rb");
  183. if(pFile != NULL)
  184. {
  185. int n = fseeko64(pFile, 0, SEEK_END);
  186. pos = ftello64(pFile);
  187. printf("File : %s is %lld bytes\n", filename, pos);
  188. if(pos >= 0xffffffff)
  189. largeFile = 1;
  190. fclose(pFile);
  191. }
  192. return largeFile;
  193. }
  194. int main(argc,argv)
  195. int argc;
  196. char *argv[];
  197. {
  198. int i;
  199. int opt_overwrite=0;
  200. int opt_compress_level=Z_DEFAULT_COMPRESSION;
  201. int opt_exclude_path=0;
  202. int zipfilenamearg = 0;
  203. char filename_try[MAXFILENAME+16];
  204. int zipok;
  205. int err=0;
  206. int size_buf=0;
  207. void* buf=NULL;
  208. const char* password=NULL;
  209. do_banner();
  210. if (argc==1)
  211. {
  212. do_help();
  213. return 0;
  214. }
  215. else
  216. {
  217. for (i=1;i<argc;i++)
  218. {
  219. if ((*argv[i])=='-')
  220. {
  221. const char *p=argv[i]+1;
  222. while ((*p)!='\0')
  223. {
  224. char c=*(p++);;
  225. if ((c=='o') || (c=='O'))
  226. opt_overwrite = 1;
  227. if ((c=='a') || (c=='A'))
  228. opt_overwrite = 2;
  229. if ((c>='0') && (c<='9'))
  230. opt_compress_level = c-'0';
  231. if ((c=='j') || (c=='J'))
  232. opt_exclude_path = 1;
  233. if (((c=='p') || (c=='P')) && (i+1<argc))
  234. {
  235. password=argv[i+1];
  236. i++;
  237. }
  238. }
  239. }
  240. else
  241. {
  242. if (zipfilenamearg == 0)
  243. {
  244. zipfilenamearg = i ;
  245. }
  246. }
  247. }
  248. }
  249. size_buf = WRITEBUFFERSIZE;
  250. buf = (void*)malloc(size_buf);
  251. if (buf==NULL)
  252. {
  253. printf("Error allocating memory\n");
  254. return ZIP_INTERNALERROR;
  255. }
  256. if (zipfilenamearg==0)
  257. {
  258. zipok=0;
  259. }
  260. else
  261. {
  262. int i,len;
  263. int dot_found=0;
  264. zipok = 1 ;
  265. strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1);
  266. /* strncpy doesnt append the trailing NULL, of the string is too long. */
  267. filename_try[ MAXFILENAME ] = '\0';
  268. len=(int)strlen(filename_try);
  269. for (i=0;i<len;i++)
  270. if (filename_try[i]=='.')
  271. dot_found=1;
  272. if (dot_found==0)
  273. strcat(filename_try,".zip");
  274. if (opt_overwrite==2)
  275. {
  276. /* if the file don't exist, we not append file */
  277. if (check_exist_file(filename_try)==0)
  278. opt_overwrite=1;
  279. }
  280. else
  281. if (opt_overwrite==0)
  282. if (check_exist_file(filename_try)!=0)
  283. {
  284. char rep=0;
  285. do
  286. {
  287. char answer[128];
  288. int ret;
  289. printf("The file %s exists. Overwrite ? [y]es, [n]o, [a]ppend : ",filename_try);
  290. ret = scanf("%1s",answer);
  291. if (ret != 1)
  292. {
  293. exit(EXIT_FAILURE);
  294. }
  295. rep = answer[0] ;
  296. if ((rep>='a') && (rep<='z'))
  297. rep -= 0x20;
  298. }
  299. while ((rep!='Y') && (rep!='N') && (rep!='A'));
  300. if (rep=='N')
  301. zipok = 0;
  302. if (rep=='A')
  303. opt_overwrite = 2;
  304. }
  305. }
  306. if (zipok==1)
  307. {
  308. zipFile zf;
  309. int errclose;
  310. # ifdef USEWIN32IOAPI
  311. zlib_filefunc64_def ffunc;
  312. fill_win32_filefunc64A(&ffunc);
  313. zf = zipOpen2_64(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc);
  314. # else
  315. zf = zipOpen64(filename_try,(opt_overwrite==2) ? 2 : 0);
  316. # endif
  317. if (zf == NULL)
  318. {
  319. printf("error opening %s\n",filename_try);
  320. err= ZIP_ERRNO;
  321. }
  322. else
  323. printf("creating %s\n",filename_try);
  324. for (i=zipfilenamearg+1;(i<argc) && (err==ZIP_OK);i++)
  325. {
  326. if (!((((*(argv[i]))=='-') || ((*(argv[i]))=='/')) &&
  327. ((argv[i][1]=='o') || (argv[i][1]=='O') ||
  328. (argv[i][1]=='a') || (argv[i][1]=='A') ||
  329. (argv[i][1]=='p') || (argv[i][1]=='P') ||
  330. ((argv[i][1]>='0') || (argv[i][1]<='9'))) &&
  331. (strlen(argv[i]) == 2)))
  332. {
  333. FILE * fin;
  334. int size_read;
  335. const char* filenameinzip = argv[i];
  336. const char *savefilenameinzip;
  337. zip_fileinfo zi;
  338. unsigned long crcFile=0;
  339. int zip64 = 0;
  340. zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
  341. zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
  342. zi.dosDate = 0;
  343. zi.internal_fa = 0;
  344. zi.external_fa = 0;
  345. filetime(filenameinzip,&zi.tmz_date,&zi.dosDate);
  346. /*
  347. err = zipOpenNewFileInZip(zf,filenameinzip,&zi,
  348. NULL,0,NULL,0,NULL / * comment * /,
  349. (opt_compress_level != 0) ? Z_DEFLATED : 0,
  350. opt_compress_level);
  351. */
  352. if ((password != NULL) && (err==ZIP_OK))
  353. err = getFileCrc(filenameinzip,buf,size_buf,&crcFile);
  354. zip64 = isLargeFile(filenameinzip);
  355. /* The path name saved, should not include a leading slash. */
  356. /*if it did, windows/xp and dynazip couldn't read the zip file. */
  357. savefilenameinzip = filenameinzip;
  358. while( savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/' )
  359. {
  360. savefilenameinzip++;
  361. }
  362. /*should the zip file contain any path at all?*/
  363. if( opt_exclude_path )
  364. {
  365. const char *tmpptr;
  366. const char *lastslash = 0;
  367. for( tmpptr = savefilenameinzip; *tmpptr; tmpptr++)
  368. {
  369. if( *tmpptr == '\\' || *tmpptr == '/')
  370. {
  371. lastslash = tmpptr;
  372. }
  373. }
  374. if( lastslash != NULL )
  375. {
  376. savefilenameinzip = lastslash+1; // base filename follows last slash.
  377. }
  378. }
  379. /**/
  380. err = zipOpenNewFileInZip3_64(zf,savefilenameinzip,&zi,
  381. NULL,0,NULL,0,NULL /* comment*/,
  382. (opt_compress_level != 0) ? Z_DEFLATED : 0,
  383. opt_compress_level,0,
  384. /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
  385. -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
  386. password,crcFile, zip64);
  387. if (err != ZIP_OK)
  388. printf("error in opening %s in zipfile\n",filenameinzip);
  389. else
  390. {
  391. fin = fopen64(filenameinzip,"rb");
  392. if (fin==NULL)
  393. {
  394. err=ZIP_ERRNO;
  395. printf("error in opening %s for reading\n",filenameinzip);
  396. }
  397. }
  398. if (err == ZIP_OK)
  399. do
  400. {
  401. err = ZIP_OK;
  402. size_read = (int)fread(buf,1,size_buf,fin);
  403. if (size_read < size_buf)
  404. if (feof(fin)==0)
  405. {
  406. printf("error in reading %s\n",filenameinzip);
  407. err = ZIP_ERRNO;
  408. }
  409. if (size_read>0)
  410. {
  411. err = zipWriteInFileInZip (zf,buf,size_read);
  412. if (err<0)
  413. {
  414. printf("error in writing %s in the zipfile\n",
  415. filenameinzip);
  416. }
  417. }
  418. } while ((err == ZIP_OK) && (size_read>0));
  419. if (fin)
  420. fclose(fin);
  421. if (err<0)
  422. err=ZIP_ERRNO;
  423. else
  424. {
  425. err = zipCloseFileInZip(zf);
  426. if (err!=ZIP_OK)
  427. printf("error in closing %s in the zipfile\n",
  428. filenameinzip);
  429. }
  430. }
  431. }
  432. errclose = zipClose(zf,NULL);
  433. if (errclose != ZIP_OK)
  434. printf("error in closing %s\n",filename_try);
  435. }
  436. else
  437. {
  438. do_help();
  439. }
  440. free(buf);
  441. return 0;
  442. }