bug-findutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

find exit status for file stat failures (ENOENT)


From: Jon Peatfield
Subject: find exit status for file stat failures (ENOENT)
Date: Mon, 15 Oct 2001 19:17:54 +0100

In some cases when (GNU) find is walking a tree it may return a
non-zero exit status for things like a file being missing, and in
other circumstances not.

In find.c:process_path() (or various pred.c:pred* functions) if an
xstat() is performed which fails with an errno of ENOENT then
exit_status is set to 1, and this will be returned at the end (though
find carries on of course).

In the case that noleaf is not set only _some_ paths will be have
xstat() called (until we find enough directories to match the
linkcount, unless some other pred needs the stat data).  Therefore a
file being missing will sometimes be enough to cause a non-zero return
and not at other times (so some files are treated differently than
others!)

One can clearly make all the files be xstat()'d using the noleaf
option, but I'd prefer to not have a file missing be treated as an
error (I'm generating a list of files to be backed-up so missing files
should (probably) simply be ignored, or at least return a different
exit status so we can distinguish this from hard failures).

I have a (very lightly tested) patch (against the alpha
findutils-4.1.7) which adds a new option -missferr which sets the exit
status to be returned on an xstat() of a file failing with
errno==ENOENT.

Like -mindepth (from which the code for the parser.c is cribbed), it
sets a single global value, so should probably only be used early (and
only once) in the pred list to avoid total confusion...

I don't know whether to make a similar patch for missing directories
(since they are always xstat()'d the behaviour is always the same at
least (sets exit_status=1).

The patch doesn't change the default behaviour, but allows -missferr X
to mean return X if all the errors were just xstat() failures with
errno==ENOENT on files.

In case you are interested in the patch here it is:

--cut-here--
--- find/defs.h.orig    Sun May 20 21:39:37 2001
+++ find/defs.h Mon Oct 15 18:58:13 2001
@@ -398,6 +398,7 @@
 extern boolean do_dir_first;
 extern int maxdepth;
 extern int mindepth;
+extern int missferr;
 extern int curdepth;
 extern int output_block_size;
 extern time_t start_time;
@@ -417,3 +418,10 @@
 extern int path_length;
 extern int (*xstat) ();
 extern boolean dereference;
+
+#define set_missferr \
+         if (errno == ENOENT) { \
+           if (exit_status == 0) { exit_status = missferr;} \
+         } else { \
+           exit_status = 1; \
+         }\
--- find/find.c.orig    Sun May 20 21:39:37 2001
+++ find/find.c Mon Oct 15 18:58:29 2001
@@ -81,6 +81,9 @@
 /* If >=0, don't process files above this level. */
 int mindepth;
 
+/* the value to report if a stat of a file fails */
+int missferr;
+
 /* Current depth; 0 means current path is a command line arg. */
 int curdepth;
 
@@ -170,6 +173,7 @@
   last_pred = NULL;
   do_dir_first = true;
   maxdepth = mindepth = -1;
+  missferr = 1;
   start_time = time (NULL);
   cur_day_start = start_time - DAYSECS;
   full_days = false;
@@ -400,7 +404,7 @@
       if ((*xstat) (name, &stat_buf) != 0)
        {
          error (0, errno, "%s", pathname);
-         exit_status = 1;
+         set_missferr;
          return 0;
        }
       have_stat = true;
--- find/parser.c.orig  Sun May 20 21:39:37 2001
+++ find/parser.c       Mon Oct 15 19:06:17 2001
@@ -85,6 +85,7 @@
 static boolean parse_ls PARAMS((char *argv[], int *arg_ptr));
 static boolean parse_maxdepth PARAMS((char *argv[], int *arg_ptr));
 static boolean parse_mindepth PARAMS((char *argv[], int *arg_ptr));
+static boolean parse_missferr PARAMS((char *argv[], int *arg_ptr));
 static boolean parse_mmin PARAMS((char *argv[], int *arg_ptr));
 static boolean parse_mtime PARAMS((char *argv[], int *arg_ptr));
 static boolean parse_name PARAMS((char *argv[], int *arg_ptr));
@@ -184,6 +185,7 @@
   {"ls", parse_ls},            /* GNU, Unix */
   {"maxdepth", parse_maxdepth},        /* GNU */
   {"mindepth", parse_mindepth},        /* GNU */
+  {"missferr", parse_missferr},        /* DAMTP extra */
   {"mmin", parse_mmin},                /* GNU */
   {"mount", parse_xdev},       /* Unix */
   {"mtime", parse_mtime},
@@ -689,6 +691,23 @@
     return (false);
   mindepth = atoi (argv[*arg_ptr]);
   if (mindepth < 0)
+    return (false);
+  (*arg_ptr)++;
+  return (true);
+}
+
+static boolean
+parse_missferr (char **argv, int *arg_ptr)
+{
+  int depth_len;
+
+  if ((argv == NULL) || (argv[*arg_ptr] == NULL))
+    return (false);
+  depth_len = strspn (argv[*arg_ptr], "0123456789");
+  if ((depth_len == 0) || (argv[*arg_ptr][depth_len] != '\0'))
+    return (false);
+  missferr = atoi (argv[*arg_ptr]);
+  if (missferr < 0)
     return (false);
   (*arg_ptr)++;
   return (true);
--- find/pred.c.orig    Sun May 20 21:39:37 2001
+++ find/pred.c Mon Oct 15 18:47:53 2001
@@ -277,7 +277,7 @@
          if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
            {
              error (0, errno, "%s", pathname);
-             exit_status = 1;
+             set_missferr;
              return (false);
            }
          have_stat = true;
@@ -368,7 +368,7 @@
       if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
        {
          error (0, errno, "%s", pathname);
-         exit_status = 1;
+         set_missferr;
          return (false);
        }
       have_stat = true;
@@ -929,7 +929,7 @@
       if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
        {
          error (0, errno, "%s", pathname);
-         exit_status = 1;
+         set_missferr;
          return (false);
        }
       have_stat = true;
@@ -1007,7 +1007,7 @@
          if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
            {
              error (0, errno, "%s", pathname);
-             exit_status = 1;
+             set_missferr;
              return (false);
            }
          have_stat = true;
@@ -1215,7 +1215,7 @@
        /* Mimic behavior of ls -lL. */
        return (pred_type (pathname, stat_buf, pred_ptr));
       error (0, errno, "%s", pathname);
-      exit_status = 1;
+      set_missferr;
       return (false);
     }
   return (pred_type (pathname, &sbuf, pred_ptr));
--cut-here--

I've be grateful of any suggestions for improvements (including the
pred name), or other changes to achieve the same (or similar) effects.
Do you also want a patch to the man page, -help info at all?
-- 
Jon Peatfield,  DAMTP,  Computer Officer,   University of Cambridge
Telephone: +44 1223  3 37852    Mail: address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]