summaryrefslogtreecommitdiff
path: root/libbb/recursive_action.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-10-27 23:42:25 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-10-27 23:42:25 +0000
commit8c35d65c43216bb840326ac7476a180e2ae36fe9 (patch)
tree13d20b31e817dcff5124498ca0bec2cdf9781014 /libbb/recursive_action.c
parente80e2a3660bf09cc549cb2dfd2bdeb77ccde1231 (diff)
downloadbusybox-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.c40
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
26static int true_action(const char *fileName, struct stat *statbuf, void* userData) 25static 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
31int recursive_action(const char *fileName, 36int 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 }