3 #include "iobuffer.hpp"
7 #include <boost/algorithm/string/classification.hpp>
8 #include <boost/algorithm/string/split.hpp>
12 #include <sys/types.h>
14 #include <gflags/gflags.h>
18 DEFINE_string(config_dir
, "", "path to support/config files");
20 #include <sys/utsname.h>
24 #include <sys/socket.h>
25 #include <sys/types.h>
27 #include <glog/logging.h>
31 fs::path
get_config_dir()
33 if (!FLAGS_config_dir
.empty()) {
34 return FLAGS_config_dir
;
37 return get_exe_path().parent_path();
39 // Maybe work from some installed location...
40 // if ends in /bin, switch to /share or /etc
42 // auto path = get_exe_path().parent_path();
43 // if (fs::is_directory(path) && (path.filename() == "bin")) {
45 // share.replace_filename("share");
46 // if (fs::exists(share) && fs::is_directory(share))
52 fs::path
get_exe_path()
54 // The std::experimental::filesystem::read_symlink() as shipped with
55 // GCC 7.2.1 20170915 included with Fedora 27 is unusable when lstat
56 // returns st_size of zero, as happens with /proc/self/exe.
58 // This problem has been corrected in later versions, but this code
59 // should work on everything POSIX.
61 auto constexpr exe
= "/proc/self/exe";
63 auto constexpr max_link
= 4 * 1024;
66 auto const len
{::readlink(exe
, buf
, max_link
)};
68 PCHECK(len
!= -1) << "readlink";
69 if (len
== max_link
) {
70 LOG(FATAL
) << exe
<< " link too long";
76 fs::path
get_home_dir()
78 auto const homedir_ev
{getenv("HOME")};
83 errno
= 0; // See GETPWNAM(3)
85 PCHECK(pw
= getpwuid(getuid()));
90 std::string
get_hostname()
93 PCHECK(uname(&un
) == 0);
95 auto node
= std::string(un
.nodename
);
97 // auto labels{std::vector<std::string>{}};
98 // boost::algorithm::split(labels, node,
99 // boost::algorithm::is_any_of("."));
100 // if (labels.size() < 2) {
101 // node += ".digilicious.com";
107 uint16_t get_port(char const* const service
, char const* const proto
)
110 auto const service_no
{strtoul(service
, &ep
, 10)};
111 if (ep
&& (*ep
== '\0')) {
112 CHECK_LE(service_no
, std::numeric_limits
<uint16_t>::max());
113 return static_cast<uint16_t>(service_no
);
116 iobuffer
<char> str_buf
{1024}; // suggested by getservbyname_r(3)
118 auto result_buf
{servent
{}};
119 servent
* result_ptr
= nullptr;
120 while (getservbyname_r(service
, proto
, &result_buf
, str_buf
.data(),
121 str_buf
.size(), &result_ptr
)
123 CHECK_LT(str_buf
.size(), 64 * 1024); // ridiculous
124 str_buf
.resize(str_buf
.size() * 2);
126 if (result_ptr
== nullptr) {
127 LOG(FATAL
) << "service " << service
<< " unknown";
129 return ntohs(result_buf
.s_port
);
132 std::vector
<fs::path
> list_directory(
133 fs::path
const& path
,
134 // pattern should be std::string_view see p0506r0:
135 // <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0506r0.pdf>
137 std::string
const& pattern
)
139 std::vector
<fs::path
> ret
;
141 auto const traits
= std::regex_constants::ECMAScript
142 #if defined(__APPLE__) || defined(_WIN32)
143 | std::regex_constants::icase
147 std::regex
const pattern_regex(pattern
, traits
);
149 auto const di
= fs::directory_iterator(path
);
150 for (auto const& it
: di
) {
151 auto const it_filename
= it
.path().filename().string();
153 if (std::regex_match(it_filename
, matches
, pattern_regex
)) {
154 ret
.push_back(it
.path());
161 } // namespace osutil