Subject: Re: pax problem+fix
To: None <tech-userlevel@netbsd.org, tech-pkg@netbsd.org>
From: Hans Bulfone <jsb@atnet.at>
List: tech-pkg
Date: 06/21/2003 21:50:18
hi!
On Sat, Jun 21, 2003 at 01:29:48PM -0400, Jan Schaumann wrote:
> > I'm using pkgsrc (and therefore pax) on Linux and have found the following
> > problem:
> >
> > When installing the libxml2 package, the following command is executed:
> >
> > cd tutorial && $(PAX) -rwpppm . $(DESTDIR)$(TARGET_DIR)/tutorial
> >
> > As pax does not treat '.' specially, it checks if
> > $(DESTDIR)$(TARGET_DIR)/tutorial/. exists, which is the case, and
> > then tries to remove it.
>
> I'm not sure if I follow you here. How does pax not treat "." in a
> special way? Or rather, how should it? When I install libxml2, it
> performs the step you mentioned without any problems. It cd's into the
> 'tutorial' directory, then paxes everything from that directory ('.')
> into the other directory ('-rw'), preserving appropriate permissions and
> timestamps ('-pppm').
>
> Why should it try to remove a directory?
>
> Or am I missing something?
Maybe I was not clear enough:
The endless loop only occurs on Linux when the ext2 filesystem is used
(as far as I have tested). It is actually not a problem on *BSD.
For example, when pax is invoked as follows:
mkdir /root/test1 ; mkdir /root/test2 ; (create some files in test1)
cd /root/test1 ; pax -rwpppm . /root/test2
the following happens:
- in ar_subs.c:copy(), the first destination path is '/root/test2/.',
it is created using node_creat():
/*
* create a link or special file
*/
if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
res = lnk_creat(arcn);
else
res = node_creat(arcn);
- node_creat() tries to create the directory '/root/test2/.', but
it already exists:
mkdir("/root/test2/.", 0755) = -1 EEXIST (File exists)
- node_creat() calls unlnk_exist() to move the existing file
out of the way, which happens to be the destination
directory itself :(
rmdir("/root/test2/.") = 0
on *BSD, this call fails with an EINVAL error, but as
unlnk_exist checks if it had to remove a directory because
a directory has to be created, the error is not shown to
the user and the process continues normally.
on linux, the directory is removed.
- after this node_creat() tries again to create the directory:
mkdir("/root/test2/.", 0755) = -1 ENOENT (No such file or directory)
but it cannot be created using this path because test2
does not exist anymore.
- after failing for the 2nd time, node_creat() calls chk_path() to
create any missing parent directories:
lstat("/root", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat("/root/test2", 0xbfffda4c) = -1 ENOENT (No such file or directory)
mkdir("/root/test2", 0777) = 0
access("/root/test2", R_OK|W_OK|X_OK) = 0
- node_creat() tries again:
mkdir("/root/test2/.", 0755) = -1 EEXIST (File exists)
- from this point on, the process hangs in an endless loop.
in each iteration, the directory is first unlinked by calling
unlnk_exist() and then recreated using chk_path().
> P.S.: Should we move this thread to tech-pkg?
I've also wondered which of the two lists is more appropriate, as it's
only a problem when using pkgsrc on Linux, but I don't know since I'm
new to both :(
hans.