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