components/gzip/patches/gzip.c.patch
author Nobutomo Nakano <nobutomo.nakano@oracle.com>
Mon, 08 Oct 2012 19:44:45 -0700
branchs11u1-sru
changeset 2370 c539542fe61d
parent 794 adae50e39183
permissions -rw-r--r--
7198440 update zoneinfo timezones to 2012f (Fiji)

--- gzip-1.4/gzip.c.orig	2012-04-16 11:27:08.478456051 -0700
+++ gzip-1.4/gzip.c	2012-04-23 13:06:53.395234301 -0700
@@ -1699,36 +1699,25 @@
     int fd;
     char *dir;
 {
+    struct dirent **namelist;
     struct dirent *dp;
-    DIR      *dirp;
     char     nbuf[MAX_PATH_LEN];
-    int      len;
+    int      len, n;
 
-    dirp = fdopendir (fd);
-
-    if (dirp == NULL) {
+    /* Adjusted to use scandir to prevent compressing files multiple times
+     * on file systems that use a hash lookup for directory entries (such
+     * as btrfs and ZFS.
+     */
+    if ((n = scandir(dir, &namelist, 0, NULL)) < 0) {
 	progerror(dir);
 	close (fd);
 	return ;
     }
-    /*
-     ** WARNING: the following algorithm could occasionally cause
-     ** compress to produce error warnings of the form "<filename>.gz
-     ** already has .gz suffix - ignored". This occurs when the
-     ** .gz output file is inserted into the directory below
-     ** readdir's current pointer.
-     ** These warnings are harmless but annoying, so they are suppressed
-     ** with option -r (except when -v is on). An alternative
-     ** to allowing this would be to store the entire directory
-     ** list in memory, then compress the entries in the stored
-     ** list. Given the depth-first recursive algorithm used here,
-     ** this could use up a tremendous amount of memory. I don't
-     ** think it's worth it. -- Dave Mack
-     ** (An other alternative might be two passes to avoid depth-first.)
-     */
-
-    while ((errno = 0, dp = readdir(dirp)) != NULL) {
 
+    while (n--) {
+	if (errno != 0)
+	    break;
+	dp = namelist[n];
 	if (strequ(dp->d_name,".") || strequ(dp->d_name,"..")) {
 	    continue;
 	}
@@ -1747,6 +1736,7 @@
 	    }
 	    strcpy(nbuf+len, dp->d_name);
 	    treat_file(nbuf);
+	    free(dp);
 	} else {
 	    fprintf(stderr,"%s: %s/%s: pathname too long\n",
 		    program_name, dir, dp->d_name);
@@ -1755,8 +1745,8 @@
     }
     if (errno != 0)
 	progerror(dir);
-    if (CLOSEDIR(dirp) != 0)
-	progerror(dir);
+
+    free(namelist);
 }
 #endif /* ! NO_DIR */