]>
Commit | Line | Data |
---|---|---|
a8e75dea MT |
1 | --- acl-2.2.39/getfacl/getfacl.c.walk 2006-06-20 08:51:25.000000000 +0200 |
2 | +++ acl-2.2.39/getfacl/getfacl.c 2007-03-21 10:52:07.000000000 +0100 | |
3 | @@ -34,7 +34,6 @@ | |
4 | #include <dirent.h> | |
5 | #include <libgen.h> | |
6 | #include <getopt.h> | |
7 | -#include <ftw.h> | |
8 | #include <locale.h> | |
9 | #include "config.h" | |
10 | #include "user_group.h" | |
11 | @@ -70,9 +69,9 @@ | |
12 | const char *progname; | |
13 | const char *cmd_line_options; | |
14 | ||
15 | -int opt_recursive; /* recurse into sub-directories? */ | |
16 | -int opt_walk_logical; /* always follow symbolic links */ | |
17 | -int opt_walk_physical; /* never follow symbolic links */ | |
18 | +int opt_recursive = 0; /* recurse into sub-directories? */ | |
19 | +int opt_walk_logical = 0; /* always follow symbolic links */ | |
20 | +int opt_walk_physical = 0; /* never follow symbolic links */ | |
21 | int opt_print_acl = 0; | |
22 | int opt_print_default_acl = 0; | |
23 | int opt_strip_leading_slash = 1; | |
24 | @@ -562,71 +561,140 @@ | |
25 | ||
26 | ||
27 | static int __errors; | |
28 | -int __do_print(const char *file, const struct stat *stat, | |
29 | - int flag, struct FTW *ftw) | |
30 | + | |
31 | +int walk_tree(const char *file) | |
32 | { | |
33 | - int saved_errno = errno; | |
34 | + static int level = 0; | |
35 | + static int link_count = 0; | |
36 | + DIR *dir; | |
37 | + struct dirent *entry; | |
38 | + struct stat buf; | |
39 | + char path[FILENAME_MAX]; | |
40 | + char path2[FILENAME_MAX]; | |
41 | + char path3[FILENAME_MAX]; | |
42 | + char *dir_name; | |
43 | + size_t len; | |
44 | + ssize_t slen; | |
45 | + int res; | |
46 | ||
47 | /* Process the target of a symbolic link, and traverse the link, | |
48 | only if doing a logical walk, or if the symbolic link was | |
49 | specified on the command line. Always skip symbolic links if | |
50 | doing a physical walk. */ | |
51 | ||
52 | - if (S_ISLNK(stat->st_mode) && | |
53 | - (opt_walk_physical || (ftw->level > 0 && !opt_walk_logical))) | |
54 | + len = strlen(file); | |
55 | + /* check for FILENAME_MAX */ | |
56 | + if (len >= FILENAME_MAX) { | |
57 | + fprintf(stderr, "%s: %s: %s\n", progname, xquote(file), | |
58 | + strerror(ENAMETOOLONG)); | |
59 | + __errors++; | |
60 | return 0; | |
61 | + } | |
62 | + /* string ends with '/', remove it and restart */ | |
63 | + if (len > 1 && file[len-1] == '/') { | |
64 | + strncpy(path, file, len); | |
65 | + path[len-1] = '\0'; /* overwrite slash */ | |
66 | + return walk_tree(path); | |
67 | + } | |
68 | ||
69 | - if (do_print(file, stat)) | |
70 | - __errors++; | |
71 | + if (level > 0 && !opt_recursive) | |
72 | + return 0; | |
73 | ||
74 | - if (flag == FTW_DNR && opt_recursive) { | |
75 | - /* Item is a directory which can't be read. */ | |
76 | - fprintf(stderr, "%s: %s: %s\n", | |
77 | - progname, file, strerror(saved_errno)); | |
78 | + if (lstat(file, &buf) != 0) { | |
79 | + fprintf(stderr, "%s: %s: %s\n", progname, xquote(file), | |
80 | + strerror(errno)); | |
81 | + __errors++; | |
82 | return 0; | |
83 | } | |
84 | ||
85 | - /* We also get here in non-recursive mode. In that case, | |
86 | - return something != 0 to abort nftw. */ | |
87 | + if (S_ISLNK(buf.st_mode)) { | |
88 | + /* physical means: no links at all */ | |
89 | + if (opt_walk_physical) | |
90 | + return 1; | |
91 | + | |
92 | + /* logical: show information or walk if points to directory | |
93 | + * also for symbolic link arguments on level 0 */ | |
94 | + if (opt_walk_logical || level == 0) { | |
95 | + /* copy and append terminating '\0' */ | |
96 | + strncpy(path2, file, len+1); | |
97 | + | |
98 | + /* get directory name */ | |
99 | + dir_name = dirname(path2); | |
100 | + | |
101 | + /* get link target */ | |
102 | + slen = readlink(file, path, FILENAME_MAX-1); | |
103 | + if (slen < 0) { | |
104 | + fprintf(stderr, "%s: %s: %s\n", progname, | |
105 | + xquote(file), strerror(errno)); | |
106 | + __errors++; | |
107 | + return 0; | |
108 | + } | |
109 | + path[slen] = '\0'; | |
110 | ||
111 | - if (!opt_recursive) | |
112 | - return 1; | |
113 | + if (slen == 0 || path[0] == '/') { | |
114 | + /* absolute: | |
115 | + * copy and append terminating '\0' */ | |
116 | + strncpy(path3, path, slen+1); | |
117 | + } else | |
118 | + /* relative */ | |
119 | + snprintf(path3, FILENAME_MAX, "%s/%s", | |
120 | + dir_name, path); | |
121 | + | |
122 | + if (lstat(path3, &buf) != 0) { | |
123 | + fprintf(stderr, "%s: %s: %s\n", progname, | |
124 | + xquote(path), strerror(errno)); | |
125 | + __errors++; | |
126 | + return 0; | |
127 | + } | |
128 | ||
129 | - return 0; | |
130 | -} | |
131 | + if ((S_ISDIR(buf.st_mode) && opt_recursive && | |
132 | + link_count < 1) || S_ISLNK(buf.st_mode)) { | |
133 | + /* walk directory or follow symlink on level | |
134 | + * 0 */ | |
135 | + link_count++; | |
136 | + res = walk_tree(path3); | |
137 | + link_count--; | |
138 | + if (res != 1) | |
139 | + return 0; | |
140 | + } else | |
141 | + if (do_print(path3, &buf)) | |
142 | + __errors++; | |
143 | ||
144 | -char *resolve_symlinks(const char *file) | |
145 | -{ | |
146 | - static char buffer[4096]; | |
147 | - char *path = NULL; | |
148 | - ssize_t len; | |
149 | - | |
150 | - len = readlink(file, buffer, sizeof(buffer)-1); | |
151 | - if (len < 0) { | |
152 | - if (errno == EINVAL) /* not a symlink, use given path */ | |
153 | - path = (char *)file; | |
154 | - } else { | |
155 | - buffer[len+1] = '\0'; | |
156 | - path = buffer; | |
157 | + return 1; | |
158 | + } | |
159 | } | |
160 | - return path; | |
161 | -} | |
162 | - | |
163 | -int walk_tree(const char *file) | |
164 | -{ | |
165 | - const char *p; | |
166 | ||
167 | - __errors = 0; | |
168 | - if ((p = resolve_symlinks(file)) == NULL) { | |
169 | - fprintf(stderr, "%s: %s: %s\n", progname, | |
170 | - xquote(file), strerror(errno)); | |
171 | - __errors++; | |
172 | - } else if (nftw(p, __do_print, 0, opt_walk_logical? 0 : FTW_PHYS) < 0) { | |
173 | - fprintf(stderr, "%s: %s: %s\n", progname, xquote(file), | |
174 | - strerror(errno)); | |
175 | + if (do_print(file, &buf)) | |
176 | __errors++; | |
177 | + | |
178 | + /* it is a directory, walk */ | |
179 | + if (S_ISDIR(buf.st_mode)) { | |
180 | + dir = opendir(file); | |
181 | + if (!dir) { | |
182 | + fprintf(stderr, "%s: %s: %s\n", progname, | |
183 | + xquote(file), strerror(errno)); | |
184 | + __errors++; | |
185 | + return 0; | |
186 | + } | |
187 | + | |
188 | + level++; | |
189 | + while ((entry = readdir(dir)) != NULL) { | |
190 | + if (! strcmp(entry->d_name, ".") || | |
191 | + ! strcmp(entry->d_name, "..")) | |
192 | + continue; | |
193 | + | |
194 | + snprintf(path, FILENAME_MAX, "%s/%s", file, | |
195 | + entry->d_name); | |
196 | + | |
197 | + /* ignore result, walk every entry */ | |
198 | + res = walk_tree(path); | |
199 | + } | |
200 | + level--; | |
201 | + | |
202 | + closedir(dir); | |
203 | } | |
204 | - return __errors; | |
205 | + | |
206 | + return 1; | |
207 | } | |
208 | ||
209 | int main(int argc, char *argv[]) | |
210 | @@ -762,15 +830,22 @@ | |
211 | if (*line == '\0') | |
212 | continue; | |
213 | ||
214 | - had_errors += walk_tree(line); | |
215 | + /* ignore result of walk_tree, use __errors */ | |
216 | + __errors = 0; | |
217 | + walk_tree(line); | |
218 | + had_errors += __errors; | |
219 | } | |
220 | if (!feof(stdin)) { | |
221 | fprintf(stderr, _("%s: Standard input: %s\n"), | |
222 | progname, strerror(errno)); | |
223 | had_errors++; | |
224 | } | |
225 | - } else | |
226 | - had_errors += walk_tree(argv[optind]); | |
227 | + } else { | |
228 | + /* ignore result of walk_tree, use __errors */ | |
229 | + __errors = 0; | |
230 | + walk_tree(argv[optind]); | |
231 | + had_errors += __errors; | |
232 | + } | |
233 | optind++; | |
234 | } while (optind < argc); | |
235 |