mirror of
https://git.savannah.gnu.org/git/coreutils.git
synced 2025-09-10 07:59:52 +02:00
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:
53
src/ls.c
53
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);
|
||||
|
||||
Reference in New Issue
Block a user