]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
ls: print "?", not "0" as inode of dereferenced dangling symlink
authorJim Meyering <meyering@redhat.com>
Mon, 28 Sep 2009 18:24:41 +0000 (20:24 +0200)
committerJim Meyering <meyering@redhat.com>
Tue, 29 Sep 2009 09:42:45 +0000 (11:42 +0200)
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

NEWS
src/ls.c
tests/ls/dangle

diff --git a/NEWS b/NEWS
index d0a9a7d6290d11a3faaee9e84b0793db095ee509..68ac24b107bffefec7924224bfd3028b23207c1a 100644 (file)
--- 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
index 86f5c3260c269ed3df667a293c51d8a67de35802..c8e8abb6d333977bd37914c9934840b10b83c4d0 100644 (file)
--- 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,
index b2f8539b81e54732cf2a42aecfa8eb4c63be9092..6abad9213d1611530364b26fd72b7309f5fbd9c8 100755 (executable)
@@ -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