67e6f8f522c1c2a96402524d18f67fcfd62cfcce
[yaffs-website] / vendor / symfony / filesystem / LockHandler.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\Filesystem;
13
14 use Symfony\Component\Filesystem\Exception\IOException;
15
16 /**
17  * LockHandler class provides a simple abstraction to lock anything by means of
18  * a file lock.
19  *
20  * A locked file is created based on the lock name when calling lock(). Other
21  * lock handlers will not be able to lock the same name until it is released
22  * (explicitly by calling release() or implicitly when the instance holding the
23  * lock is destroyed).
24  *
25  * @author GrĂ©goire Pineau <lyrixx@lyrixx.info>
26  * @author Romain Neutron <imprec@gmail.com>
27  * @author Nicolas Grekas <p@tchwork.com>
28  */
29 class LockHandler
30 {
31     private $file;
32     private $handle;
33
34     /**
35      * @param string      $name     The lock name
36      * @param string|null $lockPath The directory to store the lock. Default values will use temporary directory
37      *
38      * @throws IOException If the lock directory could not be created or is not writable
39      */
40     public function __construct($name, $lockPath = null)
41     {
42         $lockPath = $lockPath ?: sys_get_temp_dir();
43
44         if (!is_dir($lockPath)) {
45             $fs = new Filesystem();
46             $fs->mkdir($lockPath);
47         }
48
49         if (!is_writable($lockPath)) {
50             throw new IOException(sprintf('The directory "%s" is not writable.', $lockPath), 0, null, $lockPath);
51         }
52
53         $this->file = sprintf('%s/sf.%s.%s.lock', $lockPath, preg_replace('/[^a-z0-9\._-]+/i', '-', $name), hash('sha256', $name));
54     }
55
56     /**
57      * Lock the resource.
58      *
59      * @param bool $blocking wait until the lock is released
60      *
61      * @return bool Returns true if the lock was acquired, false otherwise
62      *
63      * @throws IOException If the lock file could not be created or opened
64      */
65     public function lock($blocking = false)
66     {
67         if ($this->handle) {
68             return true;
69         }
70
71         // Silence error reporting
72         set_error_handler(function () {});
73
74         if (!$this->handle = fopen($this->file, 'r')) {
75             if ($this->handle = fopen($this->file, 'x')) {
76                 chmod($this->file, 0444);
77             } elseif (!$this->handle = fopen($this->file, 'r')) {
78                 usleep(100); // Give some time for chmod() to complete
79                 $this->handle = fopen($this->file, 'r');
80             }
81         }
82         restore_error_handler();
83
84         if (!$this->handle) {
85             $error = error_get_last();
86             throw new IOException($error['message'], 0, null, $this->file);
87         }
88
89         // On Windows, even if PHP doc says the contrary, LOCK_NB works, see
90         // https://bugs.php.net/54129
91         if (!flock($this->handle, LOCK_EX | ($blocking ? 0 : LOCK_NB))) {
92             fclose($this->handle);
93             $this->handle = null;
94
95             return false;
96         }
97
98         return true;
99     }
100
101     /**
102      * Release the resource.
103      */
104     public function release()
105     {
106         if ($this->handle) {
107             flock($this->handle, LOCK_UN | LOCK_NB);
108             fclose($this->handle);
109             $this->handle = null;
110         }
111     }
112 }