PHP / Windows - Opendir() fails opening subdirectories within symbolic linked directories - php

Does anyone know a solution to this problem? I'm unable to open a subdirectory within a symboliclink'd directory. I've confirmed that the paths are correct (even copy & pasted the path into explorer, which parsed it fine). This is a strange, annoying, bug :|.
Example:
C:\folder\symbolic_link\dir1\dir2 - opening dir2 fails.
C:\folder\symbolic_link\dir1 - works
C:\folder\real_directory\dir1\dir2 - works
C:\folder\real_directory\dir1 - works

Alright, I finally found a hack to solve this bug in php's handling of symlinks on windows. The bug occurs when recursively iterating through files/directories using opendir(). If a symlink to a directory exists in the current directory, opendir() will fail to read the directories in the directory symlink. It is caused by something funky in php's statcache, and can be resolved by calling clearstatcache() before calling opendir() on the directory symlink (also, the parent directory's file-handle must be closed).
Here is an example of the fix:
<?php
class Filesystem
{
public static function files($path, $stats = FALSE)
{
clearstatcache();
$ret = array();
$handle = opendir($path);
$files = array();
// Store files in directory, subdirectories can't be read until current handle is closed & statcache cleared.
while (FALSE !== ($file = readdir($handle)))
{
if ($file != '.' && $file != '..')
{
$files[] = $file;
}
}
// Handle _must_ be closed before statcache is cleared, cache from open handles won't be cleared!
closedir($handle);
foreach ($files as $file)
{
clearstatcache($path);
if (is_dir($path . '/' . $file))
{
$dir_files = self::files($path . '/' . $file);
foreach ($dir_files as $dir_file)
{
$ret[] = $file . '/' . $dir_file;
}
}
else if (is_file($path . '/' . $file))
{
$ret[] = $file;
}
}
return $ret;
}
}
var_dump(filessystem::files('c:\\some_path'));
Edit: It seems that clearstatcache($path) must be called before any file-handling functions on the symlink'd dir. Php isn't caching symlink'd dirs properly.

Related

How to detect folders names in a directory usinig php?

I need php to detect folder names in a directory on my computer not in the project directory in wamp server. i tried all the answers on
Using scandir() to find folders in a directory (PHP)
but it didn't work
it says the directory is not on the project directory when i tested scandir as in this code:
$path = 'extracted/' . $name[0];
$results = scandir($path);
foreach ($results as $result) {
if ($result === '.' or $result === '..') continue;
if (is_dir($path . '/' . $result)) {
//code to use if directory
}
}
I am trying this also but i got empty array
$path = 'D:\tests\Ed';
$folders=glob("{$path}/*");
print_r($folders);
the only way i could run the code is by putting the folder in the project directory ,
$path = 'C:\wamp\www\my project php\ED';
but is there another way?

Can't get scandir to scan root directory

I've tried every path I can think of.
''
'/'
'htdocs/'
No matter what I try, I cant figure out how to scan the root directory.
So, how do you do it?
Current Code:
function pathing(){
$files = scandir('/');
foreach ($files as $file) {
if ($file === '.' OR $file === '..') {
} else {
print_r($file . ' ');
}
}
}
I'm moving my comment to an answer in order to bring attention to the solution for others who stumble across this question.
The directory root location is accessible in the $_SERVER array.
$_SERVER['DOCUMENT_ROOT']

Finding broken symlinks using php

I'm writing a build/deploy script using a CLI php script.
Say I have a directory /environment and in it there are simply two broken symlinks.
I'm running glob(/environment/{,.}*). When I foreach over the glob, all I see are . and ... The symlinks never show up in the list.
How can you loop over a directory, detect broken symlinks, and unlink() them using PHP?
On a broken symlink is_link() returns true and file_exists() returns false.
Since glob() does not list broken symlinks, you have to list the contents in a different way.
Here is an example using scandir()
foreach(scandir($dir) as $entry) {
$path = $dir . DIRECTORY_SEPARATOR . $entry;
if (is_link($path) && !file_exists($path)) {
#unlink($path);
}
}
use realpath function:
foreach(scandir($dir) as $entry) {
$path = $dir . DIRECTORY_SEPARATOR . $entry;
if (!realpath($path)) {
#unlink($path);
}
}

Warning: opendir(): The system cannot find the file specified. (code: 2)

I'm trying to turn the files in my 'objects' directory into an array, then use them to load the objects. But, for some reason, I continue to get this error
Warning: opendir(C:\xampp\htdocs/objects,C:\xampp\htdocs/objects): The system cannot find the file specified. (code: 2)
here is the code:
public function loadObjects(){
$files = array();
if ($handle = opendir(APP_PATH . 'objects'))
{
while (false !== ($entry = readdir($handle)))
{
if ($entry != "." && $entry != "..")
{
$files[] = $entry;
}
}
}
closedir($handle);
if(is_array($files) && count($files) > 0)
{
foreach($files as $value)
{
require_once(APP_PATH . 'objects/' . $value);
$value = stristr($value, '.', true);
self::$objects[$value] = new $object(self::$instance);
}
}
}
I know this is an old question but for any future viewers I will post an anwser just in case.
This type of error usually comes from a simple oversight. When developing most aplication the developer usualy uses a path like
http://localhost/myAppHome
or
http://96.82.102.233/myAppHome(if on remote server)
In this perticular case the APP_PATH is probably defined somethig like that:
define('APP_PATH',$_SERVER['DOCUMENT_ROOT']);
This will be wrong in every case when the app is being developed outside of a domain name.
$_SERVER['DOCUMENT_ROOT'] will resolve to the root of domain which in this case will be
http://localhost or http://96.82.102.233
The main directory for localhost or the IP address is going to be the diretory root of the server itself => drive:/xampp/htdocs (for example)
Basically to avoid this issue you should always mind not to ask for 'DOCUMENT_ROOT' when developing without a domain pointing to you app.
If you dont require reqular deploys you can just add the missing folder to the definition like so :
define('APP_PATH',$_SERVER['DOCUMENT_ROOT'].'/myAppHome');
In case you deploy on reqular basis and you are afraid you will forget to rever this change before depoying you can always insert an IF when defing APP_PATH like:
if($_SERVER['SERVER_NAME']=='localhost'){
define('APP_PATH', $_SERVER['DOCUMENT_ROOT'].'/myAppHome');
}else{
define('APP_PATH', $_SERVER['DOCUMENT_ROOT']);
}
You are trying to open that directory with a "/".
Try to replace:
C:\xampp\htdocs/objects
to
C:\xampp\htdocs\objects
Please be sure APP_PATH variable is not null and correct values. There is no scandir function usage on your codes.
After that, i suggest you to use DirectoryIterator.
http://www.php.net/manual/en/class.directoryiterator.php
Complete example:
http://fabien.potencier.org/article/43/find-your-files
APP_HOST = DIR folder;
APP_PATH = APP_PATH + DIR folder;
Example = "C:/xampp/htdocs" + "/parent/child/index.php"
if ($_SERVER['SERVER_NAME'] == "localhost") {
define('APP_HOST', pathinfo($_SERVER['PHP_SELF'], PATHINFO_DIRNAME));
define('APP_PATH', $_SERVER['DOCUMENT_ROOT'] . APP_HOST);
} else {
define('APP_PATH', $_SERVER['DOCUMENT_ROOT']);
}

How to get a directory content and move to another directory with PHP

I've been trying to get this done with no luck. I've got a php script that downloads and UNZIPS a file. No problem here.
After that, I need to get the unzipped files and replace all the files of the root directory with the files on this folder. Problem is, the folder is in the root directory.
Eg.: my directory is something like this
/
/folder 1
/folder 2
/folder 3
/file.php
/file2.php
etc...
After I run my download script I unzip the archive to a folder called update in the root of the dir
/update/--UNZIPED STUFF--
I need to delete virtually all files/dirs from the root DIR excluding the update folder I guess and a couple of other files and then move the files/folders inside the update folder to the root of the dir.
Any ideas?
UPDATE
Ok, so I've made a code that seems to be right but I get a lot of file permission to when using unlink or rename. How can I go about that?
Here is the bit of code I've made
echo '<table>';
$updateContents = scandir('./');
foreach($updateContents as $number=>$fileName){
if($fileName != 'update' && $fileName != 'config.ini' && $fileName != 'layout.php' && $fileName != '..' && $fileName != '.' && $fileName != '.git' && $fileName != '.gitignore'){
if(is_dir($fileName)){
moveDownload($fileName, 'old/'.$fileName);
} else {
if(rename($fileName, 'old/'.$fileName)){
echo '<tr><td>'.$fileName.' moved successfully </td><td><font color="green">OK</font></td></tr>';
} else {
echo '<tr><td>Could not move file '.$fileName.'</td><td><font color="red">ERROR</font></td></tr>';
}
}
}
}
echo '</table>';
and the moveDownload function is one I found here somewhere. It moves a non empty folder and it was slightly modified by me.
function moveDownload($src,$dst){
$dir = opendir($src);
while(false !== ($file = readdir($dir))){
if (($file != '.') && ($file != '..') && ($file != 'config.ini') && ($file != 'layout.php') && ($file != 'sbpcache') && ($file !='update')){
if (is_dir($src.'/'.$file)){
if(file_exists($dst.'/'.$file)){
rrmdir($dst.'/'.$file);
}
}
if(#rename($src . '/' . $file, $dst . '/' . $file)){
echo '<tr><td>'.$file.' moved successfully </td><td><font color="green">OK</font></td></tr>';
} else {
if(#chmod($src.'/'.$file, 0777)){
if(#rename($src . '/' . $file, $dst . '/' . $file)){
echo '<tr><td>'.$file.' moved successfully </td><td><font color="green">OK</font></td></tr>';
} else {
echo '<tr><td>Could not move file '.$file.'</td><td><font color="red">ERROR RENAME</font></td></tr>';
}
} else {
echo '<tr><td>Could not move file '.$file.'</td><td><font color="red">ERROR CHMOD</font></td></tr>';
}
}
}
}
closedir($dir);
}
I also do the same in the again but moving from the update folder.
So basically, first instead of deleting things I am just moving them to a folder called old and then I try to move the new things in, but I get permission problems everywhere. Some files move, some don't, even if I have ' sudo chmod 777 -R'. Any ideas?
PHP's opendir will allow you to iterate along all the files and directories inside the root directory. You can use unlink to delete the files or folders and add an if clause to check if the item is to be deleted or not.
Why don't you just get a list of all directories / files under root and then loop through them, delete them (using unlink) while ignoring the "backup" directory.
Next you can either run a php copy OR shell_exec mv * command to move the files from backup to root.
what for to use root folder. use /tmp
what the problem with unlink / rmdir

Categories