shared_dir_helpers.hpp 6.7 KB

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