php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #45040 64 bit inode stat fails without LFS flags (ex: recursive mkdir)
Submitted: 2008-05-19 19:58 UTC Modified: 2009-04-30 19:46 UTC
Votes:9
Avg. Score:4.3 ± 0.8
Reproduced:7 of 7 (100.0%)
Same Version:3 (42.9%)
Same OS:3 (42.9%)
From: ntang at communityconnect dot com Assigned:
Status: Verified Package: Filesystem function related
PHP Version: 5.*, 6CVS (2009-04-30) OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: ntang at communityconnect dot com
New email:
PHP Version: OS:

 

 [2008-05-19 19:58 UTC] 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



Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-04-30 19:44 UTC] 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..
 [2009-04-30 19:46 UTC] jani@php.net
See also bug #27792
 [2019-11-08 11:39 UTC] 7eggert at gmx dot de
Congratulations to the most recent aniversary of this bug, it seems to have survived till 7.3.10.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Nov 22 00:01:30 2024 UTC