bug-tar
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Bug-tar] tar-1.25: test 39 fails on FreeBSD


From: Paul Eggert
Subject: Re: [Bug-tar] tar-1.25: test 39 fails on FreeBSD
Date: Mon, 22 Nov 2010 14:49:31 -0800
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.15) Gecko/20101027 Thunderbird/3.0.10

On 11/22/10 13:05, Christian Weisgerber wrote:
> On FreeBSD 7.3, test #39 "extract over symlinks" fails.  Specifically,
> it's this snippet of extrac13
> 
>   ln -s target1 dst2/file1
>   echo target1 >dst2/target1
>   tar --overwrite -xf archive.tar -C dst2 --warning=no-timestamp
> 
> that errors out:
> 
>   tar: ./file1: Cannot open: Too many links
> 
> ktrace shows that an open() call with O_NOFOLLOW set fails...
> 
>  44351 tar      CALL  
> open(0x800c1b100,O_WRONLY|O_NONBLOCK|O_NOFOLLOW|O_CREAT|O_TRUNC|O_NOCTTY,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
>  44351 tar      NAMI  "./file1"
>  44351 tar      RET   open -1 errno 31 Too many links
> 
> ... and tar proceeds to the error message.  This open() behavior
> is expected, so I'm unclear what GNU tar expects.

The open() behavior is indeed fine.  What's probably busted is
the stuff that happens after open() fails.

If I understand things correctly, src/extract.c's extract_file
is invoking open_output_file, which returns -1 with errno==ELOOP.
extract_file then should invoke:

   maybe_recoverable ("./file1", true, &interdir_made)

maybe_recoverable should execute this code:

    if (*interdir_made)
      return RECOVER_NO;

    switch (e)
      {
      case ELOOP:
        if (! regular
            || old_files_option != OVERWRITE_OLD_FILES || dereference_option)
          break;
        if (strchr (file_name, '/'))
          {
            if (deref_stat (file_name, &st) != 0)
              break;
            stp = &st;
          }

*interdir_made should be false, and regular should be true, and
old_files_option should be OVERWRITE_OLD_FILES, and dereference_option
should be false, so this should invoke

     deref_stat ("./file1", &st)

which should in turn invoke

     fstatat (7, "./file1", &st, AT_SYMLINK_NOFOLLOW)

(or some file descriptor other than 7),
which should eventually invoke the equivalent of

     lstat ("./file1", &st)

but your ktrace output doesn't show any such lstat.

My guess is that the problem occurs somewhere between the call
to fstatat and the call to lstat.  Perhaps "configure" thought
that fstatat works on your host, but it doesn't.

Can you fire up a debugger and see where my analysis went wrong?



reply via email to

[Prev in Thread] Current Thread [Next in Thread]