ID: 48746 Updated by: j...@php.net Reported By: ddkees at illinois dot edu -Status: Open +Status: Assigned -Bug Type: *Directory/Filesystem functions +Bug Type: Directory function related Operating System: Windows Server 2003 PHP Version: 5.3.0 Assigned To: pajoye
Previous Comments: ------------------------------------------------------------------------ [2009-06-30 20:30:47] dr dot e dot sheppard at web dot de This bug can easily be reproduced with the following scenario: - change to a directory within your webserver's document root - create a junction named "apps" pointing to the desired target within the directory tree - calling a php file (residing in parallel to the "apps" folder) with the following code: if(file_exists('./apps') === true){ echo 'yes!'; } else { echo 'no!'; } The result will be "no!". ------------------------------------------------------------------------ [2009-06-30 19:10:21] ddkees at illinois dot edu The file structure looks like this. Junction points are followed by an asterisk; that asterisk is _not_ a part of the folder's name within the filesystem. / /includes /includes/classes* /includes/classes/.SwiftMailer /includes/classes/course_websites /includes/classes/directory /includes/classes/faculty_awards* /includes/classes/FirePHP There are more folders than what's listed above, but that's enough to give you the idea, I hope. If not, let me know. As you can see from the code example above, we start the process in /includes/classes and look for folders/files to identify class definitions to include. Using this code and 5.3.0 this morning, we found that, using the above list, only the faculty_awards junction point would be identified as a directory when using is_dir() and when using DirectoryIterator::isDir(). Here's a script to show what fails: function find_directories($directory) { $files = new DirectoryIterator($directory); foreach($files as $file) { if($file->isDot() || $file->getFilename()=="_notes") continue; echo "Analyzing: $file<br>"; var_dump($file->isDir()); echo "Analysis Complete.<br><br>"; } } --- If we execute that function as follows: find_directories($_SERVER["DOCUMENT_ROOT"] . "/includes/classes"); We would expect that all of the information listed above would result in true. However, the actual results of that test were: Analyzing: .SwiftMailer bool(false) Analysis Complete Analyzing: course_websites bool(false) Analysis Complete Analyzing: directories bool(false) Analysis Complete Analyzing: faculty_awards bool(true) Analysis Complete Analyzing: FirePHP bool(false) Analysis Complete ------------------------------------------------------------------------ [2009-06-30 17:58:46] paj...@php.net Please provide a simple example to show what exactly does not work, which function or method exactly and using which path: - describe the directory tree you use and which parts of it are junction - provide a simple script to show which function(s) fail(s) ------------------------------------------------------------------------ [2009-06-30 17:35:59] ddkees at illinois dot edu It should be noted, that using 5.2.9-1 works exactly as expected. ------------------------------------------------------------------------ [2009-06-30 17:19:27] ddkees at illinois dot edu Description: ------------ After updating this morning (June 30) to 5.3.0, our __autoload() function failed to identify any classes located in subfolders of the windows Junction Point which contains our class files. Our __autoload() function is recursive, descending into the filesystem looking for class files which match the one that we're trying to load. However, since the /includes/classes folder is a Junction Point, only other Junction Points return true when we use both is_dir() and DirectoryIterator::isDir() to try and identify folders from files. DirectoryIterator::isLink() also returns false. However, if we change our __autoloader() to include files from the source of the Junction Point, it works as expected, but this is only a solution for a sub-set of the sites that are available on our server. Reproduce code: --------------- function __autoload($class) { if(!function_exists("find_file")) { function find_file($directory, $target) { $dir = opendir($directory); while(($file = readdir($dir))!==false) { if($file == "_notes" || substr($file, 0, 1)==".") continue; if(is_dir($directory . "/" . $file)) find_file($directory . "/" . $file, $target); elseif(basename($file, ".php") == $target) { require_once($directory . "/" . $file); return; } } } } find_file($_SERVER['DOCUMENT_ROOT'] . "includes/classes", strtolower($class)); } Expected result: ---------------- The expected result is that starting from $_SERVER["DOCUMENT_ROOt"] . "/includes/classes" we identify folders and descend into them to look for a file named $class.php where $class is the parameter sent to __autoload(). When that file is found, it's included. Actual result: -------------- No folders are actually traversed, either when using the code above or when altering it to use the DirectoryIteratory SPL object. All non-Junction Points return false from is_dir() and, as a result, they are never traversed and the system will also attempt to include them as files if the elseif-conditional evaluates to true. ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=48746&edit=1