Hi,

first, thanks to Daniel for the patch! I have exactly the same problem
with our automatic Apport crash bug retracers (which operate in a data
center where I don't have (and want) root). rm failures drove me up
the wall...

On amd64, rm seems to call __fxstat() instead of __fxstatat64(), so I
did a copy&paste of Daniel's __fxstatat64() wrapping (with struct
stat64 -> stat, of course), and now it works great again!

To demonstrate this easily, I modified the test script a bit:

--- fakechroot-2.6.orig/test/fakechroot.sh
+++ fakechroot-2.6/test/fakechroot.sh
@@ -32,6 +32,7 @@
     /bin/ls \
     /bin/pwd \
     /bin/sh \
+    /bin/rm \
     /usr/bin/id \
     /usr/bin/find \
     /usr/bin/perl \
@@ -63,5 +64,5 @@
 if [ -n "$*" ]; then
     HOME=/root /usr/sbin/chroot `pwd`/testtree "$@"
 else
-    HOME=/root /usr/sbin/chroot `pwd`/testtree /bin/sh
+    HOME=/root /usr/sbin/chroot `pwd`/testtree /bin/bash

Then this can be reproduced with

  strace -f ./fakechroot.sh sh -c 'echo hi > bin/foo; ls /bin/foo; rm /bin/foo'
[...]
[pid 29432] newfstatat(AT_FDCWD, "/bin/foo", 0x7fff9b659860, 
AT_SYMLINK_NOFOLLOW) = -1 ENOENT (No such file or directory)

With the patch applied, you get the correct

[pid  3699] newfstatat(AT_FDCWD, 
"/home/martin/ubuntu/fakechroot/fakechroot-2.6/test/testtree/bin/foo", 
{st_mode=S_IFREG|0644, st_size=3, ...}, AT_SYMLINK_NOFOLLOW) = 0
[...]
[pid  3699] unlinkat(AT_FDCWD, 
"/home/martin/ubuntu/fakechroot/fakechroot-2.6/test/testtree/bin/foo", 0) = 0

instead.

FYI, I attach the complete debdiff which I uploaded to Ubuntu.

Thanks,

Martin
-- 
Martin Pitt                        | http://www.piware.de
Ubuntu Developer (www.ubuntu.com)  | Debian Developer  (www.debian.org)
diff -u fakechroot-2.6/debian/changelog fakechroot-2.6/debian/changelog
--- fakechroot-2.6/debian/changelog
+++ fakechroot-2.6/debian/changelog
@@ -1,3 +1,14 @@
+fakechroot (2.6-1.3ubuntu1) intrepid; urgency=low
+
+  * src/libfakechroot.c: Provide wrapping of unlinkat(), __fxstatat(), and
+    __fxstatat64() to unbreak rm'ing absolute directories. This extends the
+    original patch from Daniel Kahn Gillmor in Debian #473682. Still
+    incomplete, since other *at() functions are still missing, but those are
+    the most pressing which cause the Apport retracers to fail so badly.
+  * test/fakechroot.sh: Add /bin/rm, and call bash instead of sh.
+
+ -- Martin Pitt <[EMAIL PROTECTED]>  Thu, 08 May 2008 20:45:48 +0200
+
 fakechroot (2.6-1.3) unstable; urgency=low
 
   * Non-maintainer upload to fix the fix for the fix for #422586
diff -u fakechroot-2.6/src/libfakechroot.c fakechroot-2.6/src/libfakechroot.c
--- fakechroot-2.6/src/libfakechroot.c
+++ fakechroot-2.6/src/libfakechroot.c
@@ -463,6 +463,9 @@
 static int     (*next_truncate64) (const char *path, off64_t length) = NULL;
 #endif
 static int     (*next_unlink) (const char *pathname) = NULL;
+static int     (*next_unlinkat) (int dirfd, const char *pathname, int flags) = 
NULL;
+static int     (*next___fxstatat) (int ver, int dirfd, const char *pathname, 
struct stat *buf, int flags) = NULL;
+static int     (*next___fxstatat64) (int ver, int dirfd, const char *pathname, 
struct stat64 *buf, int flags) = NULL;
 #ifdef HAVE_ULCKPWDF
 /* static int     (*next_ulckpwdf) (void) = NULL; */
 #endif
@@ -678,6 +681,9 @@
     nextsym(truncate64, "truncate64");
 #endif
     nextsym(unlink, "unlink");
+    nextsym(unlinkat, "unlinkat");
+    nextsym(__fxstatat, "__fxstatat");
+    nextsym(__fxstatat64, "__fxstatat64");
 #ifdef HAVE_ULCKPWDF
 /*    nextsym(ulckpwdf, "ulckpwdf"); */
 #endif
@@ -2222,6 +2228,31 @@
     return next_unlink(pathname);
 }
 
+/* #include <fcntl.h> */
+int unlinkat (int dirfd, const char *pathname, int flags)
+{
+    char *fakechroot_path, *fakechroot_ptr, fakechroot_buf[FAKECHROOT_MAXPATH];
+    expand_chroot_path(pathname, fakechroot_path, fakechroot_ptr, 
fakechroot_buf);
+    if (next_unlinkat == NULL) fakechroot_init();
+    return next_unlinkat(dirfd, pathname, flags);
+}
+
+/* #include <fcntl.h> */
+/* #include <sys/stat.h> */
+int __fxstatat (int ver, int dirfd, const char *pathname, struct stat *buf, 
int flags)
+{
+    char *fakechroot_path, *fakechroot_ptr, fakechroot_buf[FAKECHROOT_MAXPATH];
+    expand_chroot_path(pathname, fakechroot_path, fakechroot_ptr, 
fakechroot_buf);
+    if (next___fxstatat == NULL) fakechroot_init();
+    return next___fxstatat(ver, dirfd, pathname, buf, flags);
+}
+int __fxstatat64 (int ver, int dirfd, const char *pathname, struct stat64 
*buf, int flags)
+{
+    char *fakechroot_path, *fakechroot_ptr, fakechroot_buf[FAKECHROOT_MAXPATH];
+    expand_chroot_path(pathname, fakechroot_path, fakechroot_ptr, 
fakechroot_buf);
+    if (next___fxstatat64 == NULL) fakechroot_init();
+    return next___fxstatat64(ver, dirfd, pathname, buf, flags);
+}
 
 /* #include <sys/types.h> */
 /* #include <utime.h> */
only in patch2:
unchanged:
--- fakechroot-2.6.orig/test/fakechroot.sh
+++ fakechroot-2.6/test/fakechroot.sh
@@ -32,6 +32,7 @@
     /bin/ls \
     /bin/pwd \
     /bin/sh \
+    /bin/rm \
     /usr/bin/id \
     /usr/bin/find \
     /usr/bin/perl \
@@ -63,5 +64,5 @@
 if [ -n "$*" ]; then
     HOME=/root /usr/sbin/chroot `pwd`/testtree "$@"
 else
-    HOME=/root /usr/sbin/chroot `pwd`/testtree /bin/sh
+    HOME=/root /usr/sbin/chroot `pwd`/testtree /bin/bash
 fi

Attachment: signature.asc
Description: Digital signature

Reply via email to