Bug #70943 [Com]: fopen() can't open a file if path is 259 characters long

[email protected] ("emanuele at fondani dot it")
Newsgroups php.bugs
Message-ID <[email protected]>
Edit report at https://bugs.php.net/bug.php?id=70943&edit=1

 ID:                 70943
 Comment by:         emanuele at fondani dot it
 Reported by:        emanuele at fondani dot it
 Summary:            fopen() can't open a file if path is 259 characters
                     long
 Status:             Open
 Type:               Bug
 Package:            Filesystem function related
 Operating System:   Windows 10
 PHP Version:        5.6.15
 Block user comment: N
 Private report:     N

 New Comment:

I think it's a bug because, as noted by webmaster at tubo-world dot de, for files with a path of 259 characters, there is an inconsistent behaviour among different php file functions. Some support it and some don't.
Anyway, path lengths of 259 characters (260, including null terminator) should be supported on Windows, as they are within the allowed maximum path length.


Previous Comments:
------------------------------------------------------------------------
[2015-12-19 01:39:22] [email protected]

I'm wondering if this is more a request than a bug. The current behaviour is not wrong per se, it's just a limitation of the specific Windows APIs in use.

------------------------------------------------------------------------
[2015-12-19 01:08:17] webmaster at tubo-world dot de

I confirm the problem and investigated which filesystem functions work with different lengths of filenames. In theory filesnames up to 259 length should work on Windows as it is below the 260 MAX_PATH length (including terminating null char). I could find out that some functions work with length 259 (touch, rename, file_exists etc), while other functions fail (copy, fopen, realpath, file_put_contents) for the same filename. So for these functions PHP does seem to do something inconsistently in a bad way which causes hard to debug problems.


Test script:
------------
<?php

$tmpDir = sys_get_temp_dir() . DIRECTORY_SEPARATOR;
$tmpDirLen = strlen($tmpDir);

foreach (array(258, 259, 260) as $fileLen) {
    $filename = $tmpDir . str_repeat('a', $fileLen - $tmpDirLen);
    var_dump($filename);

    echo 'touch: ';
    var_dump(@touch($filename));

    echo 'chmod: ';
    var_dump(@chmod($filename, 0666));

    echo 'file_exists: ';
    var_dump(file_exists($filename));

    echo 'is_file: ';
    var_dump(is_file($filename));

    echo 'stat: ';
    var_dump(@stat($filename) ? true : false);

    echo 'realpath: ';
    var_dump(realpath($filename) ? true : false);

    echo 'fopen: ';
    var_dump(($handle = @fopen($filename, 'r')) ? true : false);

    if ($handle) {
        fclose($handle);
    }

    echo 'unlink: ';
    var_dump(@unlink($filename));

    $tmpFile = tempnam(sys_get_temp_dir(), 'tmp');

    echo 'copy: ';
    var_dump(@copy($tmpFile, $filename));

    echo 'file_put_contents: ';
    var_dump(@file_put_contents($filename, 'test data') ? true : false);

    echo 'rename: ';
    var_dump($rename = @rename($tmpFile, $filename));

    unlink($rename ? $filename : $tmpFile);

    echo "\n\n";
}


Expected result:
----------------

string(258) "..."
touch: bool(true)
chmod: bool(true)
file_exists: bool(true)
is_file: bool(true)
stat: bool(true)
realpath: bool(true)
fopen: bool(true)
unlink: bool(true)
copy: bool(true)
file_put_contents: bool(true)
rename: bool(true)


string(259) "..."
touch: bool(true)
chmod: bool(true)
file_exists: bool(true)
is_file: bool(true)
stat: bool(true)
realpath: bool(true)
fopen: bool(true)
unlink: bool(true)
copy: bool(true)
file_put_contents: bool(true)
rename: bool(true)


string(260) "..."
touch: bool(false)
chmod: bool(false)
file_exists: bool(false)
is_file: bool(false)
stat: bool(false)
realpath: bool(false)
fopen: bool(false)
unlink: bool(false)
copy: bool(false)
file_put_contents: bool(false)
rename: bool(false)


Actual result:
--------------

string(258) "..."
touch: bool(true)
chmod: bool(true)
file_exists: bool(true)
is_file: bool(true)
stat: bool(true)
realpath: bool(true)
fopen: bool(true)
unlink: bool(true)
copy: bool(true)
file_put_contents: bool(true)
rename: bool(true)


string(259) "..."
touch: bool(true)
chmod: bool(true)
file_exists: bool(true)
is_file: bool(true)
stat: bool(true)
realpath: bool(false)
fopen: bool(false)
unlink: bool(true)
copy: bool(false)
file_put_contents: bool(false)
rename: bool(true)


string(260) "..."
touch: bool(false)
chmod: bool(false)
file_exists: bool(false)
is_file: bool(false)
stat: bool(false)
realpath: bool(false)
fopen: bool(false)
unlink: bool(false)
copy: bool(false)
file_put_contents: bool(false)
rename: bool(false)

------------------------------------------------------------------------
[2015-12-18 22:43:46] nathanael at gnat dot ca

I have the same problem on Windows Server 2008, php 5.6.16

------------------------------------------------------------------------
[2015-12-08 07:58:30] a dot ehrsam at hotmail dot com

I think we have the following limitation of Windows: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath . This has been a discussion for .NET as well: https://github.com/dotnet/corefx/issues/645

------------------------------------------------------------------------
[2015-12-08 06:52:45] [email protected]

Note: Most file systems support up to 255 chars for file names. Path length are unlimited mostly.

https://en.wikipedia.org/wiki/Comparison_of_file_systems

------------------------------------------------------------------------


The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at

    https://bugs.php.net/bug.php?id=70943


--
Edit this bug report at https://bugs.php.net/bug.php?id=70943&edit=1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.