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.
This commit is contained in:
Jim Meyering
2006-02-26 10:01:00 +00:00
parent 256239cd3d
commit 33eb3efe9f

View File

@@ -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);