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