summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Meyering <meyering@redhat.com>2009-09-28 20:24:41 +0200
committerJim Meyering <meyering@redhat.com>2009-09-29 11:42:45 +0200
commit36edf7bad2ab76720a0bf6519074d23d4b8823a7 (patch)
tree8c762204a8de0171ba33fee50d8ae931291e2f8e
parent242689c7f93de72693979f877dd31b3ef7178eea (diff)
downloadcoreutils-36edf7bad2ab76720a0bf6519074d23d4b8823a7.tar.xz
ls: print "?", not "0" as inode of dereferenced dangling symlink
ls prints inode numbers two ways: for long (-l) listings, and for short ones, e.g., ls -li and ls -i. The code to print long listings properly printed "?" when the inode was unknown, but the code for handling short listings would print 0 instead. Factor out the formatting code into a new function so ls prints the right string ("?") from both places: * NEWS (Bug fixes): Mention it. * src/ls.c (format_inode): New function. (print_long_format): Use it here. (print_file_name_and_frills): Use it here, too. * tests/ls/dangle: Exercise this fix. Reported by Yang Ren in http://bugzilla.redhat.com/525400
-rw-r--r--NEWS3
-rw-r--r--src/ls.c18
-rwxr-xr-xtests/ls/dangle8
3 files changed, 24 insertions, 5 deletions
diff --git a/NEWS b/NEWS
index d0a9a7d62..68ac24b10 100644
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,9 @@ GNU coreutils NEWS -*- outline -*-
ls -LR exits with status 2, not 0, when it encounters a cycle
+ ls -Li is now consistent with ls -Lil in printing "?", not "0" as the
+ inode of a dangling symlink.
+
** Portability
On Solaris 9, many commands would mistakenly treat file/ the same as
diff --git a/src/ls.c b/src/ls.c
index 86f5c3260..c8e8abb6d 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -3556,9 +3556,19 @@ format_group_width (gid_t g)
return format_user_or_group_width (numeric_ids ? NULL : getgroup (g), g);
}
+/* Return a pointer to a formatted version of F->stat.st_ino,
+ possibly using buffer, BUF, of length BUFLEN, which must be at least
+ INT_BUFSIZE_BOUND (uintmax_t) bytes. */
+static char *
+format_inode (char *buf, size_t buflen, const struct fileinfo *f)
+{
+ assert (INT_BUFSIZE_BOUND (uintmax_t) <= buflen);
+ return (f->stat.st_ino == NOT_AN_INODE_NUMBER
+ ? (char *) "?"
+ : umaxtostr (f->stat.st_ino, buf));
+}
/* Print information about F in long format. */
-
static void
print_long_format (const struct fileinfo *f)
{
@@ -3615,9 +3625,7 @@ print_long_format (const struct fileinfo *f)
{
char hbuf[INT_BUFSIZE_BOUND (uintmax_t)];
sprintf (p, "%*s ", inode_number_width,
- (f->stat.st_ino == NOT_AN_INODE_NUMBER
- ? "?"
- : umaxtostr (f->stat.st_ino, hbuf)));
+ format_inode (hbuf, sizeof hbuf, f));
/* Increment by strlen (p) here, rather than by inode_number_width + 1.
The latter is wrong when inode_number_width is zero. */
p += strlen (p);
@@ -4004,7 +4012,7 @@ print_file_name_and_frills (const struct fileinfo *f, size_t start_col)
if (print_inode)
printf ("%*s ", format == with_commas ? 0 : inode_number_width,
- umaxtostr (f->stat.st_ino, buf));
+ format_inode (buf, sizeof buf, f));
if (print_block_size)
printf ("%*s ", format == with_commas ? 0 : block_size_width,
diff --git a/tests/ls/dangle b/tests/ls/dangle
index b2f8539b8..6abad9213 100755
--- a/tests/ls/dangle
+++ b/tests/ls/dangle
@@ -26,6 +26,9 @@ fi
ln -s no-such-file dangle || framework_failure
mkdir -p dir/sub || framework_failure
ln -s dir slink-to-dir || framework_failure
+mkdir d || framework_failure
+ln -s no-such d/dangle || framework_failure
+echo '? dangle' > subdir_exp || framework_failure
fail=0
@@ -50,4 +53,9 @@ EOF
compare out exp || fail=1
+# Ensure that ls -Li prints "?" as the inode of a dangling symlink.
+rm -f out
+ls -Li d > out 2>/dev/null && fail=1
+compare out subdir_exp || fail=1
+
Exit $fail