with php fopen() flock() file() Why does it work like this - php

so
if i fopen one file with a+ like
fopen($filepath,'a+');
file($filepath);
and then i use file($filepath) get the file contents it's ok
but why i when
i locked the file with flock i also can use file() function get the content
why ?
$fp = fopen($filepath, "a+");
while (1) {
$f =flock($fp,LOCK_EX);
if($f){
fwrite($fp,'abc');
echo "ok loked \n";
sleep(1);
$te =file($filepath);
if(strlen($te[0])==10){
echo "this is cont ".$te[0]."\n";
echo "ok this the end \n";
ftruncate($fp,0);
fflush($fp);
}
flock($fp, LOCK_UN);
break;
}
}
fclose($fp);
what about they relation?
when flock file the file()function is use the fopen resource?
file is independent function or use fopen?

fopen and file are two different functions.
fopen The fopen function does something entirely different—it opens a file
descriptor, which functions as a stream to read or write the file. It
is a much lower-level function, a simple wrapper around the C fopen
function, and simply calling fopen won't do anything but open a
stream.
file — Reads entire file into an array

flock is per process. So if the same process (including all threads) attempts flock multiple times it will always succeed.
Read the warnings at the end of the documentation:
https://www.php.net/manual/en/function.flock.php

Related

PHP block file from reading

I am trying a simple algorithm which says:
File1: (lock.php)
Open a File
Lock the File, so that no other PHP file can read this
Sleep
Release Lock
File2: (lockstatus.php)
Try to open the file.
If not opening
Wait for Lock to release
Else
Read the file
My code implementation:
Lock.php:
<?php
$f = fopen("key",'a');
if (flock($f, LOCK_EX | LOCK_NB)) {
echo "File Locked. For Next 60 Seconds\n";
sleep(60);
var_dump(flock($f, LOCK_UN)); //release lock
echo "lock released";
} else {
echo "blocked";
}
?>
Lockstatus.php
<?php
do {
echo "\n";
$f = fopen("key",'a');
if ($f) {
echo "Readable\n";
fclose ($f);
} else {
echo "Blocked! I am waiting\n";
sleep(10);
}
} while (!$f); //wait until fopen does not work
?>
Problem:
Even, flock is applied, the Lockstatus.php is able to open the file.
Question:
How to block the file reading at Lockstatus.php once it is locked by Lock.php?
The problem is that flock() only provides advisory locking. The other program may completely ignore this and proceed to fopen and fread or whatever else. The key is to use flock in your Lockstatus.php as well after your do the fopen to check if there are existing locks. flock in Lockstatus.php would fail and then you would know there is an existing lock.
This function flock() has different behavior on linux and windows.
Take a deep look at "Notes" on PHP docs. This might be your issue.
flock on PHP Docs
After that, pay attention on r+ parameter, it´s mandatory for reading+locking.
$fp = fopen('/tmp/lock.txt', 'r+');
It wont work with a.

Should I use flock when reading a file in PHP?

Ok so I am new to PHP and the example from the book shows that when I write to a file in php i should use flock($fp, LOCK_EX) after opening the file and then flock($fp, LOCK_UN) before closing the file. Like this:
$fp = fopen("$DOCUMENT_ROOT/order.txt", 'ab');
flock($fp, LOCK_EX);
fwrite($fp, $outputstring, strlent($outputstring));
flock ($fp, LOCK_UN);
fclose($fp);
But in the other example of how to read a file I am not sure if the author forgot to put flock() or it is not necessary to put flock() when reading a file. Here is the example:
$fp = fopen("$DOCUMENT_ROOT/order.txt", 'rb');
while (!feof($fp))
{
$order = fgets($fp, 999)
echo $order."<br/>";
}
fclose($fp);
So should I put flock() in the second example or not?
Thank you in advance.
It is only necessary to use flock if there are going to be multiple processes accessing the file at the same time.
If the code that writes to the file is only ever going to have have one copy running at any time, then you probably don't need to use flock. However if it is possible that multiple processes could try to run the code (and therefore access the file) at the same time, then you should use flock to make sure they do it one at a time.

fopen(file,w+) truncates the file before I can check if it's locked with flock()

I have a function which receives a filename and a json object to write to a text file.
The object is updated and needs to entirely replace the current contents of the file. Each site visitor has their own file. Multiple rapid changes create a situation where the file is truncated by fopen(file,w+), then not written to as it's locked. End result is empty file.
I'm sure there's a standard simply way to do this as it's such a usual activity. Ideally what I'm looking for is a way to check if a file has a lock before truncating the file with fopen in w+ mode or a way to switch modes.
It seems strange that you would have to truncate the file with fopen() to get a file handle to pass to flock() to check if it's locked -- but you just truncated it, so what's the point?
Here's the function I have so far:
function updateFile($filename, $jsonFileData) {
$fp = fopen($filename,"w+");
if (flock($fp, LOCK_EX)) {
fwrite($fp, $jsonFileData);
flock($fp, LOCK_UN);
fclose($fp);
return true;
} else {
fclose($fp);
return false;
}
}
Example #1 from the PHP manual will do what you want with a slight modification. Use the "c" mode to open the file for writing, create it if it doesn't exist, and don't truncate it.
$fp = fopen("/tmp/lock.txt", "c");
if (flock($fp, LOCK_EX)) { // acquire an exclusive lock
ftruncate($fp, 0); // truncate file
fwrite($fp, "Write something here\n");
fflush($fp); // flush output before releasing the lock
flock($fp, LOCK_UN); // release the lock
} else {
echo "Couldn't get the lock!";
}
fclose($fp);
Full description of the "c" mode:
Open the file for writing. If the file does not exist, it is created. If it exists, it is neither truncated (as opposed to 'w'), nor the call to this function fails (as is the case with 'x'). The file pointer is positioned on the beginning of the file. This may be useful if it's desired to get an advisory lock (see flock()) before attempting to modify the file, as using 'w' could truncate the file before the lock was obtained (if truncation is desired, ftruncate() can be used after the lock is requested).
It doesn't look like you need it, but there's also a corresponding "c+" mode if you want to both read and write.

Having problems reading/writing the php://temp stream

I'm having trouble with reading and writing the php://temp stream in PHP 5.3.2
I basically have:
file_put_contents('php://temp/test', 'test');
var_dump(file_get_contents('php://temp/test'));
The only output I get is string(0) ""
Shouldn't I get my 'test' back?
php://temp is not a file path, it's a pseudo protocol that always creates a new random temp file when used. The /test is actually being ignored entirely. The only extra "arguments" the php://temp wrapper accepts is /maxmemory:n. You need to keep a file handle around to the opened temp stream, or it will be discarded:
$tmp = fopen('php://temp', 'r+');
fwrite($tmp, 'test');
rewind($tmp);
fpassthru($tmp);
fclose($tmp);
See http://php.net/manual/en/wrappers.php.php#refsect1-wrappers.php-examples
Each time, when you use fopen to get handler, content of php://temp will be flushed. Use rewind() and stream_get_contents() to get content. Or, use normal cachers, like APC or memcache :)
Finally found a documented small note, that explains why
Example 5 at the PHP Manual used almost your exact same code sample and says
php://memory and php://temp are not reusable, i.e. after the streams
have been closed there is no way to refer to them again.
file_put_contents('php://memory', 'PHP');
echo file_get_contents('php://memory'); // prints nothing
I guess this means that file_put_contents() closes the stream internally, which makes file_get_contents() unable to recover the data in the stream again
I know this is late, but in addition to #OZ_'s answer, i just discovered that 'fread' works too, after you rewind.
$handle = fopen('php://temp', 'w+');
fwrite($handle, 'I am freaking awesome');
fread($handle); // returns '';
rewind($handle); // resets the position of pointer
fread($handle, fstat($handle)['size']); // I am freaking awesome

Read and write to a file while keeping lock

I am making a simple page load counter by storing the current count in a file. This is how I want to do this:
Lock the file (flock)
Read the current count (fread)
Increment it (++)
Write new count (fwrite)
Unlock file/close it (flock/fclose)
Can this be done without losing the lock?
As I understand it, the file can't be written to without losing the lock. The only way I have come up with to tackle this, is to write a character using "r+" mode, and then counting characters.
As said, you could use FLock. A simple example would be:
//Open the File Stream
$handle = fopen("file.txt","r+");
//Lock File, error if unable to lock
if(flock($handle, LOCK_EX)) {
$count = fread($handle, filesize("file.txt")); //Get Current Hit Count
$count = $count + 1; //Increment Hit Count by 1
ftruncate($handle, 0); //Truncate the file to 0
rewind($handle); //Set write pointer to beginning of file
fwrite($handle, $count); //Write the new Hit Count
flock($handle, LOCK_UN); //Unlock File
} else {
echo "Could not Lock File!";
}
//Close Stream
fclose($handle);
I believe you can achieve this using flock. Open a pointer to your file, flock it, read the data, write the data, then close (close automatically unlocks).
http://php.net/flock
Yes, you have to use rewind before ftruncate. Otherwise, the old content of the file is only refilled with zeros.
The working sequence is:
fopen
flock LOCK_EX
fread filesize
rewind
ftruncate 0
fwrite
flock LOCK_UN
fclose

Categories