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