|   | php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | 
| 
  [2015-11-19 18:01 UTC] emanuele at fondani dot it
 Description:
------------
fopen() function cannot access files whose path is more than 258 characters long.
Test script:
---------------
<?php
// Generates a sample file whose path is exactly 259 characters long
$testFile = __DIR__."\\".str_repeat("a", 254 - strlen(__DIR__)).".dat";
echo "Generating a file with a path length of ".strlen($testFile)." characters...\r\n";
touch($testFile);
echo "Opening file... ";
if ($fp = fopen($testFile, "r")) {
  fclose($fp);
  echo "OK";
}
Expected result:
----------------
Generating a file with a path length of 259 characters...
Opening file... OK
Actual result:
--------------
Generating a file with a path length of 259 characters...
Opening file... 
Warning: fopen(S:\Emanuele\Temp\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.dat): failed to open stream: Invalid argument in test.php on line 8
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits             | |||||||||||||||||||||||||||||||||||||
|  Copyright © 2001-2025 The PHP Group All rights reserved. | Last updated: Thu Oct 30 23:00:01 2025 UTC | 
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)