Skip to content

Commit 2da5b04

Browse files
committed
Add -r (recursive) option to minizip, if dirent.h is available
1 parent da607da commit 2da5b04

3 files changed

Lines changed: 164 additions & 109 deletions

File tree

contrib/minizip/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ check_function_exists(fseeko HAVE_FSEEKO)
8181
#
8282
check_include_file(unistd.h HAVE_UNISTD_H)
8383

84+
#
85+
# Check for dirent.h
86+
#
87+
check_include_file(dirent.h HAVE_DIRENT_H)
88+
8489
#
8590
# Check to see if we have large file support
8691
#
@@ -145,6 +150,7 @@ if(MINIZIP_BUILD_SHARED)
145150
PRIVATE $<$<BOOL:${MSVC}>:_CRT_SECURE_NO_WARNINGS>
146151
$<$<BOOL:${HAVE___ATTR__VIS_HIDDEN}>:HAVE_HIDDEN>
147152
$<$<BOOL:${HAVE_UNISTD_H}>:HAVE_UNISTD_H=1>
153+
$<$<BOOL:${HAVE_DIRENT_H}>:HAVE_DIRENT_H=1>
148154
PUBLIC $<$<BOOL:${HAVE_OFF64_T}>:_LARGEFILE64_SOURCE=1>
149155
$<$<BOOL:${BZIP2_FOUND}>:HAVE_BZIP2=1>
150156
$<$<BOOL:NOT:${HAVE_FOPEN64}>:USE_FILE32API=1>)
@@ -189,6 +195,7 @@ if(MINIZIP_BUILD_STATIC)
189195
PRIVATE $<$<BOOL:${MSVC}>:_CRT_SECURE_NO_WARNINGS>
190196
$<$<BOOL:${HAVE___ATTR__VIS_HIDDEN}>:HAVE_HIDDEN>
191197
$<$<BOOL:${HAVE_UNISTD_H}>:HAVE_UNISTD_H=1>
198+
$<$<BOOL:${HAVE_DIRENT_H}>:HAVE_DIRENT_H=1>
192199
PUBLIC $<$<BOOL:${HAVE_OFF64_T}>:_LARGEFILE64_SOURCE=1>
193200
$<$<BOOL:${BZIP2_FOUND}>:HAVE_BZIP2=1>
194201
$<$<BOOL:NOT:${HAVE_FOPEN64}>:USE_FILE32API=1>)

contrib/minizip/configure.ac

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,7 @@ AM_CONDITIONAL([WIN32], [test "${WIN32}" = "yes"])
2828

2929
AC_SUBST([HAVE_UNISTD_H], [0])
3030
AC_CHECK_HEADER([unistd.h], [HAVE_UNISTD_H=1], [])
31+
AC_SUBST([HAVE_DIRENT_H], [0])
32+
AC_CHECK_HEADER([dirent.h], [HAVE_DIRENT_H=1], [])
3133
AC_CONFIG_FILES([Makefile minizip.pc])
3234
AC_OUTPUT

contrib/minizip/minizip.c

Lines changed: 155 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
#ifndef _CRT_SECURE_NO_WARNINGS
4444
# define _CRT_SECURE_NO_WARNINGS
4545
#endif
46+
#ifdef HAVE_DIRENT_H
47+
# include <dirent.h>
48+
#endif
4649
#include <stdio.h>
4750
#include <stdlib.h>
4851
#include <string.h>
@@ -167,7 +170,8 @@ static void do_banner(void) {
167170
}
168171

169172
static void do_help(void) {
170-
printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] [-j] file.zip [files_to_add]\n\n" \
173+
printf("Usage : minizip [-r] [-o] [-a] [-0 to -9] [-p password] [-j] file.zip [files_to_add]\n\n" \
174+
" -r Scan directories recursively\n" \
171175
" -o Overwrite existing file.zip\n" \
172176
" -a Append to existing file.zip\n" \
173177
" -0 Store only\n" \
@@ -237,8 +241,151 @@ static int isLargeFile(const char* filename) {
237241
return largeFile;
238242
}
239243

244+
void addFileToZip(zipFile zf, const char *filenameinzip, const char *password, int opt_exclude_path,int opt_compress_level) {
245+
FILE * fin = NULL;
246+
size_t size_read;
247+
const char *savefilenameinzip;
248+
zip_fileinfo zi;
249+
unsigned long crcFile=0;
250+
int zip64 = 0;
251+
int err=0;
252+
int size_buf=WRITEBUFFERSIZE;
253+
unsigned char buf[WRITEBUFFERSIZE];
254+
zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
255+
zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
256+
zi.dosDate = 0;
257+
zi.internal_fa = 0;
258+
zi.external_fa = 0;
259+
filetime(filenameinzip,&zi.tmz_date,&zi.dosDate);
260+
261+
/*
262+
err = zipOpenNewFileInZip(zf,filenameinzip,&zi,
263+
NULL,0,NULL,0,NULL / * comment * /,
264+
(opt_compress_level != 0) ? Z_DEFLATED : 0,
265+
opt_compress_level);
266+
*/
267+
if ((password != NULL) && (err==ZIP_OK))
268+
err = getFileCrc(filenameinzip,buf,size_buf,&crcFile);
269+
270+
zip64 = isLargeFile(filenameinzip);
271+
272+
/* The path name saved, should not include a leading slash. */
273+
/*if it did, windows/xp and dynazip couldn't read the zip file. */
274+
savefilenameinzip = filenameinzip;
275+
while( savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/' )
276+
{
277+
savefilenameinzip++;
278+
}
279+
280+
/*should the zip file contain any path at all?*/
281+
if( opt_exclude_path )
282+
{
283+
const char *tmpptr;
284+
const char *lastslash = 0;
285+
for( tmpptr = savefilenameinzip; *tmpptr; tmpptr++)
286+
{
287+
if( *tmpptr == '\\' || *tmpptr == '/')
288+
{
289+
lastslash = tmpptr;
290+
}
291+
}
292+
if( lastslash != NULL )
293+
{
294+
savefilenameinzip = lastslash+1; /* base filename follows last slash. */
295+
}
296+
}
297+
298+
/**/
299+
err = zipOpenNewFileInZip3_64(zf,savefilenameinzip,&zi,
300+
NULL,0,NULL,0,NULL /* comment*/,
301+
(opt_compress_level != 0) ? Z_DEFLATED : 0,
302+
opt_compress_level,0,
303+
/* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
304+
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
305+
password,crcFile, zip64);
306+
307+
if (err != ZIP_OK)
308+
printf("error in opening %s in zipfile\n",filenameinzip);
309+
else
310+
{
311+
fin = FOPEN_FUNC(filenameinzip,"rb");
312+
if (fin==NULL)
313+
{
314+
err=ZIP_ERRNO;
315+
printf("error in opening %s for reading\n",filenameinzip);
316+
}
317+
}
318+
319+
if (err == ZIP_OK)
320+
do
321+
{
322+
err = ZIP_OK;
323+
size_read = fread(buf,1,size_buf,fin);
324+
if (size_read < size_buf)
325+
if (feof(fin)==0)
326+
{
327+
printf("error in reading %s\n",filenameinzip);
328+
err = ZIP_ERRNO;
329+
}
330+
331+
if (size_read>0)
332+
{
333+
err = zipWriteInFileInZip (zf,buf,(unsigned)size_read);
334+
if (err<0)
335+
{
336+
printf("error in writing %s in the zipfile\n",
337+
filenameinzip);
338+
}
339+
340+
}
341+
} while ((err == ZIP_OK) && (size_read>0));
342+
343+
if (fin)
344+
fclose(fin);
345+
346+
if (err<0)
347+
err=ZIP_ERRNO;
348+
else
349+
{
350+
err = zipCloseFileInZip(zf);
351+
if (err!=ZIP_OK)
352+
printf("error in closing %s in the zipfile\n",
353+
filenameinzip);
354+
}
355+
}
356+
357+
358+
void addPathToZip(zipFile zf, const char *filenameinzip, const char *password, int opt_exclude_path,int opt_compress_level) {
359+
#ifdef HAVE_DIRENT_H
360+
# if defined(_MSC_VER)
361+
# define snprintf _snprintf
362+
# endif
363+
char newname[MAXFILENAME+1+MAXFILENAME+1];
364+
struct dirent *dp;
365+
366+
DIR *dir = opendir(filenameinzip);
367+
if (dir == NULL) {
368+
addFileToZip(zf,filenameinzip,password,opt_exclude_path,opt_compress_level);
369+
return;
370+
}
371+
while ((dp = readdir(dir)))
372+
{
373+
if(strcmp(dp->d_name,".")==0) continue;
374+
if(strcmp(dp->d_name,"..")==0) continue;
375+
snprintf(newname, sizeof(newname), "%.*s/%.*s", MAXFILENAME, filenameinzip, MAXFILENAME, dp->d_name);
376+
addPathToZip(zf,newname,password,opt_exclude_path,opt_compress_level));
377+
}
378+
379+
closedir(dir);
380+
#else
381+
printf("-r option not supported");
382+
#endif
383+
}
384+
385+
240386
int main(int argc, char *argv[]) {
241387
int i;
388+
int opt_recursive=0;
242389
int opt_overwrite=0;
243390
int opt_compress_level=Z_DEFAULT_COMPRESSION;
244391
int opt_exclude_path=0;
@@ -276,6 +423,8 @@ int main(int argc, char *argv[]) {
276423
opt_compress_level = c-'0';
277424
if ((c=='j') || (c=='J'))
278425
opt_exclude_path = 1;
426+
if ((c=='r') || (c=='R'))
427+
opt_recursive = 1;
279428

280429
if (((c=='p') || (c=='P')) && (i+1<argc))
281430
{
@@ -383,117 +532,14 @@ int main(int argc, char *argv[]) {
383532
((argv[i][1]=='o') || (argv[i][1]=='O') ||
384533
(argv[i][1]=='a') || (argv[i][1]=='A') ||
385534
(argv[i][1]=='p') || (argv[i][1]=='P') ||
535+
(argv[i][1]=='r') || (argv[i][1]=='R') ||
386536
((argv[i][1]>='0') && (argv[i][1]<='9'))) &&
387537
(strlen(argv[i]) == 2)))
388538
{
389-
FILE * fin = NULL;
390-
size_t size_read;
391-
const char* filenameinzip = argv[i];
392-
const char *savefilenameinzip;
393-
zip_fileinfo zi;
394-
unsigned long crcFile=0;
395-
int zip64 = 0;
396-
397-
zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
398-
zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
399-
zi.dosDate = 0;
400-
zi.internal_fa = 0;
401-
zi.external_fa = 0;
402-
filetime(filenameinzip,&zi.tmz_date,&zi.dosDate);
403-
404-
/*
405-
err = zipOpenNewFileInZip(zf,filenameinzip,&zi,
406-
NULL,0,NULL,0,NULL / * comment * /,
407-
(opt_compress_level != 0) ? Z_DEFLATED : 0,
408-
opt_compress_level);
409-
*/
410-
if ((password != NULL) && (err==ZIP_OK))
411-
err = getFileCrc(filenameinzip,buf,size_buf,&crcFile);
412-
413-
zip64 = isLargeFile(filenameinzip);
414-
415-
/* The path name saved, should not include a leading slash. */
416-
/*if it did, windows/xp and dynazip couldn't read the zip file. */
417-
savefilenameinzip = filenameinzip;
418-
while( savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/' )
419-
{
420-
savefilenameinzip++;
421-
}
422-
423-
/*should the zip file contain any path at all?*/
424-
if( opt_exclude_path )
425-
{
426-
const char *tmpptr;
427-
const char *lastslash = 0;
428-
for( tmpptr = savefilenameinzip; *tmpptr; tmpptr++)
429-
{
430-
if( *tmpptr == '\\' || *tmpptr == '/')
431-
{
432-
lastslash = tmpptr;
433-
}
434-
}
435-
if( lastslash != NULL )
436-
{
437-
savefilenameinzip = lastslash+1; /* base filename follows last slash. */
438-
}
439-
}
440-
441-
/**/
442-
err = zipOpenNewFileInZip3_64(zf,savefilenameinzip,&zi,
443-
NULL,0,NULL,0,NULL /* comment*/,
444-
(opt_compress_level != 0) ? Z_DEFLATED : 0,
445-
opt_compress_level,0,
446-
/* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
447-
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
448-
password,crcFile, zip64);
449-
450-
if (err != ZIP_OK)
451-
printf("error in opening %s in zipfile\n",filenameinzip);
452-
else
453-
{
454-
fin = FOPEN_FUNC(filenameinzip,"rb");
455-
if (fin==NULL)
456-
{
457-
err=ZIP_ERRNO;
458-
printf("error in opening %s for reading\n",filenameinzip);
459-
}
460-
}
461-
462-
if (err == ZIP_OK)
463-
do
464-
{
465-
err = ZIP_OK;
466-
size_read = fread(buf,1,size_buf,fin);
467-
if (size_read < size_buf)
468-
if (feof(fin)==0)
469-
{
470-
printf("error in reading %s\n",filenameinzip);
471-
err = ZIP_ERRNO;
472-
}
473-
474-
if (size_read>0)
475-
{
476-
err = zipWriteInFileInZip (zf,buf,(unsigned)size_read);
477-
if (err<0)
478-
{
479-
printf("error in writing %s in the zipfile\n",
480-
filenameinzip);
481-
}
482-
483-
}
484-
} while ((err == ZIP_OK) && (size_read>0));
485-
486-
if (fin)
487-
fclose(fin);
488-
489-
if (err<0)
490-
err=ZIP_ERRNO;
491-
else
492-
{
493-
err = zipCloseFileInZip(zf);
494-
if (err!=ZIP_OK)
495-
printf("error in closing %s in the zipfile\n",
496-
filenameinzip);
539+
if(opt_recursive) {
540+
addPathToZip(zf,argv[i],password,opt_exclude_path,opt_compress_level);
541+
} else {
542+
addFileToZip(zf,argv[i],password,opt_exclude_path,opt_compress_level);
497543
}
498544
}
499545
}

0 commit comments

Comments
 (0)