]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
In ls, avoid calling stat for --inode (-i), when possible.
authorJim Meyering <jim@meyering.net>
Sun, 26 Feb 2006 10:01:00 +0000 (10:01 +0000)
committerJim Meyering <jim@meyering.net>
Sun, 26 Feb 2006 10:01:00 +0000 (10:01 +0000)
(main): Prefer dirent.d_ino to stat when possible.
(gobble_file): Add inode argument.
(print_dir): Pass inode if available.
(usage): Remove inaccuracy.

src/ls.c

index 39f07b52442c3ddce7f93e4a5151edba00a162a7..9fae7fa0517585b51c753ecc055484b6b2bfb8be 100644 (file)
--- a/src/ls.c
+++ b/src/ls.c
@@ -231,7 +231,8 @@ static char *make_link_name (char const *name, char const *linkname);
 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 *realname, bool command_line_arg)
                  || 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 filetype type, bool command_line_arg,
 
   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 filetype type, bool command_line_arg,
              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 filetype type, bool command_line_arg,
       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 filetype type, bool command_line_arg,
   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 mandatory for short options too.\n\
       --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);