php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #22488 Permission denied for unlink() , copy(), rename(), move_uploaded_file() FAT32
Submitted: 2003-03-01 10:18 UTC Modified: 2012-05-23 23:56 UTC
From: ajes2kemais at gmail dot com Assigned: felipe (profile)
Status: Closed Package: *General Issues
PHP Version: 4.2.3 OS: Windows NT 4.0 SP6
Private report: No CVE-ID: None
 [2003-03-01 10:18 UTC] ajes2kemais at gmail dot com
(I have tested this with PHP 4.2.3 and PHP 4.3.1 running as a CGI process under IIS 4 on NT4-SP6 server with FAT file system)

The situation:
After receiving a submission from an HTML form which includes an uploaded file, I need to move the uploaded file from its temporary place to its final place.

The problem:
Whenever the target location already have a file with the same name, the PHP command would fail with either 'unable to create' and/or 'permission denied' type of warnings.  It does not matter whether I use one simple move_uploaded_file() function or a combination of unlink(), copy() and rename() functions.  It even fails when I use the system() or exec() function.  Please remember that the existing file is not marked 'read-only' and the user account  (I_USR) does have write capability on the intended directory.

I have already tried using double backward slash as path separator (instead of forward slash), using full path to root of drive (instead of relative), giving I_USR account administrator priviledges, sharing the target directory, moving temp directory to the same drive as the target directory, disabling warning message generation (using the @ prefix), trying to unlink or move the files using multiple strategy one after the other, etc.

Interesting behaviour:
The PHP commands would not always fail.  Once in a while, it would succeed. Espescially after the script has died. (Seems to react differently when there is a time lapse)

**** SAMPLE SCRIPT FOR BUG TESTING:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>
<head>
	<title>upload test</title>
	<META HTTP-EQUIV="PRAGMA" CONTENT="no-cache"> 
	<META HTTP-EQUIV="expires" CONTENT="Fri, 1 January 1999 12:00:00 EST"> 
</head>

<body>
<form method="post" enctype="multipart/form-data">
<input type="hidden" name="MAX_FILE_SIZE" value="65536">
<?php

$vname = 'myfile';

$target = './my_uploaded_image.jpg';

$name = $_FILES[$vname]['name'];
$type = $_FILES[$vname]['type'];
$size = $_FILES[$vname]['size'];
$temp = $_FILES[$vname]['tmp_name'];
$err  = $_FILES[$vname]['error'];

if (is_uploaded_file($temp)) {
	if (!move_uploaded_file($temp, $target)) {
		echo "<strong>Error:</strong> Unable to accept file $name<br>";
	}
}

if (is_file($target)) {
	echo sprintf('<img src="%s" border="0">', $target);
} else {
	echo "(no image file)";
} 

?><br>
Specify here an jpeg image file to be uploaded:<br>
<input type="file" name="<?php echo $vname; ?>"><br>
<input type="Submit" value="Upload">
</form>


</body>
</html>

**** WORK AROUND THAT SEEMS TO WORK:
change the simple move_uploaded_file() invocation to:

$n = 0;
while (!@move_uploaded_file($temp, $target) and $n<100) {
	clearstatcache();
	sleep(1);
	$n++;
}


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-03-01 20:06 UTC] kemal at thelimelight dot nl
**** Additional test done with PHP 4.3.2-dev (build date Mar 2 2003 02:16:38): same result as with previous versions.
 [2003-03-02 03:49 UTC] kemal at thelimelight dot nl
**** New Discovery: the 'permission denied' problem outlined above only manifests itself when the existing file to be overwriten has just been recently accessed by IIS (ie the image file has been very recently requested by a HTML page).  

Eliminating the line which contains the <IMG SRC="%s"> tag in the sample script above results in perfect running of the script.

Conclusion: any attempt to overwrite the file was denied by the OS (NT4 in my case) because the file was marked "in-use". It should not have been so, because the file is only accessed for a short time, and it happened a few minutes before. I don't know whether this is an IIS bug or PHP bug.
 [2003-03-02 05:18 UTC] wez@php.net
Not a bug in PHP; PHP cannot write to a file that is in use; it is your responsibility to work around this problem with IIS in your script.

As a suggestion, you could try adding a 2 second sleep before attempting to move the file; this should allow enough time for the OS to decide that the access is OK.

 [2003-03-17 10:19 UTC] kemal at thelimelight dot nl
*** Still more info:

Microsoft acknowledge this problem (caching of objects requested via FTP/HTTP) affecting IIS 4.0. See for example:
http://support.microsoft.com/default.aspx?scid=KB;en-us;q184956
http://support.microsoft.com/default.aspx?scid=kb;en-us;191742
http://support.microsoft.com/default.aspx?scid=kb;EN-US;182626

Suggested workarounds:
a) Disable IIS caching (registry change)
b) Lowers caching time (registry change)
c) Wait ~30 seconds in a loop while overwriting file (script change)
d) Use copy() instead of move_uploaded_file() (script change). It appears that copy() has less problem than other methods.
 [2012-05-18 14:25 UTC] ajes2kemais at gmail dot com
-: kemal@thelimelight.nl +: ajes2kemais at gmail dot com -Package: Filesystem function related +Package: *General Issues
 [2012-05-23 23:53 UTC] felipe@php.net
-Status: Closed +Status: Open
 [2012-05-23 23:56 UTC] felipe@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: felipe
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 26 04:01:30 2024 UTC