Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // (C) Copyright Ion Gaztanaga 2007-2014. Distributed under the Boost Chris@102: // Software License, Version 1.0. (See accompanying file Chris@102: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@102: // Chris@102: // See http://www.boost.org/libs/interprocess for documentation. Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_DIR_HELPERS_HPP Chris@102: #define BOOST_INTERPROCESS_DETAIL_SHARED_DIR_HELPERS_HPP Chris@102: Chris@102: #ifndef BOOST_CONFIG_HPP Chris@102: # include Chris@102: #endif Chris@102: # Chris@102: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@102: # pragma once Chris@102: #endif Chris@102: Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: Chris@102: #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) && defined(BOOST_INTERPROCESS_WINDOWS) Chris@102: #include Chris@102: #endif Chris@102: Chris@102: namespace boost { Chris@102: namespace interprocess { Chris@102: namespace ipcdetail { Chris@102: Chris@102: #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) Chris@102: #if defined(BOOST_INTERPROCESS_WINDOWS) Chris@102: //This type will initialize the stamp Chris@102: struct windows_bootstamp Chris@102: { Chris@102: windows_bootstamp() Chris@102: { Chris@102: //Throw if bootstamp not available Chris@102: if(!winapi::get_last_bootup_time(stamp)){ Chris@102: error_info err = system_error_code(); Chris@102: throw interprocess_exception(err); Chris@102: } Chris@102: } Chris@102: //Use std::string. Even if this will be constructed in shared memory, all Chris@102: //modules/dlls are from this process so internal raw pointers to heap are always valid Chris@102: std::string stamp; Chris@102: }; Chris@102: Chris@102: inline void get_bootstamp(std::string &s, bool add = false) Chris@102: { Chris@102: const windows_bootstamp &bootstamp = windows_intermodule_singleton::get(); Chris@102: if(add){ Chris@102: s += bootstamp.stamp; Chris@102: } Chris@102: else{ Chris@102: s = bootstamp.stamp; Chris@102: } Chris@102: } Chris@102: #elif defined(BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME) Chris@102: inline void get_bootstamp(std::string &s, bool add = false) Chris@102: { Chris@102: // FreeBSD specific: sysctl "kern.boottime" Chris@102: int request[2] = { CTL_KERN, KERN_BOOTTIME }; Chris@102: struct ::timeval result; Chris@102: std::size_t result_len = sizeof result; Chris@102: Chris@102: if (::sysctl (request, 2, &result, &result_len, 0, 0) < 0) Chris@102: return; Chris@102: Chris@102: char bootstamp_str[256]; Chris@102: Chris@102: const char Characters [] = Chris@102: { '0', '1', '2', '3', '4', '5', '6', '7' Chris@102: , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; Chris@102: Chris@102: std::size_t char_counter = 0; Chris@102: //32 bit values to allow 32 and 64 bit process IPC Chris@102: boost::uint32_t fields[2] = { boost::uint32_t(result.tv_sec), boost::uint32_t(result.tv_usec) }; Chris@102: for(std::size_t field = 0; field != 2; ++field){ Chris@102: for(std::size_t i = 0; i != sizeof(fields[0]); ++i){ Chris@102: const char *ptr = (const char *)&fields[field]; Chris@102: bootstamp_str[char_counter++] = Characters[(ptr[i]&0xF0)>>4]; Chris@102: bootstamp_str[char_counter++] = Characters[(ptr[i]&0x0F)]; Chris@102: } Chris@102: } Chris@102: bootstamp_str[char_counter] = 0; Chris@102: if(add){ Chris@102: s += bootstamp_str; Chris@102: } Chris@102: else{ Chris@102: s = bootstamp_str; Chris@102: } Chris@102: } Chris@102: #else Chris@102: #error "BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME defined with no known implementation" Chris@102: #endif Chris@102: #endif //#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) Chris@102: Chris@102: inline void get_shared_dir_root(std::string &dir_path) Chris@102: { Chris@102: #if defined (BOOST_INTERPROCESS_WINDOWS) Chris@102: winapi::get_shared_documents_folder(dir_path); Chris@102: #else Chris@102: dir_path = "/tmp"; Chris@102: #endif Chris@102: //We always need this path, so throw on error Chris@102: if(dir_path.empty()){ Chris@102: error_info err = system_error_code(); Chris@102: throw interprocess_exception(err); Chris@102: } Chris@102: //Remove final null. Chris@102: dir_path += "/boost_interprocess"; Chris@102: } Chris@102: Chris@102: inline void get_shared_dir(std::string &shared_dir) Chris@102: { Chris@102: #if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH) Chris@102: shared_dir = BOOST_INTERPROCESS_SHARED_DIR_PATH; Chris@102: #else Chris@102: get_shared_dir_root(shared_dir); Chris@102: #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) Chris@102: shared_dir += "/"; Chris@102: get_bootstamp(shared_dir, true); Chris@102: #endif Chris@102: #endif Chris@102: } Chris@102: Chris@102: inline void shared_filepath(const char *filename, std::string &filepath) Chris@102: { Chris@102: get_shared_dir(filepath); Chris@102: filepath += "/"; Chris@102: filepath += filename; Chris@102: } Chris@102: Chris@102: inline void create_shared_dir_and_clean_old(std::string &shared_dir) Chris@102: { Chris@102: #if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH) Chris@102: shared_dir = BOOST_INTERPROCESS_SHARED_DIR_PATH; Chris@102: #else Chris@102: //First get the temp directory Chris@102: std::string root_shared_dir; Chris@102: get_shared_dir_root(root_shared_dir); Chris@102: Chris@102: //If fails, check that it's because already exists Chris@102: if(!create_directory(root_shared_dir.c_str())){ Chris@102: error_info info(system_error_code()); Chris@102: if(info.get_error_code() != already_exists_error){ Chris@102: throw interprocess_exception(info); Chris@102: } Chris@102: } Chris@102: Chris@102: #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) Chris@102: get_shared_dir(shared_dir); Chris@102: Chris@102: //If fails, check that it's because already exists Chris@102: if(!create_directory(shared_dir.c_str())){ Chris@102: error_info info(system_error_code()); Chris@102: if(info.get_error_code() != already_exists_error){ Chris@102: throw interprocess_exception(info); Chris@102: } Chris@102: } Chris@102: //Now erase all old directories created in the previous boot sessions Chris@102: std::string subdir = shared_dir; Chris@102: subdir.erase(0, root_shared_dir.size()+1); Chris@102: delete_subdirectories(root_shared_dir, subdir.c_str()); Chris@102: #else Chris@102: shared_dir = root_shared_dir; Chris@102: #endif Chris@102: #endif Chris@102: } Chris@102: Chris@102: inline void create_shared_dir_cleaning_old_and_get_filepath(const char *filename, std::string &shared_dir) Chris@102: { Chris@102: create_shared_dir_and_clean_old(shared_dir); Chris@102: shared_dir += "/"; Chris@102: shared_dir += filename; Chris@102: } Chris@102: Chris@102: inline void add_leading_slash(const char *name, std::string &new_name) Chris@102: { Chris@102: if(name[0] != '/'){ Chris@102: new_name = '/'; Chris@102: } Chris@102: new_name += name; Chris@102: } Chris@102: Chris@102: } //namespace boost{ Chris@102: } //namespace interprocess { Chris@102: } //namespace ipcdetail { Chris@102: Chris@102: #include Chris@102: Chris@102: #endif //ifndef BOOST_INTERPROCESS_DETAIL_SHARED_DIR_HELPERS_HPP