diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-10-27 23:42:25 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-10-27 23:42:25 +0000 |
commit | 8c35d65c43216bb840326ac7476a180e2ae36fe9 (patch) | |
tree | 13d20b31e817dcff5124498ca0bec2cdf9781014 /libbb/recursive_action.c | |
parent | e80e2a3660bf09cc549cb2dfd2bdeb77ccde1231 (diff) | |
download | busybox-w32-8c35d65c43216bb840326ac7476a180e2ae36fe9.tar.gz busybox-w32-8c35d65c43216bb840326ac7476a180e2ae36fe9.tar.bz2 busybox-w32-8c35d65c43216bb840326ac7476a180e2ae36fe9.zip |
recursive_action: add depth param
chmod: match coreutils versus following links
Diffstat (limited to 'libbb/recursive_action.c')
-rw-r--r-- | libbb/recursive_action.c | 40 |
1 files changed, 24 insertions, 16 deletions
diff --git a/libbb/recursive_action.c b/libbb/recursive_action.c index 0d6567dda..ddaf9b896 100644 --- a/libbb/recursive_action.c +++ b/libbb/recursive_action.c | |||
@@ -11,7 +11,6 @@ | |||
11 | 11 | ||
12 | #undef DEBUG_RECURS_ACTION | 12 | #undef DEBUG_RECURS_ACTION |
13 | 13 | ||
14 | |||
15 | /* | 14 | /* |
16 | * Walk down all the directories under the specified | 15 | * Walk down all the directories under the specified |
17 | * location, and do something (something specified | 16 | * location, and do something (something specified |
@@ -23,16 +22,23 @@ | |||
23 | * is so stinking huge. | 22 | * is so stinking huge. |
24 | */ | 23 | */ |
25 | 24 | ||
26 | static int true_action(const char *fileName, struct stat *statbuf, void* userData) | 25 | static int true_action(const char *fileName, struct stat *statbuf, void* userData, int depth) |
27 | { | 26 | { |
28 | return TRUE; | 27 | return TRUE; |
29 | } | 28 | } |
30 | 29 | ||
30 | /* | ||
31 | * followLinks=0/1 differs mainly in handling of links to dirs. | ||
32 | * 0: lstat(statbuf). Calls fileAction on link name even if points to dir. | ||
33 | * 1: stat(statbuf). Calls dirAction and optionally recurse on link to dir. | ||
34 | */ | ||
35 | |||
31 | int recursive_action(const char *fileName, | 36 | int recursive_action(const char *fileName, |
32 | int recurse, int followLinks, int depthFirst, | 37 | int recurse, int followLinks, int depthFirst, |
33 | int (*fileAction) (const char *fileName, struct stat * statbuf, void* userData), | 38 | int (*fileAction)(const char *fileName, struct stat *statbuf, void* userData, int depth), |
34 | int (*dirAction) (const char *fileName, struct stat * statbuf, void* userData), | 39 | int (*dirAction)(const char *fileName, struct stat *statbuf, void* userData, int depth), |
35 | void* userData) | 40 | void* userData, |
41 | int depth) | ||
36 | { | 42 | { |
37 | struct stat statbuf; | 43 | struct stat statbuf; |
38 | int status; | 44 | int status; |
@@ -53,21 +59,23 @@ int recursive_action(const char *fileName, | |||
53 | return FALSE; | 59 | return FALSE; |
54 | } | 60 | } |
55 | 61 | ||
56 | if (!followLinks && (S_ISLNK(statbuf.st_mode))) { | 62 | /* If S_ISLNK(m), then we know that !S_ISDIR(m). |
57 | return fileAction(fileName, &statbuf, userData); | 63 | * Then we can skip checking first part: if it is true, then |
64 | * (!dir) is also true! */ | ||
65 | if ( /* (!followLinks && S_ISLNK(statbuf.st_mode)) || */ | ||
66 | !S_ISDIR(statbuf.st_mode) | ||
67 | ) { | ||
68 | return fileAction(fileName, &statbuf, userData, depth); | ||
58 | } | 69 | } |
59 | 70 | ||
71 | /* It's a directory (or a link to one, and followLinks is set) */ | ||
72 | |||
60 | if (!recurse) { | 73 | if (!recurse) { |
61 | if (S_ISDIR(statbuf.st_mode)) { | 74 | return dirAction(fileName, &statbuf, userData, depth); |
62 | return dirAction(fileName, &statbuf, userData); | ||
63 | } | ||
64 | } | 75 | } |
65 | 76 | ||
66 | if (!S_ISDIR(statbuf.st_mode)) | ||
67 | return fileAction(fileName, &statbuf, userData); | ||
68 | |||
69 | if (!depthFirst) { | 77 | if (!depthFirst) { |
70 | status = dirAction(fileName, &statbuf, userData); | 78 | status = dirAction(fileName, &statbuf, userData, depth); |
71 | if (!status) { | 79 | if (!status) { |
72 | bb_perror_msg("%s", fileName); | 80 | bb_perror_msg("%s", fileName); |
73 | return FALSE; | 81 | return FALSE; |
@@ -88,14 +96,14 @@ int recursive_action(const char *fileName, | |||
88 | if (nextFile == NULL) | 96 | if (nextFile == NULL) |
89 | continue; | 97 | continue; |
90 | if (!recursive_action(nextFile, TRUE, followLinks, depthFirst, | 98 | if (!recursive_action(nextFile, TRUE, followLinks, depthFirst, |
91 | fileAction, dirAction, userData)) { | 99 | fileAction, dirAction, userData, depth+1)) { |
92 | status = FALSE; | 100 | status = FALSE; |
93 | } | 101 | } |
94 | free(nextFile); | 102 | free(nextFile); |
95 | } | 103 | } |
96 | closedir(dir); | 104 | closedir(dir); |
97 | if (depthFirst) { | 105 | if (depthFirst) { |
98 | if (!dirAction(fileName, &statbuf, userData)) { | 106 | if (!dirAction(fileName, &statbuf, userData, depth)) { |
99 | bb_perror_msg("%s", fileName); | 107 | bb_perror_msg("%s", fileName); |
100 | return FALSE; | 108 | return FALSE; |
101 | } | 109 | } |