]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 |