1 --- gzip-1.4/gzip.c.orig 2012-04-16 11:27:08.478456051 -0700 |
|
2 +++ gzip-1.4/gzip.c 2012-04-23 13:06:53.395234301 -0700 |
|
3 @@ -1699,36 +1699,25 @@ |
|
4 int fd; |
|
5 char *dir; |
|
6 { |
|
7 + struct dirent **namelist; |
|
8 struct dirent *dp; |
|
9 - DIR *dirp; |
|
10 char nbuf[MAX_PATH_LEN]; |
|
11 - int len; |
|
12 + int len, n; |
|
13 |
|
14 - dirp = fdopendir (fd); |
|
15 - |
|
16 - if (dirp == NULL) { |
|
17 + /* Adjusted to use scandir to prevent compressing files multiple times |
|
18 + * on file systems that use a hash lookup for directory entries (such |
|
19 + * as btrfs and ZFS. |
|
20 + */ |
|
21 + if ((n = scandir(dir, &namelist, 0, NULL)) < 0) { |
|
22 progerror(dir); |
|
23 close (fd); |
|
24 return ; |
|
25 } |
|
26 - /* |
|
27 - ** WARNING: the following algorithm could occasionally cause |
|
28 - ** compress to produce error warnings of the form "<filename>.gz |
|
29 - ** already has .gz suffix - ignored". This occurs when the |
|
30 - ** .gz output file is inserted into the directory below |
|
31 - ** readdir's current pointer. |
|
32 - ** These warnings are harmless but annoying, so they are suppressed |
|
33 - ** with option -r (except when -v is on). An alternative |
|
34 - ** to allowing this would be to store the entire directory |
|
35 - ** list in memory, then compress the entries in the stored |
|
36 - ** list. Given the depth-first recursive algorithm used here, |
|
37 - ** this could use up a tremendous amount of memory. I don't |
|
38 - ** think it's worth it. -- Dave Mack |
|
39 - ** (An other alternative might be two passes to avoid depth-first.) |
|
40 - */ |
|
41 - |
|
42 - while ((errno = 0, dp = readdir(dirp)) != NULL) { |
|
43 |
|
44 + while (n--) { |
|
45 + if (errno != 0) |
|
46 + break; |
|
47 + dp = namelist[n]; |
|
48 if (strequ(dp->d_name,".") || strequ(dp->d_name,"..")) { |
|
49 continue; |
|
50 } |
|
51 @@ -1747,6 +1736,7 @@ |
|
52 } |
|
53 strcpy(nbuf+len, dp->d_name); |
|
54 treat_file(nbuf); |
|
55 + free(dp); |
|
56 } else { |
|
57 fprintf(stderr,"%s: %s/%s: pathname too long\n", |
|
58 program_name, dir, dp->d_name); |
|
59 @@ -1755,8 +1745,8 @@ |
|
60 } |
|
61 if (errno != 0) |
|
62 progerror(dir); |
|
63 - if (CLOSEDIR(dirp) != 0) |
|
64 - progerror(dir); |
|
65 + |
|
66 + free(namelist); |
|
67 } |
|
68 #endif /* ! NO_DIR */ |
|
69 |
|