Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
81.82% covered (warning)
81.82%
18 / 22
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
flock
81.82% covered (warning)
81.82%
18 / 22
75.00% covered (warning)
75.00%
3 / 4
11.73
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 acquire
73.33% covered (warning)
73.33%
11 / 15
0.00% covered (danger)
0.00%
0 / 1
7.93
 owns_lock
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 release
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2/**
3*
4* This file is part of the phpBB Forum Software package.
5*
6* @copyright (c) phpBB Limited <https://www.phpbb.com>
7* @license GNU General Public License, version 2 (GPL-2.0)
8*
9* For full copyright and license information, please see
10* the docs/CREDITS.txt file.
11*
12*/
13
14namespace phpbb\lock;
15
16/**
17* File locking class
18*/
19class flock
20{
21    /**
22    * Path to the file to which access is controlled
23    *
24    * @var string
25    */
26    private $path;
27
28    /**
29    * File pointer for the lock file
30    * @var resource|closed-resource|false
31    */
32    private $lock_fp;
33
34    /**
35    * Constructor.
36    *
37    * You have to call acquire() to actually acquire the lock.
38    *
39    * @param    string    $path    Path to the file to which access is controlled
40    */
41    public function __construct($path)
42    {
43        $this->path = $path;
44        $this->lock_fp = false;
45    }
46
47    /**
48    * Tries to acquire the lock.
49    *
50    * If the lock is already held by another process, this call will block
51    * until the other process releases the lock. If a lock is acquired and
52    * is not released before script finishes but the process continues to
53    * live (apache/fastcgi) then subsequent processes trying to acquire
54    * the same lock will be blocked forever.
55    *
56    * If the lock is already held by the same process via another instance
57    * of this class, this call will block forever.
58    *
59    * If flock function is disabled in php or fails to work, lock
60    * acquisition will fail and false will be returned.
61    *
62    * @return    bool            true if lock was acquired
63    *                            false otherwise
64    */
65    public function acquire()
66    {
67        if ($this->lock_fp)
68        {
69            return false;
70        }
71
72        // For systems that can't have two processes opening
73        // one file for writing simultaneously
74        if (file_exists($this->path . '.lock'))
75        {
76            $mode = 'rb+';
77        }
78        else
79        {
80            $mode = 'wb';
81        }
82
83        $this->lock_fp = @fopen($this->path . '.lock', $mode);
84
85        if ($mode == 'wb')
86        {
87            if (!$this->lock_fp)
88            {
89                // Two processes may attempt to create lock file at the same time.
90                // Have the losing process try opening the lock file again for reading
91                // on the assumption that the winning process created it
92                $mode = 'rb+';
93                $this->lock_fp = @fopen($this->path . '.lock', $mode);
94            }
95            else
96            {
97                // Only need to set mode when the lock file is written
98                @chmod($this->path . '.lock', 0666);
99            }
100        }
101
102        if ($this->lock_fp)
103        {
104            if (!@flock($this->lock_fp, LOCK_EX))
105            {
106                throw new \phpbb\exception\http_exception(500, 'Failure while aqcuiring locks.');
107            }
108        }
109
110        return (bool) $this->lock_fp;
111    }
112
113    /**
114    * Does this process own the lock?
115    *
116    * @return    bool            true if lock is owned
117    *                            false otherwise
118    */
119    public function owns_lock()
120    {
121        return (bool) $this->lock_fp;
122    }
123
124    /**
125    * Releases the lock.
126    *
127    * The lock must have been previously obtained, that is, acquire() call
128    * was issued and returned true.
129    *
130    * Note: Attempting to release a lock that is already released,
131    * that is, calling release() multiple times, is harmless.
132    *
133    * @return void
134    */
135    public function release()
136    {
137        if ($this->lock_fp)
138        {
139            @flock($this->lock_fp, LOCK_UN);
140            fclose($this->lock_fp);
141            $this->lock_fp = false;
142        }
143    }
144}