https://sourceforge.net/p/infozip/patches/25/ From 706b9fdc032582a258f0f8e5444fde4ee5bab220 Mon Sep 17 00:00:00 2001 From: Mingye Wang Date: Sat, 25 Jan 2020 23:07:03 +0800 Subject: [PATCH 2/2] unix: reproducible directory order (scandir) This commit replaces the readdir() loop with scandir. This means a well- defined, reproducible sort order, with the downside that we will need to store ALL directory entries in memory to sort them. I am too lazy to add a switch to change how it is supposed to work. This is only a proof-of-concept. Co-Authored-By: Bernhard M. Wiedemann --- unix/unix.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) Index: zip30/unix/unix.c =================================================================== --- zip30.orig/unix/unix.c +++ zip30/unix/unix.c @@ -92,6 +92,10 @@ DIR *dirp; #define closedir(dirp) fclose(dirp) #endif /* NO_DIR */ +#ifdef NO_SCANDIR +/* TODO Port the FreeBSD libc version */ +#error "We need scandir now." +#endif local char *readd(d) DIR *d; /* directory stream to read from */ @@ -111,12 +115,14 @@ int caseflag; /* true to force an error code in the ZE_ class. */ { char *a; /* path and name for recursion */ - DIR *d; /* directory stream from opendir() */ - char *e; /* pointer to name from readd() */ + char *e; /* pointer to name from scandir() */ + int c; /* number of entries from scandir() */ + int i; /* entry index */ int m; /* matched flag */ char *p; /* path for recursion */ z_stat s; /* result of stat() */ struct zlist far *z; /* steps through zfiles list */ + struct dirent **namelist; if (strcmp(n, "-") == 0) /* if compressing stdin */ return newname(n, 0, caseflag); @@ -176,14 +182,16 @@ int caseflag; /* true to force } } /* recurse into directory */ - if (recurse && (d = opendir(n)) != NULL) + if (recurse && (c = scandir(n, &namelist, NULL, alphasort)) >= 0) { - while ((e = readd(d)) != NULL) { + for (i = 0; i < c; i++) { + e = namelist[i]->d_name; if (strcmp(e, ".") && strcmp(e, "..")) { if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL) { - closedir(d); + for (; i < c; i++) free(namelist[i]); + free(namelist); free((zvoid *)p); return ZE_MEM; } @@ -197,8 +205,9 @@ int caseflag; /* true to force } free((zvoid *)a); } + free(namelist[i]); } - closedir(d); + free(namelist); } free((zvoid *)p); } /* (s.st_mode & S_IFDIR) */ Index: zip30/test.sh =================================================================== --- /dev/null +++ zip30/test.sh @@ -0,0 +1,10 @@ +#!/bin/sh -e +mkdir -p test/{a,b,c} +echo x > test/a/x +echo y > test/a/y +echo y > test/b/y +export SOURCE_DATE_EPOCH=1 +./zip -X -r test.zip test +md5sum test.zip +echo "89057b9c9501ce122973d24b68a0522a test.zip" | md5sum -c +