Re: [PATCH] ls: don't use an undefined struct stat after failed stat/lstat

2009-10-06 Thread Paul Eggert
Pádraig Brady  writes:

> -human_readable (ST_NBLOCKS (f->stat), buf, human_output_opts,
> -ST_NBLOCKSIZE, output_block_size));
> +! f->stat_ok ? "?"
> +: human_readable (ST_NBLOCKS (f->stat), buf, human_output_opts,
> +  ST_NBLOCKSIZE, output_block_size));

Just as a style thing, it's better to parenthesize expressions that
cross line boundaries, e.g.:

(! f->stat_ok ? "?"
 : human_readable (ST_NBLOCKS (f->stat), buf, human_output_opts,
  ST_NBLOCKSIZE, output_block_size))




Re: [PATCH] ls: don't use an undefined struct stat after failed stat/lstat

2009-09-30 Thread Jim Meyering
Pádraig Brady wrote:
> Jim Meyering wrote:
>> Pádraig Brady wrote:
>>> Jim Meyering wrote:
 Thanks for the review.
 BTW, here's the merged version:
>>> And attached one handles the `ls -Ls` case,
>>> which I'll push soon.
>>>
>>> cheers,
>>> Pádraig.
>>> >From 3edaa2363db0367e8fa472c4dc5c5696537cde61 Mon Sep 17 00:00:00 2001
>>> From: =?utf-8?q?P=C3=A1draig=20Brady?= 
>>> Date: Tue, 29 Sep 2009 15:43:01 +0100
>>> Subject: [PATCH] ls: always print "?" for allocated size of a dereferenced 
>>> dangling symlink
>>>
>>> Previously for `ls -Ls` (but not `ls -Lsl`), we referenced
>>> the st_blocks returned from the previous failed stat() call.
>>> This undefined value was seen to be 0 for danglink symlinks at least.
>>> * src/ls.c (print_file_name_and_frills, length_of_file_name_and_frills):
>>> Don't use st_blocks if the previous stat() failed
>>> * tests/ls/dangle: Add a test case
>>> * NEWS: Mention the bug fix
>>
>> Good catch.  Thanks!
>
> The NEWS is getting a bit verbose on this minor issue.
> Unless there are objections I'll roll up the NEWS from:
>
>   ls -Li is now consistent with ls -Lil in printing "?", not "0" as the
>   inode of a dangling symlink.
>
>   ls -Li no longer relies on unspecified behavior of stat/lstat.
>   Before this change, "ls -Li dangling-symlink" would mistakenly
>   print the inode number of the symlink under some conditions.
>
>   ls -Ls is now consistent with ls -Lsl in printing "?", not "0" as the
>   allocated size of a dangling symlink.
>
> to:
>
>   ls -is is now consistent with ls -lis in ignoring values returned
>   from a failed stat/lstat.  For example ls -Lis now prints "?", not "0",
>   for the inode number and allocated size of a dereferenced dangling symlink.

Agreed.  Thanks.




Re: [PATCH] ls: don't use an undefined struct stat after failed stat/lstat

2009-09-30 Thread Pádraig Brady
Jim Meyering wrote:
> Pádraig Brady wrote:
>> Jim Meyering wrote:
>>> Thanks for the review.
>>> BTW, here's the merged version:
>> And attached one handles the `ls -Ls` case,
>> which I'll push soon.
>>
>> cheers,
>> Pádraig.
>> >From 3edaa2363db0367e8fa472c4dc5c5696537cde61 Mon Sep 17 00:00:00 2001
>> From: =?utf-8?q?P=C3=A1draig=20Brady?= 
>> Date: Tue, 29 Sep 2009 15:43:01 +0100
>> Subject: [PATCH] ls: always print "?" for allocated size of a dereferenced 
>> dangling symlink
>>
>> Previously for `ls -Ls` (but not `ls -Lsl`), we referenced
>> the st_blocks returned from the previous failed stat() call.
>> This undefined value was seen to be 0 for danglink symlinks at least.
>> * src/ls.c (print_file_name_and_frills, length_of_file_name_and_frills):
>> Don't use st_blocks if the previous stat() failed
>> * tests/ls/dangle: Add a test case
>> * NEWS: Mention the bug fix
> 
> Good catch.  Thanks!

The NEWS is getting a bit verbose on this minor issue.
Unless there are objections I'll roll up the NEWS from:

  ls -Li is now consistent with ls -Lil in printing "?", not "0" as the
  inode of a dangling symlink.

  ls -Li no longer relies on unspecified behavior of stat/lstat.
  Before this change, "ls -Li dangling-symlink" would mistakenly
  print the inode number of the symlink under some conditions.

  ls -Ls is now consistent with ls -Lsl in printing "?", not "0" as the
  allocated size of a dangling symlink.

to:

  ls -is is now consistent with ls -lis in ignoring values returned
  from a failed stat/lstat.  For example ls -Lis now prints "?", not "0",
  for the inode number and allocated size of a dereferenced dangling symlink.

cheers,
Pádraig.




Re: [PATCH] ls: don't use an undefined struct stat after failed stat/lstat

2009-09-30 Thread Jim Meyering
Pádraig Brady wrote:
> Jim Meyering wrote:
>> Thanks for the review.
>> BTW, here's the merged version:
>
> And attached one handles the `ls -Ls` case,
> which I'll push soon.
>
> cheers,
> Pádraig.
>>From 3edaa2363db0367e8fa472c4dc5c5696537cde61 Mon Sep 17 00:00:00 2001
> From: =?utf-8?q?P=C3=A1draig=20Brady?= 
> Date: Tue, 29 Sep 2009 15:43:01 +0100
> Subject: [PATCH] ls: always print "?" for allocated size of a dereferenced 
> dangling symlink
>
> Previously for `ls -Ls` (but not `ls -Lsl`), we referenced
> the st_blocks returned from the previous failed stat() call.
> This undefined value was seen to be 0 for danglink symlinks at least.
> * src/ls.c (print_file_name_and_frills, length_of_file_name_and_frills):
> Don't use st_blocks if the previous stat() failed
> * tests/ls/dangle: Add a test case
> * NEWS: Mention the bug fix

Good catch.  Thanks!




Re: [PATCH] ls: don't use an undefined struct stat after failed stat/lstat

2009-09-30 Thread Pádraig Brady
Jim Meyering wrote:
> 
> Thanks for the review.
> BTW, here's the merged version:

And attached one handles the `ls -Ls` case,
which I'll push soon.

cheers,
Pádraig.
>From 3edaa2363db0367e8fa472c4dc5c5696537cde61 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?P=C3=A1draig=20Brady?= 
Date: Tue, 29 Sep 2009 15:43:01 +0100
Subject: [PATCH] ls: always print "?" for allocated size of a dereferenced dangling symlink

Previously for `ls -Ls` (but not `ls -Lsl`), we referenced
the st_blocks returned from the previous failed stat() call.
This undefined value was seen to be 0 for danglink symlinks at least.
* src/ls.c (print_file_name_and_frills, length_of_file_name_and_frills):
Don't use st_blocks if the previous stat() failed
* tests/ls/dangle: Add a test case
* NEWS: Mention the bug fix
---
 NEWS|3 +++
 src/ls.c|   12 +++-
 tests/ls/dangle |   10 --
 3 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/NEWS b/NEWS
index f1f7347..e6a860c 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,9 @@ GNU coreutils NEWS-*- outline -*-
   Before this change, "ls -Li dangling-symlink" would mistakenly
   print the inode number of the symlink under some conditions.
 
+  ls -Ls is now consistent with ls -Lsl in printing "?", not "0" as the
+  allocated size 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 801e717..30df92c 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -4016,8 +4016,9 @@ print_file_name_and_frills (const struct fileinfo *f, size_t start_col)
 
   if (print_block_size)
 printf ("%*s ", format == with_commas ? 0 : block_size_width,
-human_readable (ST_NBLOCKS (f->stat), buf, human_output_opts,
-ST_NBLOCKSIZE, output_block_size));
+! f->stat_ok ? "?"
+: human_readable (ST_NBLOCKS (f->stat), buf, human_output_opts,
+  ST_NBLOCKSIZE, output_block_size));
 
   if (print_scontext)
 printf ("%*s ", format == with_commas ? 0 : scontext_width, f->scontext);
@@ -4234,9 +4235,10 @@ length_of_file_name_and_frills (const struct fileinfo *f)
 
   if (print_block_size)
 len += 1 + (format == with_commas
-? strlen (human_readable (ST_NBLOCKS (f->stat), buf,
-  human_output_opts, ST_NBLOCKSIZE,
-  output_block_size))
+? strlen (! f->stat_ok ? "?"
+  : human_readable (ST_NBLOCKS (f->stat), buf,
+human_output_opts, ST_NBLOCKSIZE,
+output_block_size))
 : block_size_width);
 
   if (print_scontext)
diff --git a/tests/ls/dangle b/tests/ls/dangle
index 6abad92..687d3df 100755
--- a/tests/ls/dangle
+++ b/tests/ls/dangle
@@ -28,7 +28,8 @@ 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
+printf '? dangle\n' > subdir_Li_exp || framework_failure
+printf 'total 0\n? dangle\n' > subdir_Ls_exp || framework_failure
 
 fail=0
 
@@ -56,6 +57,11 @@ 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
+compare out subdir_Li_exp || fail=1
+
+# Ensure that ls -Ls prints "?" as the allocation of a dangling symlink.
+rm -f out
+ls -Ls d > out 2>/dev/null && fail=1
+compare out subdir_Ls_exp || fail=1
 
 Exit $fail
-- 
1.6.2.5



Re: [PATCH] ls: don't use an undefined struct stat after failed stat/lstat

2009-09-29 Thread Jim Meyering
Eric Blake wrote:
> According to Jim Meyering on 9/29/2009 5:13 AM:
>> -  /* The failed stat/lstat may have modified f->stat.  Clear it,
>> - since we may use at least its st_ino member, e.g.,
>> - when trying to print the inode of dangling symlink:
>> - mkdir d; ln -s no-such d/s; ls -Li d  */
>> -  memset (&f->stat, 0, sizeof (f->stat));
>> +  f->stat.st_ino = 22;
>
> Why 22?  Is this debugging leftovers?

Thanks for the review.
BTW, here's the merged version:

>From b7aaa0da8b47f4f373d3e0876bd540986278c6e2 Mon Sep 17 00:00:00 2001
From: Jim Meyering 
Date: Tue, 29 Sep 2009 07:28:01 +0200
Subject: [PATCH] ls: don't use an undefined struct stat after failed stat/lstat
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* src/ls.c (format_inode): Access f->stat only if f->stat_ok is set.
* NEWS (Bug fixes): Mention it.
Improved-by: Pádraig Brady 
---
 NEWS |4 
 src/ls.c |6 +++---
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/NEWS b/NEWS
index 68ac24b..075c0fa 100644
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,10 @@ GNU coreutils NEWS-*- 
outline -*-
   ls -Li is now consistent with ls -Lil in printing "?", not "0" as the
   inode of a dangling symlink.

+  ls -Li no longer relies on unspecified behavior of stat/lstat.
+  Before this change, "ls -Li dangling-symlink" would mistakenly
+  print the inode number of the symlink under some conditions.
+
 ** Portability

   On Solaris 9, many commands would mistakenly treat file/ the same as
diff --git a/src/ls.c b/src/ls.c
index c8e8abb..801e717 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -3563,9 +3563,9 @@ 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));
+  return (f->stat_ok && f->stat.st_ino != NOT_AN_INODE_NUMBER
+  ? umaxtostr (f->stat.st_ino, buf)
+  : (char *) "?");
 }

 /* Print information about F in long format.  */
--
1.6.5.rc2.177.ga9dd6




Re: [PATCH] ls: don't use an undefined struct stat after failed stat/lstat

2009-09-29 Thread Jim Meyering
Eric Blake wrote:

> According to Jim Meyering on 9/29/2009 5:13 AM:
>> -  /* The failed stat/lstat may have modified f->stat.  Clear it,
>> - since we may use at least its st_ino member, e.g.,
>> - when trying to print the inode of dangling symlink:
>> - mkdir d; ln -s no-such d/s; ls -Li d  */
>> -  memset (&f->stat, 0, sizeof (f->stat));
>> +  f->stat.st_ino = 22;
>
> Why 22?  Is this debugging leftovers?

haha, yes.  Thanks ;-)




Re: [PATCH] ls: don't use an undefined struct stat after failed stat/lstat

2009-09-29 Thread Eric Blake
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

According to Jim Meyering on 9/29/2009 5:13 AM:
> -  /* The failed stat/lstat may have modified f->stat.  Clear it,
> - since we may use at least its st_ino member, e.g.,
> - when trying to print the inode of dangling symlink:
> - mkdir d; ln -s no-such d/s; ls -Li d  */
> -  memset (&f->stat, 0, sizeof (f->stat));
> +  f->stat.st_ino = 22;

Why 22?  Is this debugging leftovers?

- --
Don't work too hard, make some time for fun as well!

Eric Blake e...@byu.net
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.9 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkrB8f4ACgkQ84KuGfSFAYAh0ACgrKtuS+Eg9QMsjOQAa2LrMWAm
XkQAn2rHcJzA1p22poZd0kviMH0dbKWH
=hb9Q
-END PGP SIGNATURE-




Re: [PATCH] ls: don't use an undefined struct stat after failed stat/lstat

2009-09-29 Thread Jim Meyering
Pádraig Brady wrote:

> Jim Meyering wrote:
>> Nearly missed this one.
>> ls initializes a struct stat to all NUL bytes.
>> It calls stat or lstat on a dangling symlink, and that fails.
>> ls then tests stat.st_ino.
>>
>> Sometimes, it's 0, but sometimes it's the inode of the symlink,
>> possibly depending on how the package was configured/built or
>> the environment.
>> I haven't determined precisely what makes the difference,
>> but ls (from coreutils-7.6) built some way prints 0 as the inode
>> number, and other ways, it prints the inode of the dangling symlink.
>>
>>
>>>From f7db178fdff1ebb113841035b55b103e074b5f6f Mon Sep 17 00:00:00 2001
>> From: Jim Meyering 
>> Date: Tue, 29 Sep 2009 07:28:01 +0200
>> Subject: [PATCH] ls: don't use an undefined struct stat after failed 
>> stat/lstat
>>
>> * src/ls.c (gobble_file): After a failed stat/lstat call,
>> clear the f->stat buffer, since the syscall may have modified it,
>> and we may need to know that stat.st_ino is zero.
>
> Well spotted. By the same token is this useful?

Well spotted yourself!
I should have remembered to use the stat_ok member.

I'll merge something like this into my patch.

Thanks!

diff --git a/src/ls.c b/src/ls.c
index dc2f86e..03ef9b0 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -2777,11 +2777,7 @@ gobble_file (char const *name, enum filetype type, ino_t 
inode,

   if (err != 0)
 {
-  /* The failed stat/lstat may have modified f->stat.  Clear it,
- since we may use at least its st_ino member, e.g.,
- when trying to print the inode of dangling symlink:
- mkdir d; ln -s no-such d/s; ls -Li d  */
-  memset (&f->stat, 0, sizeof (f->stat));
+  f->stat.st_ino = 22;

   /* Failure to stat a command line argument leads to
  an exit status of 2.  For other files, stat failure
@@ -3569,9 +3565,9 @@ 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));
+  return (f->stat_ok && f->stat.st_ino != NOT_AN_INODE_NUMBER
+  ? umaxtostr (f->stat.st_ino, buf)
+  : (char *) "?");
 }

 /* Print information about F in long format.  */




Re: [PATCH] ls: don't use an undefined struct stat after failed stat/lstat

2009-09-29 Thread Pádraig Brady
Jim Meyering wrote:
> Nearly missed this one.
> ls initializes a struct stat to all NUL bytes.
> It calls stat or lstat on a dangling symlink, and that fails.
> ls then tests stat.st_ino.
> 
> Sometimes, it's 0, but sometimes it's the inode of the symlink,
> possibly depending on how the package was configured/built or
> the environment.
> I haven't determined precisely what makes the difference,
> but ls (from coreutils-7.6) built some way prints 0 as the inode
> number, and other ways, it prints the inode of the dangling symlink.
> 
> 
>>From f7db178fdff1ebb113841035b55b103e074b5f6f Mon Sep 17 00:00:00 2001
> From: Jim Meyering 
> Date: Tue, 29 Sep 2009 07:28:01 +0200
> Subject: [PATCH] ls: don't use an undefined struct stat after failed 
> stat/lstat
> 
> * src/ls.c (gobble_file): After a failed stat/lstat call,
> clear the f->stat buffer, since the syscall may have modified it,
> and we may need to know that stat.st_ino is zero.

Well spotted. By the same token is this useful?

diff --git a/src/ls.c b/src/ls.c
index 4531b94..fe51bb8 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -4001,8 +4001,9 @@ print_file_name_and_frills (const struct fileinfo *f, 
size_t start_col)

   if (print_block_size)
 printf ("%*s ", format == with_commas ? 0 : block_size_width,
-human_readable (ST_NBLOCKS (f->stat), buf, human_output_opts,
-ST_NBLOCKSIZE, output_block_size));
+! f->stat_ok ? "?"
+: human_readable (ST_NBLOCKS (f->stat), buf, human_output_opts,
+  ST_NBLOCKSIZE, output_block_size));

   if (print_scontext)
 printf ("%*s ", format == with_commas ? 0 : scontext_width, f->scontext);
@@ -4219,9 +4220,10 @@ length_of_file_name_and_frills (const struct fileinfo *f)

   if (print_block_size)
 len += 1 + (format == with_commas
-? strlen (human_readable (ST_NBLOCKS (f->stat), buf,
-  human_output_opts, ST_NBLOCKSIZE,
-  output_block_size))
+? strlen (! f->stat_ok ? "?"
+  : human_readable (ST_NBLOCKS (f->stat), buf,
+human_output_opts, ST_NBLOCKSIZE,
+output_block_size))
 : block_size_width);

   if (print_scontext)






[PATCH] ls: don't use an undefined struct stat after failed stat/lstat

2009-09-29 Thread Jim Meyering
Nearly missed this one.
ls initializes a struct stat to all NUL bytes.
It calls stat or lstat on a dangling symlink, and that fails.
ls then tests stat.st_ino.

Sometimes, it's 0, but sometimes it's the inode of the symlink,
possibly depending on how the package was configured/built or
the environment.
I haven't determined precisely what makes the difference,
but ls (from coreutils-7.6) built some way prints 0 as the inode
number, and other ways, it prints the inode of the dangling symlink.


>From f7db178fdff1ebb113841035b55b103e074b5f6f Mon Sep 17 00:00:00 2001
From: Jim Meyering 
Date: Tue, 29 Sep 2009 07:28:01 +0200
Subject: [PATCH] ls: don't use an undefined struct stat after failed stat/lstat

* src/ls.c (gobble_file): After a failed stat/lstat call,
clear the f->stat buffer, since the syscall may have modified it,
and we may need to know that stat.st_ino is zero.
* NEWS (Bug fixes): Mention it.
---
 NEWS |4 
 src/ls.c |6 ++
 2 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/NEWS b/NEWS
index 1a0c847..d5270c8 100644
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,10 @@ GNU coreutils NEWS-*- 
outline -*-
 ls: cannot access d/s: No such file or directory
 ? s

+  ls -Li no longer relies on unspecified behavior of stat/lstat.
+  Before this change, "ls -Li dangling-symlink" would mistakenly
+  print the inode number of the symlink under some conditions.
+
 ** Portability

   On Solaris 9, many commands would mistakenly treat file/ the same as
diff --git a/src/ls.c b/src/ls.c
index c8e8abb..dc2f86e 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -2777,6 +2777,12 @@ gobble_file (char const *name, enum filetype type, ino_t 
inode,

   if (err != 0)
 {
+  /* The failed stat/lstat may have modified f->stat.  Clear it,
+ since we may use at least its st_ino member, e.g.,
+ when trying to print the inode of dangling symlink:
+ mkdir d; ln -s no-such d/s; ls -Li d  */
+  memset (&f->stat, 0, sizeof (f->stat));
+
   /* Failure to stat a command line argument leads to
  an exit status of 2.  For other files, stat failure
  provokes an exit status of 1.  */
--
1.6.5.rc2.177.ga9dd6