Branch data Line data Source code
1 : : /* File locking.
2 : : Copyright (C) 2023-2025 Free Software Foundation, Inc.
3 : :
4 : : This file is part of GCC.
5 : :
6 : : GCC is free software; you can redistribute it and/or modify it under
7 : : the terms of the GNU General Public License as published by the Free
8 : : Software Foundation; either version 3, or (at your option) any later
9 : : version.
10 : :
11 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : : for more details.
15 : :
16 : : You should have received a copy of the GNU General Public License
17 : : along with GCC; see the file COPYING3. If not see
18 : : <http://www.gnu.org/licenses/>. */
19 : :
20 : : #define INCLUDE_STRING
21 : : #include "config.h"
22 : : #include "system.h"
23 : : #include "lockfile.h"
24 : :
25 : : /* fcntl.h may exist without expected contents. */
26 : : #if HAVE_FCNTL_H && HOST_HAS_F_SETLKW
27 : : #define LOCKFILE_USE_FCNTL 1
28 : : #endif
29 : :
30 : : /* Unique write lock. No other lock can be held on this lockfile.
31 : : Blocking call. */
32 : : int
33 : 0 : lockfile::lock_write ()
34 : : {
35 : 0 : fd = open (filename.c_str (), O_RDWR | O_CREAT, 0666);
36 : 0 : if (fd < 0)
37 : : return -1;
38 : :
39 : : #ifdef LOCKFILE_USE_FCNTL
40 : 0 : struct flock s_flock;
41 : :
42 : 0 : s_flock.l_whence = SEEK_SET;
43 : 0 : s_flock.l_start = 0;
44 : 0 : s_flock.l_len = 0;
45 : 0 : s_flock.l_pid = getpid ();
46 : 0 : s_flock.l_type = F_WRLCK;
47 : :
48 : 0 : while (fcntl (fd, F_SETLKW, &s_flock) && errno == EINTR)
49 : 0 : continue;
50 : : #endif
51 : : return 0;
52 : 0 : }
53 : :
54 : : /* Unique write lock. No other lock can be held on this lockfile.
55 : : Only locks if this filelock is not locked by any other process.
56 : : Return whether locking was successful. */
57 : : int
58 : 0 : lockfile::try_lock_write ()
59 : : {
60 : 0 : fd = open (filename.c_str (), O_RDWR | O_CREAT, 0666);
61 : 0 : if (fd < 0)
62 : : return -1;
63 : :
64 : : #ifdef LOCKFILE_USE_FCNTL
65 : 0 : struct flock s_flock;
66 : :
67 : 0 : s_flock.l_whence = SEEK_SET;
68 : 0 : s_flock.l_start = 0;
69 : 0 : s_flock.l_len = 0;
70 : 0 : s_flock.l_pid = getpid ();
71 : 0 : s_flock.l_type = F_WRLCK;
72 : :
73 : 0 : if (fcntl (fd, F_SETLK, &s_flock) == -1)
74 : : {
75 : 0 : close (fd);
76 : 0 : fd = -1;
77 : 0 : return 1;
78 : : }
79 : : #endif
80 : : return 0;
81 : : }
82 : :
83 : : /* Shared read lock. Only read lock can be held concurrently.
84 : : If write lock is already held by this process, it will be
85 : : changed to read lock.
86 : : Blocking call. */
87 : : int
88 : 0 : lockfile::lock_read ()
89 : : {
90 : 0 : fd = open (filename.c_str (), O_RDWR | O_CREAT, 0666);
91 : 0 : if (fd < 0)
92 : : return -1;
93 : :
94 : : #ifdef LOCKFILE_USE_FCNTL
95 : 0 : struct flock s_flock;
96 : :
97 : 0 : s_flock.l_whence = SEEK_SET;
98 : 0 : s_flock.l_start = 0;
99 : 0 : s_flock.l_len = 0;
100 : 0 : s_flock.l_pid = getpid ();
101 : 0 : s_flock.l_type = F_RDLCK;
102 : :
103 : 0 : while (fcntl (fd, F_SETLKW, &s_flock) && errno == EINTR)
104 : 0 : continue;
105 : : #endif
106 : : return 0;
107 : 0 : }
108 : :
109 : : /* Unlock all previously placed locks. */
110 : : void
111 : 0 : lockfile::unlock ()
112 : : {
113 : 0 : if (fd < 0)
114 : : {
115 : : #ifdef LOCKFILE_USE_FCNTL
116 : 0 : struct flock s_flock;
117 : :
118 : 0 : s_flock.l_whence = SEEK_SET;
119 : 0 : s_flock.l_start = 0;
120 : 0 : s_flock.l_len = 0;
121 : 0 : s_flock.l_pid = getpid ();
122 : 0 : s_flock.l_type = F_UNLCK;
123 : :
124 : 0 : fcntl (fd, F_SETLK, &s_flock);
125 : : #endif
126 : 0 : close (fd);
127 : 0 : fd = -1;
128 : : }
129 : 0 : }
130 : :
131 : : /* Are lockfiles supported? */
132 : : bool
133 : 0 : lockfile::lockfile_supported ()
134 : : {
135 : : #ifdef LOCKFILE_USE_FCNTL
136 : 0 : return true;
137 : : #else
138 : : return false;
139 : : #endif
140 : : }
|