Ondrej Vasik ae3959
diff -urNp coreutils-7.6-orig/doc/coreutils.texi coreutils-7.6/doc/coreutils.texi
Ondrej Vasik ae3959
--- coreutils-7.6-orig/doc/coreutils.texi	2009-09-22 15:12:55.000000000 +0200
Ondrej Vasik ae3959
+++ coreutils-7.6/doc/coreutils.texi	2009-10-02 16:09:57.000000000 +0200
Ondrej Vasik ae3959
@@ -6114,7 +6114,8 @@ Exit status:
Ondrej Vasik ae3959
   specified as a command line argument.  This happens when listing a
Ondrej Vasik ae3959
   directory in which entries are actively being removed or renamed.)
Ondrej Vasik ae3959
 2 serious trouble (e.g., memory exhausted, invalid option or failure
Ondrej Vasik ae3959
-  to access file or directory specified as a command line argument)
Ondrej Vasik ae3959
+  to access file or directory specified as a command line argument
Ondrej Vasik ae3959
+  or a directory loop)
Ondrej Vasik ae3959
 @end display
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
 Also see @ref{Common options}.
Ondrej Vasik ae3959
Ondrej Vasik ae3959
diff -urNp coreutils-7.6-orig/src/ls.c coreutils-7.6/src/ls.c
Ondrej Vasik ae3959
--- coreutils-7.6-orig/src/ls.c	2009-09-22 15:12:55.000000000 +0200
Ondrej Vasik ae3959
+++ coreutils-7.6/src/ls.c	2009-10-02 16:19:54.000000000 +0200
Ondrej Vasik ae3959
@@ -2494,6 +2494,7 @@ print_dir (char const *name, char const 
Ondrej Vasik ae3959
           error (0, 0, _("%s: not listing already-listed directory"),
Ondrej Vasik ae3959
                  quotearg_colon (name));
Ondrej Vasik ae3959
           closedir (dirp);
Ondrej Vasik ae3959
+          set_exit_status (true);
Ondrej Vasik ae3959
           return;
Ondrej Vasik ae3959
         }
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
@@ -3582,6 +3583,18 @@ format_user_width (uid_t u)
Ondrej Vasik ae3959
   return format_user_or_group_width (numeric_ids ? NULL : getuser (u), u);
Ondrej Vasik ae3959
 }
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
+/* Return a pointer to a formatted version of F->stat.st_ino,
Ondrej Vasik ae3959
+ possibly using buffer, BUF, of length BUFLEN, which must be at least
Ondrej Vasik ae3959
+ INT_BUFSIZE_BOUND (uintmax_t) bytes. */
Ondrej Vasik ae3959
+static char *
Ondrej Vasik ae3959
+format_inode (char *buf, size_t buflen, const struct fileinfo *f)
Ondrej Vasik ae3959
+{
Ondrej Vasik ae3959
+ assert (INT_BUFSIZE_BOUND (uintmax_t) <= buflen);
Ondrej Vasik ae3959
+ return (f->stat_ok && f->stat.st_ino != NOT_AN_INODE_NUMBER
Ondrej Vasik ae3959
+ ? umaxtostr (f->stat.st_ino, buf)
Ondrej Vasik ae3959
+ : (char *) "?");
Ondrej Vasik ae3959
+}
Ondrej Vasik ae3959
+
Ondrej Vasik ae3959
 /* Likewise, for groups.  */
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
 static int
Ondrej Vasik ae3959
@@ -3712,9 +3725,7 @@ print_long_format (const struct fileinfo
Ondrej Vasik ae3959
     {
Ondrej Vasik ae3959
       char hbuf[INT_BUFSIZE_BOUND (uintmax_t)];
Ondrej Vasik ae3959
       sprintf (p, "%*s ", inode_number_width,
Ondrej Vasik ae3959
-               (f->stat.st_ino == NOT_AN_INODE_NUMBER
Ondrej Vasik ae3959
-                ? "?"
Ondrej Vasik ae3959
-                : umaxtostr (f->stat.st_ino, hbuf)));
Ondrej Vasik ae3959
+              format_inode (hbuf, sizeof hbuf, f));
Ondrej Vasik ae3959
       /* Increment by strlen (p) here, rather than by inode_number_width + 1.
Ondrej Vasik ae3959
          The latter is wrong when inode_number_width is zero.  */
Ondrej Vasik ae3959
       p += strlen (p);
Ondrej Vasik ae3959
@@ -4104,12 +4115,13 @@ print_file_name_and_frills (const struct
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
   if (print_inode)
Ondrej Vasik ae3959
     printf ("%*s ", format == with_commas ? 0 : inode_number_width,
Ondrej Vasik ae3959
-            umaxtostr (f->stat.st_ino, buf));
Ondrej Vasik ae3959
+            format_inode (buf, sizeof buf, f));
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
   if (print_block_size)
Ondrej Vasik ae3959
     printf ("%*s ", format == with_commas ? 0 : block_size_width,
Ondrej Vasik ae3959
-            human_readable (ST_NBLOCKS (f->stat), buf, human_output_opts,
Ondrej Vasik ae3959
-                            ST_NBLOCKSIZE, output_block_size));
Ondrej Vasik ae3959
+  ! f->stat_ok ? "?"
Ondrej Vasik ae3959
+  : human_readable (ST_NBLOCKS (f->stat), buf, human_output_opts,
Ondrej Vasik ae3959
+  ST_NBLOCKSIZE, output_block_size));
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
   size_t width = print_name_with_quoting (f->name, FILE_OR_LINK_MODE (f),
Ondrej Vasik ae3959
                                           f->linkok, f->stat_ok, f->filetype,
Ondrej Vasik ae3959
@@ -4320,9 +4332,10 @@ length_of_file_name_and_frills (const st
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
   if (print_block_size)
Ondrej Vasik ae3959
     len += 1 + (format == with_commas
Ondrej Vasik ae3959
-                ? strlen (human_readable (ST_NBLOCKS (f->stat), buf,
Ondrej Vasik ae3959
-                                          human_output_opts, ST_NBLOCKSIZE,
Ondrej Vasik ae3959
-                                          output_block_size))
Ondrej Vasik ae3959
+    ? strlen (! f->stat_ok ? "?"
Ondrej Vasik ae3959
+    : human_readable (ST_NBLOCKS (f->stat), buf,
Ondrej Vasik ae3959
+    human_output_opts, ST_NBLOCKSIZE,
Ondrej Vasik ae3959
+    output_block_size))
Ondrej Vasik ae3959
                 : block_size_width);
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
   quote_name (NULL, f->name, filename_quoting_options, &name_width);
Ondrej Vasik ae3959
diff -urNp coreutils-7.6-orig/tests/ls/dangle coreutils-7.6/tests/ls/dangle
Ondrej Vasik ae3959
--- coreutils-7.6-orig/tests/ls/dangle	2009-09-01 13:01:16.000000000 +0200
Ondrej Vasik ae3959
+++ coreutils-7.6/tests/ls/dangle	2009-10-02 16:21:06.000000000 +0200
Ondrej Vasik ae3959
@@ -26,6 +26,10 @@ fi
Ondrej Vasik ae3959
 ln -s no-such-file dangle || framework_failure
Ondrej Vasik ae3959
 mkdir -p dir/sub || framework_failure
Ondrej Vasik ae3959
 ln -s dir slink-to-dir || framework_failure
Ondrej Vasik ae3959
+mkdir d || framework_failure
Ondrej Vasik ae3959
+ln -s no-such d/dangle || framework_failure
Ondrej Vasik ae3959
+printf '? dangle\n' > subdir_Li_exp || framework_failure
Ondrej Vasik ae3959
+printf 'total 0\n? dangle\n' > subdir_Ls_exp || framework_failure
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
 fail=0
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
@@ -50,4 +54,14 @@ EOF
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
 compare out exp || fail=1
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
+# Ensure that ls -Li prints "?" as the inode of a dangling symlink.
Ondrej Vasik ae3959
+rm -f out
Ondrej Vasik ae3959
+ls -Li d > out 2>/dev/null && fail=1
Ondrej Vasik ae3959
+compare out subdir_Li_exp || fail=1
Ondrej Vasik ae3959
+
Ondrej Vasik ae3959
+# Ensure that ls -Ls prints "?" as the allocation of a dangling symlink.
Ondrej Vasik ae3959
+rm -f out
Ondrej Vasik ae3959
+ls -Ls d > out 2>/dev/null && fail=1
Ondrej Vasik ae3959
+compare out subdir_Ls_exp || fail=1
Ondrej Vasik ae3959
+
Ondrej Vasik ae3959
 Exit $fail
Ondrej Vasik ae3959
diff -urNp coreutils-7.6-orig/tests/ls/infloop coreutils-7.6/tests/ls/infloop
Ondrej Vasik ae3959
--- coreutils-7.6-orig/tests/ls/infloop	2009-09-01 13:01:16.000000000 +0200
Ondrej Vasik ae3959
+++ coreutils-7.6/tests/ls/infloop	2009-10-02 16:12:11.000000000 +0200
Ondrej Vasik ae3959
@@ -1,6 +1,7 @@
Ondrej Vasik ae3959
 #!/bin/sh
Ondrej Vasik ae3959
 # show that the following no longer makes ls infloop
Ondrej Vasik ae3959
 # mkdir loop; cd loop; ln -s ../loop sub; ls -RL
Ondrej Vasik ae3959
+# Also ensure ls exits with status = 2 in that case.
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
 # Copyright (C) 2001-2002, 2004, 2006-2009 Free Software Foundation, Inc.
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
@@ -27,21 +28,22 @@ fi
Ondrej Vasik ae3959
 mkdir loop || framework_failure
Ondrej Vasik ae3959
 ln -s ../loop loop/sub || framework_failure
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
-fail=0
Ondrej Vasik ae3959
-
Ondrej Vasik ae3959
-ls -RL loop 2>err | head -n 7 > out
Ondrej Vasik ae3959
-# With an inf-looping ls, out will contain these 7 lines:
Ondrej Vasik ae3959
-cat <<EOF > bad
Ondrej Vasik ae3959
+cat <<\EOF > exp-out || framework_failure
Ondrej Vasik ae3959
 loop:
Ondrej Vasik ae3959
 sub
Ondrej Vasik ae3959
+EOF
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
-loop/sub:
Ondrej Vasik ae3959
-sub
Ondrej Vasik ae3959
-
Ondrej Vasik ae3959
-loop/sub/sub:
Ondrej Vasik ae3959
+cat <<\EOF > exp-err || framework_failure
Ondrej Vasik ae3959
+ls: loop/sub: not listing already-listed directory
Ondrej Vasik ae3959
 EOF
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
-# Make sure we don't get the "bad" output.
Ondrej Vasik ae3959
-compare out bad > /dev/null 2>&1 && fail=1
Ondrej Vasik ae3959
+fail=0
Ondrej Vasik ae3959
+
Ondrej Vasik ae3959
+timeout 1 ls -RL loop 2>err > out
Ondrej Vasik ae3959
+# Ensure that ls exits with status 2 upon detecting a cycle
Ondrej Vasik ae3959
+test $? = 2 || fail=1
Ondrej Vasik ae3959
+
Ondrej Vasik ae3959
+compare err exp-err || fail=1
Ondrej Vasik ae3959
+compare out exp-out || fail=1
Ondrej Vasik ae3959
 
Ondrej Vasik ae3959
 Exit $fail
Ondrej Vasik ae3959