[Toybox] ls -l broken
Rob Landley
rob at landley.net
Sat Nov 23 03:14:18 PST 2019
On 11/20/19 11:52 PM, enh wrote:
> On Wed, Nov 20, 2019 at 9:44 PM Rob Landley <rob at landley.net> wrote:
>> I don't understand why you moved this test:
>>
>> + sym = AT_SYMLINK_NOFOLLOW*!(flags&DIRTREE_SYMFOLLOW), okay = 1;
>>
>> // stat dangling symlinks
>> if (fstatat(fd, name, &st, sym)) {
>> - if (errno != ENOENT
>> - || (!sym && fstatat(fd, name, &st, AT_SYMLINK_NOFOLLOW)))
>> - {
>> - if (flags&DIRTREE_STATLESS) statless++;
>> - else goto error;
>> - }
>> + okay = (errno == ENOENT && !sym &&
>> + !fstatat(fd, name, &st, AT_SYMLINK_NOFOLLOW));
>> + }
>> + if (!okay) {
>> + if (flags&DIRTREE_STATLESS) statless++;
>> + else goto error;
>> }
>>
>> If "okay" can only be zeroed when we go into the first fstatat()'s if() block,
>> what does moving the test to after the block accomplish? You don't use "okay"
>> again outside that stanza...
>
> the point is that before the ls case where the first fstatat fails
> couldn't fall through to the statless++/goto error block.
You only set statless++ when the first fstatat() fails. There's nothing for it
to "fall through" for when the first fstatat() didn't fail.
This is expressed in your new logic too: okay = 1; if (false) {not entered;};
if (!okay) {can never be reached.}
What did moving it down accomplish?
> so that
> needed to move out, and then you need a way to tell how you got there.
> (otherwise you _either_ fail the find tests
The find tests are all passing with (or without) the simpler fix?
> _or_ you fail the [fixed] ls tests.)
I'm confused by "fixed" here: you switch the test from looking for the word
"missing" to the word "non-existent" and on debian TEST_HOST the error message is:
$ ls does-not-exist
ls: cannot access 'does-not-exist': No such file or directory
"A strange game. The only winning move is not to play." - Wargames
I did this:
-testing "missing" "$IN && ls does-not-exist 2>err ; grep -q 'ls:.*missing.*: No
-such file' err || echo missing error; $OUT" "" "" ""
+testing "missing" "$IN && ls does-not-exist 2>&1 >/dev/null | grep -o
does-not-exist; $OUT" "does-not-exist\n" "" ""
But the problem is I'm not reproducing your issue _without_ changes to
lib/dirtree.c:
$ ./ls missing
ls: missing: No such file or directory
$ echo $/
1
It wasn't failing for me before? How do I reproduce the failure?
>> Let's see, old test:
>>
>> if (errno != ENOENT || (!sym && fstatat()))
>>
>> was effectively replaced with:
>>
>> if (!(errno == ENOENT && !sym && !fstatat()))
>>
>> But a straight inversion of the first test would be...
>>
>> if (!(errno == ENOENT && (sym || !fstatat())))
>>
>> So it _looks_ like the fix you applied is basically just changing the existing
>> test to:
>>
>> if (errno != ENOENT || sym || fstatat())
>
> no, the important part is moving the statless++/goto error part out
> far enough that you can get to it whether or not you do a second
> fstatat.
But it never triggers if you didn't go into the first if() block.
> the currently checked in code just carries on with an uninitialized struct stat.
Hmmm, uninitialized value being used. That would be a potential bug I couldn't
necessarily reproduce, yes. Let's see...
Ah! If the first stat fails but sym was set, we don't do the second attempt and
that _also_ skips the else goto error. Yeah, that's a bug.
Try now?
Rob
More information about the Toybox
mailing list