Line data Source code
1 : /* File locking.
2 : Copyright (C) 2023-2026 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 : }
|