]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // | |
3 | // (C) Copyright Ion Gaztanaga 2005-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_DETAIL_OS_FILE_FUNCTIONS_HPP | |
12 | #define BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_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 | #include <boost/interprocess/errors.hpp> | |
25 | #include <boost/interprocess/permissions.hpp> | |
26 | ||
27 | #include <string> | |
28 | #include <limits> | |
29 | #include <climits> | |
30 | #include <boost/move/detail/type_traits.hpp> //make_unsigned | |
31 | ||
32 | #if defined (BOOST_INTERPROCESS_WINDOWS) | |
33 | # include <boost/interprocess/detail/win32_api.hpp> | |
34 | #else | |
35 | # ifdef BOOST_HAS_UNISTD_H | |
36 | # include <fcntl.h> | |
37 | # include <unistd.h> | |
38 | # include <sys/types.h> | |
39 | # include <sys/stat.h> | |
40 | # include <errno.h> | |
41 | # include <cstdio> | |
42 | # include <dirent.h> | |
43 | # if 0 | |
44 | # include <sys/file.h> | |
45 | # endif | |
46 | # else | |
47 | # error Unknown platform | |
48 | # endif | |
49 | #endif | |
50 | ||
51 | #include <cstring> | |
52 | #include <cstdlib> | |
53 | ||
54 | namespace boost { | |
55 | namespace interprocess { | |
56 | ||
57 | #if defined (BOOST_INTERPROCESS_WINDOWS) | |
58 | ||
59 | typedef void * file_handle_t; | |
60 | typedef __int64 offset_t; | |
61 | typedef struct mapping_handle_impl_t{ | |
62 | void * handle; | |
63 | bool is_shm; | |
64 | } mapping_handle_t; | |
65 | ||
66 | typedef enum { read_only = winapi::generic_read | |
67 | , read_write = winapi::generic_read | winapi::generic_write | |
68 | , copy_on_write | |
69 | , read_private | |
70 | , invalid_mode = 0xffff | |
71 | } mode_t; | |
72 | ||
73 | typedef enum { file_begin = winapi::file_begin | |
74 | , file_end = winapi::file_end | |
75 | , file_current = winapi::file_current | |
76 | } file_pos_t; | |
77 | ||
78 | typedef unsigned long map_options_t; | |
79 | static const map_options_t default_map_options = map_options_t(-1); | |
80 | ||
81 | namespace ipcdetail{ | |
82 | ||
83 | inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd) | |
84 | { | |
85 | mapping_handle_t ret; | |
86 | ret.handle = hnd; | |
87 | ret.is_shm = false; | |
88 | return ret; | |
89 | } | |
90 | ||
91 | inline mapping_handle_t mapping_handle_from_shm_handle(file_handle_t hnd) | |
92 | { | |
93 | mapping_handle_t ret; | |
94 | ret.handle = hnd; | |
95 | ret.is_shm = true; | |
96 | return ret; | |
97 | } | |
98 | ||
99 | inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd) | |
100 | { return hnd.handle; } | |
101 | ||
102 | inline bool create_directory(const char *path) | |
103 | { return winapi::create_directory(path); } | |
104 | ||
105 | inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &required_len) | |
106 | { | |
107 | required_len = 0; | |
108 | //std::size_t is always bigger or equal than unsigned long in Windows systems | |
109 | //In case std::size_t is bigger than unsigned long | |
110 | unsigned long buf = buf_len; | |
111 | if(buf_len != buf){ //maybe overflowed | |
112 | return false; | |
113 | } | |
114 | required_len = winapi::get_temp_path(buf_len, buffer); | |
115 | const bool ret = !(buf_len < required_len); | |
116 | if(ret && buffer[required_len-1] == '\\'){ | |
117 | buffer[required_len-1] = 0; | |
118 | } | |
119 | return ret; | |
120 | } | |
121 | ||
122 | inline file_handle_t create_new_file | |
123 | (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) | |
124 | { | |
125 | unsigned long attr = temporary ? winapi::file_attribute_temporary : 0; | |
126 | return winapi::create_file | |
127 | ( name, (unsigned int)mode, winapi::create_new, attr | |
128 | , (winapi::interprocess_security_attributes*)perm.get_permissions()); | |
129 | } | |
130 | ||
131 | inline file_handle_t create_or_open_file | |
132 | (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) | |
133 | { | |
134 | unsigned long attr = temporary ? winapi::file_attribute_temporary : 0; | |
135 | return winapi::create_file | |
136 | ( name, (unsigned int)mode, winapi::open_always, attr | |
137 | , (winapi::interprocess_security_attributes*)perm.get_permissions()); | |
138 | } | |
139 | ||
140 | inline file_handle_t open_existing_file | |
141 | (const char *name, mode_t mode, bool temporary = false) | |
142 | { | |
143 | unsigned long attr = temporary ? winapi::file_attribute_temporary : 0; | |
144 | return winapi::create_file | |
145 | (name, (unsigned int)mode, winapi::open_existing, attr, 0); | |
146 | } | |
147 | ||
148 | inline bool delete_file(const char *name) | |
149 | { return winapi::unlink_file(name); } | |
150 | ||
151 | inline bool truncate_file (file_handle_t hnd, std::size_t size) | |
152 | { | |
153 | offset_t filesize; | |
154 | if(!winapi::get_file_size(hnd, filesize)) | |
155 | return false; | |
156 | ||
157 | typedef ::boost::move_detail::make_unsigned<offset_t>::type uoffset_t; | |
158 | const uoffset_t max_filesize = uoffset_t((std::numeric_limits<offset_t>::max)()); | |
159 | const uoffset_t uoff_size = uoffset_t(size); | |
160 | //Avoid unused variable warnings in 32 bit systems | |
161 | if(uoff_size > max_filesize){ | |
162 | winapi::set_last_error(winapi::error_file_too_large); | |
163 | return false; | |
164 | } | |
165 | ||
166 | if(offset_t(size) > filesize){ | |
167 | if(!winapi::set_file_pointer_ex(hnd, filesize, 0, winapi::file_begin)){ | |
168 | return false; | |
169 | } | |
170 | //We will write zeros in the end of the file | |
171 | //since set_end_of_file does not guarantee this | |
172 | for(std::size_t remaining = size - filesize, write_size = 0 | |
173 | ;remaining > 0 | |
174 | ;remaining -= write_size){ | |
175 | const std::size_t DataSize = 512; | |
176 | static char data [DataSize]; | |
177 | write_size = DataSize < remaining ? DataSize : remaining; | |
178 | unsigned long written; | |
179 | winapi::write_file(hnd, data, (unsigned long)write_size, &written, 0); | |
180 | if(written != write_size){ | |
181 | return false; | |
182 | } | |
183 | } | |
184 | } | |
185 | else{ | |
186 | if(!winapi::set_file_pointer_ex(hnd, size, 0, winapi::file_begin)){ | |
187 | return false; | |
188 | } | |
189 | if(!winapi::set_end_of_file(hnd)){ | |
190 | return false; | |
191 | } | |
192 | } | |
193 | return true; | |
194 | } | |
195 | ||
196 | inline bool get_file_size(file_handle_t hnd, offset_t &size) | |
197 | { return winapi::get_file_size(hnd, size); } | |
198 | ||
199 | inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos) | |
200 | { return winapi::set_file_pointer_ex(hnd, off, 0, (unsigned long) pos); } | |
201 | ||
202 | inline bool get_file_pointer(file_handle_t hnd, offset_t &off) | |
203 | { return winapi::set_file_pointer_ex(hnd, 0, &off, winapi::file_current); } | |
204 | ||
205 | inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata) | |
206 | { | |
207 | unsigned long written; | |
208 | return 0 != winapi::write_file(hnd, data, (unsigned long)numdata, &written, 0); | |
209 | } | |
210 | ||
211 | inline file_handle_t invalid_file() | |
212 | { return winapi::invalid_handle_value; } | |
213 | ||
214 | inline bool close_file(file_handle_t hnd) | |
215 | { return 0 != winapi::close_handle(hnd); } | |
216 | ||
217 | inline bool acquire_file_lock(file_handle_t hnd) | |
218 | { | |
219 | static winapi::interprocess_overlapped overlapped; | |
220 | const unsigned long len = ((unsigned long)-1); | |
221 | // winapi::interprocess_overlapped overlapped; | |
222 | // std::memset(&overlapped, 0, sizeof(overlapped)); | |
223 | return winapi::lock_file_ex | |
224 | (hnd, winapi::lockfile_exclusive_lock, 0, len, len, &overlapped); | |
225 | } | |
226 | ||
227 | inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired) | |
228 | { | |
229 | const unsigned long len = ((unsigned long)-1); | |
230 | winapi::interprocess_overlapped overlapped; | |
231 | std::memset(&overlapped, 0, sizeof(overlapped)); | |
232 | if(!winapi::lock_file_ex | |
233 | (hnd, winapi::lockfile_exclusive_lock | winapi::lockfile_fail_immediately, | |
234 | 0, len, len, &overlapped)){ | |
235 | return winapi::get_last_error() == winapi::error_lock_violation ? | |
236 | acquired = false, true : false; | |
237 | ||
238 | } | |
239 | return (acquired = true); | |
240 | } | |
241 | ||
242 | inline bool release_file_lock(file_handle_t hnd) | |
243 | { | |
244 | const unsigned long len = ((unsigned long)-1); | |
245 | winapi::interprocess_overlapped overlapped; | |
246 | std::memset(&overlapped, 0, sizeof(overlapped)); | |
247 | return winapi::unlock_file_ex(hnd, 0, len, len, &overlapped); | |
248 | } | |
249 | ||
250 | inline bool acquire_file_lock_sharable(file_handle_t hnd) | |
251 | { | |
252 | const unsigned long len = ((unsigned long)-1); | |
253 | winapi::interprocess_overlapped overlapped; | |
254 | std::memset(&overlapped, 0, sizeof(overlapped)); | |
255 | return winapi::lock_file_ex(hnd, 0, 0, len, len, &overlapped); | |
256 | } | |
257 | ||
258 | inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired) | |
259 | { | |
260 | const unsigned long len = ((unsigned long)-1); | |
261 | winapi::interprocess_overlapped overlapped; | |
262 | std::memset(&overlapped, 0, sizeof(overlapped)); | |
263 | if(!winapi::lock_file_ex | |
264 | (hnd, winapi::lockfile_fail_immediately, 0, len, len, &overlapped)){ | |
265 | return winapi::get_last_error() == winapi::error_lock_violation ? | |
266 | acquired = false, true : false; | |
267 | } | |
268 | return (acquired = true); | |
269 | } | |
270 | ||
271 | inline bool release_file_lock_sharable(file_handle_t hnd) | |
272 | { return release_file_lock(hnd); } | |
273 | ||
274 | inline bool delete_subdirectories_recursive | |
275 | (const std::string &refcstrRootDirectory, const char *dont_delete_this, unsigned int count) | |
276 | { | |
277 | bool bSubdirectory = false; // Flag, indicating whether | |
278 | // subdirectories have been found | |
279 | void * hFile; // Handle to directory | |
280 | std::string strFilePath; // Filepath | |
281 | std::string strPattern; // Pattern | |
282 | winapi::win32_find_data FileInformation; // File information | |
283 | ||
284 | //Find all files and directories | |
285 | strPattern = refcstrRootDirectory + "\\*.*"; | |
286 | hFile = winapi::find_first_file(strPattern.c_str(), &FileInformation); | |
287 | if(hFile != winapi::invalid_handle_value){ | |
288 | do{ | |
289 | //If it's not "." or ".." or the pointed root_level dont_delete_this erase it | |
290 | if(FileInformation.cFileName[0] != '.' && | |
291 | !(dont_delete_this && count == 0 && std::strcmp(dont_delete_this, FileInformation.cFileName) == 0)){ | |
292 | strFilePath.erase(); | |
293 | strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName; | |
294 | ||
295 | //If it's a directory, go recursive | |
296 | if(FileInformation.dwFileAttributes & winapi::file_attribute_directory){ | |
297 | // Delete subdirectory | |
298 | if(!delete_subdirectories_recursive(strFilePath, dont_delete_this, count+1)){ | |
299 | winapi::find_close(hFile); | |
300 | return false; | |
301 | } | |
302 | } | |
303 | //If it's a file, just delete it | |
304 | else{ | |
305 | // Set file attributes | |
306 | //if(::SetFileAttributes(strFilePath.c_str(), winapi::file_attribute_normal) == 0) | |
307 | //return winapi::get_last_error(); | |
308 | // Delete file | |
309 | winapi::unlink_file(strFilePath.c_str()); | |
310 | } | |
311 | } | |
312 | //Go to the next file | |
313 | } while(winapi::find_next_file(hFile, &FileInformation) == 1); | |
314 | ||
315 | // Close handle | |
316 | winapi::find_close(hFile); | |
317 | ||
318 | //See if the loop has ended with an error or just because we've traversed all the files | |
319 | if(winapi::get_last_error() != winapi::error_no_more_files){ | |
320 | return false; | |
321 | } | |
322 | else | |
323 | { | |
324 | //Erase empty subdirectories or original refcstrRootDirectory | |
325 | if(!bSubdirectory && count) | |
326 | { | |
327 | // Set directory attributes | |
328 | //if(::SetFileAttributes(refcstrRootDirectory.c_str(), FILE_ATTRIBUTE_NORMAL) == 0) | |
329 | //return ::GetLastError(); | |
330 | // Delete directory | |
331 | if(winapi::remove_directory(refcstrRootDirectory.c_str()) == 0) | |
332 | return false; | |
333 | } | |
334 | } | |
335 | } | |
336 | return true; | |
337 | } | |
338 | ||
339 | //This function erases all the subdirectories of a directory except the one pointed by "dont_delete_this" | |
340 | inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const char *dont_delete_this) | |
341 | { | |
342 | return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this, 0u); | |
343 | } | |
344 | ||
345 | ||
346 | template<class Function> | |
347 | inline bool for_each_file_in_dir(const char *dir, Function f) | |
348 | { | |
349 | void * hFile; // Handle to directory | |
350 | winapi::win32_find_data FileInformation; // File information | |
351 | ||
352 | //Get base directory | |
353 | std::string str(dir); | |
354 | const std::size_t base_root_dir_len = str.size(); | |
355 | ||
356 | //Find all files and directories | |
357 | str += "\\*.*"; | |
358 | hFile = winapi::find_first_file(str.c_str(), &FileInformation); | |
359 | if(hFile != winapi::invalid_handle_value){ | |
360 | do{ //Now loop every file | |
361 | str.erase(base_root_dir_len); | |
362 | //If it's not "." or ".." skip it | |
363 | if(FileInformation.cFileName[0] != '.'){ | |
364 | str += "\\"; str += FileInformation.cFileName; | |
365 | //If it's a file, apply erase logic | |
366 | if(!(FileInformation.dwFileAttributes & winapi::file_attribute_directory)){ | |
367 | f(str.c_str(), FileInformation.cFileName); | |
368 | } | |
369 | } | |
370 | //Go to the next file | |
371 | } while(winapi::find_next_file(hFile, &FileInformation) == 1); | |
372 | ||
373 | // Close handle and see if the loop has ended with an error | |
374 | winapi::find_close(hFile); | |
375 | if(winapi::get_last_error() != winapi::error_no_more_files){ | |
376 | return false; | |
377 | } | |
378 | } | |
379 | return true; | |
380 | } | |
381 | ||
382 | ||
383 | #else //#if defined (BOOST_INTERPROCESS_WINDOWS) | |
384 | ||
385 | typedef int file_handle_t; | |
386 | typedef off_t offset_t; | |
387 | ||
388 | typedef struct mapping_handle_impl_t | |
389 | { | |
390 | file_handle_t handle; | |
391 | bool is_xsi; | |
392 | } mapping_handle_t; | |
393 | ||
394 | typedef enum { read_only = O_RDONLY | |
395 | , read_write = O_RDWR | |
396 | , copy_on_write | |
397 | , read_private | |
398 | , invalid_mode = 0xffff | |
399 | } mode_t; | |
400 | ||
401 | typedef enum { file_begin = SEEK_SET | |
402 | , file_end = SEEK_END | |
403 | , file_current = SEEK_CUR | |
404 | } file_pos_t; | |
405 | ||
406 | typedef int map_options_t; | |
407 | static const map_options_t default_map_options = map_options_t(-1); | |
408 | ||
409 | namespace ipcdetail{ | |
410 | ||
411 | inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd) | |
412 | { | |
413 | mapping_handle_t ret; | |
414 | ret.handle = hnd; | |
415 | ret.is_xsi = false; | |
416 | return ret; | |
417 | } | |
418 | ||
419 | inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd) | |
420 | { return hnd.handle; } | |
421 | ||
422 | inline bool create_directory(const char *path) | |
423 | { return ::mkdir(path, 0777) == 0 && ::chmod(path, 0777) == 0; } | |
424 | ||
425 | inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &required_len) | |
426 | { | |
427 | required_len = 5u; | |
428 | if(buf_len < required_len) | |
429 | return false; | |
430 | else{ | |
431 | std::strcpy(buffer, "/tmp"); | |
432 | } | |
433 | return true; | |
434 | } | |
435 | ||
436 | inline file_handle_t create_new_file | |
437 | (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) | |
438 | { | |
439 | (void)temporary; | |
440 | int ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions()); | |
441 | if(ret >= 0){ | |
442 | ::fchmod(ret, perm.get_permissions()); | |
443 | } | |
444 | return ret; | |
445 | } | |
446 | ||
447 | inline file_handle_t create_or_open_file | |
448 | (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) | |
449 | { | |
450 | (void)temporary; | |
451 | int ret = -1; | |
452 | //We need a loop to change permissions correctly using fchmod, since | |
453 | //with "O_CREAT only" ::open we don't know if we've created or opened the file. | |
454 | while(1){ | |
455 | ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions()); | |
456 | if(ret >= 0){ | |
457 | ::fchmod(ret, perm.get_permissions()); | |
458 | break; | |
459 | } | |
460 | else if(errno == EEXIST){ | |
461 | if((ret = ::open(name, (int)mode)) >= 0 || errno != ENOENT){ | |
462 | break; | |
463 | } | |
464 | } | |
465 | else{ | |
466 | break; | |
467 | } | |
468 | } | |
469 | return ret; | |
470 | } | |
471 | ||
472 | inline file_handle_t open_existing_file | |
473 | (const char *name, mode_t mode, bool temporary = false) | |
474 | { | |
475 | (void)temporary; | |
476 | return ::open(name, (int)mode); | |
477 | } | |
478 | ||
479 | inline bool delete_file(const char *name) | |
480 | { return ::unlink(name) == 0; } | |
481 | ||
482 | inline bool truncate_file (file_handle_t hnd, std::size_t size) | |
483 | { | |
484 | typedef boost::move_detail::make_unsigned<off_t>::type uoff_t; | |
485 | if(uoff_t((std::numeric_limits<off_t>::max)()) < size){ | |
486 | errno = EINVAL; | |
487 | return false; | |
488 | } | |
489 | return 0 == ::ftruncate(hnd, off_t(size)); | |
490 | } | |
491 | ||
492 | inline bool get_file_size(file_handle_t hnd, offset_t &size) | |
493 | { | |
494 | struct stat data; | |
495 | bool ret = 0 == ::fstat(hnd, &data); | |
496 | if(ret){ | |
497 | size = data.st_size; | |
498 | } | |
499 | return ret; | |
500 | } | |
501 | ||
502 | inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos) | |
503 | { return ((off_t)(-1)) != ::lseek(hnd, off, (int)pos); } | |
504 | ||
505 | inline bool get_file_pointer(file_handle_t hnd, offset_t &off) | |
506 | { | |
507 | off = ::lseek(hnd, 0, SEEK_CUR); | |
508 | return off != ((off_t)-1); | |
509 | } | |
510 | ||
511 | inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata) | |
512 | { return (ssize_t(numdata)) == ::write(hnd, data, numdata); } | |
513 | ||
514 | inline file_handle_t invalid_file() | |
515 | { return -1; } | |
516 | ||
517 | inline bool close_file(file_handle_t hnd) | |
518 | { return ::close(hnd) == 0; } | |
519 | ||
520 | inline bool acquire_file_lock(file_handle_t hnd) | |
521 | { | |
522 | struct ::flock lock; | |
523 | lock.l_type = F_WRLCK; | |
524 | lock.l_whence = SEEK_SET; | |
525 | lock.l_start = 0; | |
526 | lock.l_len = 0; | |
527 | return -1 != ::fcntl(hnd, F_SETLKW, &lock); | |
528 | } | |
529 | ||
530 | inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired) | |
531 | { | |
532 | struct ::flock lock; | |
533 | lock.l_type = F_WRLCK; | |
534 | lock.l_whence = SEEK_SET; | |
535 | lock.l_start = 0; | |
536 | lock.l_len = 0; | |
537 | int ret = ::fcntl(hnd, F_SETLK, &lock); | |
538 | if(ret == -1){ | |
539 | return (errno == EAGAIN || errno == EACCES) ? | |
540 | acquired = false, true : false; | |
541 | } | |
542 | return (acquired = true); | |
543 | } | |
544 | ||
545 | inline bool release_file_lock(file_handle_t hnd) | |
546 | { | |
547 | struct ::flock lock; | |
548 | lock.l_type = F_UNLCK; | |
549 | lock.l_whence = SEEK_SET; | |
550 | lock.l_start = 0; | |
551 | lock.l_len = 0; | |
552 | return -1 != ::fcntl(hnd, F_SETLK, &lock); | |
553 | } | |
554 | ||
555 | inline bool acquire_file_lock_sharable(file_handle_t hnd) | |
556 | { | |
557 | struct ::flock lock; | |
558 | lock.l_type = F_RDLCK; | |
559 | lock.l_whence = SEEK_SET; | |
560 | lock.l_start = 0; | |
561 | lock.l_len = 0; | |
562 | return -1 != ::fcntl(hnd, F_SETLKW, &lock); | |
563 | } | |
564 | ||
565 | inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired) | |
566 | { | |
567 | struct flock lock; | |
568 | lock.l_type = F_RDLCK; | |
569 | lock.l_whence = SEEK_SET; | |
570 | lock.l_start = 0; | |
571 | lock.l_len = 0; | |
572 | int ret = ::fcntl(hnd, F_SETLK, &lock); | |
573 | if(ret == -1){ | |
574 | return (errno == EAGAIN || errno == EACCES) ? | |
575 | acquired = false, true : false; | |
576 | } | |
577 | return (acquired = true); | |
578 | } | |
579 | ||
580 | inline bool release_file_lock_sharable(file_handle_t hnd) | |
581 | { return release_file_lock(hnd); } | |
582 | ||
583 | #if 0 | |
584 | inline bool acquire_file_lock(file_handle_t hnd) | |
585 | { return 0 == ::flock(hnd, LOCK_EX); } | |
586 | ||
587 | inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired) | |
588 | { | |
589 | int ret = ::flock(hnd, LOCK_EX | LOCK_NB); | |
590 | acquired = ret == 0; | |
591 | return (acquired || errno == EWOULDBLOCK); | |
592 | } | |
593 | ||
594 | inline bool release_file_lock(file_handle_t hnd) | |
595 | { return 0 == ::flock(hnd, LOCK_UN); } | |
596 | ||
597 | inline bool acquire_file_lock_sharable(file_handle_t hnd) | |
598 | { return 0 == ::flock(hnd, LOCK_SH); } | |
599 | ||
600 | inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired) | |
601 | { | |
602 | int ret = ::flock(hnd, LOCK_SH | LOCK_NB); | |
603 | acquired = ret == 0; | |
604 | return (acquired || errno == EWOULDBLOCK); | |
605 | } | |
606 | ||
607 | inline bool release_file_lock_sharable(file_handle_t hnd) | |
608 | { return 0 == ::flock(hnd, LOCK_UN); } | |
609 | #endif | |
610 | ||
611 | inline bool delete_subdirectories_recursive | |
612 | (const std::string &refcstrRootDirectory, const char *dont_delete_this) | |
613 | { | |
614 | DIR *d = opendir(refcstrRootDirectory.c_str()); | |
615 | if(!d) { | |
616 | return false; | |
617 | } | |
618 | ||
619 | struct dir_close | |
620 | { | |
621 | DIR *d_; | |
622 | dir_close(DIR *d) : d_(d) {} | |
623 | ~dir_close() { ::closedir(d_); } | |
624 | } dc(d); (void)dc; | |
625 | ||
626 | struct ::dirent *de; | |
627 | struct ::stat st; | |
628 | std::string fn; | |
629 | ||
630 | while((de=::readdir(d))) { | |
631 | if( de->d_name[0] == '.' && ( de->d_name[1] == '\0' | |
632 | || (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){ | |
633 | continue; | |
634 | } | |
635 | if(dont_delete_this && std::strcmp(dont_delete_this, de->d_name) == 0){ | |
636 | continue; | |
637 | } | |
638 | fn = refcstrRootDirectory; | |
639 | fn += '/'; | |
640 | fn += de->d_name; | |
641 | ||
642 | if(std::remove(fn.c_str())) { | |
643 | if(::stat(fn.c_str(), & st)) { | |
644 | return false; | |
645 | } | |
646 | if(S_ISDIR(st.st_mode)) { | |
647 | if(!delete_subdirectories_recursive(fn, 0) ){ | |
648 | return false; | |
649 | } | |
650 | } else { | |
651 | return false; | |
652 | } | |
653 | } | |
654 | } | |
655 | return std::remove(refcstrRootDirectory.c_str()) ? false : true; | |
656 | } | |
657 | ||
658 | template<class Function> | |
659 | inline bool for_each_file_in_dir(const char *dir, Function f) | |
660 | { | |
661 | std::string refcstrRootDirectory(dir); | |
662 | ||
663 | DIR *d = opendir(refcstrRootDirectory.c_str()); | |
664 | if(!d) { | |
665 | return false; | |
666 | } | |
667 | ||
668 | struct dir_close | |
669 | { | |
670 | DIR *d_; | |
671 | dir_close(DIR *d) : d_(d) {} | |
672 | ~dir_close() { ::closedir(d_); } | |
673 | } dc(d); (void)dc; | |
674 | ||
675 | struct ::dirent *de; | |
676 | struct ::stat st; | |
677 | std::string fn; | |
678 | ||
679 | while((de=::readdir(d))) { | |
680 | if( de->d_name[0] == '.' && ( de->d_name[1] == '\0' | |
681 | || (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){ | |
682 | continue; | |
683 | } | |
684 | fn = refcstrRootDirectory; | |
685 | fn += '/'; | |
686 | fn += de->d_name; | |
687 | ||
688 | if(::stat(fn.c_str(), & st)) { | |
689 | return false; | |
690 | } | |
691 | //If it's a file, apply erase logic | |
692 | if(!S_ISDIR(st.st_mode)) { | |
693 | f(fn.c_str(), de->d_name); | |
694 | } | |
695 | } | |
696 | return true; | |
697 | } | |
698 | ||
699 | ||
700 | //This function erases all the subdirectories of a directory except the one pointed by "dont_delete_this" | |
701 | inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const char *dont_delete_this) | |
702 | { | |
703 | return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this ); | |
704 | } | |
705 | ||
706 | #endif //#if defined (BOOST_INTERPROCESS_WINDOWS) | |
707 | ||
708 | inline bool open_or_create_directory(const char *dir_name) | |
709 | { | |
710 | //If fails, check that it's because it already exists | |
711 | if(!create_directory(dir_name)){ | |
712 | error_info info(system_error_code()); | |
713 | if(info.get_error_code() != already_exists_error){ | |
714 | return false; | |
715 | } | |
716 | } | |
717 | return true; | |
718 | } | |
719 | ||
720 | inline std::string get_temporary_path() | |
721 | { | |
722 | std::size_t required_len = 0; | |
723 | get_temporary_path(0, 0, required_len); | |
724 | std::string ret_str(required_len, char(0)); | |
725 | get_temporary_path(&ret_str[0], ret_str.size(), required_len); | |
726 | while(!ret_str.empty() && !ret_str[ret_str.size()-1]){ | |
727 | ret_str.erase(ret_str.size()-1); | |
728 | } | |
729 | ||
730 | return ret_str; | |
731 | } | |
732 | ||
733 | } //namespace ipcdetail{ | |
734 | } //namespace interprocess { | |
735 | } //namespace boost { | |
736 | ||
737 | #include <boost/interprocess/detail/config_end.hpp> | |
738 | ||
739 | #endif //BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP |