php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #77077 rmdir() should return FALSE if directory locked by dir()
Submitted: 2018-10-28 20:45 UTC Modified: 2018-12-10 16:51 UTC
From: edgaras dot janusauskas at gmail dot com Assigned:
Status: Verified Package: *Directory/Filesystem functions
PHP Version: 7.2.11 OS: Windows 10
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2018-10-28 20:45 UTC] edgaras dot janusauskas at gmail dot com
Description:
------------
On Windows, if directory is opened by dir() or opendir(), but not closed, then call to rmdir() on that directory returns TRUE, but then there is few inconsistencies exist:

- Second call to rmdir() on same directory fails (Permission denied)
- You cannot delete parent directory (Directory not empty)
- glob() doesn't see directory, but scandir() still sees it as existing.


Test script:
---------------
mkdir('testdir');
mkdir('testdir/sub');

$d = dir('testdir/sub');
while (false !== ($entry = $d->read())) {
    //echo $entry . "\n";
}
//$d->close();

printf("rmdir=%d\n", rmdir('testdir/sub'));
printf("glob=[%s]\n", implode(', ', glob('testdir/*')));
printf("scandir=[%s]\n", implode(', ', scandir('testdir')));

Expected result:
----------------
rmdir() should really succeed deleting folder and any further operations should work as with not existing one.

rmdir=1
glob=[]
scandir=[., ..]
Deleting parent directory succeeds

or

rmdir() should fail with "Permission denied" on first try and any further operations should work as with still existing one.

rmdir=0
glob=[testdir/sub]
scandir=[., .., sub]
Deleting parent directory fails

Actual result:
--------------
rmdir=1
glob=[]               on PHP 7.0-7.2
glob=[testdir/sub]    on PHP 5.6
scandir=[., .., sub]

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-10-29 12:20 UTC] cmb@php.net
-Status: Open +Status: Verified
 [2018-10-29 12:20 UTC] cmb@php.net
Well, the basic issue is that contrary to POSIX' rmdir()[1],
Windows' RemoveDirectory()[2] only “marks a directory for deletion
on close”, but claims success, even if the directory is not
immediately removed.

The difference between glob() and scandir() on Windows is that the
former calls php_sys_lstat() on the directory (which fails), but
the latter does not.

[1] <http://pubs.opengroup.org/onlinepubs/9699919799/>
[1] <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-removedirectoryw>
 [2018-12-10 16:51 UTC] ab@php.net
The described is the expected behavior. What indeed could be fixed, is that scandir shouldn't deliver items scheduled for deletion. That however would require a refactoring of the scandir/readdir implementation, not just a bugfix. However even then I'd be not sure it would always deliver result by this usage. The enumeration used for the internal implementation would deliver per se an undefined result, if items are deleted/created after the enumeration has been started. Best way is to avoid such usage as there's in 99% of cases no need on this. Otherwise we might be striving to satisfy an edge case while making the normal usage some slower.

Thanks.
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Mon Jun 24 16:01:26 2019 UTC