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