*
* Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
*
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include "libbb.h"
* is so stinking huge.
*/
-static int FAST_FUNC true_action(const char *fileName ATTRIBUTE_UNUSED,
- struct stat *statbuf ATTRIBUTE_UNUSED,
- void* userData ATTRIBUTE_UNUSED,
- int depth ATTRIBUTE_UNUSED)
+static int FAST_FUNC true_action(const char *fileName UNUSED_PARAM,
+ struct stat *statbuf UNUSED_PARAM,
+ void* userData UNUSED_PARAM,
+ int depth UNUSED_PARAM)
{
return TRUE;
}
* into that directory, instead recursive_action() returns 0 (if FALSE)
* or 1 (if SKIP)
*
- * followLinks=0/1 differs mainly in handling of links to dirs.
+ * ACTION_FOLLOWLINKS mainly controls handling of links to dirs.
* 0: lstat(statbuf). Calls fileAction on link name even if points to dir.
* 1: stat(statbuf). Calls dirAction and optionally recurse on link to dir.
*/
unsigned depth)
{
struct stat statbuf;
+ unsigned follow;
int status;
DIR *dir;
struct dirent *next;
if (!fileAction) fileAction = true_action;
if (!dirAction) dirAction = true_action;
- status = ACTION_FOLLOWLINKS; /* hijack a variable for bitmask... */
- if (!depth)
- status = ACTION_FOLLOWLINKS | ACTION_FOLLOWLINKS_L0;
- status = ((flags & status) ? stat : lstat)(fileName, &statbuf);
+ follow = ACTION_FOLLOWLINKS;
+ if (depth == 0)
+ follow = ACTION_FOLLOWLINKS | ACTION_FOLLOWLINKS_L0;
+ follow &= flags;
+ status = (follow ? stat : lstat)(fileName, &statbuf);
if (status < 0) {
#ifdef DEBUG_RECURS_ACTION
bb_error_msg("status=%d flags=%x", status, flags);
#endif
+ if ((flags & ACTION_DANGLING_OK)
+ && errno == ENOENT
+ && lstat(fileName, &statbuf) == 0
+ ) {
+ /* Dangling link */
+ return fileAction(fileName, &statbuf, userData, depth);
+ }
goto done_nak_warn;
}
if (!recursive_action(nextFile, flags, fileAction, dirAction,
userData, depth + 1))
status = FALSE;
+// s = recursive_action(nextFile, flags, fileAction, dirAction,
+// userData, depth + 1);
free(nextFile);
+//#define RECURSE_RESULT_ABORT 3
+// if (s == RECURSE_RESULT_ABORT) {
+// closedir(dir);
+// return s;
+// }
+// if (s == FALSE)
+// status = FALSE;
}
closedir(dir);
return status;
done_nak_warn:
- bb_simple_perror_msg(fileName);
+ if (!(flags & ACTION_QUIET))
+ bb_simple_perror_msg(fileName);
return FALSE;
}