Edit report at https://bugs.php.net/bug.php?id=45040&edit=1
ID: 45040
Comment by: 7eggert at gmx dot de
Reported by: ntang at communityconnect dot com
Summary: 64 bit inode stat fails without LFS flags (ex:
recursive mkdir)
Status: Verified
Type: Bug
Package: Filesystem function related
Operating System: Linux
PHP Version: 5.*, 6CVS (2009-04-30)
Block user comment: N
Private report: N
New Comment:
Congratulations to the most recent aniversary of this bug, it seems to have survived till 7.3.10.
Previous Comments:
------------------------------------------------------------------------
[2017-03-17 22:55:36] pollita@php.net
Related To: Bug #65445
------------------------------------------------------------------------
[2009-04-30 19:46:16] jani@php.net
See also bug #27792
------------------------------------------------------------------------
[2009-04-30 19:44:03] jani@php.net
Confirmed that using LFS flags fixes this. See also bug #48099 in which
this was tested and confirmed to work.
However, LFS support requires a bit more fixes than just a compile
flags..
------------------------------------------------------------------------
[2008-05-19 19:58:17] ntang at communityconnect dot com
Description:
------------
Using a filesystem w/ 64 bit inodes fails on Linux. Functions that require stat'ing files
(such as a recursive mkdir) fail - even when stat64 returns a 0 it overflows and sees it as
non-existant... the end result is that if directory /x/y/z exists on a filesystem w/ 64 bit inodes,
and you do a recursive mkdir of /x/y/z/a/b/c, c b and a will all return "does not exist"
properly, but then it will keep going past z and y and try to create x (at which point it returns an
error saying that x already exists).
What we found from testing and then googling, is that after you include <stdio.h>, you need to
add this define for 64 bit inodes to be recognized by the gnu libraries:
#define __USE_FILE_OFFSET64
Here's some c code to test, you can run it with and without the define to see what happens:
#include <stdio.h>
#define __USE_FILE_OFFSET64
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/statvfs.h>
int main(int argc, char** argv)
{
struct stat buf;
if (stat(argv[1], &buf) != 0)
{
printf("stat failed!\n");
return 2;
}
printf("inode is %llu\n", buf.st_ino);
return 0;
}
Long story short: the define above needs to be baked into PHP anytime it makes filesystem calls (or
at least be added as a flag as a compile-time option for ./configure).
Reproduce code:
---------------
To test:
#!/usr/local/bin/php
<?php
mkdir('/mnt/test/blarg/bagga/booga/zim/zam/zoo',0755,true);
?>
Expected result:
----------------
It should create /mnt/test/blarg/bagga/booga/zim/zam/zoo.
Actual result:
--------------
It doesn't create the directory. Note that even when stat64 succeeds and returns 0, it still
keeps going.
stat64("/mnt/test/blarg/bagga/booga/zim/zam", 0xbff6f2f0) = -1 ENOENT (No such file or
directory)
write(2, "stat(\"/mnt/test/blarg/bagga/boog"...,
49stat("/mnt/test/blarg/bagga/booga/zim/zam") = -1
) = 49
stat64("/mnt/test/blarg/bagga/booga/zim", 0xbff6f2f0) = -1 ENOENT (No such file or
directory)
write(2, "stat(\"/mnt/test/blarg/bagga/boog"...,
45stat("/mnt/test/blarg/bagga/booga/zim") = -1
) = 45
stat64("/mnt/test/blarg/bagga/booga", 0xbff6f2f0) = -1 ENOENT (No such file or directory)
write(2, "stat(\"/mnt/test/blarg/bagga/boog"...,
41stat("/mnt/test/blarg/bagga/booga") = -1
) = 41
stat64("/mnt/test/blarg/bagga", 0xbff6f2f0) = -1 ENOENT (No such file or directory)
write(2, "stat(\"/mnt/test/blarg/bagga\") = "...,
35stat("/mnt/test/blarg/bagga") = -1
) = 35
stat64("/mnt/test/blarg", 0xbff6f2f0) = -1 ENOENT (No such file or directory)
write(2, "stat(\"/mnt/test/blarg\") = -1\n", 29stat("/mnt/test/blarg")
= -1
) = 29
stat64("/mnt/test", {st_dev=makedev(0, 54), st_ino=4294967298, st_mode=S_IFDIR|0755,
st_nlink=19, st_uid=99, st_gid=98, st_blksize=4096, st_blocks=8, st_size=4096,
st_atime=2008/05/16-18:10:05, st_mtime=2008/05/16-17:20:29, st_ctime=2008/05/16-17:20:29}) = 0
write(2, "stat(\"/mnt/test\") = -1\n", 23stat("/mnt/test") = -1
) = 23
stat64("/mnt", {st_dev=makedev(8, 7), st_ino=98306, st_mode=S_IFDIR|0755, st_nlink=5,
st_uid=0, st_gid=0, st_blksize=4096, st_blocks=16, st_size=4096, st_atime=2008/05/16-18:10:03,
st_mtime=2008/05/16-16:55:20, st_ctime=2008/05/16-16:55:20}) = 0
write(2, "stat(\"/mnt\") = 0\n", 17stat("/mnt") = 0
) = 17
mkdir("/mnt/test", 0755) = -1 EEXIST (File exists)
write(1, "\nWarning: mkdir(): File exists i"..., 57
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=45040&edit=1