shared_dir_helpers.hpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2007-2014. 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_DETAIL_SHARED_DIR_HELPERS_HPP
  11. #define BOOST_INTERPROCESS_DETAIL_SHARED_DIR_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 <boost/interprocess/detail/os_file_functions.hpp>
  22. #include <boost/interprocess/errors.hpp>
  23. #include <boost/interprocess/exceptions.hpp>
  24. #include <string>
  25. #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) && defined(BOOST_INTERPROCESS_WINDOWS)
  26. #include <boost/interprocess/detail/windows_intermodule_singleton.hpp>
  27. #endif
  28. namespace boost {
  29. namespace interprocess {
  30. namespace ipcdetail {
  31. template<class CharT>
  32. struct shared_dir_constants;
  33. template<>
  34. struct shared_dir_constants<char>
  35. {
  36. static char dir_separator()
  37. { return '/'; }
  38. static const char *dir_interprocess()
  39. { return "/boost_interprocess"; }
  40. };
  41. template<>
  42. struct shared_dir_constants<wchar_t>
  43. {
  44. static wchar_t dir_separator()
  45. { return L'/'; }
  46. static const wchar_t *dir_interprocess()
  47. { return L"/boost_interprocess"; }
  48. };
  49. #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
  50. #if defined(BOOST_INTERPROCESS_WINDOWS)
  51. //This type will initialize the stamp
  52. template<class CharT>
  53. struct windows_bootstamp
  54. {
  55. windows_bootstamp()
  56. {
  57. //Throw if bootstamp not available
  58. if(!winapi::get_last_bootup_time(stamp)){
  59. error_info err = system_error_code();
  60. throw interprocess_exception(err);
  61. }
  62. }
  63. //Use std::string. Even if this will be constructed in shared memory, all
  64. //modules/dlls are from this process so internal raw pointers to heap are always valid
  65. std::basic_string<CharT> stamp;
  66. };
  67. template <class CharT>
  68. inline void get_bootstamp(std::basic_string<CharT> &s, bool add = false)
  69. {
  70. const windows_bootstamp<CharT> &bootstamp = windows_intermodule_singleton<windows_bootstamp<CharT> >::get();
  71. if(add){
  72. s += bootstamp.stamp;
  73. }
  74. else{
  75. s = bootstamp.stamp;
  76. }
  77. }
  78. #elif defined(BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME)
  79. inline void get_bootstamp(std::string &s, bool add = false)
  80. {
  81. // FreeBSD specific: sysctl "kern.boottime"
  82. int request[2] = { CTL_KERN, KERN_BOOTTIME };
  83. struct ::timeval result;
  84. std::size_t result_len = sizeof result;
  85. if (::sysctl (request, 2, &result, &result_len, 0, 0) < 0)
  86. return;
  87. char bootstamp_str[256];
  88. const char Characters [] =
  89. { '0', '1', '2', '3', '4', '5', '6', '7'
  90. , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
  91. std::size_t char_counter = 0;
  92. //32 bit values to allow 32 and 64 bit process IPC
  93. boost::uint32_t fields[2] = { boost::uint32_t(result.tv_sec), boost::uint32_t(result.tv_usec) };
  94. for(std::size_t field = 0; field != 2; ++field){
  95. for(std::size_t i = 0; i != sizeof(fields[0]); ++i){
  96. const char *ptr = (const char *)&fields[field];
  97. bootstamp_str[char_counter++] = Characters[(ptr[i]&0xF0)>>4];
  98. bootstamp_str[char_counter++] = Characters[(ptr[i]&0x0F)];
  99. }
  100. }
  101. bootstamp_str[char_counter] = 0;
  102. if(add){
  103. s += bootstamp_str;
  104. }
  105. else{
  106. s = bootstamp_str;
  107. }
  108. }
  109. #else
  110. #error "BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME defined with no known implementation"
  111. #endif
  112. #endif //#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
  113. template <class CharT>
  114. inline void get_shared_dir_root(std::basic_string<CharT> &dir_path)
  115. {
  116. #if defined (BOOST_INTERPROCESS_WINDOWS)
  117. winapi::get_shared_documents_folder(dir_path);
  118. #else
  119. dir_path = "/tmp";
  120. #endif
  121. //We always need this path, so throw on error
  122. if(dir_path.empty()){
  123. error_info err = system_error_code();
  124. throw interprocess_exception(err);
  125. }
  126. dir_path += shared_dir_constants<CharT>::dir_interprocess();
  127. }
  128. #if defined(BOOST_INTERPROCESS_SHARED_DIR_FUNC) && defined(BOOST_INTERPROCESS_SHARED_DIR_PATH)
  129. #error "Error: Both BOOST_INTERPROCESS_SHARED_DIR_FUNC and BOOST_INTERPROCESS_SHARED_DIR_PATH defined!"
  130. #endif
  131. #ifdef BOOST_INTERPROCESS_SHARED_DIR_FUNC
  132. // When BOOST_INTERPROCESS_SHARED_DIR_FUNC is defined, users have to implement
  133. // get_shared_dir
  134. void get_shared_dir(std::string &shared_dir);
  135. // When BOOST_INTERPROCESS_SHARED_DIR_FUNC is defined, users have to implement
  136. // get_shared_dir
  137. void get_shared_dir(std::wstring &shared_dir);
  138. #else
  139. template<class CharT>
  140. inline void get_shared_dir(std::basic_string<CharT> &shared_dir)
  141. {
  142. #if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH)
  143. shared_dir = BOOST_INTERPROCESS_SHARED_DIR_PATH;
  144. #else
  145. get_shared_dir_root(shared_dir);
  146. #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
  147. shared_dir += shared_dir_constants<CharT>::dir_separator();
  148. get_bootstamp(shared_dir, true);
  149. #endif
  150. #endif
  151. }
  152. #endif
  153. template<class CharT>
  154. inline void shared_filepath(const CharT *filename, std::basic_string<CharT> &filepath)
  155. {
  156. get_shared_dir(filepath);
  157. filepath += shared_dir_constants<CharT>::dir_separator();
  158. filepath += filename;
  159. }
  160. template<class CharT>
  161. inline void create_shared_dir_and_clean_old(std::basic_string<CharT> &shared_dir)
  162. {
  163. #if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH) || defined(BOOST_INTERPROCESS_SHARED_DIR_FUNC)
  164. get_shared_dir(shared_dir);
  165. #else
  166. //First get the temp directory
  167. std::basic_string<CharT> root_shared_dir;
  168. get_shared_dir_root(root_shared_dir);
  169. //If fails, check that it's because already exists
  170. if(!create_directory(root_shared_dir.c_str())){
  171. error_info info(system_error_code());
  172. if(info.get_error_code() != already_exists_error){
  173. throw interprocess_exception(info);
  174. }
  175. }
  176. #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
  177. get_shared_dir(shared_dir);
  178. //If fails, check that it's because already exists
  179. if(!create_directory(shared_dir.c_str())){
  180. error_info info(system_error_code());
  181. if(info.get_error_code() != already_exists_error){
  182. throw interprocess_exception(info);
  183. }
  184. }
  185. //Now erase all old directories created in the previous boot sessions
  186. std::basic_string<CharT> subdir = shared_dir;
  187. subdir.erase(0, root_shared_dir.size()+1);
  188. delete_subdirectories(root_shared_dir, subdir.c_str());
  189. #else
  190. shared_dir = root_shared_dir;
  191. #endif
  192. #endif
  193. }
  194. template<class CharT>
  195. inline void create_shared_dir_cleaning_old_and_get_filepath(const CharT *filename, std::basic_string<CharT> &shared_dir)
  196. {
  197. create_shared_dir_and_clean_old(shared_dir);
  198. shared_dir += shared_dir_constants<CharT>::dir_separator();
  199. shared_dir += filename;
  200. }
  201. template<class CharT>
  202. inline void add_leading_slash(const CharT *name, std::basic_string<CharT> &new_name)
  203. {
  204. if(name[0] != shared_dir_constants<CharT>::dir_separator()){
  205. new_name = shared_dir_constants<CharT>::dir_separator();
  206. }
  207. new_name += name;
  208. }
  209. } //namespace boost{
  210. } //namespace interprocess {
  211. } //namespace ipcdetail {
  212. #include <boost/interprocess/detail/config_end.hpp>
  213. #endif //ifndef BOOST_INTERPROCESS_DETAIL_SHARED_DIR_HELPERS_HPP