bug-findutils
[Top][All Lists]
Advanced

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

[patch] findutils-4.1.20: use d_type in struct dirent


From: Tim Waugh
Subject: [patch] findutils-4.1.20: use d_type in struct dirent
Date: Thu, 18 Mar 2004 14:16:49 +0000
User-agent: Mutt/1.4.1i

Hi,

Here is a patch (originally by Jakub Jelinek) to use d_type in struct
dirent, if available, to avoid unnecessary stat() calls in some
expressions.

What do you think?

Tim.
*/

--- findutils-4.1.20/gnulib/lib/savedir.c.d_type        2001-08-31 
10:09:53.000000000 +0100
+++ findutils-4.1.20/gnulib/lib/savedir.c       2004-03-18 13:58:58.000000000 
+0000
@@ -65,7 +65,9 @@
 
 /* Return a freshly allocated string containing the filenames
    in directory DIR, separated by '\0' characters;
-   the end is marked by two '\0' characters in a row.
+   if D_TYPE_IN_DIRENT is defined, this is followed by
+   one character with file type (DT_*);
+   the end is marked by "" filename.
    Return NULL (setting errno) if DIR cannot be opened, read, or closed.  */
 
 #ifndef NAME_SIZE_DEFAULT
@@ -97,6 +99,9 @@
       if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0')
        {
          size_t entry_size = strlen (entry) + 1;
+#ifdef D_TYPE_IN_DIRECT
+         entry_size++;
+#endif
          if (used + entry_size < used)
            xalloc_die ();
          if (allocated <= used + entry_size)
@@ -111,7 +116,10 @@
 
              name_space = xrealloc (name_space, allocated);
            }
-         memcpy (name_space + used, entry, entry_size);
+         memcpy (name_space + used, entry, entry_size - 1);
+#ifdef D_TYPE_IN_DIRENT
+         name_space[used + entry_size - 1] = dp->d_type;
+#endif
          used += entry_size;
        }
     }
--- findutils-4.1.20/find/defs.h.d_type 2003-05-26 14:37:29.000000000 +0100
+++ findutils-4.1.20/find/defs.h        2004-03-18 13:53:37.000000000 +0000
@@ -255,8 +255,12 @@
   /* True if this predicate node requires default print be turned off. */
   boolean no_default_print;
 
-  /* True if this predicate node requires a stat system call to execute. */
-  boolean need_stat;
+  /* PRED_NEED_STAT if this predicate node requires a stat system
+     call to execute, PRED_NEED_TYPE if either stat or valid DT_* file
+     type is needed.  */
+#define PRED_NEED_STAT 3
+#define PRED_NEED_TYPE 1
+  char need_stat;
 
   /* Information needed by the predicate processor.
      Next to each member are listed the predicates that use it. */
--- findutils-4.1.20/find/tree.c.d_type 2003-05-24 19:36:25.000000000 +0100
+++ findutils-4.1.20/find/tree.c        2004-03-18 13:53:37.000000000 +0000
@@ -356,7 +356,7 @@
   new_parent = (struct predicate *) xmalloc (sizeof (struct predicate));
   new_parent->p_type = BI_OP;
   new_parent->p_prec = high_prec;
-  new_parent->need_stat = false;
+  new_parent->need_stat = 0;
 
   switch (high_prec)
     {
@@ -408,10 +408,10 @@
    get executed (because the expression value is determined earlier.)
    So every expression needing stat must be marked as such, not just
    the earliest, to be sure to obtain the stat.  This still guarantees 
-   that a stat is made as late as possible.  Return true if the top node 
+   that a stat is made as late as possible.  Return 2 if the top node 
    in TREE requires a stat, false if not. */
 
-boolean
+int
 mark_stat (struct predicate *tree)
 {
   /* The tree is executed in-order, so walk this way (apologies to Aerosmith)
@@ -423,8 +423,7 @@
       return tree->need_stat;
 
     case UNI_OP:
-      if (mark_stat (tree->pred_right))
-       tree->need_stat = true;
+      tree->need_stat |= mark_stat (tree->pred_right);
       return (false);
 
     case BI_OP:
@@ -432,9 +431,7 @@
       if (tree->pred_left != NULL)
        mark_stat (tree->pred_left);
 
-      if (mark_stat (tree->pred_right))
-       tree->need_stat = true;
-
+      tree->need_stat |= mark_stat (tree->pred_right);
       return (false);
 
     default:
--- findutils-4.1.20/find/pred.c.d_type 2003-05-24 19:36:25.000000000 +0100
+++ findutils-4.1.20/find/pred.c        2004-03-18 13:53:37.000000000 +0000
@@ -274,7 +274,8 @@
                                            pred_ptr->pred_left))
     {
       /* Check whether we need a stat here. */
-      if (pred_ptr->need_stat)
+      if (pred_ptr->need_stat == PRED_NEED_STAT
+         || (pred_ptr->need_stat && stat_buf->st_mode == 0))
        {
          if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
            {
@@ -365,7 +366,8 @@
     (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
                                       pred_ptr->pred_left);
   /* Check whether we need a stat here. */
-  if (pred_ptr->need_stat)
+  if (pred_ptr->need_stat == PRED_NEED_STAT
+      || (pred_ptr->need_stat && stat_buf->st_mode == 0))
     {
       if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
        {
@@ -926,7 +928,8 @@
 pred_negate (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
 {
   /* Check whether we need a stat here. */
-  if (pred_ptr->need_stat)
+  if (pred_ptr->need_stat == PRED_NEED_STAT
+      || (pred_ptr->need_stat && stat_buf->st_mode == 0))
     {
       if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
        {
@@ -1004,7 +1007,8 @@
                                             pred_ptr->pred_left))
     {
       /* Check whether we need a stat here. */
-      if (pred_ptr->need_stat)
+      if (pred_ptr->need_stat == PRED_NEED_STAT
+         || (pred_ptr->need_stat && stat_buf->st_mode == 0))
        {
          if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
            {
@@ -1210,6 +1214,11 @@
   struct stat sbuf;
   int (*ystat) ();
 
+#ifdef S_ISLNK
+  if (xstat == lstat && !S_ISLNK (stat_buf->st_mode))
+    return (pred_type (pathname, stat_buf, pred_ptr));
+#endif
+
   ystat = xstat == lstat ? stat : lstat;
   if ((*ystat) (rel_pathname, &sbuf) != 0)
     {
--- findutils-4.1.20/find/find.c.d_type 2003-05-24 19:36:25.000000000 +0100
+++ findutils-4.1.20/find/find.c        2004-03-18 13:53:37.000000000 +0000
@@ -38,6 +38,20 @@
 #include <locale.h>
 #endif
 
+#if HAVE_DIRENT_H
+# include <dirent.h>
+#else
+# if HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+#  include <ndir.h>
+# endif
+#endif
+
 #if ENABLE_NLS
 # include <libintl.h>
 # define _(Text) gettext (Text)
@@ -52,11 +66,15 @@
 # define N_(String) (String)
 #endif
 
+#ifndef DT_UNKNOWN
+# define DT_UNKNOWN 0
+#endif
+
 #define apply_predicate(pathname, stat_buf_ptr, node)  \
   (*(node)->pred_func)((pathname), (stat_buf_ptr), (node))
 
 static void process_top_path PARAMS((char *pathname));
-static int process_path PARAMS((char *pathname, char *name, boolean leaf, char 
*parent));
+static int process_path PARAMS((char *pathname, char *name, boolean leaf, char 
*parent, char d_type));
 static void process_dir PARAMS((char *pathname, char *name, int pathlen, 
struct stat *statp, char *parent));
 static boolean no_side_effects PARAMS((struct predicate *pred));
 static boolean default_prints PARAMS((struct predicate *pred));
@@ -343,11 +361,11 @@
          cur_stat_buf.st_ino != stat_buf.st_ino)
        error (1, 0, _("%s changed during execution of %s"), pathname, 
program_name);
 
-      process_path (pathname, ".", false, ".");
+      process_path (pathname, ".", false, ".", DT_UNKNOWN);
       chdir_back ();
     }
   else
-    process_path (pathname, pathname, false, ".");
+    process_path (pathname, pathname, false, ".", DT_UNKNOWN);
 }
 
 /* Info on each directory in the current tree branch, to avoid
@@ -381,7 +399,7 @@
    Return nonzero iff PATHNAME is a directory. */
 
 static int
-process_path (char *pathname, char *name, boolean leaf, char *parent)
+process_path (char *pathname, char *name, boolean leaf, char *parent, char 
d_type)
 {
   struct stat stat_buf;
   static dev_t root_dev;       /* Device ID of current argument pathname. */
@@ -394,6 +412,56 @@
 
   rel_pathname = name;
 
+#ifdef D_TYPE_IN_DIRENT
+# ifdef DTTOIF
+  if (d_type != DT_DIR
+      && DTTOIF (DT_UNKNOWN) == 0
+#  ifdef DT_WHT
+      && d_type != DT_WHT
+#  endif
+      && (d_type != DT_LNK || xstat == lstat))
+    stat_buf.st_mode = DTTOIF (d_type);
+# else
+  switch (d_type)
+    {
+    /* Don't do anything for DT_DIR, it needs a full stat to get ino/dev.  */
+#  if defined DT_CHR
+    case DT_CHR:
+      stat_buf.st_mode = S_IFCHR;
+      break;
+#  endif
+#  if defined DT_BLK
+    case DT_BLK:
+      stat_buf.st_mode = S_IFBLK;
+      break;
+#  endif
+#  if defined DT_REG
+    case DT_REG:
+      stat_buf.st_mode = S_IFREG;
+      break;
+#  endif
+#  if defined DT_LNK && defined S_IFLNK
+    case DT_LNK:
+      if (xstat == lstat)
+       stat_buf.st_mode = S_IFLNK;
+      break;
+#  endif
+#  if defined DT_FIFO && defined S_IFIFO
+    case DT_FIFO:
+      stat_buf.st_mode = S_IFIFO;
+      break;
+#  endif
+#  if defined DT_SOCK && defined S_IFSOCK
+    case DT_SOCK:
+      stat_buf.st_mode = S_IFSOCK;
+      break;
+#  endif
+    }
+# endif
+  if (stat_buf.st_mode)
+    have_stat = false;
+  else
+#endif
   if (leaf)
     have_stat = false;
   else
@@ -527,10 +595,21 @@
          stat_buf.st_ino != dir_ids[dir_curr].ino)
        error (1, 0, _("%s changed during execution of %s"), starting_dir, 
program_name);
 
-      for (namep = name_space; *namep; namep += file_len - pathname_len + 1)
+      for (namep = name_space; *namep;
+#ifdef D_TYPE_IN_DIRENT
+          namep += file_len - pathname_len + 2
+#else
+          namep += file_len - pathname_len + 1
+#endif
+         )
        {
+         char d_type = DT_UNKNOWN;
+
          /* Append this directory entry's name to the path being searched. */
          file_len = pathname_len + strlen (namep);
+#ifdef D_TYPE_IN_DIRENT
+         d_type = namep[file_len - pathname_len + 1];
+#endif
          if (file_len > cur_path_size)
            {
              while (file_len > cur_path_size)
@@ -555,11 +634,11 @@
               that the rest of the entries are non-directories --
               in other words, leaf files. */
            subdirs_left -= process_path (cur_path, cur_name,
-                                         subdirs_left == 0, pathname);
+                                         subdirs_left == 0, pathname, d_type);
          else
            /* There might be weird (e.g., CD-ROM or MS-DOS) filesystems
               mounted, which don't have Unix-like directory link counts. */
-           process_path (cur_path, cur_name, false, pathname);
+           process_path (cur_path, cur_name, false, pathname, d_type);
          curdepth--;
        }
 
--- findutils-4.1.20/find/util.c.d_type 2003-05-24 19:36:25.000000000 +0100
+++ findutils-4.1.20/find/util.c        2004-03-18 13:53:37.000000000 +0000
@@ -65,7 +65,7 @@
   last_pred->p_prec = NO_PREC;
   last_pred->side_effects = false;
   last_pred->no_default_print = false;
-  last_pred->need_stat = true;
+  last_pred->need_stat = PRED_NEED_STAT;
   last_pred->args.str = NULL;
   last_pred->pred_next = NULL;
   last_pred->pred_left = NULL;
@@ -98,7 +98,7 @@
 #endif /* DEBUG */
        new_pred->p_type = BI_OP;
        new_pred->p_prec = AND_PREC;
-       new_pred->need_stat = false;
+       new_pred->need_stat = 0;
        new_pred->args.str = NULL;
 
       default:
--- findutils-4.1.20/find/parser.c.d_type       2003-05-24 19:36:25.000000000 
+0100
+++ findutils-4.1.20/find/parser.c      2004-03-18 13:53:37.000000000 +0000
@@ -280,7 +280,7 @@
 #endif /* DEBUG */
   our_pred->p_type = BI_OP;
   our_pred->p_prec = AND_PREC;
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   return (true);
 }
 
@@ -318,7 +318,7 @@
 #endif /* DEBUG */
   our_pred->p_type = CLOSE_PAREN;
   our_pred->p_prec = NO_PREC;
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   return (true);
 }
 
@@ -371,7 +371,7 @@
 #endif /* DEBUG */
   our_pred->p_type = BI_OP;
   our_pred->p_prec = COMMA_PREC;
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   return (true);
 }
 
@@ -425,7 +425,7 @@
   struct predicate *our_pred;
 
   our_pred = insert_primary (pred_false);
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   return (true);
 }
 
@@ -482,7 +482,7 @@
   our_pred->args.stream = open_output_file (argv[*arg_ptr]);
   our_pred->side_effects = true;
   our_pred->no_default_print = true;
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   (*arg_ptr)++;
   return (true);
 }
@@ -498,7 +498,7 @@
   our_pred->args.stream = open_output_file (argv[*arg_ptr]);
   our_pred->side_effects = true;
   our_pred->no_default_print = true;
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   (*arg_ptr)++;
   return (true);
 }
@@ -588,6 +588,7 @@
     return (false);
   our_pred = insert_primary (pred_ilname);
   our_pred->args.str = argv[*arg_ptr];
+  our_pred->need_stat = PRED_NEED_TYPE;
   (*arg_ptr)++;
   return (true);
 }
@@ -600,7 +601,7 @@
   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
     return (false);
   our_pred = insert_primary (pred_iname);
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   our_pred->args.str = argv[*arg_ptr];
   (*arg_ptr)++;
   return (true);
@@ -620,7 +621,7 @@
   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
     return (false);
   our_pred = insert_primary (pred_ipath);
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   our_pred->args.str = argv[*arg_ptr];
   (*arg_ptr)++;
   return (true);
@@ -647,6 +648,7 @@
     return (false);
   our_pred = insert_primary (pred_lname);
   our_pred->args.str = argv[*arg_ptr];
+  our_pred->need_stat = PRED_NEED_TYPE;
   (*arg_ptr)++;
   return (true);
 }
@@ -731,7 +733,7 @@
   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
     return (false);
   our_pred = insert_primary (pred_name);
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   our_pred->args.str = argv[*arg_ptr];
   (*arg_ptr)++;
   return (true);
@@ -749,7 +751,7 @@
 #endif /* DEBUG */
   our_pred->p_type = UNI_OP;
   our_pred->p_prec = NEGATE_PREC;
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   return (true);
 }
 
@@ -876,7 +878,7 @@
 #endif /* DEBUG */
   our_pred->p_type = OPEN_PAREN;
   our_pred->p_prec = NO_PREC;
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   return (true);
 }
 
@@ -892,7 +894,7 @@
 #endif /* DEBUG */
   our_pred->p_type = BI_OP;
   our_pred->p_prec = OR_PREC;
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   return (true);
 }
 
@@ -904,7 +906,7 @@
   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
     return (false);
   our_pred = insert_primary (pred_path);
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   our_pred->args.str = argv[*arg_ptr];
   (*arg_ptr)++;
   return (true);
@@ -970,7 +972,7 @@
      already specified -print. */
   our_pred->side_effects = true;
   our_pred->no_default_print = true;
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   return (true);
 }
 
@@ -985,7 +987,7 @@
      already specified -print0. */
   our_pred->side_effects = true;
   our_pred->no_default_print = true;
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   return (true);
 }
 
@@ -1003,7 +1005,7 @@
   struct predicate *our_pred;
 
   our_pred = insert_primary (pred_prune);
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   /* -prune has a side effect that it does not descend into
      the current directory. */
   our_pred->side_effects = true;
@@ -1026,7 +1028,7 @@
   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
     return (false);
   our_pred = insert_primary (pred_regex);
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   re = (struct re_pattern_buffer *)
     xmalloc (sizeof (struct re_pattern_buffer));
   our_pred->args.regex = re;
@@ -1121,7 +1123,7 @@
   struct predicate *our_pred;
 
   our_pred = insert_primary (pred_true);
-  our_pred->need_stat = false;
+  our_pred->need_stat = 0;
   return (true);
 }
 
@@ -1256,13 +1258,14 @@
     }
   our_pred = insert_primary (which_pred);
   our_pred->args.type = type_cell;
+  our_pred->need_stat = PRED_NEED_TYPE;
   (*arg_ptr)++;                        /* Move on to next argument. */
   return (true);
 }
 
-/* If true, we've determined that the current fprintf predicate
+/* If non-zero, we've determined that the current fprintf predicate
    uses stat information. */
-static boolean fprintf_stat_needed;
+static char fprintf_stat_needed;
 
 static boolean
 insert_fprintf (FILE *fp, boolean (*func) (/* ??? */), char **argv, int 
*arg_ptr)
@@ -1275,7 +1278,7 @@
 
   format = argv[(*arg_ptr)++];
 
-  fprintf_stat_needed = false; /* Might be overridden later. */
+  fprintf_stat_needed = 0;     /* Might be overridden later. */
   our_pred = insert_primary (func);
   our_pred->side_effects = true;
   our_pred->no_default_print = true;
@@ -1429,14 +1432,16 @@
     case 'g':                  /* group name */
     case 'i':                  /* inode number */
     case 'k':                  /* size in 1K blocks */
-    case 'l':                  /* object of symlink */
     case 'n':                  /* number of links */
     case 's':                  /* size in bytes */
     case 't':                  /* mtime in `ctime' format */
     case 'T':                  /* mtime in user-specified strftime format */
     case 'U':                  /* UID number */
     case 'u':                  /* user name */
-      fprintf_stat_needed = true;
+      fprintf_stat_needed = PRED_NEED_STAT;
+      /* FALLTHROUGH */
+    case 'l':                  /* object of symlink */
+      fprintf_stat_needed |= PRED_NEED_TYPE;
       /* FALLTHROUGH */
     case 'f':                  /* basename of path */
     case 'h':                  /* leading directories part of path */
@@ -1452,7 +1457,7 @@
 
     case 'm':                  /* mode as octal number (perms only) */
       *fmt++ = 'o';
-      fprintf_stat_needed = true;
+      fprintf_stat_needed = PRED_NEED_STAT;
       break;
     }
   *fmt = '\0';




reply via email to

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