10 #include <sys/xattr.h>
37 *calling_uid = getuid();
38 *effective_uid = geteuid();
42 const char *arg1,
const char *arg2,
const char *arg3)
44 char *argv[] = { strdup(binary),
45 arg1 ? strdup(arg1) : NULL,
46 arg2 ? strdup(arg2) : NULL,
47 arg3 ? strdup(arg3) : NULL,
49 char *environ[] = { NULL };
51 int retval = setuid(0);
53 fprintf(stderr,
"failed to gain root privileges (%d)\n", errno);
57 execve(binary, argv, environ);
58 fprintf(stderr,
"failed to run %s... (%d)\n", binary, errno);
63 const char *arg2,
const char *arg3)
67 fprintf(stderr,
"failed to fork %s... (%d)\n", binary, errno);
69 }
else if (child == 0) {
73 waitpid(child, &wstatus, 0);
74 if (WIFSIGNALED(wstatus)) {
75 exit(128 + WTERMSIG(wstatus));
76 }
else if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus)) {
77 exit(WEXITSTATUS(wstatus));
83 string remount_option =
"remount,";
86 remount_option +=
"rw";
89 remount_option +=
"ro";
92 fprintf(stderr,
"internal error\n");
96 ExecAsRoot(
"/bin/mount",
"-o", remount_option.c_str(), path.c_str());
99 static void Mount(
const string &path) {
107 string(
"/run/systemd/generator/") + systemd_unit))
110 if (resolved_path.empty()) {
111 fprintf(stderr,
"cannot resolve %s\n", path.c_str());
117 ExecAsRoot(
"/bin/systemctl",
"reset-failed", systemd_unit.c_str(), NULL);
119 ExecAsRoot(
"/bin/mount", path.c_str(), NULL, NULL);
124 ExecAsRoot(
"/bin/umount", path.c_str(), NULL, NULL);
128 ExecAsRoot(
"/bin/umount",
"-l", path.c_str(), NULL);
134 if (fqrn.find(
"/") != string::npos || fqrn.find(
"\\") != string::npos) {
138 const string mountpoint = string(
kSpoolArea) +
"/" + fqrn +
"/rdonly";
140 if (!retval || pid.empty())
143 if (!pid_sanitizer.
IsValid(pid))
145 ExecAsRoot(
"/bin/kill",
"-9", pid.c_str(), NULL);
152 , directory_handle_(NULL)
154 ChangeDirectory(path);
155 directory_handle_ = opendir(
".");
159 if (directory_handle_ != NULL) {
160 closedir(directory_handle_);
162 ChangeDirectory(previous_path_);
165 operator bool()
const {
return directory_handle_ != NULL; }
175 IsDotEntry(dirent)) {}
176 if (dirent == NULL) {
186 entry->
name = dirent->d_name;
193 const char* cwd = getcwd(path, PATH_MAX);
199 const int retval = chdir(path.c_str());
204 return (strcmp(dirent->d_name,
".") == 0) ||
205 (strcmp(dirent->d_name,
"..") == 0);
224 : (unlink(dirent.
name.c_str()) == 0);
232 fprintf(stderr,
"failed to clear %s\n", path.c_str());
239 const string scratch = string(
kSpoolArea) +
"/" + fqrn +
"/scratch/current";
244 const string wastebin = string(
kSpoolArea) +
"/" + fqrn +
"/scratch/wastebin";
249 if ((pid = fork()) == 0) {
250 int retval = setsid();
252 if ((pid = fork()) == 0) {
253 int null_read = open(
"/dev/null", O_RDONLY);
254 int null_write = open(
"/dev/null", O_WRONLY);
255 assert((null_read >= 0) && (null_write >= 0));
256 retval = dup2(null_read, 0);
258 retval = dup2(null_write, 1);
260 retval = dup2(null_write, 2);
270 waitpid(pid, &statloc, 0);
277 static void Usage(
const string &exe, FILE *output) {
279 "Usage: %s lock|open|rw_mount|rw_umount|rdonly_mount|rdonly_umount|"
280 "clear_scratch|clear_scratch_async|kill_cvmfs <fqrn>\n"
281 "Example: %s rw_umount atlas.cern.ch\n"
282 "This binary is typically called by cvmfs_server.\n",
283 exe.c_str(), exe.c_str());
287 int main(
int argc,
char *argv[]) {
292 uid_t calling_uid, effective_uid, repository_uid;
294 if (effective_uid != 0) {
295 fprintf(stderr,
"Needs to run as root\n");
301 Usage(argv[0], stderr);
304 const string command = argv[1];
305 const string fqrn = argv[2];
311 fprintf(stderr,
"unknown repository: %s\n", fqrn.c_str());
314 repository_uid = info.st_uid;
317 if ((calling_uid != 0) && (calling_uid != repository_uid)) {
318 fprintf(stderr,
"called as %d, repository owned by %d\n",
319 calling_uid, repository_uid);
323 if (command ==
"lock") {
325 }
else if (command ==
"open") {
327 }
else if (command ==
"kill_cvmfs") {
329 }
else if (command ==
"rw_mount") {
330 Mount(
"/cvmfs/" + fqrn);
331 }
else if (command ==
"rw_umount") {
333 }
else if (command ==
"rw_lazy_umount") {
335 }
else if (command ==
"rdonly_mount") {
337 }
else if (command ==
"rdonly_umount") {
339 }
else if (command ==
"rdonly_lazy_umount") {
341 }
else if (command ==
"clear_scratch") {
343 }
else if (command ==
"clear_scratch_async") {
346 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)
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)
~ScopedWorkingDirectory()
string GetCurrentWorkingDirectory()
string EscapeSystemdUnit(const string &path)
static void Umount(const string &path)
string ResolvePath(const std::string &path)
ScopedWorkingDirectory(const string &path)
static void ExecAsRoot(const char *binary, const char *arg1, const char *arg2, const char *arg3)
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)