We've run into something similar, and I think I can explain what's going
on. In our particular case, we're using pbuilder to build packages in a
chroot and we're seeing that fakeroot will very rarely start reporting
that a directory is a regular file. Once it starts it will often do so
for several runs, and then it will go back to working.
The culprit seems to be the statically linked ldconfig in the pbuilder
chroot which runs shortly before a mkdir. Since fakeroot can't wrap its
calls, ldconfig is able to call unlink without fakeroot updating its
database. Then the inodes of the unlinked files can be reused for new
files for which fakeroot will report out of date information.
In the most common failure we've seen, the inode that holds
/etc/ld.so.cache is noted by fakeroot when it's untarred and chowned,
then it's unlinked by ldconfig and the the same inode is given to a
subsequent mkdir in /etc, which then stats as a file when it's really a
directory. It's probably also possible for ldconfig to remove a symlink
and then have that inode reused for a regular file or directory later
on, but I haven't seen that happen.
Because it requires an inode be reused, it's difficult to reproduce
this. It may be more likely to happen on almost empty or almost full
filesystems. I've had luck reproducing it somewhat consistently in very
small loop mounts using the approach/hack pasted below.
I'm posting this under issue 414601 as it's closest to what we've seen,
but I believe 366067 and 425007 could have the same or similar
underlying cause and might warrant merging.
--------------
While fakerooted inside a chroot:
[EMAIL PROTECTED]:/# chmod 0644 /etc/ld.so.cache
[EMAIL PROTECTED]:/# stat /etc/ld.so.cache
File: `/etc/ld.so.cache'
Size: 9486 Blocks: 24 IO Block: 4096 regular file
Device: 700h/1792d Inode: 61120 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2008-09-08 15:28:10.000000000 -0400
Modify: 2008-09-08 15:27:42.000000000 -0400
Change: 2008-09-08 15:28:04.000000000 -0400
[EMAIL PROTECTED]:/# /sbin/ldconfig
[EMAIL PROTECTED]:/# stat /etc/ld.so.cache
File: `/etc/ld.so.cache'
Size: 9486 Blocks: 24 IO Block: 4096 regular file
Device: 700h/1792d Inode: 61076 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2008-09-08 15:28:41.000000000 -0400
Modify: 2008-09-08 15:28:20.000000000 -0400
Change: 2008-09-08 15:28:20.000000000 -0400
[EMAIL PROTECTED]:/# ./mkdirwithinode a 61120
trying for inode 61120
hit on try a4
[EMAIL PROTECTED]:/# stat a4
File: `a4'
Size: 4096 Blocks: 8 IO Block: 4096 regular file
Device: 700h/1792d Inode: 61120 Links: 2
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2008-09-08 15:28:52.000000000 -0400
Modify: 2008-09-08 15:28:52.000000000 -0400
Change: 2008-09-08 15:28:52.000000000 -0400
[EMAIL PROTECTED]:/# cd a4
[EMAIL PROTECTED]:/a4# ls
[EMAIL PROTECTED]:/a4# cd ..
[EMAIL PROTECTED]:/#
On that final stat, faked --debug prints:
FAKEROOT: r=56, received message type=1, message=3
FAKEROOT: process stat oldstate=dev:ino=(700:61120), mode=040755,
own=(10062,100), nlink=2, rdev=0
FAKEROOT: (previously known): fake=dev:ino=(700:61120), mode=0100755,
own=(0,0), nlink=2, rdev=0
Source of mkdirwithinode.c:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
if(argc != 3) return -1;
char *prefix = argv[1];
long inode = atol(argv[2]);
printf("trying for inode %d\n", inode);
char filename[100];
struct stat st;
for(int i = 0; i < 1000; i++) {
sprintf(filename, "%s%d", prefix, i);
mkdir(filename, 0777);
stat(filename, &st);
if(st.st_ino == inode) {
printf("hit on try %s%d\n", prefix, i);
return 0;
}
}
printf("failed\n");
return 1;
}
--
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]