0

I have a text file which multiple users will be simultaneously editing (limited to an individual line per edit, per user). I have already found a solution for the "line editing" part of the required functionality right here on StackOverflow.com, specifically, the 4th solution (for large files) offered by @Gnarf in the following question:

how to replace a particular line in a text file using php?

It basically rewrites the entire file contents to a new temporary file (with the user's edit included) and then renames the temporary file to the original file once finished. It's great!

To avoid one user's edit causing a conflict with another user's edit if they are both attempting an edit at the same time, I have introduced flock() functionality, as can be seen in my variation on the code here:

$reading = fopen($file, 'r');
$writing = fopen($temp, 'w');

$replaced = false;

if ((flock($reading, LOCK_EX)) and (flock($writing, LOCK_EX))) {

    echo 'Lock acquired.<br>';

    while (!feof($reading)) {

        $line = fgets($reading);

        $values = explode("|",$line);

        if ($values[0] == $id) {

            $line = $id."|comment edited!".PHP_EOL;
            $replaced = true;
        }

        fputs($writing, $line);
    }

    flock($reading, LOCK_UN);
    flock($writing, LOCK_UN);

    fclose($reading);
    fclose($writing);

} else {

    echo 'Lock not acquired.<br>';
}

I've made sure the $temp file always has a unique filename. Full code here: https://pastebin.com/E31hR9Mz

I understand that flock() will force any other execution of the script to wait in a queue until the first execution has finished and the flock() has been released. So far so good.

However, the problem starts at the end of the script, when the time has come to rename() the temporary file to replace the original file.

if ($replaced) {

    rename($temp, $file);

} else {

    unlink($temp);
}

From what I have seen, rename() will fail if the original file still has a flock(), so I need to release the flock() before this point. However, I also need it to remain locked, or rename() will fail when another user running the same script immediately opens a new flock() as soon as the previous flock() is released. When this happens, it will return:

Warning: rename(temporary.txt,original.txt): Access is denied. (code: 5)

tl;dr: I seem to be in a bit of a Catch-22. It looks like rename() won't work on a locked file, but unlocking the file will allow another user to immediately lock it again before the rename() can take place.

Any ideas?

update: After some extensive research into how flock() works, (in layman's terms, there is no guarantee that another script will respect the "lock", and therefore it is not really a "lock" at all as one would assume from the literal meaning of the word) I have opted for this solution instead which works like a charm:

https://docstore.mik.ua/orelly/webprog/pcook/ch18_25.htm

"Good lock" on your locking adventures.

  • have you tried `copy` + `unlink`, not sure if it will make a difference but, worth a shot. – ArtisticPhoenix Jan 04 '19 at 02:53
  • How about creating custom logic and lock mechanism? If it's only prohibited to edit same line at a time, just create a lock file which tells which lines are currently locked and by whom. Just an idea – user3647971 Jan 04 '19 at 06:56
  • What is your host operating system? – SPlatten Jan 04 '19 at 10:07
  • @SPlatten I am testing this on a Windows system, with Apache 2.4 and PHP 5.6, however it will also need to work on Linux too. I understand that the specifics of flock() functionality are somewhat dependent on the intricacies of each OS but hopefully I can find a global solution. – juanitojuandejuanes Jan 04 '19 at 10:14
  • The reason I asked is that Linux has a much better file system than Windows. You should consider the differences between operating systems as Windows will let you do things that other more secure operating systems will not. Implement a solution that works on all. – SPlatten Jan 04 '19 at 10:18
  • @SPLatten, what does 'more secure operating systems' mean? There is no point in making such comparisons. – Michael Chourdakis Jan 08 '19 at 14:43
  • @Michael , if you have experience with both them it’s obvious. Windows is easy to use but secure it isn’t. – SPlatten Jan 08 '19 at 14:48

0 Answers0