7 #ifndef __STDC_FORMAT_MACROS
9 #define __STDC_FORMAT_MACROS
12 #include "cvmfs_config.h"
15 #include <arpa/inet.h>
20 #include <netinet/in.h>
25 #include <sys/resource.h>
26 #include <sys/socket.h>
29 #include <sys/mount.h>
31 #include <sys/statfs.h>
34 #include <sys/types.h>
36 #include <sys/utsname.h>
41 #ifdef HAS_VALGRIND_HEADERS
42 #include <valgrind/valgrind.h>
72 #define CVMFS_HAS_STATFS_F_FLAGS
74 #ifdef __GLIBC_MINOR__
75 #if __GLIBC_MINOR__ < 12
76 #undef CVMFS_HAS_STATFS_F_FLAGS
84 extern char **environ;
88 #ifdef CVMFS_NAMESPACE_GUARD
89 namespace CVMFS_NAMESPACE_GUARD {
99 if (path.length() == 0)
return path;
101 if (path[path.length()-1] ==
'/') {
102 return path.substr(0, path.length()-1);
114 const std::string &path,
115 std::string *dirname,
116 std::string *filename)
118 size_t dir_sep = path.rfind(
'/');
119 if (dir_sep != std::string::npos) {
120 *dirname = path.substr(0, dir_sep);
121 *filename = path.substr(dir_sep+1);
133 const std::string::size_type idx = path.find_last_of(
'/');
134 if (idx != std::string::npos) {
135 return path.substr(0, idx);
146 const std::string::size_type idx = path.find_last_of(
'/');
147 if (idx != std::string::npos) {
148 return path.substr(idx+1);
156 return (!path.empty() && path[0] ==
'/');
169 if (path.length() < 7) {
173 std::string prefix = path.substr(0, 8);
174 std::transform(prefix.begin(), prefix.end(), prefix.begin(), ::tolower);
176 return prefix.substr(0, 7) ==
"http://" || prefix ==
"https://";
184 int retval = statfs(path.c_str(), &info);
188 switch (info.f_type) {
208 #ifdef CVMFS_HAS_STATFS_F_FLAGS
213 retval = access(path.c_str(), W_OK);
225 char buf[PATH_MAX + 1];
226 ssize_t nchars = readlink(path.c_str(), buf, PATH_MAX);
229 return std::string(buf);
240 if (path.empty() || (path ==
"/"))
243 std::string result = name;
247 result = parent + (parent ==
"/" ?
"" :
"/") + name;
249 char *real_result = realpath(result.c_str(), NULL);
251 result = real_result;
255 char buf[PATH_MAX + 1];
256 ssize_t nchars = readlink(result.c_str(), buf, PATH_MAX);
269 for (
unsigned i = 0; i < mount_list.size(); ++i) {
270 if (mount_list[i] == resolved_path)
281 const std::string &path,
283 const bool ignore_failure)
285 int fd = open(path.c_str(), O_CREAT, mode);
300 struct sockaddr_un sock_addr;
301 unsigned max_length =
sizeof(sock_addr.sun_path);
305 if (tmp_path.empty())
307 std::string link = tmp_path +
"/l";
309 if (result.length() >= max_length) {
310 rmdir(tmp_path.c_str());
315 rmdir(tmp_path.c_str());
323 unlink(link.c_str());
332 std::string short_path(path);
333 struct sockaddr_un sock_addr;
334 if (path.length() >=
sizeof(sock_addr.sun_path)) {
338 if (short_path.empty())
341 sock_addr.sun_family = AF_UNIX;
342 strncpy(sock_addr.sun_path, short_path.c_str(),
343 sizeof(sock_addr.sun_path));
345 const int socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
351 if (fchmod(socket_fd, mode) != 0)
352 goto make_socket_failure;
355 if (bind(socket_fd, reinterpret_cast<struct sockaddr *>(&sock_addr),
356 sizeof(sock_addr.sun_family) +
sizeof(sock_addr.sun_path)) < 0)
358 if ((errno == EADDRINUSE) && (unlink(path.c_str()) == 0)) {
360 if (bind(socket_fd, reinterpret_cast<struct sockaddr *>(&sock_addr),
361 sizeof(sock_addr.sun_family) +
sizeof(sock_addr.sun_path)) < 0)
364 goto make_socket_failure;
368 goto make_socket_failure;
372 if (short_path != path)
379 if (short_path != path)
390 const int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
393 int retval = setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on));
396 struct sockaddr_in endpoint_addr;
397 memset(&endpoint_addr, 0,
sizeof(endpoint_addr));
398 endpoint_addr.sin_family = AF_INET;
399 if (ipv4_address.empty()) {
400 endpoint_addr.sin_addr.s_addr = INADDR_ANY;
402 retval = inet_aton(ipv4_address.c_str(), &(endpoint_addr.sin_addr));
409 endpoint_addr.sin_port = htons(portno);
411 retval = bind(socket_fd, reinterpret_cast<struct sockaddr *>(&endpoint_addr),
412 sizeof(endpoint_addr));
428 std::string short_path(path);
429 struct sockaddr_un sock_addr;
430 if (path.length() >=
sizeof(sock_addr.sun_path)) {
434 if (short_path.empty())
437 sock_addr.sun_family = AF_UNIX;
438 strncpy(sock_addr.sun_path, short_path.c_str(),
sizeof(sock_addr.sun_path));
440 const int socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
444 connect(socket_fd, reinterpret_cast<struct sockaddr *>(&sock_addr),
445 sizeof(sock_addr.sun_family) +
sizeof(sock_addr.sun_path));
446 if (short_path != path)
462 const int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
465 struct sockaddr_in endpoint_addr;
466 memset(&endpoint_addr, 0,
sizeof(endpoint_addr));
467 endpoint_addr.sin_family = AF_INET;
468 int retval = inet_aton(ipv4_address.c_str(), &(endpoint_addr.sin_addr));
474 endpoint_addr.sin_port = htons(portno);
477 connect(socket_fd, reinterpret_cast<struct sockaddr *>(&endpoint_addr),
478 sizeof(endpoint_addr));
493 int retval = pipe(pipe_fd);
504 num_bytes = write(fd, buf, nbyte);
505 }
while ((num_bytes < 0) && (errno == EINTR));
506 assert((num_bytes >= 0) && (static_cast<size_t>(num_bytes) == nbyte));
516 num_bytes = read(fd, buf, nbyte);
517 }
while ((num_bytes < 0) && (errno == EINTR));
518 assert((num_bytes >= 0) && (static_cast<size_t>(num_bytes) == nbyte));
525 bool ReadHalfPipe(
int fd,
void *buf,
size_t nbyte,
unsigned timeout_ms) {
528 unsigned backoff_ms = 1;
529 uint64_t duration_ms = 0;
530 uint64_t timestamp = 0;
534 const unsigned max_backoff_ms = 256;
538 num_bytes = read(fd, buf, nbyte);
539 if ((num_bytes < 0) && (errno == EINTR))
543 if ((i > 3000) && (num_bytes == 0)) {
546 if (backoff_ms < max_backoff_ms) backoff_ms *= 2;
548 if ((timeout_ms != 0) && (num_bytes == 0)) {
550 if (duration_ms > timeout_ms)
553 }
while (num_bytes == 0);
554 assert((num_bytes >= 0) && (static_cast<size_t>(num_bytes) == nbyte));
572 bool DiffTree(
const std::string &path_a,
const std::string &path_b) {
574 std::vector<std::string> ls_a;
575 std::vector<std::string> ls_b;
576 std::vector<std::string> subdirs;
578 DIR *dirp_a = opendir(path_a.c_str());
579 if (dirp_a == NULL)
return false;
580 DIR *dirp_b = opendir(path_b.c_str());
581 if (dirp_b == NULL) {
588 const std::string name(dirent->d_name);
589 if ((name ==
".") || (name ==
".."))
591 const std::string path = path_a +
"/" + name;
592 ls_a.push_back(path);
601 if (S_ISDIR(info.st_mode)) subdirs.push_back(name);
604 const std::string name(dirent->d_name);
605 if ((name ==
".") || (name ==
".."))
607 const std::string path = path_b +
"/" + name;
608 ls_b.push_back(path);
613 sort(ls_a.begin(), ls_a.end());
614 sort(ls_b.begin(), ls_b.end());
615 if (ls_a.size() != ls_b.size())
617 for (
unsigned i = 0; i < ls_a.size(); ++i) {
622 if (retval != 0)
return false;
624 if (retval != 0)
return false;
625 if ((info_a.st_mode != info_b.st_mode) ||
626 (info_a.st_uid != info_b.st_uid) ||
627 (info_a.st_gid != info_b.st_gid) ||
628 ((info_a.st_size != info_b.st_size) && !S_ISDIR(info_a.st_mode)))
634 for (
unsigned i = 0; i < subdirs.size(); ++i) {
635 bool retval_subtree =
DiffTree(path_a +
"/" + subdirs[i],
636 path_b +
"/" + subdirs[i]);
637 if (!retval_subtree)
return false;
648 int flags = fcntl(filedes, F_GETFL);
650 int retval = fcntl(filedes, F_SETFL, flags & ~O_NONBLOCK);
659 int flags = fcntl(filedes, F_GETFL);
661 int retval = fcntl(filedes, F_SETFL, flags | O_NONBLOCK);
682 struct cmsghdr align;
684 unsigned char buf[CMSG_SPACE(
sizeof(
int))];
687 memset(ctrl_msg.buf, 0,
sizeof(ctrl_msg.buf));
690 msgh.msg_name = NULL;
691 msgh.msg_namelen = 0;
693 unsigned char dummy = 0;
695 iov.iov_base = &dummy;
700 msgh.msg_control = ctrl_msg.buf;
701 msgh.msg_controllen =
sizeof(ctrl_msg.buf);
702 struct cmsghdr *cmsgp = CMSG_FIRSTHDR(&msgh);
703 cmsgp->cmsg_len = CMSG_LEN(
sizeof(
int));
704 cmsgp->cmsg_level = SOL_SOCKET;
705 cmsgp->cmsg_type = SCM_RIGHTS;
706 memcpy(CMSG_DATA(cmsgp), &passing_fd,
sizeof(
int));
708 ssize_t retval = sendmsg(socket_fd, &msgh, 0);
709 return (retval != -1);
722 struct cmsghdr align;
724 unsigned char buf[CMSG_SPACE(
sizeof(
int))];
727 memset(ctrl_msg.buf, 0,
sizeof(ctrl_msg.buf));
730 msgh.msg_name = NULL;
731 msgh.msg_namelen = 0;
735 iov.iov_base = &dummy;
740 msgh.msg_control = ctrl_msg.buf;
741 msgh.msg_controllen =
sizeof(ctrl_msg.buf);
743 ssize_t retval = recvmsg(msg_fd, &msgh, 0);
747 struct cmsghdr *cmsgp = CMSG_FIRSTHDR(&msgh);
749 if (cmsgp->cmsg_len != CMSG_LEN(
sizeof(
int)))
751 assert(cmsgp->cmsg_level == SOL_SOCKET);
752 assert(cmsgp->cmsg_type == SCM_RIGHTS);
755 memcpy(&passing_fd, CMSG_DATA(cmsgp),
sizeof(
int));
773 const bool temporarily)
776 "euid %d egid %d, switching to %d %d (temp: %d)",
777 getuid(), getgid(), geteuid(), getegid(), uid, gid, temporarily);
780 if (gid != getegid())
781 retval = setegid(gid);
782 if ((retval == 0) && (uid != geteuid()))
783 retval = seteuid(uid);
786 if ((getuid() == 0) && (getuid() != geteuid())) {
791 retval = setgid(gid) || setuid(uid);
805 S_ISREG(info.st_mode));
827 S_ISDIR(info.st_mode));
837 S_ISLNK(info.st_mode));
845 int retval = unlink(dest.c_str());
846 if ((retval != 0) && (errno != ENOENT))
848 retval = symlink(src.c_str(), dest.c_str());
858 const std::string &path,
860 bool verify_writable)
862 if (path ==
"")
return false;
864 int retval = mkdir(path.c_str(), mode);
865 if (retval == 0)
return true;
867 if ((errno == ENOENT) &&
870 return MkdirDeep(path, mode, verify_writable);
873 if (errno == EEXIST) {
875 if ((
platform_stat(path.c_str(), &info) == 0) && S_ISDIR(info.st_mode)) {
876 if (verify_writable) {
877 retval = utimes(path.c_str(), NULL);
896 std::string this_path = canonical_path +
"/quarantaine";
897 if (!
MkdirDeep(this_path, mode,
false))
return false;
899 this_path = canonical_path +
"/ff";
903 this_path = canonical_path +
"/txn";
906 for (
int i = 0; i <= 0xff; i++) {
908 snprintf(hex,
sizeof(hex),
"%02x", i);
909 this_path = canonical_path +
"/" + std::string(hex);
925 const int fd_lockfile = open(path.c_str(), O_RDONLY | O_CREAT, 0600);
929 if (flock(fd_lockfile, LOCK_EX | LOCK_NB) != 0) {
931 if (errno != EWOULDBLOCK)
947 const int fd = open(path.c_str(), O_CREAT | O_RDWR, 0600);
950 if (flock(fd, LOCK_EX | LOCK_NB) != 0) {
952 if (errno != EWOULDBLOCK)
958 int flags = fcntl(fd, F_GETFD);
961 flags = fcntl(fd, F_SETFD, flags);
966 snprintf(buf,
sizeof(buf),
"%" PRId64
"\n", static_cast<uint64_t>(getpid()));
968 (ftruncate(fd, 0) == 0) &&
SafeWrite(fd, buf, strlen(buf));
983 const int fd_lockfile = open(path.c_str(), O_RDONLY | O_CREAT, 0600);
988 if (flock(fd_lockfile, LOCK_EX | LOCK_NB) != 0) {
989 if (errno != EWOULDBLOCK) {
995 if (flock(fd_lockfile, LOCK_EX) != 0) {
1007 int retval = flock(filedes, LOCK_UN);
1017 const char *open_flags, std::string *final_path)
1019 *final_path = path_prefix +
".XXXXXX";
1020 char *tmp_file =
strdupa(final_path->c_str());
1021 int tmp_fd = mkstemp(tmp_file);
1025 if (fchmod(tmp_fd, mode) != 0) {
1030 *final_path = tmp_file;
1031 FILE *tmp_fp = fdopen(tmp_fd, open_flags);
1059 std::string dir = path_prefix +
".XXXXXX";
1060 char *tmp_dir =
strdupa(dir.c_str());
1061 tmp_dir = mkdtemp(tmp_dir);
1062 if (tmp_dir == NULL)
1064 return std::string(tmp_dir);
1073 return (getcwd(cwd,
sizeof(cwd)) != NULL) ? std::string(cwd) : std::string();
1086 void RemoveFile(
const std::string &parent_path,
const std::string &name) {
1087 int retval = unlink((parent_path +
"/" + name).c_str());
1091 void RemoveDir(
const std::string &parent_path,
const std::string &name) {
1092 int retval = rmdir((parent_path +
"/" + name).c_str());
1096 bool TryRemoveDir(
const std::string &parent_path,
const std::string &name) {
1097 int retval = rmdir((parent_path +
"/" + name).c_str());
1098 return (retval != 0);
1110 return errno == ENOENT;
1111 if (!S_ISDIR(info.st_mode))
1125 bool result = remove_tree_helper->
success;
1126 delete remove_tree_helper;
1136 const std::string &dir,
1137 const std::string &suffix)
1139 std::vector<std::string> result;
1140 DIR *dirp = opendir(dir.c_str());
1146 const std::string name(dirent->d_name);
1147 if ((name.length() >= suffix.length()) &&
1148 (name.substr(name.length()-suffix.length()) == suffix))
1150 result.push_back(dir +
"/" + name);
1154 std::sort(result.begin(), result.end());
1163 const std::string &dir,
1164 const std::string &prefix)
1166 std::vector<std::string> result;
1167 DIR *dirp = opendir(dir.c_str());
1173 const std::string name(dirent->d_name);
1174 if ((name.length() >= prefix.length()) &&
1175 (name.substr(0, prefix.length()) == prefix))
1177 result.push_back(dir +
"/" + name);
1181 std::sort(result.begin(), result.end());
1191 std::vector<std::string> result;
1192 DIR *dirp = opendir(parent_dir.c_str());
1198 const std::string name(dirent->d_name);
1199 if ((name ==
".") || (name ==
".."))
1201 const std::string path = parent_dir +
"/" + name;
1207 if (S_ISDIR(info.st_mode))
1208 result.push_back(path);
1211 sort(result.begin(), result.end());
1220 std::vector<std::string> *names,
1221 std::vector<mode_t> *modes)
1223 DIR *dirp = opendir(directory.c_str());
1229 const std::string name(dirent->d_name);
1230 if ((name ==
".") || (name ==
".."))
1232 const std::string path = directory +
"/" + name;
1241 names->push_back(name);
1242 modes->push_back(info.st_mode);
1259 std::vector<std::string> search_paths;
1260 if (exe[0] ==
'/') {
1263 char *path_env = getenv(
"PATH");
1269 for (
unsigned i = 0; i < search_paths.size(); ++i) {
1270 if (search_paths[i].empty())
1272 if (search_paths[i][0] !=
'/')
1275 std::string path = search_paths[i] +
"/" +
GetFileName(exe);
1280 if (!S_ISREG(info.st_mode))
1282 retval = access(path.c_str(), X_OK);
1295 struct passwd *result = NULL;
1296 int bufsize = 16 * 1024;
1297 char *buf =
static_cast<char *
>(smalloc(bufsize));
1298 while (getpwuid_r(geteuid(), &pwd, buf, bufsize, &result) == ERANGE) {
1300 buf =
static_cast<char *
>(srealloc(buf, bufsize));
1302 if (result == NULL) {
1306 std::string user_name = pwd.pw_name;
1313 struct passwd *result = NULL;
1314 int bufsize = 16 * 1024;
1315 char *buf =
static_cast<char *
>(smalloc(bufsize));
1316 while (getpwuid_r(geteuid(), &pwd, buf, bufsize, &result) == ERANGE) {
1318 buf =
static_cast<char *
>(srealloc(buf, bufsize));
1320 if (result == NULL) {
1324 std::string shell = pwd.pw_shell;
1334 struct passwd *result = NULL;
1335 int bufsize = 16 * 1024;
1336 char *buf =
static_cast<char *
>(smalloc(bufsize));
1337 while (getpwuid_r(uid, &pwd, buf, bufsize, &result) == ERANGE) {
1339 buf =
static_cast<char *
>(srealloc(buf, bufsize));
1341 if (result == NULL) {
1346 *username = result->pw_name;
1355 bool GetUidOf(
const std::string &username, uid_t *uid, gid_t *main_gid) {
1357 struct passwd *result = NULL;
1358 int bufsize = 16 * 1024;
1359 char *buf =
static_cast<char *
>(smalloc(bufsize));
1360 while (getpwnam_r(username.c_str(), &pwd, buf, bufsize, &result) == ERANGE) {
1362 buf =
static_cast<char *
>(srealloc(buf, bufsize));
1364 if (result == NULL) {
1368 *uid = result->pw_uid;
1369 *main_gid = result->pw_gid;
1378 bool GetGidOf(
const std::string &groupname, gid_t *gid) {
1380 struct group *result = NULL;
1381 int bufsize = 16 * 1024;
1382 char *buf =
static_cast<char *
>(smalloc(bufsize));
1383 while (getgrnam_r(groupname.c_str(), &grp, buf, bufsize, &result) == ERANGE) {
1385 buf =
static_cast<char *
>(srealloc(buf, bufsize));
1387 if (result == NULL) {
1391 *gid = result->gr_gid;
1403 const mode_t my_umask = umask(0);
1413 int ngroups = getgroups(0, NULL);
1416 gid_t *groups =
static_cast<gid_t *
>(smalloc((ngroups+1) *
sizeof(gid_t)));
1417 int retval = getgroups(ngroups, groups);
1422 for (
int i = 0; i < ngroups; ++i) {
1423 if (groups[i] == gid) {
1428 groups[ngroups] = gid;
1429 retval = setgroups(ngroups+1, groups);
1436 uid_t uid = getuid();
1438 struct passwd *result = NULL;
1439 int bufsize = 16 * 1024;
1440 char *buf =
static_cast<char *
>(smalloc(bufsize));
1441 while (getpwuid_r(uid, &pwd, buf, bufsize, &result) == ERANGE) {
1443 buf =
static_cast<char *
>(srealloc(buf, bufsize));
1445 if (result == NULL) {
1449 std::string home_dir = result->pw_dir;
1458 struct utsname info;
1459 int retval = uname(&info);
1461 return info.machine;
1471 memset(&rpl, 0,
sizeof(rpl));
1472 getrlimit(RLIMIT_NOFILE, &rpl);
1473 if (rpl.rlim_max < limit_nofile)
1474 rpl.rlim_max = limit_nofile;
1475 rpl.rlim_cur = limit_nofile;
1476 int retval = setrlimit(RLIMIT_NOFILE, &rpl);
1480 #ifdef HAS_VALGRIND_HEADERS
1481 return RUNNING_ON_VALGRIND ? -2 : -1;
1496 memset(&rpl, 0,
sizeof(rpl));
1497 getrlimit(RLIMIT_NOFILE, &rpl);
1498 *soft_limit = rpl.rlim_cur;
1501 int value = sysconf(_SC_OPEN_MAX);
1503 *hard_limit = value;
1505 *hard_limit = rpl.rlim_max;
1510 std::vector<LsofEntry>
Lsof(
const std::string &path) {
1511 std::vector<LsofEntry> result;
1513 std::vector<std::string> proc_names;
1514 std::vector<mode_t> proc_modes;
1517 for (
unsigned i = 0; i < proc_names.size(); ++i) {
1518 if (!S_ISDIR(proc_modes[i]))
1520 if (proc_names[i].find_first_not_of(
"1234567890") != std::string::npos)
1523 std::vector<std::string> fd_names;
1524 std::vector<mode_t> fd_modes;
1525 std::string proc_dir =
"/proc/" + proc_names[i];
1526 std::string fd_dir = proc_dir +
"/fd";
1534 proc_uid = info.st_uid;
1537 if (
HasPrefix(cwd +
"/", path +
"/",
false )) {
1540 entry.
owner = proc_uid;
1544 result.push_back(entry);
1548 for (
unsigned j = 0; j < fd_names.size(); ++j) {
1549 if (!S_ISLNK(fd_modes[j]))
1551 if (fd_names[j].find_first_not_of(
"1234567890") != std::string::npos)
1554 std::string target =
ReadSymlink(fd_dir +
"/" + fd_names[j]);
1555 if (!
HasPrefix(target +
"/", path +
"/",
false ))
1560 entry.
owner = proc_uid;
1561 entry.
read_only = !((fd_modes[j] & S_IWUSR) == S_IWUSR);
1563 entry.
path = target;
1564 result.push_back(entry);
1574 int retval = kill(pid, 0);
1577 return (errno != ESRCH);
1586 int retval = sigemptyset(&sigset);
1588 retval = sigaddset(&sigset, signum);
1590 retval = pthread_sigmask(SIG_BLOCK, &sigset, NULL);
1603 }
while ((retval != signum) && (errno == EINTR));
1604 assert(retval == signum);
1617 pid_t retval = waitpid(pid, &statloc, 0);
1622 "waitpid failed with errno %d", errno);
1627 if (WIFEXITED(statloc))
1628 return WEXITSTATUS(statloc);
1629 if (WIFSIGNALED(statloc) && (std::find(sig_ok.begin(), sig_ok.end(),
1630 WTERMSIG(statloc)) != sig_ok.end()))
1641 assert(command_line.size() >= 1);
1647 pid_t pid_grand_child;
1649 const char *argv[command_line.size() + 1];
1650 for (
unsigned i = 0; i < command_line.size(); ++i)
1651 argv[i] = command_line[i].c_str();
1652 argv[command_line.size()] = NULL;
1653 int retval = setsid();
1656 pid_grand_child = fork();
1657 assert(pid_grand_child >= 0);
1659 if (pid_grand_child != 0){
1660 pipe_fork.Write<pid_t>(pid_grand_child);
1663 int null_read = open(
"/dev/null", O_RDONLY);
1664 int null_write = open(
"/dev/null", O_WRONLY);
1665 assert((null_read >= 0) && (null_write >= 0));
1666 retval = dup2(null_read, 0);
1668 retval = dup2(null_write, 1);
1670 retval = dup2(null_write, 2);
1675 execvp(command_line[0].c_str(), const_cast<char **>(argv));
1677 pipe_fork.CloseWriteFd();
1681 waitpid(pid, &statloc, 0);
1682 pid_t buf_child_pid = 0;
1683 pipe_fork.Read(&buf_child_pid);
1684 if (child_pid != NULL)
1685 *child_pid = buf_child_pid;
1686 pipe_fork.CloseReadFd();
1689 command_line[0].c_str(),
1690 static_cast<int>(*child_pid));
1705 if ((pid = fork()) == 0) {
1706 int retval = setsid();
1708 if ((pid = fork()) == 0) {
1709 int null_read = open(
"/dev/null", O_RDONLY);
1710 int null_write = open(
"/dev/null", O_WRONLY);
1711 assert((null_read >= 0) && (null_write >= 0));
1712 retval = dup2(null_read, 0);
1714 retval = dup2(null_write, 1);
1716 retval = dup2(null_write, 2);
1727 waitpid(pid, &statloc, 0);
1737 const std::string &binary_path,
1738 const std::vector<std::string> &argv,
1739 const bool double_fork,
1749 std::set<int> preserve_fildes;
1750 preserve_fildes.insert(0);
1751 preserve_fildes.insert(1);
1752 preserve_fildes.insert(2);
1753 std::map<int, int> map_fildes;
1754 map_fildes[pipe_stdin[0]] = 0;
1755 map_fildes[pipe_stdout[1]] = 1;
1756 map_fildes[pipe_stderr[1]] = 2;
1757 std::vector<std::string> cmd_line;
1758 cmd_line.push_back(binary_path);
1759 cmd_line.insert(cmd_line.end(), argv.begin(), argv.end());
1775 close(pipe_stdin[0]);
1776 close(pipe_stdout[1]);
1777 close(pipe_stderr[1]);
1778 *fd_stdin = pipe_stdin[1];
1779 *fd_stdout = pipe_stdout[0];
1780 *fd_stderr = pipe_stderr[0];
1789 bool Shell(
int *fd_stdin,
int *fd_stdout,
int *fd_stderr) {
1790 const bool double_fork =
true;
1791 return ExecuteBinary(fd_stdin, fd_stdout, fd_stderr,
"/bin/sh",
1792 std::vector<std::string>(), double_fork);
1810 return "Sending PID";
1814 return "Unknown Status";
1816 return "Duplicate File Descriptor";
1818 return "Close File Descriptors";
1819 case kFailGetFdFlags:
1820 return "Read File Descriptor Flags";
1821 case kFailSetFdFlags:
1822 return "Set File Descriptor Flags";
1823 case kFailDropCredentials:
1824 return "Lower User Permissions";
1826 return "Invoking execvp()";
1835 const std::set<int> &preserve_fildes,
1838 for (
int fd = 0; fd < max_fd; fd++) {
1839 if (preserve_fildes.count(fd) == 0) {
1854 DIR *dirp = opendir(
"/proc/self/fd");
1861 const std::string name(dirent->d_name);
1862 uint64_t name_uint64;
1869 int fd =
static_cast<int>(name_uint64);
1870 if (preserve_fildes.count(fd)) {
1889 int max_fd =
static_cast<int>(sysconf(_SC_OPEN_MAX));
1896 #else // ifdef __APPLE__
1897 if (max_fd > 100000) {
1904 #endif // #ifdef __APPLE__
1921 const std::set<int> &preserve_fildes,
1922 const std::map<int, int> &map_fildes,
1923 const bool drop_credentials,
1924 const bool clear_env,
1925 const bool double_fork,
1928 assert(command_line.size() >= 1);
1934 pid_t pid_grand_child;
1938 std::set<int> skip_fds = preserve_fildes;
1939 skip_fds.insert(pipe_fork.GetWriteFd());
1945 int retval = clearenv();
1950 const char *argv[command_line.size() + 1];
1951 for (
unsigned i = 0; i < command_line.size(); ++i)
1952 argv[i] = command_line[i].c_str();
1953 argv[command_line.size()] = NULL;
1956 for (std::map<int, int>::const_iterator i = map_fildes.begin(),
1957 iEnd = map_fildes.end(); i != iEnd; ++i)
1959 int retval = dup2(i->first, i->second);
1974 pid_grand_child = fork();
1975 assert(pid_grand_child >= 0);
1976 if (pid_grand_child != 0) _exit(0);
1979 fd_flags = fcntl(pipe_fork.GetWriteFd(), F_GETFD);
1984 fd_flags |= FD_CLOEXEC;
1985 if (fcntl(pipe_fork.GetWriteFd(), F_SETFD, fd_flags) < 0) {
1991 assert(setenv(
"__CVMFS_DEBUG_MODE__",
"yes", 1) == 0);
2000 pid_grand_child = getpid();
2003 pipe_fork.Write<pid_t>(pid_grand_child);
2005 execvp(command_line[0].c_str(), const_cast<char **>(argv));
2015 waitpid(pid, &statloc, 0);
2018 pipe_fork.CloseWriteFd();
2025 pipe_fork.CloseReadFd();
2033 pid_t buf_child_pid = 0;
2034 pipe_fork.Read(&buf_child_pid);
2035 if (child_pid != NULL)
2036 *child_pid = buf_child_pid;
2037 pipe_fork.CloseReadFd();
2039 command_line[0].c_str(),
2040 static_cast<int>(buf_child_pid));
2050 struct timeval wait_for;
2051 wait_for.tv_sec = ms / 1000;
2052 wait_for.tv_usec = (ms % 1000) * 1000;
2053 select(0, NULL, NULL, NULL, &wait_for);
2062 ssize_t retval = write(fd, buf, nbyte);
2068 assert(static_cast<size_t>(retval) <= nbyte);
2069 buf =
reinterpret_cast<const char *
>(buf) + retval;
2079 unsigned nbytes = 0;
2080 for (
unsigned i = 0; i < iovcnt; ++i)
2081 nbytes += iov[i].iov_len;
2082 unsigned iov_idx = 0;
2086 writev(fd, &iov[iov_idx], static_cast<int>(iovcnt - iov_idx));
2092 assert(static_cast<size_t>(retval) <= nbytes);
2095 unsigned sum_written_blocks = 0;
2096 while ((sum_written_blocks + iov[iov_idx].iov_len) <=
2097 static_cast<size_t>(retval))
2099 sum_written_blocks += iov[iov_idx].iov_len;
2101 if (iov_idx == iovcnt) {
2102 assert(sum_written_blocks == static_cast<size_t>(retval));
2106 unsigned offset = retval - sum_written_blocks;
2107 iov[iov_idx].iov_len -= offset;
2108 iov[iov_idx].iov_base =
2109 reinterpret_cast<char *
>(iov[iov_idx].iov_base) + offset;
2120 ssize_t total_bytes = 0;
2122 ssize_t retval = read(fd, buf, nbyte);
2127 }
else if (retval == 0) {
2130 assert(static_cast<size_t>(retval) <= nbyte);
2131 buf =
reinterpret_cast<char *
>(buf) + retval;
2133 total_bytes += retval;
2143 if (!final_result) {
return false;}
2145 std::string tmp_result;
2146 static const int buf_size = 4096;
2148 ssize_t total_bytes = -1;
2150 total_bytes =
SafeRead(fd, buf, buf_size);
2151 if (total_bytes < 0) {
return false;}
2152 tmp_result.append(buf, total_bytes);
2153 }
while (total_bytes == buf_size);
2154 final_result->swap(tmp_result);
2159 const std::string &path,
2161 int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, mode);
2162 if (fd < 0)
return false;
2163 bool retval =
SafeWrite(fd, content.data(), content.size());
2169 #ifdef CVMFS_NAMESPACE_GUARD
bool MakeCacheDirectories(const std::string &path, const mode_t mode)
static bool CloseAllFildesInProcSelfFd(const std::set< int > &preserve_fildes)
void RemoveFile(const std::string &parent_path, const std::string &name)
int MakeSocket(const std::string &path, const int mode)
bool SymlinkForced(const std::string &src, const std::string &dest)
NameString GetFileName(const PathString &path)
int MakeTcpEndpoint(const std::string &ipv4_address, int portno)
std::string GetUserName()
VoidCallback fn_new_symlink
VoidCallback fn_new_character_dev
void Recurse(const std::string &dir_path) const
void CreateFile(const std::string &path, const int mode, const bool ignore_failure)
bool GetUserNameOf(uid_t uid, std::string *username)
FILE * CreateTempFile(const std::string &path_prefix, const int mode, const char *open_flags, std::string *final_path)
int ConnectTcpEndpoint(const std::string &ipv4_address, int portno)
void RemoveDir(const std::string &parent_path, const std::string &name)
bool Shell(int *fd_stdin, int *fd_stdout, int *fd_stderr)
bool IsHttpUrl(const std::string &path)
bool ManagedExec(const std::vector< std::string > &command_line, const std::set< int > &preserve_fildes, const std::map< int, int > &map_fildes, const bool drop_credentials, const bool clear_env, const bool double_fork, pid_t *child_pid)
static void RemoveShortSocketLink(const std::string &short_path)
static pthread_mutex_t getumask_mutex
std::string CreateTempPath(const std::string &path_prefix, const int mode)
A simple recursion engine to abstract the recursion of directories. It provides several callback hook...
bool SafeWrite(int fd, const void *buf, size_t nbyte)
void SendMsg2Socket(const int fd, const std::string &msg)
assert((mem||(size==0))&&"Out Of Memory")
bool SafeWriteToFile(const std::string &content, const std::string &path, int mode)
std::string FindExecutable(const std::string &exe)
bool SendFd2Socket(int socket_fd, int passing_fd)
VoidCallback fn_leave_dir
int WaitForChild(pid_t pid, const std::vector< int > &sig_ok)
bool TryRemoveDir(const std::string &parent_path, const std::string &name)
bool AddGroup2Persona(const gid_t gid)
void MakePipe(int pipe_fd[2])
std::vector< std::string > FindDirectories(const std::string &parent_dir)
bool String2Uint64Parse(const std::string &value, uint64_t *result)
int SetLimitNoFile(unsigned limit_nofile)
bool SymlinkExists(const std::string &path)
static bool CloseAllFildesUntilMaxFD(const std::set< int > &preserve_fildes, int max_fd)
bool FileExists(const std::string &path)
std::string GetAbsolutePath(const std::string &path)
void SplitPath(const std::string &path, std::string *dirname, std::string *filename)
std::string GetHostname()
void GetLimitNoFile(unsigned *soft_limit, unsigned *hard_limit)
bool ReadHalfPipe(int fd, void *buf, size_t nbyte, unsigned timeout_ms)
ssize_t SafeRead(int fd, void *buf, size_t nbyte)
vector< string > SplitString(const string &str, char delim)
FileSystemInfo GetFileSystemInfo(const std::string &path)
void Nonblock2Block(int filedes)
static std::string MakeShortSocketLink(const std::string &path)
int TryLockFile(const std::string &path)
bool MkdirDeep(const std::string &path, const mode_t mode, bool verify_writable)
int LockFile(const std::string &path)
string ResolvePath(const std::string &path)
std::string GetHomeDirectory()
void WaitForSignal(int signum)
bool GetGidOf(const std::string &groupname, gid_t *gid)
std::string CreateTempDir(const std::string &path_prefix)
bool HasPrefix(const string &str, const string &prefix, const bool ignore_case)
bool DirectoryExists(const std::string &path)
bool ExecuteBinary(int *fd_stdin, int *fd_stdout, int *fd_stderr, const std::string &binary_path, const std::vector< std::string > &argv, const bool double_fork, pid_t *child_pid)
bool RemoveTree(const std::string &path)
bool SafeReadToString(int fd, std::string *final_result)
bool CloseAllFildes(const std::set< int > &preserve_fildes)
int WritePidFile(const std::string &path)
int ConnectSocket(const std::string &path)
uint64_t String2Uint64(const string &value)
VoidCallback fn_new_socket
bool GetUidOf(const std::string &username, uid_t *uid, gid_t *main_gid)
std::vector< std::string > FindFilesByPrefix(const std::string &dir, const std::string &prefix)
bool SwitchCredentials(const uid_t uid, const gid_t gid, const bool temporarily)
bool ExecAsDaemon(const std::vector< std::string > &command_line, pid_t *child_pid)
std::string ReadSymlink(const std::string &path)
PathString GetParentPath(const PathString &path)
std::vector< LsofEntry > Lsof(const std::string &path)
BoolCallback fn_new_dir_prefix
bool ListDirectory(const std::string &directory, std::vector< std::string > *names, std::vector< mode_t > *modes)
int64_t GetFileSize(const std::string &path)
void SafeSleepMs(const unsigned ms)
bool DiffTree(const std::string &path_a, const std::string &path_b)
void SortTeam(std::vector< T > *tractor, std::vector< U > *towed)
static std::string ToString(const Names name)
void Block2Nonblock(int filedes)
bool IsAbsolutePath(const std::string &path)
bool ProcessExists(pid_t pid)
std::string MakeCanonicalPath(const std::string &path)
const char * c_str() const
void WritePipe(int fd, const void *buf, size_t nbyte)
std::string GetCurrentWorkingDirectory()
void ReadPipe(int fd, void *buf, size_t nbyte)
std::vector< std::string > FindFilesBySuffix(const std::string &dir, const std::string &suffix)
void ClosePipe(int pipe_fd[2])
bool IsMountPoint(const std::string &path)
int RecvFdFromSocket(int msg_fd)
bool SafeWriteV(int fd, struct iovec *iov, unsigned iovcnt)
void UnlockFile(const int filedes)
void BlockSignal(int signum)
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)