note 124152 added to function.file-exists
| From: | varrg@php.net | Date: | Thu, 29 Aug 2019 09:55:24 +0000 |
| Subject: | note 124152 added to function.file-exists | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-212032@lists.php.net to get a copy of this message | ||
file_exists() is vulnerable to race conditions and clearstatcache() is not adequate to avoid it.
The following function is a good solution:
<?php
function file_exists_safe($file) {
if (!$fd = fopen($file, 'xb')) {
return true; // the file already exists
}
fclose($fd); // the file is now created, we don't need the file handler
return false;
}
?>
The function will create a file if non-existent, following calls will fail because the file exists
(in effect being a lock).
IMPORTANT: The file will remain on the disk if it was successfully created and you must clean up
after you, f.ex. remove it or overwrite it. This step is purposely omitted from the function as to
let scripts do calculations all the while being sure the file won't be "seized" by
another process.
NOTE: This method fails if the above function is not used for checking in all other
scripts/processes as it doesn't actually lock the file.
FIX: You could flock() the file to prevent that (although all other scripts similarly must check it
with flock() then, see https://www.php.net/manual/en/function.flock.php).
Be sure to unlock and fclose() the file AFTER you're done with it, and not within the above
function:
<?php
function create_and_lock($file) {
if (!$fd = fopen($file, 'xb')) {
return false;
}
if (!flock($fd, LOCK_EX|LOCK_NB)) { // may fail for other reasons, LOCK_NB will prevent
blocking
fclose($fd);
unlink($file); // clean up
return false;
}
return $fd;
}
if ($lock = create_and_lock("foo.txt")) {
// do stuff
flock($fd, LOCK_UN); // unlock
fclose($fd); // close
}
?>
SEE ALSO: https://linux.die.net/man/2/open about
O_CREAT|O_EXCL (which is used with the 'x' modifier for fopen()) and problems with NFS
----
Server IP: 208.43.231.9
Probable Submitter: 185.85.3.168 (proxied: 46.59.39.241)
----
Manual Page -- http://php.net/manual/en/function.file-exists.php
Edit -- https://master.php.net/note/edit/124152
Del: integrated -- https://master.php.net/note/delete/124152/integrated
Del: useless -- https://master.php.net/note/delete/124152/useless
Del: bad code -- https://master.php.net/note/delete/124152/bad+code
Del: spam -- https://master.php.net/note/delete/124152/spam
Del: non-english -- https://master.php.net/note/delete/124152/non-english
Del: in docs -- https://master.php.net/note/delete/124152/in+docs
Del: other reasons-- https://master.php.net/note/delete/124152
Reject -- https://master.php.net/note/reject/124152
Search -- https://master.php.net/manage/user-notes.php