bug-coreutils
[Top][All Lists]
Advanced

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

Re: ls -i inefficiency


From: Eric Blake
Subject: Re: ls -i inefficiency
Date: Sat, 25 Feb 2006 06:54:36 -0700
User-agent: Mozilla Thunderbird 1.0.2 (Windows/20050317)

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Jim Meyering on 2/25/2006 4:54 AM:
> Thanks for the suggestion.
> If this isn't too invasive, I'm interested.
> I think `ls -i' (without some other option requiring stat info)
> is used far less often than, say `ls -F', so it's harder to justify
> adding much complexity to optimize for this relatively unusual case.

And here's the patch.  As a nice side effect, it also optimized 'ls -L' to
avoid stat() (after all, dereferencing makes no sense when all you need is
file names, and no information from the dereference).

2006-02-25  Eric Blake  <address@hidden>

        * src/pwd.c (NOT_AN_INODE_NUMBER, D_INO): Move to ...
        * src/system.h: ... here, for use in ...
        * src/ls.c (main): ... here.  Prefer dirent.d_ino to stat when
        possible.
        (gobble_file): Add inode argument.
        (print_dir): Pass inode if available.
        (usage): Remove inaccuracy.

- --
Life is short - so eat dessert first!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFEAGGb84KuGfSFAYARAsR9AJ9Oe4NFzALSh0DACSHCQ7zq82NNzACeOVsU
jgvBPfo2j2KZo8+otKgmJSk=
=jzq9
-----END PGP SIGNATURE-----
Index: src/system.h
===================================================================
RCS file: /sources/coreutils/coreutils/src/system.h,v
retrieving revision 1.142
diff -u -p -r1.142 system.h
--- src/system.h        7 Feb 2006 22:32:50 -0000       1.142
+++ src/system.h        25 Feb 2006 13:52:11 -0000
@@ -244,6 +244,18 @@ initialize_exit_failure (int status)
 # define CLOSEDIR(d) closedir (d)
 #endif
 
+enum
+{
+  NOT_AN_INODE_NUMBER = 0
+};
+
+#ifdef D_INO_IN_DIRENT
+# define D_INO(dp) ((dp)->d_ino)
+#else
+/* Some systems don't have inodes, so fake them to avoid lots of ifdefs.  */
+# define D_INO(dp) NOT_AN_INODE_NUMBER
+#endif
+
 /* Get or fake the disk device blocksize.
    Usually defined by sys/param.h (if at all).  */
 #if !defined DEV_BSIZE && defined BSIZE
Index: src/pwd.c
===================================================================
RCS file: /sources/coreutils/coreutils/src/pwd.c,v
retrieving revision 1.58
diff -u -p -r1.58 pwd.c
--- src/pwd.c   1 Feb 2006 14:43:24 -0000       1.58
+++ src/pwd.c   25 Feb 2006 13:52:11 -0000
@@ -40,18 +40,6 @@ struct file_name
   char *start;
 };
 
-enum
-{
-  NOT_AN_INODE_NUMBER = 0
-};
-
-#ifdef D_INO_IN_DIRENT
-# define D_INO(dp) ((dp)->d_ino)
-#else
-/* Some systems don't have inodes, so fake them to avoid lots of ifdefs.  */
-# define D_INO(dp) NOT_AN_INODE_NUMBER
-#endif
-
 /* The name this program was run with. */
 char *program_name;
 
Index: src/ls.c
===================================================================
RCS file: /sources/coreutils/coreutils/src/ls.c,v
retrieving revision 1.405
diff -u -p -r1.405 ls.c
--- src/ls.c    10 Jan 2006 07:31:21 -0000      1.405
+++ src/ls.c    25 Feb 2006 13:52:11 -0000
@@ -231,7 +231,8 @@ static char *make_link_name (char const 
 static int decode_switches (int argc, char **argv);
 static bool file_ignored (char const *name);
 static uintmax_t gobble_file (char const *name, enum filetype type,
-                             bool command_line_arg, char const *dirname);
+                             ino_t inode, bool command_line_arg,
+                             char const *dirname);
 static void print_color_indicator (const char *name, mode_t mode, int linkok);
 static void put_indicator (const struct bin_str *ind);
 static void add_ignore_pattern (const char *pattern);
@@ -1222,9 +1223,8 @@ main (int argc, char **argv)
 
   format_needs_stat = sort_type == sort_time || sort_type == sort_size
     || format == long_format
-    || dereference == DEREF_ALWAYS
-    || print_block_size || print_inode;
-  format_needs_type = (!format_needs_stat
+    || print_block_size;
+  format_needs_type = (! format_needs_stat
                       && (recursive || print_with_color
                           || indicator_style != none));
 
@@ -1245,13 +1245,13 @@ main (int argc, char **argv)
   if (n_files <= 0)
     {
       if (immediate_dirs)
-       gobble_file (".", directory, true, "");
+       gobble_file (".", directory, NOT_AN_INODE_NUMBER, true, "");
       else
        queue_directory (".", NULL, true);
     }
   else
     do
-      gobble_file (argv[i++], unknown, true, "");
+      gobble_file (argv[i++], unknown, NOT_AN_INODE_NUMBER, true, "");
     while (i < argc);
 
   if (files_index)
@@ -2351,7 +2351,8 @@ print_dir (char const *name, char const 
                  || next->d_type == DT_SOCK)
                type = next->d_type;
 #endif
-             total_blocks += gobble_file (next->d_name, type, false, name);
+             total_blocks += gobble_file (next->d_name, type, D_INO (next),
+                                          false, name);
            }
        }
       else if (errno != 0)
@@ -2496,12 +2497,16 @@ clear_files (void)
    Return the number of blocks that the file occupies.  */
 
 static uintmax_t
-gobble_file (char const *name, enum filetype type, bool command_line_arg,
-            char const *dirname)
+gobble_file (char const *name, enum filetype type, ino_t inode,
+            bool command_line_arg, char const *dirname)
 {
   uintmax_t blocks;
   struct fileinfo *f;
 
+  /* An inode value prior to gobble_file necessarily came from readdir,
+     which is not used for command line arguments.  */
+  assert (! command_line_arg || inode == NOT_AN_INODE_NUMBER);
+
   if (files_index == nfiles)
     {
       files = xnrealloc (files, nfiles, 2 * sizeof *files);
@@ -2515,6 +2520,14 @@ gobble_file (char const *name, enum file
 
   if (command_line_arg
       || format_needs_stat
+      || (print_inode
+         && (inode == NOT_AN_INODE_NUMBER
+             /* When dereferencing symlinks, the inode must come from
+                stat, but readdir provides the inode of lstat.  Command
+                line dereferences are already taken care of by the above
+                assertion that the inode number is not yet known.  */
+             || (dereference == DEREF_ALWAYS
+                 && (type == symbolic_link || type == unknown))))
       || (format_needs_type
          && (type == unknown
 
@@ -2617,8 +2630,8 @@ gobble_file (char const *name, enum file
              f->linkok = true;
 
              /* Symbolic links to directories that are mentioned on the
-                command line are automatically traced if not being
-                listed as files.  */
+                command line are automatically traced if not being
+                listed as files.  */
              if (!command_line_arg || format == long_format
                  || !S_ISDIR (linkstats.st_mode))
                {
@@ -2643,13 +2656,6 @@ gobble_file (char const *name, enum file
       else
        f->filetype = normal;
 
-      {
-       char buf[INT_BUFSIZE_BOUND (uintmax_t)];
-       int len = strlen (umaxtostr (f->stat.st_ino, buf));
-       if (inode_number_width < len)
-         inode_number_width = len;
-      }
-
       blocks = ST_NBLOCKS (f->stat);
       {
        char buf[LONGEST_HUMAN_READABLE + 1];
@@ -2715,12 +2721,21 @@ gobble_file (char const *name, enum file
   else
     {
       f->filetype = type;
+      f->stat.st_ino = inode;
 #if HAVE_STRUCT_DIRENT_D_TYPE && defined DTTOIF
       f->stat.st_mode = DTTOIF (type);
 #endif
       blocks = 0;
     }
 
+  if (print_inode)
+      {
+       char buf[INT_BUFSIZE_BOUND (uintmax_t)];
+       int len = strlen (umaxtostr (f->stat.st_ino, buf));
+       if (inode_number_width < len)
+         inode_number_width = len;
+      }
+
   f->name = xstrdup (name);
   files_index++;
 
@@ -4162,7 +4177,7 @@ Mandatory arguments to long options are 
       --indicator-style=WORD append indicator with style WORD to entry 
names:\n\
                                none (default), slash (-p),\n\
                                file-type (--file-type), classify (-F)\n\
-  -i, --inode                with -l, print the index number of each file\n\
+  -i, --inode                print the index number of each file\n\
   -I, --ignore=PATTERN       do not list implied entries matching shell 
PATTERN\n\
   -k                         like --block-size=1K\n\
 "), stdout);

reply via email to

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