10 #include <sys/xattr.h>
37 *calling_uid = getuid();
38 *effective_uid = geteuid();
42 const char *arg1,
const char *arg2,
const char *arg3,
45 char *argv[] = { strdup(binary),
46 arg1 ? strdup(arg1) : NULL,
47 arg2 ? strdup(arg2) : NULL,
48 arg3 ? strdup(arg3) : NULL,
49 arg4 ? strdup(arg4) : NULL,
51 char *environ[] = { NULL };
53 int retval = setuid(0);
55 fprintf(stderr,
"failed to gain root privileges (%d)\n", errno);
59 execve(binary, argv, environ);
60 fprintf(stderr,
"failed to run %s... (%d)\n", binary, errno);
65 const char *arg2,
const char *arg3,
70 fprintf(stderr,
"failed to fork %s... (%d)\n", binary, errno);
72 }
else if (child == 0) {
76 waitpid(child, &wstatus, 0);
77 if (WIFSIGNALED(wstatus)) {
78 exit(128 + WTERMSIG(wstatus));
79 }
else if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus)) {
80 exit(WEXITSTATUS(wstatus));
86 string remount_option =
"remount,";
89 remount_option +=
"rw";
92 remount_option +=
"ro";
95 fprintf(stderr,
"internal error\n");
102 ExecAsRoot(
"/bin/mount",
"-o", remount_option.c_str(),
"dev", path.c_str());
105 static void Mount(
const string &path) {
113 string(
"/run/systemd/generator/") + systemd_unit))
116 if (resolved_path.empty()) {
117 fprintf(stderr,
"cannot resolve %s\n", path.c_str());
124 ExecAsRoot(
"/bin/systemctl",
"reset-failed", systemd_unit.c_str(),
127 ExecAsRoot(
"/bin/mount", path.c_str(), NULL, NULL, NULL);
132 ExecAsRoot(
"/bin/umount", path.c_str(), NULL, NULL, NULL);
136 ExecAsRoot(
"/bin/umount",
"-l", path.c_str(), NULL, NULL);
142 if (fqrn.find(
"/") != string::npos || fqrn.find(
"\\") != string::npos) {
146 const string mountpoint = string(
kSpoolArea) +
"/" + fqrn +
"/rdonly";
148 if (!retval || pid.empty())
151 if (!pid_sanitizer.
IsValid(pid))
153 ExecAsRoot(
"/bin/kill",
"-9", pid.c_str(), NULL, NULL);
160 , directory_handle_(NULL)
162 ChangeDirectory(path);
163 directory_handle_ = opendir(
".");
167 if (directory_handle_ != NULL) {
168 closedir(directory_handle_);
170 ChangeDirectory(previous_path_);
173 operator bool()
const {
return directory_handle_ != NULL; }
183 IsDotEntry(dirent)) {}
184 if (dirent == NULL) {
194 entry->
name = dirent->d_name;
201 const char* cwd = getcwd(path, PATH_MAX);
207 const int retval = chdir(path.c_str());
212 return (strcmp(dirent->d_name,
".") == 0) ||
213 (strcmp(dirent->d_name,
"..") == 0);
232 : (unlink(dirent.
name.c_str()) == 0);
240 fprintf(stderr,
"failed to clear %s\n", path.c_str());
247 const string scratch = string(
kSpoolArea) +
"/" + fqrn +
"/scratch/current";
252 const string wastebin = string(
kSpoolArea) +
"/" + fqrn +
"/scratch/wastebin";
257 if ((pid = fork()) == 0) {
258 int retval = setsid();
260 if ((pid = fork()) == 0) {
261 int null_read = open(
"/dev/null", O_RDONLY);
262 int null_write = open(
"/dev/null", O_WRONLY);
263 assert((null_read >= 0) && (null_write >= 0));
264 retval = dup2(null_read, 0);
266 retval = dup2(null_write, 1);
268 retval = dup2(null_write, 2);
278 waitpid(pid, &statloc, 0);
285 static void Usage(
const string &exe, FILE *output) {
287 "Usage: %s lock|open|rw_mount|rw_umount|rdonly_mount|rdonly_umount|"
288 "clear_scratch|clear_scratch_async|kill_cvmfs <fqrn>\n"
289 "Example: %s rw_umount atlas.cern.ch\n"
290 "This binary is typically called by cvmfs_server.\n",
291 exe.c_str(), exe.c_str());
295 int main(
int argc,
char *argv[]) {
300 uid_t calling_uid, effective_uid, repository_uid;
302 if (effective_uid != 0) {
303 fprintf(stderr,
"Needs to run as root\n");
309 Usage(argv[0], stderr);
312 const string command = argv[1];
313 const string fqrn = argv[2];
319 fprintf(stderr,
"unknown repository: %s\n", fqrn.c_str());
322 repository_uid = info.st_uid;
325 if ((calling_uid != 0) && (calling_uid != repository_uid)) {
326 fprintf(stderr,
"called as %d, repository owned by %d\n",
327 calling_uid, repository_uid);
331 if (command ==
"lock") {
333 }
else if (command ==
"open") {
335 }
else if (command ==
"kill_cvmfs") {
337 }
else if (command ==
"rw_mount") {
338 Mount(
"/cvmfs/" + fqrn);
339 }
else if (command ==
"rw_umount") {
341 }
else if (command ==
"rw_lazy_umount") {
343 }
else if (command ==
"rdonly_mount") {
345 }
else if (command ==
"rdonly_umount") {
347 }
else if (command ==
"rdonly_lazy_umount") {
349 }
else if (command ==
"clear_scratch") {
351 }
else if (command ==
"clear_scratch_async") {
354 Usage(argv[0], stderr);
static void Remount(const string &path, const RemountType how)
const string previous_path_
static void Mount(const string &path)
static void ForkAndExecAsRoot(const char *binary, const char *arg1, const char *arg2, const char *arg3, const char *arg4)
static void Usage(const char *progname)
static int CleanupDirectory(const string &path)
assert((mem||(size==0))&&"Out Of Memory")
static void GetCredentials(uid_t *calling_uid, uid_t *effective_uid)
bool IsDotEntry(const platform_dirent64 *dirent)
static void ExecAsRoot(const char *binary, const char *arg1, const char *arg2, const char *arg3, const char *arg4)
~ScopedWorkingDirectory()
string GetCurrentWorkingDirectory()
string EscapeSystemdUnit(const string &path)
static void Umount(const string &path)
string ResolvePath(const std::string &path)
ScopedWorkingDirectory(const string &path)
bool PathExists(const std::string &path)
static bool ClearDirectory(const string &path)
static void KillCvmfs(const string &fqrn)
bool NextDirectoryEntry(DirectoryEntry *entry)
void ChangeDirectory(const string &path)
static int DoAsynchronousScratchCleanup(const string &fqrn)
std::string GetCurrentWorkingDirectory()
static int DoSynchronousScratchCleanup(const string &fqrn)
static void LazyUmount(const string &path)