Search code examples
phpfile-permissionspermission-deniedunlink

PHP Error deleting file


Error deleting file if there are multiple connections to multiple page. Error:Warning: unlink(folder/1.txt.txt) [function.unlink]: Permission denied in C:\htdocs\fopen.php on line 7

Note: If only one connection to access everything normally occurs (no error occurs).

PHP code fopen.php:

<?php
function fastWrite($a){
    echo 'Coping file: "',$a,'" to "',$a,'.txt"<br>';
    copy($a,$a.'.txt');

    echo 'Delete file: "',$a,'.txt"<br>';
    unlink($a.'.txt');
}

for($i=0;$i<10;$i++){
    fastWrite('folder/1.txt');
    echo '<hr>';
}
?>

html/javascript code (to simulate multiple connections):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
<title>my test</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript">
function myTest(z){
    $.ajax("fopen.php?time="+(new Date().getTime()),{"success":function(data){
        $("<div></div>").addClass("sty").html(data).appendTo("body");
    },"error":function(a,b,c){
        $("<div></div>").addClass("sty").html([a,b,c]).appendTo("body");
    }});
}
</script>
<style>
.sty{
border:1px #000 solid;
overflow:auto;
margin:5px 0 0 5px;
}
</style>
</head>
<body>
<p><a href="teste.html">New test</a></p>
<script type="text/javascript">
var dd = "";
for(var i=0;i<10;i++){
    dd += "myTest(\"#a"+(i+1)+"\");\n";
}
eval(dd);
</script>
</body>
</html>

What did I do wrong?

Thanks.


Solution: clearstatcache


Solution

  • You're having a problem because two processes are trying to copy and delete the same file at the same time. Because they are separate processes, you can't easily control the order in which they do things.

    Imagine two processes, running fastWrite() at the same time:

    • t1 copies 'a' to 'a.txt'
    • t2 copies 'a' to 'a.txt'
    • t2 deletes 'a.txt'
    • t1 tries to delete 'a.txt', but fails because it does not exist

    This is called a "race condition".

    If you don't mind that the unlink call will sometimes fail, you can ignore the error by using the '@' symbol in front of the command:

    @unlink("$a.txt");
    

    I'm pretty sure that saving user-generated data into the same file over and over again isn't your ultimate goal. You obviously encountered this problem in the pursuit of something larger. Maybe you should start a new question more focused on that problem.

    If you just need a temporary file to work with during the connection, don't always name the file the same. Instead, you could:

    function doStuffToFile($fname) {
        $tempName = $fname . "." . getmypid() . "." . rand();
        copy($fname, $tempName);
        // do stuff to your temporary file
        unlink($tempName);
    }