summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2006-02-26 10:01:00 +0000
committerJim Meyering <jim@meyering.net>2006-02-26 10:01:00 +0000
commit33eb3efe9fb6d7f72245ec8640cc6daf424810cf (patch)
tree4338ab76654fa875ada710bf718bf995af27b7ea
parent256239cd3da92c6dcc3868ce86a6535b308afd5d (diff)
downloadcoreutils-33eb3efe9fb6d7f72245ec8640cc6daf424810cf.tar.xz
In ls, avoid calling stat for --inode (-i), when possible.
(main): Prefer dirent.d_ino to stat when possible. (gobble_file): Add inode argument. (print_dir): Pass inode if available. (usage): Remove inaccuracy.
-rw-r--r--src/ls.c53
1 files changed, 34 insertions, 19 deletions
diff --git a/src/ls.c b/src/ls.c
index 39f07b524..9fae7fa05 100644
--- 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);