file_locking_helpers.hpp 6.9 KB

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