/* Read the directory/files and iterate over them one at a time */
while (include) {
- if (!recursive_action(include->data, (action_recurse |
- dereferenceFlag ? action_followLinks : 0),
+ if (!recursive_action(include->data, ACTION_RECURSE |
+ (dereferenceFlag ? ACTION_FOLLOWLINKS : 0),
writeFileToTarball, writeFileToTarball, &tbInfo, 0))
{
errorFlag = TRUE;
}
if (!recursive_action(arg,
- (OPT_RECURSE ? action_recurse : 0 | /* recurse */
- OPT_TRAVERSE ? action_followLinks : 0),/* follow links if -L */
+ (OPT_RECURSE ? ACTION_RECURSE : 0) | /* recurse */
+ (OPT_TRAVERSE ? ACTION_FOLLOWLINKS : 0),/* follow links if -L */
fileAction, /* file action */
fileAction, /* dir action */
chown_func, /* user data */
* add_to_dirlist then removes root dir prefix. */
if (option_mask32 & FLAG_r) {
- recursive_action(path, action_recurse|action_followLinks,
+ recursive_action(path, ACTION_RECURSE|ACTION_FOLLOWLINKS,
add_to_dirlist, NULL,
(void*)(strlen(path)+1), 0);
} else {
G.cmd[tmp] = arg_list->data;
/* G.cmd[tmp] = NULL; - G is already zeroed out */
if (!recursive_action(argv[argc - 1],
- action_recurse|action_followLinks,
+ ACTION_RECURSE|ACTION_FOLLOWLINKS,
act, /* file action */
act, /* dir action */
NULL, /* user data */
USE_FEATURE_FIND_MMIN( ACTS(mmin, char mmin_char; unsigned mmin_mins;))
USE_FEATURE_FIND_NEWER( ACTS(newer, time_t newer_mtime;))
USE_FEATURE_FIND_INUM( ACTS(inum, ino_t inode_num;))
-USE_FEATURE_FIND_EXEC( ACTS(exec, char **exec_argv; unsigned int *subst_count; int exec_argc;))
+USE_FEATURE_FIND_EXEC( ACTS(exec, char **exec_argv; unsigned *subst_count; int exec_argc;))
USE_FEATURE_FIND_USER( ACTS(user, uid_t uid;))
USE_FEATURE_FIND_GROUP( ACTS(group, gid_t gid;))
USE_FEATURE_FIND_PAREN( ACTS(paren, action ***subexpr;))
static action ***actions;
static bool need_print = 1;
-static int recurse_flags = action_recurse;
+static int recurse_flags = ACTION_RECURSE;
#if ENABLE_FEATURE_FIND_EXEC
-static unsigned int count_subst(const char *str)
+static unsigned count_subst(const char *str)
{
- unsigned int count = 0;
+ unsigned count = 0;
while ((str = strstr(str, "{}"))) {
count++;
str++;
}
-static char* subst(const char *src, unsigned int count, const char* filename)
+static char* subst(const char *src, unsigned count, const char* filename)
{
char *buf, *dst, *end;
size_t flen = strlen(filename);
}
#endif
+/* Return values of ACTFs ('action functions') are a bit mask:
+ * bit 1=1: prune (use SKIP constant for setting it)
+ * bit 0=1: matched successfully (TRUE)
+ */
static int exec_actions(action ***appp, const char *fileName, struct stat *statbuf)
{
cur_group = -1;
while ((app = appp[++cur_group])) {
+ /* We invert TRUE bit (bit 0). Now 1 there means 'failure'.
+ * and bitwise OR in "rc |= TRUE ^ ap->f()" will:
+ * (1) make SKIP bit stick; and (2) detect 'failure' */
+ rc = 0; /* 'success' so far */
cur_action = -1;
while (1) {
ap = app[++cur_action];
- if (!ap) {
- /* all actions in group were successful */
- return rc;
- }
- rc = ap->f(fileName, statbuf, ap);
+ if (!ap) /* all actions in group were successful */
+ return rc ^ TRUE;
+ rc |= TRUE ^ ap->f(fileName, statbuf, ap);
#if ENABLE_FEATURE_FIND_NOT
- if (ap->invert) rc = !rc;
+ if (ap->invert) rc ^= TRUE;
#endif
- if (!rc) {
- /* current group failed, try next */
+ if (rc & TRUE) /* current group failed, try next */
break;
- }
}
}
- return rc;
+ return rc ^ TRUE; /* straighten things out */
}
const char *tmp = strrchr(fileName, '/');
if (tmp == NULL)
tmp = fileName;
- else
+ else {
tmp++;
+ if (!*tmp) { /* "foo/bar/". Oh no... go back to 'b' */
+ tmp--;
+ while (tmp != fileName && *--tmp != '/')
+ continue;
+ if (*tmp == '/')
+ tmp++;
+ }
+ }
return fnmatch(ap->pattern, tmp, FNM_PERIOD) == 0;
}
#if ENABLE_FEATURE_FIND_TYPE
*/
ACTF(prune)
{
- return SKIP;
+ return SKIP + TRUE;
}
#endif
static int fileAction(const char *fileName, struct stat *statbuf, void* junk, int depth)
{
int i;
-#ifdef CONFIG_FEATURE_FIND_XDEV
+#if ENABLE_FEATURE_FIND_XDEV
if (S_ISDIR(statbuf->st_mode) && xdev_count) {
for (i = 0; i < xdev_count; i++) {
if (xdev_dev[i] != statbuf->st_dev)
#endif
i = exec_actions(actions, fileName, statbuf);
/* Had no explicit -print[0] or -exec? then print */
- if (i && need_print)
+ if ((i & TRUE) && need_print)
puts(fileName);
/* Cannot return 0: our caller, recursive_action(),
* will perror() and skip dirs (if called on dir) */
- return i == 0 ? TRUE : i;
+ return (i & SKIP) ? SKIP : TRUE;
}
USE_FEATURE_FIND_GROUP( "-group" ,)
USE_FEATURE_FIND_DEPTH( "-depth" ,)
USE_FEATURE_FIND_PAREN( "(" ,)
- USE_FEATURE_FIND_SIZE( "-size" ,)
- USE_FEATURE_FIND_PRUNE( "-prune" ,)
+ USE_FEATURE_FIND_SIZE( "-size" ,)
+ USE_FEATURE_FIND_PRUNE( "-prune" ,)
#if ENABLE_DESKTOP
"-and" ,
"-or" ,
}
#endif
#if ENABLE_FEATURE_FIND_PERM
-/* TODO:
- * -perm mode File's permission bits are exactly mode (octal or symbolic).
+/* -perm mode File's permission bits are exactly mode (octal or symbolic).
* Symbolic modes use mode 0 as a point of departure.
* -perm -mode All of the permission bits mode are set for the file.
* -perm +mode Any of the permission bits mode are set for the file.
ap->exec_argv = ++argv; /* first arg after -exec */
ap->exec_argc = 0;
while (1) {
- if (!*argv) /* did not see ';' util end */
+ if (!*argv) /* did not see ';' until end */
bb_error_msg_and_die(bb_msg_requires_arg, arg);
if (LONE_CHAR(argv[0], ';'))
break;
#endif
#if ENABLE_FEATURE_FIND_DEPTH
else if (parm == PARM_depth) {
- recurse_flags |= action_depthFirst;
+ recurse_flags |= ACTION_DEPTHFIRST;
}
#endif
#if ENABLE_FEATURE_FIND_PAREN
NULL
};
- bool dereference = FALSE;
char *arg;
char **argp;
int i, firstopt, status = EXIT_SUCCESS;
while ((arg = argp[0])) {
i = index_in_str_array(options, arg);
if (i == 0) { /* -follow */
- dereference = TRUE;
+ recurse_flags |= ACTION_FOLLOWLINKS;
argp[0] = (char*)"-a";
}
#if ENABLE_FEATURE_FIND_XDEV
for (i = 1; i < firstopt; i++) {
if (!recursive_action(argv[i],
- recurse_flags|(1<<dereference), /* flags */
+ recurse_flags, /* flags */
fileAction, /* file action */
fileAction, /* dir action */
NULL, /* user data */
{
int matched = 0;
recursive_action(dir,
- /* recurse= */ action_recurse |
- /* followLinks= */ /* no. 0 | */
- /* depthFirst= */ action_depthFirst,
+ /* recurse=yes */ ACTION_RECURSE |
+ /* followLinks=no */
+ /* depthFirst=yes */ ACTION_DEPTHFIRST,
/* fileAction= */ file_action_grep,
/* dirAction= */ NULL,
/* userData= */ &matched,
/* buffer allocation schemes */
#if ENABLE_FEATURE_BUFFERS_GO_ON_STACK
-#define RESERVE_CONFIG_BUFFER(buffer,len) char buffer[len]
+#define RESERVE_CONFIG_BUFFER(buffer,len) char buffer[len]
#define RESERVE_CONFIG_UBUFFER(buffer,len) unsigned char buffer[len]
#define RELEASE_CONFIG_BUFFER(buffer) ((void)0)
#else
#define RESERVE_CONFIG_UBUFFER(buffer,len) static unsigned char buffer[len]
#define RELEASE_CONFIG_BUFFER(buffer) ((void)0)
#else
-#define RESERVE_CONFIG_BUFFER(buffer,len) char *buffer=xmalloc(len)
-#define RESERVE_CONFIG_UBUFFER(buffer,len) unsigned char *buffer=xmalloc(len)
-#define RELEASE_CONFIG_BUFFER(buffer) free (buffer)
+#define RESERVE_CONFIG_BUFFER(buffer,len) char *buffer = xmalloc(len)
+#define RESERVE_CONFIG_UBUFFER(buffer,len) unsigned char *buffer = xmalloc(len)
+#define RELEASE_CONFIG_BUFFER(buffer) free(buffer)
#endif
#endif
unsigned int mem_unit; /* Memory unit size in bytes */
char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */
};
-extern int sysinfo(struct sysinfo* info);
+int sysinfo(struct sysinfo* info);
extern void chomp(char *s);
extern int is_directory(const char *name, int followLinks, struct stat *statBuf);
extern int remove_file(const char *path, int flags);
extern int copy_file(const char *source, const char *dest, int flags);
-#define action_recurse (1<<0)
-#define action_followLinks (1<<1)
-#define action_depthFirst (1<<2)
-#define action_reverse (1<<3)
+enum {
+ ACTION_RECURSE = (1 << 0),
+ ACTION_FOLLOWLINKS = (1 << 1),
+ ACTION_DEPTHFIRST = (1 << 2),
+ /*ACTION_REVERSE = (1 << 3), - unused */
+};
extern int recursive_action(const char *fileName, unsigned flags,
int (*fileAction) (const char *fileName, struct stat* statbuf, void* userData, int depth),
int (*dirAction) (const char *fileName, struct stat* statbuf, void* userData, int depth),
void xmove_fd(int, int);
-extern DIR *xopendir(const char *path);
-extern DIR *warn_opendir(const char *path);
+DIR *xopendir(const char *path);
+DIR *warn_opendir(const char *path);
char *xrealloc_getcwd_or_warn(char *cwd);
char *xmalloc_readlink_or_warn(const char *path);
char *xmalloc_realpath(const char *path);
-extern void xstat(const char *filename, struct stat *buf);
/* Unlike waitpid, waits ONLY for one process,
* It's safe to pass negative 'pids' from failed [v]fork -
void xchdir(const char *path);
void xsetenv(const char *key, const char *value);
void xunlink(const char *pathname);
+void xstat(const char *pathname, struct stat *buf);
int xopen(const char *pathname, int flags);
int xopen3(const char *pathname, int flags, int mode);
off_t xlseek(int fd, off_t offset, int whence);
if (!fileAction) fileAction = true_action;
if (!dirAction) dirAction = true_action;
- status = (flags & action_followLinks ? stat : lstat)(fileName, &statbuf);
+ status = (flags & ACTION_FOLLOWLINKS ? stat : lstat)(fileName, &statbuf);
if (status < 0) {
#ifdef DEBUG_RECURS_ACTION
bb_error_msg("status=%d followLinks=%d TRUE=%d",
- status, flags & action_followLinks, TRUE);
+ status, flags & ACTION_FOLLOWLINKS, TRUE);
#endif
goto done_nak_warn;
}
/* If S_ISLNK(m), then we know that !S_ISDIR(m).
* Then we can skip checking first part: if it is true, then
* (!dir) is also true! */
- if ( /* (!(flags & action_followLinks) && S_ISLNK(statbuf.st_mode)) || */
+ if ( /* (!(flags & ACTION_FOLLOWLINKS) && S_ISLNK(statbuf.st_mode)) || */
!S_ISDIR(statbuf.st_mode)
) {
return fileAction(fileName, &statbuf, userData, depth);
/* It's a directory (or a link to one, and followLinks is set) */
- if (!(flags & action_recurse)) {
+ if (!(flags & ACTION_RECURSE)) {
return dirAction(fileName, &statbuf, userData, depth);
}
- if (!(flags & action_depthFirst)) {
+ if (!(flags & ACTION_DEPTHFIRST)) {
status = dirAction(fileName, &statbuf, userData, depth);
if (!status) {
goto done_nak_warn;
if (nextFile == NULL)
continue;
/* now descend into it, forcing recursion. */
- if (!recursive_action(nextFile, flags | action_recurse,
+ if (!recursive_action(nextFile, flags | ACTION_RECURSE,
fileAction, dirAction, userData, depth+1)) {
status = FALSE;
}
free(nextFile);
}
closedir(dir);
- if (flags & action_depthFirst &&
+ if ((flags & ACTION_DEPTHFIRST) &&
!dirAction(fileName, &statbuf, userData, depth)) {
goto done_nak_warn;
}
module_dir = tmdn;
else
module_dir = real_module_dir;
- recursive_action(module_dir, action_recurse,
+ recursive_action(module_dir, ACTION_RECURSE,
check_module_name_match, 0, m_fullName, 0);
free(tmdn);
}
strcpy(module_dir, _PATH_MODULES);
/* No module found under /lib/modules/`uname -r`, this
* time cast the net a bit wider. Search /lib/modules/ */
- if (!recursive_action(module_dir, action_recurse,
+ if (!recursive_action(module_dir, ACTION_RECURSE,
check_module_name_match, 0, m_fullName, 0)
) {
if (m_filename == 0