]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/interprocess/include/boost/interprocess/detail/file_locking_helpers.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / interprocess / include / boost / interprocess / detail / file_locking_helpers.hpp
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/interprocess for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10
11 #ifndef BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP
12 #define BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP
13
14 #ifndef BOOST_CONFIG_HPP
15 # include <boost/config.hpp>
16 #endif
17 #
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
19 #pragma once
20 #endif
21
22 #include <boost/interprocess/detail/config_begin.hpp>
23 #include <boost/interprocess/detail/workaround.hpp>
24
25 #include <sstream>
26 #include <string>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <errno.h>
30 #include <cstddef>
31 #include <boost/interprocess/detail/os_file_functions.hpp>
32
33 #include <boost/interprocess/detail/shared_dir_helpers.hpp>
34
35 #if defined(BOOST_INTERPROCESS_WINDOWS)
36
37 #include <fcntl.h>
38 #include <io.h>
39 #include <sys/locking.h>
40
41 #else //defined(BOOST_INTERPROCESS_WINDOWS)
42
43 #include <fcntl.h>
44 #include <sys/stat.h>
45 #include <unistd.h>
46
47 #endif //defined(BOOST_INTERPROCESS_WINDOWS)
48
49 namespace boost{
50 namespace interprocess{
51 namespace ipcdetail{
52
53 #if defined(BOOST_INTERPROCESS_WINDOWS)
54
55 struct locking_file_serial_id
56 {
57 int fd;
58 unsigned long dwVolumeSerialNumber;
59 unsigned long nFileIndexHigh;
60 unsigned long nFileIndexLow;
61 //This reference count counts the number of modules attached
62 //to the shared memory and lock file. This serves to unlink
63 //the locking file and shared memory when all modules are
64 //done with the global memory (shared memory)
65 volatile boost::uint32_t modules_attached_to_gmem_count;
66 };
67
68 inline bool lock_locking_file(int fd)
69 {
70 int ret = 0;
71 while(ret != 0 && errno == EDEADLK){
72 ret = _locking(fd, _LK_LOCK, 1/*lock_file_contents_length()*/);
73 }
74 return 0 == ret;
75 }
76
77 inline bool try_lock_locking_file(int fd)
78 {
79 return 0 == _locking(fd, _LK_NBLCK , 1);
80 }
81
82 inline int open_or_create_and_lock_file(const char *name)
83 {
84 permissions p;
85 p.set_unrestricted();
86 while(1){
87 file_handle_t handle = create_or_open_file(name, read_write, p);
88 int fd = _open_osfhandle((intptr_t)handle, _O_TEXT);
89 if(fd < 0){
90 close_file(handle);
91 return fd;
92 }
93 if(!try_lock_locking_file(fd)){
94 _close(fd);
95 return -1;
96 }
97 struct _stat s;
98 if(0 == _stat(name, &s)){
99 return fd;
100 }
101 else{
102 _close(fd);
103 }
104 }
105 }
106
107 inline int try_open_and_lock_file(const char *name)
108 {
109 file_handle_t handle = open_existing_file(name, read_write);
110 int fd = _open_osfhandle((intptr_t)handle, _O_TEXT);
111 if(fd < 0){
112 close_file(handle);
113 return fd;
114 }
115 if(!try_lock_locking_file(fd)){
116 _close(fd);
117 return -1;
118 }
119 return fd;
120 }
121
122 inline void close_lock_file(int fd)
123 { _close(fd); }
124
125 inline bool is_valid_fd(int fd)
126 {
127 struct _stat s;
128 return EBADF != _fstat(fd, &s);
129 }
130
131 inline bool is_normal_file(int fd)
132 {
133 if(_isatty(fd))
134 return false;
135 struct _stat s;
136 if(0 != _fstat(fd, &s))
137 return false;
138 return 0 != (s.st_mode & _S_IFREG);
139 }
140
141 inline std::size_t get_size(int fd)
142 {
143 struct _stat s;
144 if(0 != _fstat(fd, &s))
145 return 0u;
146 return (std::size_t)s.st_size;
147 }
148
149 inline bool fill_file_serial_id(int fd, locking_file_serial_id &id)
150 {
151 winapi::interprocess_by_handle_file_information info;
152 if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info))
153 return false;
154 id.fd = fd;
155 id.dwVolumeSerialNumber = info.dwVolumeSerialNumber;
156 id.nFileIndexHigh = info.nFileIndexHigh;
157 id.nFileIndexLow = info.nFileIndexLow;
158 id.modules_attached_to_gmem_count = 1; //Initialize attached count
159 return true;
160 }
161
162 inline bool compare_file_serial(int fd, const locking_file_serial_id &id)
163 {
164 winapi::interprocess_by_handle_file_information info;
165 if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info))
166 return false;
167
168 return id.dwVolumeSerialNumber == info.dwVolumeSerialNumber &&
169 id.nFileIndexHigh == info.nFileIndexHigh &&
170 id.nFileIndexLow == info.nFileIndexLow;
171 }
172
173 #else //UNIX
174
175 struct locking_file_serial_id
176 {
177 int fd;
178 dev_t st_dev;
179 ino_t st_ino;
180 //This reference count counts the number of modules attached
181 //to the shared memory and lock file. This serves to unlink
182 //the locking file and shared memory when all modules are
183 //done with the global memory (shared memory)
184 volatile boost::uint32_t modules_attached_to_gmem_count;
185 };
186
187 inline bool lock_locking_file(int fd)
188 {
189 int ret = 0;
190 while(ret != 0 && errno != EINTR){
191 struct flock lock;
192 lock.l_type = F_WRLCK;
193 lock.l_whence = SEEK_SET;
194 lock.l_start = 0;
195 lock.l_len = 1;
196 ret = fcntl (fd, F_SETLKW, &lock);
197 }
198 return 0 == ret;
199 }
200
201 inline bool try_lock_locking_file(int fd)
202 {
203 struct flock lock;
204 lock.l_type = F_WRLCK;
205 lock.l_whence = SEEK_SET;
206 lock.l_start = 0;
207 lock.l_len = 1;
208 return 0 == fcntl (fd, F_SETLK, &lock);
209 }
210
211 inline int open_or_create_and_lock_file(const char *name)
212 {
213 permissions p;
214 p.set_unrestricted();
215 while(1){
216 int fd = create_or_open_file(name, read_write, p);
217 if(fd < 0){
218 return fd;
219 }
220 if(!try_lock_locking_file(fd)){
221 close(fd);
222 return -1;
223 }
224 struct stat s;
225 if(0 == stat(name, &s)){
226 return fd;
227 }
228 else{
229 close(fd);
230 }
231 }
232 }
233
234 inline int try_open_and_lock_file(const char *name)
235 {
236 int fd = open_existing_file(name, read_write);
237 if(fd < 0){
238 return fd;
239 }
240 if(!try_lock_locking_file(fd)){
241 close(fd);
242 return -1;
243 }
244 return fd;
245 }
246
247 inline void close_lock_file(int fd)
248 { close(fd); }
249
250 inline bool is_valid_fd(int fd)
251 {
252 struct stat s;
253 return EBADF != fstat(fd, &s);
254 }
255
256 inline bool is_normal_file(int fd)
257 {
258 struct stat s;
259 if(0 != fstat(fd, &s))
260 return false;
261 return 0 != (s.st_mode & S_IFREG);
262 }
263
264 inline std::size_t get_size(int fd)
265 {
266 struct stat s;
267 if(0 != fstat(fd, &s))
268 return 0u;
269 return (std::size_t)s.st_size;
270 }
271
272 inline bool fill_file_serial_id(int fd, locking_file_serial_id &id)
273 {
274 struct stat s;
275 if(0 != fstat(fd, &s))
276 return false;
277 id.fd = fd;
278 id.st_dev = s.st_dev;
279 id.st_ino = s.st_ino;
280 id.modules_attached_to_gmem_count = 1; //Initialize attached count
281 return true;
282 }
283
284 inline bool compare_file_serial(int fd, const locking_file_serial_id &id)
285 {
286 struct stat info;
287 if(0 != fstat(fd, &info))
288 return false;
289
290 return id.st_dev == info.st_dev &&
291 id.st_ino == info.st_ino;
292 }
293
294 #endif
295
296 } //namespace ipcdetail{
297 } //namespace interprocess{
298 } //namespace boost{
299
300 #include <boost/interprocess/detail/config_end.hpp>
301
302 #endif //BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP