| 1 | //////////////////////////////////////////////////////////////////////////////
|
|---|
| 2 | //
|
|---|
| 3 | // (C) Copyright Ion Gaztanaga 2005-2011. 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_OS_FILE_FUNCTIONS_HPP
|
|---|
| 12 | #define BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP
|
|---|
| 13 |
|
|---|
| 14 | #include <boost/interprocess/detail/config_begin.hpp>
|
|---|
| 15 | #include <boost/interprocess/detail/workaround.hpp>
|
|---|
| 16 | #include <boost/interprocess/errors.hpp>
|
|---|
| 17 | #include <boost/interprocess/permissions.hpp>
|
|---|
| 18 |
|
|---|
| 19 | #include <string>
|
|---|
| 20 | #include <limits>
|
|---|
| 21 | #include <climits>
|
|---|
| 22 |
|
|---|
| 23 | std::string g_app_tmp_path="";
|
|---|
| 24 |
|
|---|
| 25 | #if (defined BOOST_INTERPROCESS_WINDOWS)
|
|---|
| 26 | # include <boost/interprocess/detail/win32_api.hpp>
|
|---|
| 27 | #else
|
|---|
| 28 | # ifdef BOOST_HAS_UNISTD_H
|
|---|
| 29 | # include <fcntl.h>
|
|---|
| 30 | # include <unistd.h>
|
|---|
| 31 | # include <sys/types.h>
|
|---|
| 32 | # include <sys/stat.h>
|
|---|
| 33 | # include <errno.h>
|
|---|
| 34 | # include <cstdio>
|
|---|
| 35 | # include <dirent.h>
|
|---|
| 36 | # if 0
|
|---|
| 37 | # include <sys/file.h>
|
|---|
| 38 | # endif
|
|---|
| 39 | # else
|
|---|
| 40 | # error Unknown platform
|
|---|
| 41 | # endif
|
|---|
| 42 | #endif
|
|---|
| 43 |
|
|---|
| 44 | #include <cstring>
|
|---|
| 45 | #include <cstdlib>
|
|---|
| 46 |
|
|---|
| 47 | namespace boost {
|
|---|
| 48 | namespace interprocess {
|
|---|
| 49 |
|
|---|
| 50 | #if (defined BOOST_INTERPROCESS_WINDOWS)
|
|---|
| 51 |
|
|---|
| 52 | typedef void * file_handle_t;
|
|---|
| 53 | typedef long long offset_t;
|
|---|
| 54 | typedef struct mapping_handle_impl_t{
|
|---|
| 55 | void * handle;
|
|---|
| 56 | bool is_shm;
|
|---|
| 57 | } mapping_handle_t;
|
|---|
| 58 |
|
|---|
| 59 | typedef enum { read_only = winapi::generic_read
|
|---|
| 60 | , read_write = winapi::generic_read | winapi::generic_write
|
|---|
| 61 | , copy_on_write
|
|---|
| 62 | , read_private
|
|---|
| 63 | , invalid_mode = 0xffff
|
|---|
| 64 | } mode_t;
|
|---|
| 65 |
|
|---|
| 66 | typedef enum { file_begin = winapi::file_begin
|
|---|
| 67 | , file_end = winapi::file_end
|
|---|
| 68 | , file_current = winapi::file_current
|
|---|
| 69 | } file_pos_t;
|
|---|
| 70 |
|
|---|
| 71 | namespace ipcdetail{
|
|---|
| 72 |
|
|---|
| 73 | inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
|
|---|
| 74 | {
|
|---|
| 75 | mapping_handle_t ret;
|
|---|
| 76 | ret.handle = hnd;
|
|---|
| 77 | ret.is_shm = false;
|
|---|
| 78 | return ret;
|
|---|
| 79 | }
|
|---|
| 80 |
|
|---|
| 81 | inline mapping_handle_t mapping_handle_from_shm_handle(file_handle_t hnd)
|
|---|
| 82 | {
|
|---|
| 83 | mapping_handle_t ret;
|
|---|
| 84 | ret.handle = hnd;
|
|---|
| 85 | ret.is_shm = true;
|
|---|
| 86 | return ret;
|
|---|
| 87 | }
|
|---|
| 88 |
|
|---|
| 89 | inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
|
|---|
| 90 | { return hnd.handle; }
|
|---|
| 91 |
|
|---|
| 92 | inline bool create_directory(const char *path)
|
|---|
| 93 | { return winapi::create_directory(path); }
|
|---|
| 94 |
|
|---|
| 95 | inline const char *get_temporary_path()
|
|---|
| 96 | {
|
|---|
| 97 | if(g_app_tmp_path.empty())
|
|---|
| 98 | return NULL;
|
|---|
| 99 |
|
|---|
| 100 | return std::getenv("TMP");
|
|---|
| 101 | }
|
|---|
| 102 |
|
|---|
| 103 | inline file_handle_t create_new_file
|
|---|
| 104 | (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
|
|---|
| 105 | {
|
|---|
| 106 | unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
|
|---|
| 107 | return winapi::create_file
|
|---|
| 108 | ( name, (unsigned int)mode, winapi::create_new, attr
|
|---|
| 109 | , (winapi::interprocess_security_attributes*)perm.get_permissions());
|
|---|
| 110 | }
|
|---|
| 111 |
|
|---|
| 112 | inline file_handle_t create_or_open_file
|
|---|
| 113 | (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
|
|---|
| 114 | {
|
|---|
| 115 | unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
|
|---|
| 116 | return winapi::create_file
|
|---|
| 117 | ( name, (unsigned int)mode, winapi::open_always, attr
|
|---|
| 118 | , (winapi::interprocess_security_attributes*)perm.get_permissions());
|
|---|
| 119 | }
|
|---|
| 120 |
|
|---|
| 121 | inline file_handle_t open_existing_file
|
|---|
| 122 | (const char *name, mode_t mode, bool temporary = false)
|
|---|
| 123 | {
|
|---|
| 124 | unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
|
|---|
| 125 | return winapi::create_file
|
|---|
| 126 | (name, (unsigned int)mode, winapi::open_existing, attr, 0);
|
|---|
| 127 | }
|
|---|
| 128 |
|
|---|
| 129 | inline bool delete_file(const char *name)
|
|---|
| 130 | { return winapi::unlink_file(name); }
|
|---|
| 131 |
|
|---|
| 132 | inline bool truncate_file (file_handle_t hnd, std::size_t size)
|
|---|
| 133 | {
|
|---|
| 134 | offset_t filesize;
|
|---|
| 135 | if(!winapi::get_file_size(hnd, filesize))
|
|---|
| 136 | return false;
|
|---|
| 137 |
|
|---|
| 138 | const offset_t max_filesize = (std::numeric_limits<offset_t>::max)();
|
|---|
| 139 | //Avoid unused variable warnings in 32 bit systems
|
|---|
| 140 | (void)max_filesize;
|
|---|
| 141 | if( sizeof(std::size_t) >= sizeof(offset_t) && size > std::size_t(max_filesize) ){
|
|---|
| 142 | winapi::set_last_error(winapi::error_file_too_large);
|
|---|
| 143 | return false;
|
|---|
| 144 | }
|
|---|
| 145 |
|
|---|
| 146 | if(offset_t(size) > filesize){
|
|---|
| 147 | if(!winapi::set_file_pointer_ex(hnd, filesize, 0, winapi::file_begin)){
|
|---|
| 148 | return false;
|
|---|
| 149 | }
|
|---|
| 150 | //We will write zeros in the end of the file
|
|---|
| 151 | //since set_end_of_file does not guarantee this
|
|---|
| 152 | for(std::size_t remaining = size - filesize, write_size = 0
|
|---|
| 153 | ;remaining > 0
|
|---|
| 154 | ;remaining -= write_size){
|
|---|
| 155 | const std::size_t DataSize = 512;
|
|---|
| 156 | static char data [DataSize];
|
|---|
| 157 | write_size = DataSize < remaining ? DataSize : remaining;
|
|---|
| 158 | unsigned long written;
|
|---|
| 159 | winapi::write_file(hnd, data, (unsigned long)write_size, &written, 0);
|
|---|
| 160 | if(written != write_size){
|
|---|
| 161 | return false;
|
|---|
| 162 | }
|
|---|
| 163 | }
|
|---|
| 164 | }
|
|---|
| 165 | else{
|
|---|
| 166 | if(!winapi::set_file_pointer_ex(hnd, size, 0, winapi::file_begin)){
|
|---|
| 167 | return false;
|
|---|
| 168 | }
|
|---|
| 169 | if(!winapi::set_end_of_file(hnd)){
|
|---|
| 170 | return false;
|
|---|
| 171 | }
|
|---|
| 172 | }
|
|---|
| 173 | return true;
|
|---|
| 174 | }
|
|---|
| 175 |
|
|---|
| 176 | inline bool get_file_size(file_handle_t hnd, offset_t &size)
|
|---|
| 177 | { return winapi::get_file_size(hnd, size); }
|
|---|
| 178 |
|
|---|
| 179 | inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos)
|
|---|
| 180 | { return winapi::set_file_pointer_ex(hnd, off, 0, (unsigned long) pos); }
|
|---|
| 181 |
|
|---|
| 182 | inline bool get_file_pointer(file_handle_t hnd, offset_t &off)
|
|---|
| 183 | { return winapi::set_file_pointer_ex(hnd, 0, &off, winapi::file_current); }
|
|---|
| 184 |
|
|---|
| 185 | inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata)
|
|---|
| 186 | {
|
|---|
| 187 | unsigned long written;
|
|---|
| 188 | return 0 != winapi::write_file(hnd, data, (unsigned long)numdata, &written, 0);
|
|---|
| 189 | }
|
|---|
| 190 |
|
|---|
| 191 | inline file_handle_t invalid_file()
|
|---|
| 192 | { return winapi::invalid_handle_value; }
|
|---|
| 193 |
|
|---|
| 194 | inline bool close_file(file_handle_t hnd)
|
|---|
| 195 | { return 0 != winapi::close_handle(hnd); }
|
|---|
| 196 |
|
|---|
| 197 | inline bool acquire_file_lock(file_handle_t hnd)
|
|---|
| 198 | {
|
|---|
| 199 | static winapi::interprocess_overlapped overlapped;
|
|---|
| 200 | const unsigned long len = 0xffffffff;
|
|---|
| 201 | // winapi::interprocess_overlapped overlapped;
|
|---|
| 202 | // std::memset(&overlapped, 0, sizeof(overlapped));
|
|---|
| 203 | return winapi::lock_file_ex
|
|---|
| 204 | (hnd, winapi::lockfile_exclusive_lock, 0, len, len, &overlapped);
|
|---|
| 205 | }
|
|---|
| 206 |
|
|---|
| 207 | inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
|
|---|
| 208 | {
|
|---|
| 209 | const unsigned long len = 0xffffffff;
|
|---|
| 210 | winapi::interprocess_overlapped overlapped;
|
|---|
| 211 | std::memset(&overlapped, 0, sizeof(overlapped));
|
|---|
| 212 | if(!winapi::lock_file_ex
|
|---|
| 213 | (hnd, winapi::lockfile_exclusive_lock | winapi::lockfile_fail_immediately,
|
|---|
| 214 | 0, len, len, &overlapped)){
|
|---|
| 215 | return winapi::get_last_error() == winapi::error_lock_violation ?
|
|---|
| 216 | acquired = false, true : false;
|
|---|
| 217 |
|
|---|
| 218 | }
|
|---|
| 219 | return (acquired = true);
|
|---|
| 220 | }
|
|---|
| 221 |
|
|---|
| 222 | inline bool release_file_lock(file_handle_t hnd)
|
|---|
| 223 | {
|
|---|
| 224 | const unsigned long len = 0xffffffff;
|
|---|
| 225 | winapi::interprocess_overlapped overlapped;
|
|---|
| 226 | std::memset(&overlapped, 0, sizeof(overlapped));
|
|---|
| 227 | return winapi::unlock_file_ex(hnd, 0, len, len, &overlapped);
|
|---|
| 228 | }
|
|---|
| 229 |
|
|---|
| 230 | inline bool acquire_file_lock_sharable(file_handle_t hnd)
|
|---|
| 231 | {
|
|---|
| 232 | const unsigned long len = 0xffffffff;
|
|---|
| 233 | winapi::interprocess_overlapped overlapped;
|
|---|
| 234 | std::memset(&overlapped, 0, sizeof(overlapped));
|
|---|
| 235 | return winapi::lock_file_ex(hnd, 0, 0, len, len, &overlapped);
|
|---|
| 236 | }
|
|---|
| 237 |
|
|---|
| 238 | inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
|
|---|
| 239 | {
|
|---|
| 240 | const unsigned long len = 0xffffffff;
|
|---|
| 241 | winapi::interprocess_overlapped overlapped;
|
|---|
| 242 | std::memset(&overlapped, 0, sizeof(overlapped));
|
|---|
| 243 | if(!winapi::lock_file_ex
|
|---|
| 244 | (hnd, winapi::lockfile_fail_immediately, 0, len, len, &overlapped)){
|
|---|
| 245 | return winapi::get_last_error() == winapi::error_lock_violation ?
|
|---|
| 246 | acquired = false, true : false;
|
|---|
| 247 | }
|
|---|
| 248 | return (acquired = true);
|
|---|
| 249 | }
|
|---|
| 250 |
|
|---|
| 251 | inline bool release_file_lock_sharable(file_handle_t hnd)
|
|---|
| 252 | { return release_file_lock(hnd); }
|
|---|
| 253 |
|
|---|
| 254 | inline bool delete_subdirectories_recursive
|
|---|
| 255 | (const std::string &refcstrRootDirectory, const char *dont_delete_this, unsigned int count)
|
|---|
| 256 | {
|
|---|
| 257 | bool bSubdirectory = false; // Flag, indicating whether
|
|---|
| 258 | // subdirectories have been found
|
|---|
| 259 | void * hFile; // Handle to directory
|
|---|
| 260 | std::string strFilePath; // Filepath
|
|---|
| 261 | std::string strPattern; // Pattern
|
|---|
| 262 | winapi::win32_find_data_t FileInformation; // File information
|
|---|
| 263 |
|
|---|
| 264 | //Find all files and directories
|
|---|
| 265 | strPattern = refcstrRootDirectory + "\\*.*";
|
|---|
| 266 | hFile = winapi::find_first_file(strPattern.c_str(), &FileInformation);
|
|---|
| 267 | if(hFile != winapi::invalid_handle_value){
|
|---|
| 268 | do{
|
|---|
| 269 | //If it's not "." or ".." or the pointed root_level dont_delete_this erase it
|
|---|
| 270 | if(FileInformation.cFileName[0] != '.' &&
|
|---|
| 271 | !(dont_delete_this && count == 0 && std::strcmp(dont_delete_this, FileInformation.cFileName) == 0)){
|
|---|
| 272 | strFilePath.erase();
|
|---|
| 273 | strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;
|
|---|
| 274 |
|
|---|
| 275 | //If it's a directory, go recursive
|
|---|
| 276 | if(FileInformation.dwFileAttributes & winapi::file_attribute_directory){
|
|---|
| 277 | // Delete subdirectory
|
|---|
| 278 | if(!delete_subdirectories_recursive(strFilePath, dont_delete_this, count+1))
|
|---|
| 279 | return false;
|
|---|
| 280 | }
|
|---|
| 281 | //If it's a file, just delete it
|
|---|
| 282 | else{
|
|---|
| 283 | // Set file attributes
|
|---|
| 284 | //if(::SetFileAttributes(strFilePath.c_str(), winapi::file_attribute_normal) == 0)
|
|---|
| 285 | //return winapi::get_last_error();
|
|---|
| 286 | // Delete file
|
|---|
| 287 | winapi::delete_file(strFilePath.c_str());
|
|---|
| 288 | }
|
|---|
| 289 | }
|
|---|
| 290 | //Go to the next file
|
|---|
| 291 | } while(winapi::find_next_file(hFile, &FileInformation) == 1);
|
|---|
| 292 |
|
|---|
| 293 | // Close handle
|
|---|
| 294 | winapi::find_close(hFile);
|
|---|
| 295 |
|
|---|
| 296 | //See if the loop has ended with an error or just because we've traversed all the files
|
|---|
| 297 | if(winapi::get_last_error() != winapi::error_no_more_files){
|
|---|
| 298 | return false;
|
|---|
| 299 | }
|
|---|
| 300 | else
|
|---|
| 301 | {
|
|---|
| 302 | //Erase empty subdirectories or original refcstrRootDirectory
|
|---|
| 303 | if(!bSubdirectory && count)
|
|---|
| 304 | {
|
|---|
| 305 | // Set directory attributes
|
|---|
| 306 | //if(::SetFileAttributes(refcstrRootDirectory.c_str(), FILE_ATTRIBUTE_NORMAL) == 0)
|
|---|
| 307 | //return ::GetLastError();
|
|---|
| 308 | // Delete directory
|
|---|
| 309 | if(winapi::remove_directory(refcstrRootDirectory.c_str()) == 0)
|
|---|
| 310 | return false;
|
|---|
| 311 | }
|
|---|
| 312 | }
|
|---|
| 313 | }
|
|---|
| 314 | return true;
|
|---|
| 315 | }
|
|---|
| 316 |
|
|---|
| 317 | //This function erases all the subdirectories of a directory except the one pointed by "dont_delete_this"
|
|---|
| 318 | inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const char *dont_delete_this)
|
|---|
| 319 | {
|
|---|
| 320 | return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this, 0u);
|
|---|
| 321 | }
|
|---|
| 322 |
|
|---|
| 323 |
|
|---|
| 324 | template<class Function>
|
|---|
| 325 | inline bool for_each_file_in_dir(const char *dir, Function f)
|
|---|
| 326 | {
|
|---|
| 327 | void * hFile; // Handle to directory
|
|---|
| 328 | winapi::win32_find_data_t FileInformation; // File information
|
|---|
| 329 |
|
|---|
| 330 | //Get base directory
|
|---|
| 331 | std::string str(dir);
|
|---|
| 332 | const std::size_t base_root_dir_len = str.size();
|
|---|
| 333 |
|
|---|
| 334 | //Find all files and directories
|
|---|
| 335 | str += "\\*.*";
|
|---|
| 336 | hFile = winapi::find_first_file(str.c_str(), &FileInformation);
|
|---|
| 337 | if(hFile != winapi::invalid_handle_value){
|
|---|
| 338 | do{ //Now loop every file
|
|---|
| 339 | str.erase(base_root_dir_len);
|
|---|
| 340 | //If it's not "." or ".." skip it
|
|---|
| 341 | if(FileInformation.cFileName[0] != '.'){
|
|---|
| 342 | str += "\\"; str += FileInformation.cFileName;
|
|---|
| 343 | //If it's a file, apply erase logic
|
|---|
| 344 | if(!(FileInformation.dwFileAttributes & winapi::file_attribute_directory)){
|
|---|
| 345 | f(str.c_str(), FileInformation.cFileName);
|
|---|
| 346 | }
|
|---|
| 347 | }
|
|---|
| 348 | //Go to the next file
|
|---|
| 349 | } while(winapi::find_next_file(hFile, &FileInformation) == 1);
|
|---|
| 350 |
|
|---|
| 351 | // Close handle and see if the loop has ended with an error
|
|---|
| 352 | winapi::find_close(hFile);
|
|---|
| 353 | if(winapi::get_last_error() != winapi::error_no_more_files){
|
|---|
| 354 | return false;
|
|---|
| 355 | }
|
|---|
| 356 | }
|
|---|
| 357 | return true;
|
|---|
| 358 | }
|
|---|
| 359 |
|
|---|
| 360 |
|
|---|
| 361 | #else //#if (defined BOOST_INTERPROCESS_WINDOWS)
|
|---|
| 362 |
|
|---|
| 363 | typedef int file_handle_t;
|
|---|
| 364 | typedef off_t offset_t;
|
|---|
| 365 |
|
|---|
| 366 | typedef struct mapping_handle_impl_t
|
|---|
| 367 | {
|
|---|
| 368 | file_handle_t handle;
|
|---|
| 369 | bool is_xsi;
|
|---|
| 370 | } mapping_handle_t;
|
|---|
| 371 |
|
|---|
| 372 | typedef enum { read_only = O_RDONLY
|
|---|
| 373 | , read_write = O_RDWR
|
|---|
| 374 | , copy_on_write
|
|---|
| 375 | , read_private
|
|---|
| 376 | , invalid_mode = 0xffff
|
|---|
| 377 | } mode_t;
|
|---|
| 378 |
|
|---|
| 379 | typedef enum { file_begin = SEEK_SET
|
|---|
| 380 | , file_end = SEEK_END
|
|---|
| 381 | , file_current = SEEK_CUR
|
|---|
| 382 | } file_pos_t;
|
|---|
| 383 |
|
|---|
| 384 | namespace ipcdetail{
|
|---|
| 385 |
|
|---|
| 386 | inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
|
|---|
| 387 | {
|
|---|
| 388 | mapping_handle_t ret;
|
|---|
| 389 | ret.handle = hnd;
|
|---|
| 390 | ret.is_xsi = false;
|
|---|
| 391 | return ret;
|
|---|
| 392 | }
|
|---|
| 393 |
|
|---|
| 394 | inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
|
|---|
| 395 | { return hnd.handle; }
|
|---|
| 396 |
|
|---|
| 397 | inline bool create_directory(const char *path)
|
|---|
| 398 | { return ::mkdir(path, 0777) == 0 && ::chmod(path, 0777) == 0; }
|
|---|
| 399 |
|
|---|
| 400 | inline const char *get_temporary_path()
|
|---|
| 401 | {
|
|---|
| 402 | if(g_app_tmp_path.empty())
|
|---|
| 403 | {
|
|---|
| 404 | const char *names[] = {"/tmp", "TMPDIR", "TMP", "TEMP", getenv("APPDIR")};
|
|---|
| 405 | const int names_size = sizeof(names)/sizeof(names[0]);
|
|---|
| 406 | struct stat data;
|
|---|
| 407 | for(int i = 0; i != names_size; ++i){
|
|---|
| 408 | if(::stat(names[i], &data) == 0){
|
|---|
| 409 | return names[i];
|
|---|
| 410 | }
|
|---|
| 411 | }
|
|---|
| 412 | return "/tmp";
|
|---|
| 413 | }
|
|---|
| 414 | else
|
|---|
| 415 | {
|
|---|
| 416 | return g_app_tmp_path.c_str();
|
|---|
| 417 | }
|
|---|
| 418 | return "/tmp";
|
|---|
| 419 | }
|
|---|
| 420 |
|
|---|
| 421 | inline void set_temporary_path(const char *tmp_path=NULL)
|
|---|
| 422 | {
|
|---|
| 423 | if (tmp_path != NULL)
|
|---|
| 424 | {
|
|---|
| 425 | g_app_tmp_path = tmp_path;
|
|---|
| 426 | }
|
|---|
| 427 | }
|
|---|
| 428 |
|
|---|
| 429 | inline file_handle_t create_new_file
|
|---|
| 430 | (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
|
|---|
| 431 | {
|
|---|
| 432 | (void)temporary;
|
|---|
| 433 | int ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions());
|
|---|
| 434 | if(ret >= 0){
|
|---|
| 435 | ::fchmod(ret, perm.get_permissions());
|
|---|
| 436 | }
|
|---|
| 437 | return ret;
|
|---|
| 438 | }
|
|---|
| 439 |
|
|---|
| 440 | inline file_handle_t create_or_open_file
|
|---|
| 441 | (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
|
|---|
| 442 | {
|
|---|
| 443 | (void)temporary;
|
|---|
| 444 | int ret = -1;
|
|---|
| 445 | //We need a loop to change permissions correctly using fchmod, since
|
|---|
| 446 | //with "O_CREAT only" ::open we don't know if we've created or opened the file.
|
|---|
| 447 | while(1){
|
|---|
| 448 | ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions());
|
|---|
| 449 | if(ret >= 0){
|
|---|
| 450 | ::fchmod(ret, perm.get_permissions());
|
|---|
| 451 | break;
|
|---|
| 452 | }
|
|---|
| 453 | else if(errno == EEXIST){
|
|---|
| 454 | if((ret = ::open(name, (int)mode)) >= 0 || errno != ENOENT){
|
|---|
| 455 | break;
|
|---|
| 456 | }
|
|---|
| 457 | }
|
|---|
| 458 | }
|
|---|
| 459 | return ret;
|
|---|
| 460 | }
|
|---|
| 461 |
|
|---|
| 462 | inline file_handle_t open_existing_file
|
|---|
| 463 | (const char *name, mode_t mode, bool temporary = false)
|
|---|
| 464 | {
|
|---|
| 465 | (void)temporary;
|
|---|
| 466 | return ::open(name, (int)mode);
|
|---|
| 467 | }
|
|---|
| 468 |
|
|---|
| 469 | inline bool delete_file(const char *name)
|
|---|
| 470 | { return ::unlink(name) == 0; }
|
|---|
| 471 |
|
|---|
| 472 | inline bool truncate_file (file_handle_t hnd, std::size_t size)
|
|---|
| 473 | {
|
|---|
| 474 | if(sizeof(off_t) == sizeof(std::size_t)){
|
|---|
| 475 | if(size > ((~std::size_t(0)) >> 1)){
|
|---|
| 476 | errno = EINVAL;
|
|---|
| 477 | return false;
|
|---|
| 478 | }
|
|---|
| 479 | }
|
|---|
| 480 | return 0 == ::ftruncate(hnd, off_t(size));
|
|---|
| 481 | }
|
|---|
| 482 |
|
|---|
| 483 | inline bool get_file_size(file_handle_t hnd, offset_t &size)
|
|---|
| 484 | {
|
|---|
| 485 | struct stat data;
|
|---|
| 486 | bool ret = 0 == ::fstat(hnd, &data);
|
|---|
| 487 | if(ret){
|
|---|
| 488 | size = data.st_size;
|
|---|
| 489 | }
|
|---|
| 490 | return ret;
|
|---|
| 491 | }
|
|---|
| 492 |
|
|---|
| 493 | inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos)
|
|---|
| 494 | { return ((off_t)(-1)) != ::lseek(hnd, off, (int)pos); }
|
|---|
| 495 |
|
|---|
| 496 | inline bool get_file_pointer(file_handle_t hnd, offset_t &off)
|
|---|
| 497 | {
|
|---|
| 498 | off = ::lseek(hnd, 0, SEEK_CUR);
|
|---|
| 499 | return off != ((off_t)-1);
|
|---|
| 500 | }
|
|---|
| 501 |
|
|---|
| 502 | inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata)
|
|---|
| 503 | { return (ssize_t(numdata)) == ::write(hnd, data, numdata); }
|
|---|
| 504 |
|
|---|
| 505 | inline file_handle_t invalid_file()
|
|---|
| 506 | { return -1; }
|
|---|
| 507 |
|
|---|
| 508 | inline bool close_file(file_handle_t hnd)
|
|---|
| 509 | { return ::close(hnd) == 0; }
|
|---|
| 510 |
|
|---|
| 511 | inline bool acquire_file_lock(file_handle_t hnd)
|
|---|
| 512 | {
|
|---|
| 513 | struct ::flock lock;
|
|---|
| 514 | lock.l_type = F_WRLCK;
|
|---|
| 515 | lock.l_whence = SEEK_SET;
|
|---|
| 516 | lock.l_start = 0;
|
|---|
| 517 | lock.l_len = 0;
|
|---|
| 518 | return -1 != ::fcntl(hnd, F_SETLKW, &lock);
|
|---|
| 519 | }
|
|---|
| 520 |
|
|---|
| 521 | inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
|
|---|
| 522 | {
|
|---|
| 523 | struct ::flock lock;
|
|---|
| 524 | lock.l_type = F_WRLCK;
|
|---|
| 525 | lock.l_whence = SEEK_SET;
|
|---|
| 526 | lock.l_start = 0;
|
|---|
| 527 | lock.l_len = 0;
|
|---|
| 528 | int ret = ::fcntl(hnd, F_SETLK, &lock);
|
|---|
| 529 | if(ret == -1){
|
|---|
| 530 | return (errno == EAGAIN || errno == EACCES) ?
|
|---|
| 531 | acquired = false, true : false;
|
|---|
| 532 | }
|
|---|
| 533 | return (acquired = true);
|
|---|
| 534 | }
|
|---|
| 535 |
|
|---|
| 536 | inline bool release_file_lock(file_handle_t hnd)
|
|---|
| 537 | {
|
|---|
| 538 | struct ::flock lock;
|
|---|
| 539 | lock.l_type = F_UNLCK;
|
|---|
| 540 | lock.l_whence = SEEK_SET;
|
|---|
| 541 | lock.l_start = 0;
|
|---|
| 542 | lock.l_len = 0;
|
|---|
| 543 | return -1 != ::fcntl(hnd, F_SETLK, &lock);
|
|---|
| 544 | }
|
|---|
| 545 |
|
|---|
| 546 | inline bool acquire_file_lock_sharable(file_handle_t hnd)
|
|---|
| 547 | {
|
|---|
| 548 | struct ::flock lock;
|
|---|
| 549 | lock.l_type = F_RDLCK;
|
|---|
| 550 | lock.l_whence = SEEK_SET;
|
|---|
| 551 | lock.l_start = 0;
|
|---|
| 552 | lock.l_len = 0;
|
|---|
| 553 | return -1 != ::fcntl(hnd, F_SETLKW, &lock);
|
|---|
| 554 | }
|
|---|
| 555 |
|
|---|
| 556 | inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
|
|---|
| 557 | {
|
|---|
| 558 | struct flock lock;
|
|---|
| 559 | lock.l_type = F_RDLCK;
|
|---|
| 560 | lock.l_whence = SEEK_SET;
|
|---|
| 561 | lock.l_start = 0;
|
|---|
| 562 | lock.l_len = 0;
|
|---|
| 563 | int ret = ::fcntl(hnd, F_SETLK, &lock);
|
|---|
| 564 | if(ret == -1){
|
|---|
| 565 | return (errno == EAGAIN || errno == EACCES) ?
|
|---|
| 566 | acquired = false, true : false;
|
|---|
| 567 | }
|
|---|
| 568 | return (acquired = true);
|
|---|
| 569 | }
|
|---|
| 570 |
|
|---|
| 571 | inline bool release_file_lock_sharable(file_handle_t hnd)
|
|---|
| 572 | { return release_file_lock(hnd); }
|
|---|
| 573 |
|
|---|
| 574 | #if 0
|
|---|
| 575 | inline bool acquire_file_lock(file_handle_t hnd)
|
|---|
| 576 | { return 0 == ::flock(hnd, LOCK_EX); }
|
|---|
| 577 |
|
|---|
| 578 | inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
|
|---|
| 579 | {
|
|---|
| 580 | int ret = ::flock(hnd, LOCK_EX | LOCK_NB);
|
|---|
| 581 | acquired = ret == 0;
|
|---|
| 582 | return (acquired || errno == EWOULDBLOCK);
|
|---|
| 583 | }
|
|---|
| 584 |
|
|---|
| 585 | inline bool release_file_lock(file_handle_t hnd)
|
|---|
| 586 | { return 0 == ::flock(hnd, LOCK_UN); }
|
|---|
| 587 |
|
|---|
| 588 | inline bool acquire_file_lock_sharable(file_handle_t hnd)
|
|---|
| 589 | { return 0 == ::flock(hnd, LOCK_SH); }
|
|---|
| 590 |
|
|---|
| 591 | inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
|
|---|
| 592 | {
|
|---|
| 593 | int ret = ::flock(hnd, LOCK_SH | LOCK_NB);
|
|---|
| 594 | acquired = ret == 0;
|
|---|
| 595 | return (acquired || errno == EWOULDBLOCK);
|
|---|
| 596 | }
|
|---|
| 597 |
|
|---|
| 598 | inline bool release_file_lock_sharable(file_handle_t hnd)
|
|---|
| 599 | { return 0 == ::flock(hnd, LOCK_UN); }
|
|---|
| 600 | #endif
|
|---|
| 601 |
|
|---|
| 602 | inline bool delete_subdirectories_recursive
|
|---|
| 603 | (const std::string &refcstrRootDirectory, const char *dont_delete_this)
|
|---|
| 604 | {
|
|---|
| 605 | DIR *d = opendir(refcstrRootDirectory.c_str());
|
|---|
| 606 | if(!d) {
|
|---|
| 607 | return false;
|
|---|
| 608 | }
|
|---|
| 609 |
|
|---|
| 610 | struct dir_close
|
|---|
| 611 | {
|
|---|
| 612 | DIR *d_;
|
|---|
| 613 | dir_close(DIR *d) : d_(d) {}
|
|---|
| 614 | ~dir_close() { ::closedir(d_); }
|
|---|
| 615 | } dc(d); (void)dc;
|
|---|
| 616 |
|
|---|
| 617 | struct ::dirent *de;
|
|---|
| 618 | struct ::stat st;
|
|---|
| 619 | std::string fn;
|
|---|
| 620 |
|
|---|
| 621 | while((de=::readdir(d))) {
|
|---|
| 622 | if( de->d_name[0] == '.' && ( de->d_name[1] == '\0'
|
|---|
| 623 | || (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){
|
|---|
| 624 | continue;
|
|---|
| 625 | }
|
|---|
| 626 | if(dont_delete_this && std::strcmp(dont_delete_this, de->d_name) == 0){
|
|---|
| 627 | continue;
|
|---|
| 628 | }
|
|---|
| 629 | fn = refcstrRootDirectory;
|
|---|
| 630 | fn += '/';
|
|---|
| 631 | fn += de->d_name;
|
|---|
| 632 |
|
|---|
| 633 | if(std::remove(fn.c_str())) {
|
|---|
| 634 | if(::stat(fn.c_str(), & st)) {
|
|---|
| 635 | return false;
|
|---|
| 636 | }
|
|---|
| 637 | if(S_ISDIR(st.st_mode)) {
|
|---|
| 638 | if(!delete_subdirectories_recursive(fn, 0) ){
|
|---|
| 639 | return false;
|
|---|
| 640 | }
|
|---|
| 641 | } else {
|
|---|
| 642 | return false;
|
|---|
| 643 | }
|
|---|
| 644 | }
|
|---|
| 645 | }
|
|---|
| 646 | return std::remove(refcstrRootDirectory.c_str()) ? false : true;
|
|---|
| 647 | }
|
|---|
| 648 |
|
|---|
| 649 | template<class Function>
|
|---|
| 650 | inline bool for_each_file_in_dir(const char *dir, Function f)
|
|---|
| 651 | {
|
|---|
| 652 | std::string refcstrRootDirectory(dir);
|
|---|
| 653 |
|
|---|
| 654 | DIR *d = opendir(refcstrRootDirectory.c_str());
|
|---|
| 655 | if(!d) {
|
|---|
| 656 | return false;
|
|---|
| 657 | }
|
|---|
| 658 |
|
|---|
| 659 | struct dir_close
|
|---|
| 660 | {
|
|---|
| 661 | DIR *d_;
|
|---|
| 662 | dir_close(DIR *d) : d_(d) {}
|
|---|
| 663 | ~dir_close() { ::closedir(d_); }
|
|---|
| 664 | } dc(d); (void)dc;
|
|---|
| 665 |
|
|---|
| 666 | struct ::dirent *de;
|
|---|
| 667 | struct ::stat st;
|
|---|
| 668 | std::string fn;
|
|---|
| 669 |
|
|---|
| 670 | while((de=::readdir(d))) {
|
|---|
| 671 | if( de->d_name[0] == '.' && ( de->d_name[1] == '\0'
|
|---|
| 672 | || (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){
|
|---|
| 673 | continue;
|
|---|
| 674 | }
|
|---|
| 675 | fn = refcstrRootDirectory;
|
|---|
| 676 | fn += '/';
|
|---|
| 677 | fn += de->d_name;
|
|---|
| 678 |
|
|---|
| 679 | if(::stat(fn.c_str(), & st)) {
|
|---|
| 680 | return false;
|
|---|
| 681 | }
|
|---|
| 682 | //If it's a file, apply erase logic
|
|---|
| 683 | if(!S_ISDIR(st.st_mode)) {
|
|---|
| 684 | f(fn.c_str(), de->d_name);
|
|---|
| 685 | }
|
|---|
| 686 | }
|
|---|
| 687 | return true;
|
|---|
| 688 | }
|
|---|
| 689 |
|
|---|
| 690 |
|
|---|
| 691 | //This function erases all the subdirectories of a directory except the one pointed by "dont_delete_this"
|
|---|
| 692 | inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const char *dont_delete_this)
|
|---|
| 693 | {
|
|---|
| 694 | return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this );
|
|---|
| 695 | }
|
|---|
| 696 |
|
|---|
| 697 | #endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
|
|---|
| 698 |
|
|---|
| 699 | inline bool open_or_create_directory(const char *dir_name)
|
|---|
| 700 | {
|
|---|
| 701 | //If fails, check that it's because it already exists
|
|---|
| 702 | if(!create_directory(dir_name)){
|
|---|
| 703 | error_info info(system_error_code());
|
|---|
| 704 | if(info.get_error_code() != already_exists_error){
|
|---|
| 705 | return false;
|
|---|
| 706 | }
|
|---|
| 707 | }
|
|---|
| 708 | return true;
|
|---|
| 709 | }
|
|---|
| 710 |
|
|---|
| 711 |
|
|---|
| 712 | } //namespace ipcdetail{
|
|---|
| 713 | } //namespace interprocess {
|
|---|
| 714 | } //namespace boost {
|
|---|
| 715 |
|
|---|
| 716 | #include <boost/interprocess/detail/config_end.hpp>
|
|---|
| 717 |
|
|---|
| 718 | #endif //BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP
|
|---|