-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommon.cpp
More file actions
155 lines (117 loc) · 3.87 KB
/
common.cpp
File metadata and controls
155 lines (117 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem.hpp>
#include <glib.h>
#include <fmt/format.h>
#include <grp.h>
#include "common.hpp"
#include "throw-with-trace.hpp"
namespace fs = boost::filesystem;
using fmt::literals::operator""_format;
// Opens an output stream and checks for errors
std::ofstream open_ofstream(const std::string &path)
{
std::ofstream f;
f.exceptions(std::ifstream::failbit | std::ifstream::badbit);
f.open(path);
return f;
}
// Opens an intput stream and checks for errors
std::ifstream open_ifstream(const std::string &path)
{
std::ifstream f;
// Throw on error
f.exceptions(std::ifstream::failbit | std::ifstream::badbit);
f.open(path);
return f;
}
std::ifstream open_ifstream(const boost::filesystem::path &path)
{
return open_ifstream(path.string());
}
std::ofstream open_ofstream(const boost::filesystem::path &path)
{
return open_ofstream(path.string());
}
void assert_dir_exists(const boost::filesystem::path &dir)
{
if (!fs::exists(dir))
throw_with_trace(std::runtime_error("Dir {} does not exist"_format(dir.string())));
if (!fs::is_directory(dir))
throw_with_trace(std::runtime_error("{} is not a directory"_format(dir.string())));
}
// Returns the executable basename from a commandline
std::string extract_executable_name(const std::string &cmd)
{
int argc;
char **argv;
if (!g_shell_parse_argv(cmd.c_str(), &argc, &argv, NULL))
throw_with_trace(std::runtime_error("Could not parse commandline '" + cmd + "'"));
std::string result = boost::filesystem::basename(argv[0]);
g_strfreev(argv); // Free the memory allocated for argv
return result;
}
void dir_copy(const std::string &source, const std::string &dest)
{
namespace fs = boost::filesystem;
if (!fs::exists(source) || !fs::is_directory(source))
throw_with_trace(std::runtime_error("Source directory " + source + " does not exist or is not a directory"));
if (fs::exists(dest))
throw_with_trace(std::runtime_error("Destination directory " + dest + " already exists"));
if (!fs::create_directories(dest))
throw_with_trace(std::runtime_error("Cannot create destination directory " + dest));
typedef fs::recursive_directory_iterator RDIter;
for (auto it = RDIter(source), end = RDIter(); it != end; ++it)
{
const auto &path = it->path();
auto relpath = it->path().string();
boost::replace_first(relpath, source, ""); // Convert the path to a relative path
fs::copy(path, dest + "/" + relpath);
}
}
std::string random_string(size_t length)
{
auto randchar = []() -> char
{
const char charset[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
const size_t max_index = (sizeof(charset) - 1);
return charset[rand() % max_index];
};
std::string str(length,0);
std::generate_n(str.begin(), length, randchar);
return str;
}
// Drop sudo privileges
void drop_privileges()
{
const char *uidstr = getenv("SUDO_UID");
const char *gidstr = getenv("SUDO_GID");
const char *userstr = getenv("SUDO_USER");
if (!uidstr || !gidstr || !userstr)
return;
const uid_t uid = std::stol(uidstr);
const gid_t gid = std::stol(gidstr);
if (uid == getuid() && gid == getgid())
return;
if (setgid(gid) < 0)
throw_with_trace(std::runtime_error("Cannot change gid: " + std::string(strerror(errno))));
if (initgroups(userstr, gid) < 0)
throw_with_trace(std::runtime_error("Cannot change group access list: " + std::string(strerror(errno))));
if (setuid(uid) < 0)
throw_with_trace(std::runtime_error("Cannot change uid: " + std::string(strerror(errno))));
}
void set_cpu_affinity(std::vector<uint32_t> cpus, pid_t pid)
{
// All cpus allowed
if (cpus.size() == 0)
return;
// Set CPU affinity
cpu_set_t mask;
CPU_ZERO(&mask);
for (auto cpu : cpus)
CPU_SET(cpu, &mask);
if (sched_setaffinity(pid, sizeof(mask), &mask) < 0)
throw_with_trace(std::runtime_error("Could not set CPU affinity: " + std::string(strerror(errno))));
}