tmp_dir_helpers.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2007-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_DETAIL_TMP_DIR_HELPERS_HPP
  11. #define BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP
  12. #include <boost/interprocess/detail/config_begin.hpp>
  13. #include <boost/interprocess/detail/workaround.hpp>
  14. #include <boost/interprocess/detail/os_file_functions.hpp>
  15. #include <boost/interprocess/errors.hpp>
  16. #include <boost/interprocess/exceptions.hpp>
  17. #include <string>
  18. #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) && defined(BOOST_INTERPROCESS_WINDOWS)
  19. #include <boost/interprocess/detail/windows_intermodule_singleton.hpp>
  20. #endif
  21. namespace boost {
  22. namespace interprocess {
  23. namespace ipcdetail {
  24. #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
  25. #if defined(BOOST_INTERPROCESS_WINDOWS)
  26. //This type will initialize the stamp
  27. struct windows_bootstamp
  28. {
  29. windows_bootstamp()
  30. {
  31. winapi::get_last_bootup_time(stamp);
  32. }
  33. //Use std::string. Even if this will be constructed in shared memory, all
  34. //modules/dlls are from this process so internal raw pointers to heap are always valid
  35. std::string stamp;
  36. };
  37. inline void get_bootstamp(std::string &s, bool add = false)
  38. {
  39. const windows_bootstamp &bootstamp = windows_intermodule_singleton<windows_bootstamp>::get();
  40. if(add){
  41. s += bootstamp.stamp;
  42. }
  43. else{
  44. s = bootstamp.stamp;
  45. }
  46. }
  47. #elif defined(BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME)
  48. inline void get_bootstamp(std::string &s, bool add = false)
  49. {
  50. // FreeBSD specific: sysctl "kern.boottime"
  51. int request[2] = { CTL_KERN, KERN_BOOTTIME };
  52. struct ::timeval result;
  53. std::size_t result_len = sizeof result;
  54. if (::sysctl (request, 2, &result, &result_len, 0, 0) < 0)
  55. return;
  56. char bootstamp_str[256];
  57. const char Characters [] =
  58. { '0', '1', '2', '3', '4', '5', '6', '7'
  59. , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
  60. std::size_t char_counter = 0;
  61. //32 bit values to allow 32 and 64 bit process IPC
  62. boost::uint32_t fields[2] = { boost::uint32_t(result.tv_sec), boost::uint32_t(result.tv_usec) };
  63. for(std::size_t field = 0; field != 2; ++field){
  64. for(std::size_t i = 0; i != sizeof(fields[0]); ++i){
  65. const char *ptr = (const char *)&fields[field];
  66. bootstamp_str[char_counter++] = Characters[(ptr[i]&0xF0)>>4];
  67. bootstamp_str[char_counter++] = Characters[(ptr[i]&0x0F)];
  68. }
  69. }
  70. bootstamp_str[char_counter] = 0;
  71. if(add){
  72. s += bootstamp_str;
  73. }
  74. else{
  75. s = bootstamp_str;
  76. }
  77. }
  78. #else
  79. #error "BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME defined with no known implementation"
  80. #endif
  81. #endif //#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
  82. inline void get_tmp_base_dir(std::string &tmp_name)
  83. {
  84. #if defined (BOOST_INTERPROCESS_WINDOWS)
  85. winapi::get_shared_documents_folder(tmp_name);
  86. if(tmp_name.empty() || !winapi::is_directory(tmp_name.c_str())){
  87. tmp_name = get_temporary_path();
  88. }
  89. #else
  90. tmp_name = get_temporary_path();
  91. #endif
  92. if(tmp_name.empty()){
  93. error_info err = system_error_code();
  94. throw interprocess_exception(err);
  95. }
  96. //Remove final null.
  97. tmp_name += "/boost_interprocess";
  98. }
  99. inline void tmp_folder(std::string &tmp_name)
  100. {
  101. get_tmp_base_dir(tmp_name);
  102. #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
  103. tmp_name += "/";
  104. get_bootstamp(tmp_name, true);
  105. #endif
  106. }
  107. inline void tmp_filename(const char *filename, std::string &tmp_name)
  108. {
  109. tmp_folder(tmp_name);
  110. tmp_name += "/";
  111. tmp_name += filename;
  112. }
  113. inline void create_tmp_and_clean_old(std::string &tmp_name)
  114. {
  115. //First get the temp directory
  116. std::string root_tmp_name;
  117. get_tmp_base_dir(root_tmp_name);
  118. //If fails, check that it's because already exists
  119. if(!create_directory(root_tmp_name.c_str())){
  120. error_info info(system_error_code());
  121. if(info.get_error_code() != already_exists_error){
  122. throw interprocess_exception(info);
  123. }
  124. }
  125. #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
  126. tmp_folder(tmp_name);
  127. //If fails, check that it's because already exists
  128. if(!create_directory(tmp_name.c_str())){
  129. error_info info(system_error_code());
  130. if(info.get_error_code() != already_exists_error){
  131. throw interprocess_exception(info);
  132. }
  133. }
  134. //Now erase all old directories created in the previous boot sessions
  135. std::string subdir = tmp_name;
  136. subdir.erase(0, root_tmp_name.size()+1);
  137. delete_subdirectories(root_tmp_name, subdir.c_str());
  138. #else
  139. tmp_name = root_tmp_name;
  140. #endif
  141. }
  142. inline void create_tmp_and_clean_old_and_get_filename(const char *filename, std::string &tmp_name)
  143. {
  144. create_tmp_and_clean_old(tmp_name);
  145. tmp_name += "/";
  146. tmp_name += filename;
  147. }
  148. inline void add_leading_slash(const char *name, std::string &new_name)
  149. {
  150. if(name[0] != '/'){
  151. new_name = '/';
  152. }
  153. new_name += name;
  154. }
  155. } //namespace boost{
  156. } //namespace interprocess {
  157. } //namespace ipcdetail {
  158. #include <boost/interprocess/detail/config_end.hpp>
  159. #endif //ifndef BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP