diff --git a/include/ircd/fs/path.h b/include/ircd/fs/path.h index 121559a91..e935539f0 100644 --- a/include/ircd/fs/path.h +++ b/include/ircd/fs/path.h @@ -30,6 +30,7 @@ namespace ircd::fs // convenience tls buffers of appropriate size. extern const mutable_buffer path_scratch; extern const mutable_buffer name_scratch; + const char *path_str(const string_view &); filesystem::path _path(std::string); filesystem::path _path(const string_view &); diff --git a/ircd/Makefile.am b/ircd/Makefile.am index b7f071676..9e0481096 100644 --- a/ircd/Makefile.am +++ b/ircd/Makefile.am @@ -139,6 +139,7 @@ if LINUX libircd_la_SOURCES += prof_linux.cc endif libircd_la_SOURCES += fs.cc +libircd_la_SOURCES += fs_path.cc libircd_la_SOURCES += ios.cc libircd_la_SOURCES += ctx_x86_64.S libircd_la_SOURCES += ctx.cc diff --git a/ircd/fs.cc b/ircd/fs.cc index ae11405c6..eb28eee1d 100644 --- a/ircd/fs.cc +++ b/ircd/fs.cc @@ -13,8 +13,8 @@ #include #include #ifdef IRCD_USE_AIO #include "fs_aio.h" @@ -1611,7 +1611,6 @@ noexcept namespace ircd::fs { - static const char *path_str(const string_view &); static uint posix_flags(const std::ios::openmode &mode); static long pathconf(const fd &, const int &arg); } @@ -2168,324 +2167,6 @@ ircd::fs::bytes(const const_iovec_view &iov) }); } -/////////////////////////////////////////////////////////////////////////////// -// -// fs/path.h -// - -/// Default maximum path string length (for all filesystems & platforms). -decltype(ircd::fs::NAME_MAX_LEN) -ircd::fs::NAME_MAX_LEN -{ - #ifdef NAME_MAX - NAME_MAX - #elif defined(_POSIX_NAME_MAX) - _POSIX_NAME_MAX - #else - 255 - #endif -}; - -/// Default maximum path string length (for all filesystems & platforms). -decltype(ircd::fs::PATH_MAX_LEN) -ircd::fs::PATH_MAX_LEN -{ - #ifdef PATH_MAX - PATH_MAX - #elif defined(_POSIX_PATH_MAX) - _POSIX_PATH_MAX - #else - 4096 - #endif -}; - -namespace ircd::fs -{ - thread_local char _path_scratch[PATH_MAX_LEN]; - thread_local char _name_scratch[NAME_MAX_LEN]; -} - -decltype(ircd::fs::path_scratch) -ircd::fs::path_scratch -{ - _path_scratch -}; - -decltype(ircd::fs::name_scratch) -ircd::fs::name_scratch -{ - _name_scratch -}; - -std::string -ircd::fs::cwd() -try -{ - const auto &cur - { - filesystem::current_path() - }; - - return cur.string(); -} -catch(const filesystem::filesystem_error &e) -{ - throw error{e}; -} - -ircd::string_view -ircd::fs::cwd(const mutable_buffer &buf) -try -{ - const auto &cur - { - filesystem::current_path() - }; - - return strlcpy(buf, cur.native()); -} -catch(const filesystem::filesystem_error &e) -{ - throw error{e}; -} - -#ifdef _PC_PATH_MAX -size_t -ircd::fs::path_max_len(const string_view &path) -{ - return pathconf(path, _PC_PATH_MAX); -} -#else -size_t -ircd::fs::path_max_len(const string_view &path) -{ - return PATH_MAX_LEN; -} -#endif - -#ifdef _PC_NAME_MAX -size_t -ircd::fs::name_max_len(const string_view &path) -{ - return pathconf(path, _PC_NAME_MAX); -} -#elif defined(HAVE_SYS_STATFS_H) -size_t -ircd::fs::name_max_len(const string_view &path) -{ - struct statfs f{0}; - syscall(::statfs, path_str(path), &f); - return f.f_namelen; -} -#else -size_t -ircd::fs::name_max_len(const string_view &path) -{ - return NAME_MAX_LEN; -} -#endif - -long -ircd::fs::pathconf(const string_view &path, - const int &arg) -{ - return syscall(::pathconf, path_str(path), arg); -} - -ircd::string_view -ircd::fs::filename(const mutable_buffer &buf, - const string_view &p) -{ - return path(buf, _path(p).filename()); -} - -ircd::string_view -ircd::fs::extension(const mutable_buffer &buf, - const string_view &p) -{ - return path(buf, _path(p).extension()); -} - -ircd::string_view -ircd::fs::extension(const mutable_buffer &buf, - const string_view &p, - const string_view &replace) -{ - return path(buf, _path(p).replace_extension(_path(replace))); -} - -ircd::string_view -ircd::fs::relative(const mutable_buffer &buf, - const string_view &root, - const string_view &p) -{ - return path(buf, relative(_path(p), _path(root))); -} - -bool -ircd::fs::is_relative(const string_view &p) -{ - return _path(p).is_relative(); -} - -bool -ircd::fs::is_absolute(const string_view &p) -{ - return _path(p).is_absolute(); -} - -// -// fs::path() -// - -ircd::string_view -ircd::fs::path(const mutable_buffer &buf, - const filesystem::path &path) -{ - return strlcpy(buf, path.c_str()); -} - -ircd::string_view -ircd::fs::path(const mutable_buffer &buf, - const path_strings &list) -{ - return strlcpy(buf, _path(list).c_str()); -} - -ircd::string_view -ircd::fs::path(const mutable_buffer &buf, - const path_view &list) -{ - return strlcpy(buf, _path(list).c_str()); -} - -ircd::string_view -ircd::fs::path(const mutable_buffer &buf, - const base &base, - const string_view &rest) -{ - const auto p - { - _path(std::initializer_list - { - path(base), - rest, - }) - }; - - return strlcpy(buf, p.c_str()); -} - -ircd::string_view -ircd::fs::path(const base &base) -noexcept -{ - return basepath::get(base).path; -} - -// -// fs::_path() -// - -boost::filesystem::path -ircd::fs::_path(const path_strings &list) -try -{ - filesystem::path ret; - for(const auto &s : list) - ret /= s; - - return ret.string(); -} -catch(const filesystem::filesystem_error &e) -{ - throw error{e}; -} - -boost::filesystem::path -ircd::fs::_path(const path_view &list) -try -{ - filesystem::path ret; - for(const auto &s : list) - ret /= _path(s); - - return ret.string(); -} -catch(const filesystem::filesystem_error &e) -{ - throw error{e}; -} - -boost::filesystem::path -ircd::fs::_path(const string_view &s) -try -{ - return _path(std::string{s}); -} -catch(const filesystem::filesystem_error &e) -{ - throw error{e}; -} - -boost::filesystem::path -ircd::fs::_path(std::string s) -try -{ - return filesystem::path{std::move(s)}; -} -catch(const filesystem::filesystem_error &e) -{ - throw error{e}; -} - -// -// fs::basepath -// - -namespace ircd::fs -{ - extern std::array()> basepaths; -} - -decltype(ircd::fs::basepaths) -ircd::fs::basepaths -{{ - { "installation prefix", RB_PREFIX }, - { "binary directory", RB_BIN_DIR }, - { "configuration directory", RB_CONF_DIR }, - { "data directory", RB_DATA_DIR }, - { "database directory", RB_DB_DIR }, - { "log directory", RB_LOG_DIR }, - { "library directory", RB_LIB_DIR }, - { "module directory", RB_MODULE_DIR }, -}}; - -ircd::string_view -ircd::fs::basepath::set(const base &base, - const string_view &path) -{ - log::debug - { - log, "Updating base path #%u '%s' from `%s' to `%s'", - uint(base), - basepaths.at(uint(base)).name, - basepaths.at(uint(base)).path, - path, - }; - - const string_view ret(basepaths.at(uint(base)).path); - basepaths.at(uint(base)).path = path; - return ret; -} - -const ircd::fs::basepath & -ircd::fs::basepath::get(const base &base) -noexcept -{ - return basepaths.at(uint(base)); -} - /////////////////////////////////////////////////////////////////////////////// // // fs/error.h @@ -2551,18 +2232,6 @@ ircd::fs::error::error(const boost::filesystem::filesystem_error &e) // Internal utils // -const char * -ircd::fs::path_str(const string_view &s) -{ - static const size_t sz{PATH_MAX_LEN}, cnt{8}; - thread_local char buffer[cnt][sz]; - thread_local size_t i{0}; - auto &buf(buffer[i]); - ++i %= cnt; - strlcpy(buf, s); - return buf; -} - uint ircd::fs::posix_flags(const std::ios::openmode &mode) { diff --git a/ircd/fs_path.cc b/ircd/fs_path.cc new file mode 100644 index 000000000..cf089a632 --- /dev/null +++ b/ircd/fs_path.cc @@ -0,0 +1,339 @@ +// The Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2020 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#include + +/// Default maximum path string length (for all filesystems & platforms). +decltype(ircd::fs::NAME_MAX_LEN) +ircd::fs::NAME_MAX_LEN +{ + #ifdef NAME_MAX + NAME_MAX + #elif defined(_POSIX_NAME_MAX) + _POSIX_NAME_MAX + #else + 255 + #endif +}; + +/// Default maximum path string length (for all filesystems & platforms). +decltype(ircd::fs::PATH_MAX_LEN) +ircd::fs::PATH_MAX_LEN +{ + #ifdef PATH_MAX + PATH_MAX + #elif defined(_POSIX_PATH_MAX) + _POSIX_PATH_MAX + #else + 4096 + #endif +}; + +namespace ircd::fs +{ + thread_local char _path_scratch[PATH_MAX_LEN]; + thread_local char _name_scratch[NAME_MAX_LEN]; +} + +decltype(ircd::fs::path_scratch) +ircd::fs::path_scratch +{ + _path_scratch +}; + +decltype(ircd::fs::name_scratch) +ircd::fs::name_scratch +{ + _name_scratch +}; + +std::string +ircd::fs::cwd() +try +{ + const auto &cur + { + filesystem::current_path() + }; + + return cur.string(); +} +catch(const filesystem::filesystem_error &e) +{ + throw error{e}; +} + +ircd::string_view +ircd::fs::cwd(const mutable_buffer &buf) +try +{ + const auto &cur + { + filesystem::current_path() + }; + + return strlcpy(buf, cur.native()); +} +catch(const filesystem::filesystem_error &e) +{ + throw error{e}; +} + +#ifdef _PC_PATH_MAX +size_t +ircd::fs::path_max_len(const string_view &path) +{ + return pathconf(path, _PC_PATH_MAX); +} +#else +size_t +ircd::fs::path_max_len(const string_view &path) +{ + return PATH_MAX_LEN; +} +#endif + +#ifdef _PC_NAME_MAX +size_t +ircd::fs::name_max_len(const string_view &path) +{ + return pathconf(path, _PC_NAME_MAX); +} +#elif defined(HAVE_SYS_STATFS_H) +size_t +ircd::fs::name_max_len(const string_view &path) +{ + struct statfs f{0}; + syscall(::statfs, path_str(path), &f); + return f.f_namelen; +} +#else +size_t +ircd::fs::name_max_len(const string_view &path) +{ + return NAME_MAX_LEN; +} +#endif + +long +ircd::fs::pathconf(const string_view &path, + const int &arg) +{ + return syscall(::pathconf, path_str(path), arg); +} + +ircd::string_view +ircd::fs::filename(const mutable_buffer &buf, + const string_view &p) +{ + return path(buf, _path(p).filename()); +} + +ircd::string_view +ircd::fs::extension(const mutable_buffer &buf, + const string_view &p) +{ + return path(buf, _path(p).extension()); +} + +ircd::string_view +ircd::fs::extension(const mutable_buffer &buf, + const string_view &p, + const string_view &replace) +{ + return path(buf, _path(p).replace_extension(_path(replace))); +} + +ircd::string_view +ircd::fs::relative(const mutable_buffer &buf, + const string_view &root, + const string_view &p) +{ + return path(buf, relative(_path(p), _path(root))); +} + +bool +ircd::fs::is_relative(const string_view &p) +{ + return _path(p).is_relative(); +} + +bool +ircd::fs::is_absolute(const string_view &p) +{ + return _path(p).is_absolute(); +} + +// +// fs::path() +// + +ircd::string_view +ircd::fs::path(const mutable_buffer &buf, + const filesystem::path &path) +{ + return strlcpy(buf, path.c_str()); +} + +ircd::string_view +ircd::fs::path(const mutable_buffer &buf, + const path_strings &list) +{ + return strlcpy(buf, _path(list).c_str()); +} + +ircd::string_view +ircd::fs::path(const mutable_buffer &buf, + const path_view &list) +{ + return strlcpy(buf, _path(list).c_str()); +} + +ircd::string_view +ircd::fs::path(const mutable_buffer &buf, + const base &base, + const string_view &rest) +{ + const auto p + { + _path(std::initializer_list + { + path(base), + rest, + }) + }; + + return strlcpy(buf, p.c_str()); +} + +ircd::string_view +ircd::fs::path(const base &base) +noexcept +{ + return basepath::get(base).path; +} + +// +// fs::_path() +// + +boost::filesystem::path +ircd::fs::_path(const path_strings &list) +try +{ + filesystem::path ret; + for(const auto &s : list) + ret /= s; + + return ret.string(); +} +catch(const filesystem::filesystem_error &e) +{ + throw error{e}; +} + +boost::filesystem::path +ircd::fs::_path(const path_view &list) +try +{ + filesystem::path ret; + for(const auto &s : list) + ret /= _path(s); + + return ret.string(); +} +catch(const filesystem::filesystem_error &e) +{ + throw error{e}; +} + +boost::filesystem::path +ircd::fs::_path(const string_view &s) +try +{ + return _path(std::string{s}); +} +catch(const filesystem::filesystem_error &e) +{ + throw error{e}; +} + +boost::filesystem::path +ircd::fs::_path(std::string s) +try +{ + return filesystem::path{std::move(s)}; +} +catch(const filesystem::filesystem_error &e) +{ + throw error{e}; +} + +const char * +ircd::fs::path_str(const string_view &s) +{ + static const size_t sz{PATH_MAX_LEN}, cnt{8}; + thread_local char buffer[cnt][sz]; + thread_local size_t i{0}; + auto &buf(buffer[i]); + ++i %= cnt; + strlcpy(buf, s); + return buf; +} + +// +// fs::basepath +// + +namespace ircd::fs +{ + extern std::array()> basepaths; +} + +decltype(ircd::fs::basepaths) +ircd::fs::basepaths +{{ + { "installation prefix", RB_PREFIX }, + { "binary directory", RB_BIN_DIR }, + { "configuration directory", RB_CONF_DIR }, + { "data directory", RB_DATA_DIR }, + { "database directory", RB_DB_DIR }, + { "log directory", RB_LOG_DIR }, + { "library directory", RB_LIB_DIR }, + { "module directory", RB_MODULE_DIR }, +}}; + +ircd::string_view +ircd::fs::basepath::set(const base &base, + const string_view &path) +{ + log::debug + { + log, "Updating base path #%u '%s' from `%s' to `%s'", + uint(base), + basepaths.at(uint(base)).name, + basepaths.at(uint(base)).path, + path, + }; + + const string_view ret(basepaths.at(uint(base)).path); + basepaths.at(uint(base)).path = path; + return ret; +} + +const ircd::fs::basepath & +ircd::fs::basepath::get(const base &base) +noexcept +{ + return basepaths.at(uint(base)); +}