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