Remove trailing whitespace. Update copyright to include 2004.
[platform/upstream/busybox.git] / libbb / recursive_action.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Utility routines.
4  *
5  * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <dirent.h>
25 #include <sys/stat.h>
26 #include <stdlib.h>     /* free() */
27 #include "libbb.h"
28
29 #undef DEBUG_RECURS_ACTION
30
31
32 /*
33  * Walk down all the directories under the specified
34  * location, and do something (something specified
35  * by the fileAction and dirAction function pointers).
36  *
37  * Unfortunately, while nftw(3) could replace this and reduce
38  * code size a bit, nftw() wasn't supported before GNU libc 2.1,
39  * and so isn't sufficiently portable to take over since glibc2.1
40  * is so stinking huge.
41  */
42 int recursive_action(const char *fileName,
43                                         int recurse, int followLinks, int depthFirst,
44                                         int (*fileAction) (const char *fileName,
45                                                                            struct stat * statbuf,
46                                                                            void* userData),
47                                         int (*dirAction) (const char *fileName,
48                                                                           struct stat * statbuf,
49                                                                           void* userData),
50                                         void* userData)
51 {
52         int status;
53         struct stat statbuf;
54         struct dirent *next;
55
56         if (followLinks)
57                 status = stat(fileName, &statbuf);
58         else
59                 status = lstat(fileName, &statbuf);
60
61         if (status < 0) {
62 #ifdef DEBUG_RECURS_ACTION
63                 bb_error_msg("status=%d followLinks=%d TRUE=%d",
64                                 status, followLinks, TRUE);
65 #endif
66                 bb_perror_msg("%s", fileName);
67                 return FALSE;
68         }
69
70         if (! followLinks && (S_ISLNK(statbuf.st_mode))) {
71                 if (fileAction == NULL)
72                         return TRUE;
73                 else
74                         return fileAction(fileName, &statbuf, userData);
75         }
76
77         if (! recurse) {
78                 if (S_ISDIR(statbuf.st_mode)) {
79                         if (dirAction != NULL)
80                                 return (dirAction(fileName, &statbuf, userData));
81                         else
82                                 return TRUE;
83                 }
84         }
85
86         if (S_ISDIR(statbuf.st_mode)) {
87                 DIR *dir;
88
89                 if (dirAction != NULL && ! depthFirst) {
90                         status = dirAction(fileName, &statbuf, userData);
91                         if (! status) {
92                                 bb_perror_msg("%s", fileName);
93                                 return FALSE;
94                         } else if (status == SKIP)
95                                 return TRUE;
96                 }
97                 dir = opendir(fileName);
98                 if (!dir) {
99                         bb_perror_msg("%s", fileName);
100                         return FALSE;
101                 }
102                 status = TRUE;
103                 while ((next = readdir(dir)) != NULL) {
104                         char *nextFile;
105
106                         nextFile = concat_subpath_file(fileName, next->d_name);
107                         if(nextFile == NULL)
108                                 continue;
109                         if (! recursive_action(nextFile, TRUE, followLinks, depthFirst,
110                                                 fileAction, dirAction, userData)) {
111                                 status = FALSE;
112                         }
113                         free(nextFile);
114                 }
115                 closedir(dir);
116                 if (dirAction != NULL && depthFirst) {
117                         if (! dirAction(fileName, &statbuf, userData)) {
118                                 bb_perror_msg("%s", fileName);
119                                 return FALSE;
120                         }
121                 }
122                 if (! status)
123                         return FALSE;
124         } else {
125                 if (fileAction == NULL)
126                         return TRUE;
127                 else
128                         return fileAction(fileName, &statbuf, userData);
129         }
130         return TRUE;
131 }
132
133
134 /* END CODE */
135 /*
136 Local Variables:
137 c-file-style: "linux"
138 c-basic-offset: 4
139 tab-width: 4
140 End:
141 */