summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2003-01-15 11:59:07 +0000
committerJim Meyering <jim@meyering.net>2003-01-15 11:59:07 +0000
commit800f3a1e77d6185038d3d553b4188ea138a08881 (patch)
treec0d6d6bddd8fb3478da2c1273814d27eec43c346 /src
parentb1ebf2a3838cb7c673a641884fd4a64833d99258 (diff)
downloadcoreutils-800f3a1e77d6185038d3d553b4188ea138a08881.tar.xz
(gobble_file): Fall back on using lstat when required:
when --dereference (-L) is not specified, and - when operating on a dangling symlink - when operating on command-line-symlink-to-directories This fixes numerous problems. Here are examples: - `ls dangling-symlink' would fail with `no such file...' Now it prints `dangling-symlink'. - `ls -i symlink' would mistakenly print the inode of the referent. Now it prints the inode of the symlink. Likewise for --size (-s). Based on a patch from Michael Stone. Reported by Deepak Goel as Debian bug #173793.
Diffstat (limited to 'src')
-rw-r--r--src/ls.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/src/ls.c b/src/ls.c
index bbd1dd034..e15d5cfa9 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -2337,7 +2337,7 @@ gobble_file (const char *name, enum filetype type, int explicit_arg,
{
/* `path' is the absolute pathname of this file. */
- int val;
+ int err;
if (name[0] == '/' || dirname[0] == 0)
path = (char *) name;
@@ -2347,11 +2347,37 @@ gobble_file (const char *name, enum filetype type, int explicit_arg,
attach (path, dirname, name);
}
- val = (DEREF_ALWAYS <= dereference + explicit_arg
- ? stat (path, &files[files_index].stat)
- : lstat (path, &files[files_index].stat));
+ switch (dereference)
+ {
+ case DEREF_ALWAYS:
+ err = stat (path, &files[files_index].stat);
+ break;
+
+ case DEREF_COMMAND_LINE_SYMLINK_TO_DIR:
+ if (explicit_arg)
+ {
+ int need_lstat;
+ err = stat (path, &files[files_index].stat);
+ /* If stat failed because of ENOENT (maybe indicating a
+ dangling symlink), or if it succeeded and PATH refers
+ to a non-directory (hence PATH may be a symlink to a
+ non-directory and we may not dereference it), fall
+ through so that we call lstat instead. */
+ need_lstat = (err < 0
+ ? errno == ENOENT
+ : ! S_ISDIR (files[files_index].stat.st_mode));
+ if (!need_lstat)
+ break;
+ }
+
+ /* fall through. */
+
+ default: /* DEREF_NEVER */
+ err = lstat (path, &files[files_index].stat);
+ break;
+ }
- if (val < 0)
+ if (err < 0)
{
error (0, errno, "%s", quotearg_colon (path));
exit_status = 1;