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