busybox: 1.15.1 find fix
authorPeter Korsgaard <jacmet@sunsite.dk>
Wed, 30 Sep 2009 05:27:01 +0000 (07:27 +0200)
committerPeter Korsgaard <jacmet@sunsite.dk>
Wed, 30 Sep 2009 05:27:01 +0000 (07:27 +0200)
Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
package/busybox/busybox-1.15.1-find.patch [new file with mode: 0644]

diff --git a/package/busybox/busybox-1.15.1-find.patch b/package/busybox/busybox-1.15.1-find.patch
new file mode 100644 (file)
index 0000000..da2700a
--- /dev/null
@@ -0,0 +1,230 @@
+diff -urpN busybox-1.15.1/findutils/find.c busybox-1.15.1-find/findutils/find.c
+--- busybox-1.15.1/findutils/find.c    2009-09-12 17:55:58.000000000 +0200
++++ busybox-1.15.1-find/findutils/find.c       2009-09-30 02:23:54.000000000 +0200
+@@ -62,9 +62,6 @@
+ /* This is a NOEXEC applet. Be very careful! */
+-IF_FEATURE_FIND_XDEV(static dev_t *xdev_dev;)
+-IF_FEATURE_FIND_XDEV(static int xdev_count;)
+-
+ typedef int (*action_fp)(const char *fileName, struct stat *statbuf, void *) FAST_FUNC;
+ typedef struct {
+@@ -100,9 +97,24 @@ IF_FEATURE_FIND_DELETE( ACTS(delete))
+ IF_FEATURE_FIND_EXEC(   ACTS(exec,  char **exec_argv; unsigned *subst_count; int exec_argc;))
+ IF_FEATURE_FIND_GROUP(  ACTS(group, gid_t gid;))
+-static action ***actions;
+-static bool need_print = 1;
+-static int recurse_flags = ACTION_RECURSE;
++struct globals {
++      IF_FEATURE_FIND_XDEV(dev_t *xdev_dev;)
++      IF_FEATURE_FIND_XDEV(int xdev_count;)
++      action ***actions;
++      bool need_print;
++      recurse_flags_t recurse_flags;
++};
++#define G (*(struct globals*)&bb_common_bufsiz1)
++#define INIT_G() do { \
++      struct G_sizecheck { \
++              char G_sizecheck[sizeof(G) > COMMON_BUFSIZE ? -1 : 1]; \
++      }; \
++      G.xdev_dev = NULL; \
++      G.xdev_count = 0; \
++      G.actions = NULL; \
++      G.need_print = 1; \
++      G.recurse_flags = ACTION_RECURSE; \
++} while (0)
+ #if ENABLE_FEATURE_FIND_EXEC
+ static unsigned count_subst(const char *str)
+@@ -363,7 +375,7 @@ ACTF(context)
+       security_context_t con;
+       int rc;
+-      if (recurse_flags & ACTION_FOLLOWLINKS) {
++      if (G.recurse_flags & ACTION_FOLLOWLINKS) {
+               rc = getfilecon(fileName, &con);
+       } else {
+               rc = lgetfilecon(fileName, &con);
+@@ -392,18 +404,18 @@ static int FAST_FUNC fileAction(const ch
+ #endif
+ #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)
++      if (S_ISDIR(statbuf->st_mode) && G.xdev_count) {
++              for (i = 0; i < G.xdev_count; i++) {
++                      if (G.xdev_dev[i] == statbuf->st_dev)
+                               break;
+               }
+-              if (i == xdev_count)
++              if (i == G.xdev_count)
+                       return SKIP;
+       }
+ #endif
+-      i = exec_actions(actions, fileName, statbuf);
++      i = exec_actions(G.actions, fileName, statbuf);
+       /* Had no explicit -print[0] or -exec? then print */
+-      if ((i & TRUE) && need_print)
++      if ((i & TRUE) && G.need_print)
+               puts(fileName);
+       /* Cannot return 0: our caller, recursive_action(),
+        * will perror() and skip dirs (if called on dir) */
+@@ -431,7 +443,7 @@ static int find_type(const char *type)
+       else if (*type == 's')
+               mask = S_IFSOCK;
+-      if (mask == 0 || *(type + 1) != '\0')
++      if (mask == 0 || type[1] != '\0')
+               bb_error_msg_and_die(bb_msg_invalid_arg, type, "-type");
+       return mask;
+@@ -592,21 +604,21 @@ static action*** parse_params(char **arg
+       /* --- Tests and actions --- */
+               else if (parm == PARM_print) {
+-                      need_print = 0;
++                      G.need_print = 0;
+                       /* GNU find ignores '!' here: "find ! -print" */
+                       IF_FEATURE_FIND_NOT( invert_flag = 0; )
+                       (void) ALLOC_ACTION(print);
+               }
+ #if ENABLE_FEATURE_FIND_PRINT0
+               else if (parm == PARM_print0) {
+-                      need_print = 0;
++                      G.need_print = 0;
+                       IF_FEATURE_FIND_NOT( invert_flag = 0; )
+                       (void) ALLOC_ACTION(print0);
+               }
+ #endif
+ #if ENABLE_FEATURE_FIND_DEPTH
+               else if (parm == PARM_depth) {
+-                      recurse_flags |= ACTION_DEPTHFIRST;
++                      G.recurse_flags |= ACTION_DEPTHFIRST;
+               }
+ #endif
+ #if ENABLE_FEATURE_FIND_PRUNE
+@@ -617,8 +629,8 @@ static action*** parse_params(char **arg
+ #endif
+ #if ENABLE_FEATURE_FIND_DELETE
+               else if (parm == PARM_delete) {
+-                      need_print = 0;
+-                      recurse_flags |= ACTION_DEPTHFIRST;
++                      G.need_print = 0;
++                      G.recurse_flags |= ACTION_DEPTHFIRST;
+                       (void) ALLOC_ACTION(delete);
+               }
+ #endif
+@@ -626,7 +638,7 @@ static action*** parse_params(char **arg
+               else if (parm == PARM_exec) {
+                       int i;
+                       action_exec *ap;
+-                      need_print = 0;
++                      G.need_print = 0;
+                       IF_FEATURE_FIND_NOT( invert_flag = 0; )
+                       ap = ALLOC_ACTION(exec);
+                       ap->exec_argv = ++argv; /* first arg after -exec */
+@@ -834,6 +846,8 @@ IF_FEATURE_FIND_MAXDEPTH(OPT_MINDEPTH,)
+ #define minmaxdepth NULL
+ #endif
++      INIT_G();
++
+       for (firstopt = 1; firstopt < argc; firstopt++) {
+               if (argv[firstopt][0] == '-')
+                       break;
+@@ -861,21 +875,21 @@ IF_FEATURE_FIND_MAXDEPTH(OPT_MINDEPTH,)
+       while ((arg = argp[0])) {
+               int opt = index_in_strings(options, arg);
+               if (opt == OPT_FOLLOW) {
+-                      recurse_flags |= ACTION_FOLLOWLINKS;
++                      G.recurse_flags |= ACTION_FOLLOWLINKS | ACTION_DANGLING_OK;
+                       argp[0] = (char*)"-a";
+               }
+ #if ENABLE_FEATURE_FIND_XDEV
+               if (opt == OPT_XDEV) {
+                       struct stat stbuf;
+-                      if (!xdev_count) {
+-                              xdev_count = firstopt - 1;
+-                              xdev_dev = xmalloc(xdev_count * sizeof(dev_t));
++                      if (!G.xdev_count) {
++                              G.xdev_count = firstopt - 1;
++                              G.xdev_dev = xmalloc(G.xdev_count * sizeof(dev_t));
+                               for (i = 1; i < firstopt; i++) {
+                                       /* not xstat(): shouldn't bomb out on
+                                        * "find not_exist exist -xdev" */
+                                       if (stat(argv[i], &stbuf))
+                                               stbuf.st_dev = -1L;
+-                                      xdev_dev[i-1] = stbuf.st_dev;
++                                      G.xdev_dev[i-1] = stbuf.st_dev;
+                               }
+                       }
+                       argp[0] = (char*)"-a";
+@@ -894,11 +908,11 @@ IF_FEATURE_FIND_MAXDEPTH(OPT_MINDEPTH,)
+               argp++;
+       }
+-      actions = parse_params(&argv[firstopt]);
++      G.actions = parse_params(&argv[firstopt]);
+       for (i = 1; i < firstopt; i++) {
+               if (!recursive_action(argv[i],
+-                              recurse_flags,  /* flags */
++                              G.recurse_flags,/* flags */
+                               fileAction,     /* file action */
+                               fileAction,     /* dir action */
+ #if ENABLE_FEATURE_FIND_MAXDEPTH
+diff -urpN busybox-1.15.1/include/libbb.h busybox-1.15.1-find/include/libbb.h
+--- busybox-1.15.1/include/libbb.h     2009-09-12 17:55:58.000000000 +0200
++++ busybox-1.15.1-find/include/libbb.h        2009-09-30 02:20:21.000000000 +0200
+@@ -286,7 +286,9 @@ enum {
+       ACTION_DEPTHFIRST     = (1 << 3),
+       /*ACTION_REVERSE      = (1 << 4), - unused */
+       ACTION_QUIET          = (1 << 5),
++      ACTION_DANGLING_OK    = (1 << 6),
+ };
++typedef uint8_t recurse_flags_t;
+ extern int recursive_action(const char *fileName, unsigned flags,
+       int FAST_FUNC (*fileAction)(const char *fileName, struct stat* statbuf, void* userData, int depth),
+       int FAST_FUNC (*dirAction)(const char *fileName, struct stat* statbuf, void* userData, int depth),
+diff -urpN busybox-1.15.1/libbb/recursive_action.c busybox-1.15.1-find/libbb/recursive_action.c
+--- busybox-1.15.1/libbb/recursive_action.c    2009-09-12 17:55:36.000000000 +0200
++++ busybox-1.15.1-find/libbb/recursive_action.c       2009-09-30 02:20:21.000000000 +0200
+@@ -61,6 +61,7 @@ int FAST_FUNC recursive_action(const cha
+               unsigned depth)
+ {
+       struct stat statbuf;
++      unsigned follow;
+       int status;
+       DIR *dir;
+       struct dirent *next;
+@@ -68,14 +69,22 @@ int FAST_FUNC recursive_action(const cha
+       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;
+       }