X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Futil.c;h=7a4dacd2138ca52eff63e338ddf255d893e516ef;hp=c20dff2f7cebaa0050a6478bc854b167e66c6323;hb=be8f4e9e8eb3b0c34a49c2e80a5c5b7dc6d175f0;hpb=9d50e74a0aeefa5b66eae1ad3e38af59fdc4ca62 diff --git a/src/shared/util.c b/src/shared/util.c index c20dff2f7..7a4dacd21 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -73,6 +73,7 @@ #include "log.h" #include "strv.h" #include "label.h" +#include "mkdir.h" #include "path-util.h" #include "exit-status.h" #include "hashmap.h" @@ -1370,23 +1371,27 @@ bool ignore_file(const char *filename) { assert(filename); if (endswith(filename, "~")) - return false; + return true; return ignore_file_allow_backup(filename); } int fd_nonblock(int fd, bool nonblock) { - int flags; + int flags, nflags; assert(fd >= 0); - if ((flags = fcntl(fd, F_GETFL, 0)) < 0) + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) return -errno; if (nonblock) - flags |= O_NONBLOCK; + nflags = flags | O_NONBLOCK; else - flags &= ~O_NONBLOCK; + nflags = flags & ~O_NONBLOCK; + + if (nflags == flags) + return 0; if (fcntl(fd, F_SETFL, flags) < 0) return -errno; @@ -1395,17 +1400,21 @@ int fd_nonblock(int fd, bool nonblock) { } int fd_cloexec(int fd, bool cloexec) { - int flags; + int flags, nflags; assert(fd >= 0); - if ((flags = fcntl(fd, F_GETFD, 0)) < 0) + flags = fcntl(fd, F_GETFD, 0); + if (flags < 0) return -errno; if (cloexec) - flags |= FD_CLOEXEC; + nflags = flags | FD_CLOEXEC; else - flags &= ~FD_CLOEXEC; + nflags = flags & ~FD_CLOEXEC; + + if (nflags == flags) + return 0; if (fcntl(fd, F_SETFD, flags) < 0) return -errno; @@ -2016,7 +2025,6 @@ int ignore_signals(int sig, ...) { va_list ap; int r = 0; - if (sigaction(sig, &sa, NULL) < 0) r = -errno; @@ -2442,6 +2450,24 @@ void sigset_add_many(sigset_t *ss, ...) { va_end(ap); } +int sigprocmask_many(int how, ...) { + va_list ap; + sigset_t ss; + int sig; + + assert_se(sigemptyset(&ss) == 0); + + va_start(ap, how); + while ((sig = va_arg(ap, int)) > 0) + assert_se(sigaddset(&ss, sig) == 0); + va_end(ap); + + if (sigprocmask(how, &ss, NULL) < 0) + return -errno; + + return 0; +} + char* gethostname_malloc(void) { struct utsname u; @@ -2482,7 +2508,7 @@ static char *lookup_uid(uid_t uid) { if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw) return strdup(pw->pw_name); - if (asprintf(&name, "%lu", (unsigned long) uid) < 0) + if (asprintf(&name, UID_FMT, uid) < 0) return NULL; return name; @@ -2607,7 +2633,7 @@ int get_ctty(pid_t pid, dev_t *_devnr, char **r) { /* This is an ugly hack */ if (major(devnr) == 136) { - asprintf(&b, "pts/%lu", (unsigned long) minor(devnr)); + asprintf(&b, "pts/%u", minor(devnr)); goto finish; } @@ -3327,22 +3353,49 @@ char *ellipsize(const char *s, size_t length, unsigned percent) { return ellipsize_mem(s, strlen(s), length, percent); } -int touch(const char *path) { +int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) { _cleanup_close_ int fd; + int r; assert(path); - /* This just opens the file for writing, ensuring it - * exists. It doesn't call utimensat() the way /usr/bin/touch - * does it. */ + if (parents) + mkdir_parents(path, 0755); - fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644); + fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644); if (fd < 0) return -errno; + if (mode > 0) { + r = fchmod(fd, mode); + if (r < 0) + return -errno; + } + + if (uid != (uid_t) -1 || gid != (gid_t) -1) { + r = fchown(fd, uid, gid); + if (r < 0) + return -errno; + } + + if (stamp != (usec_t) -1) { + struct timespec ts[2]; + + timespec_store(&ts[0], stamp); + ts[1] = ts[0]; + r = futimens(fd, ts); + } else + r = futimens(fd, NULL); + if (r < 0) + return -errno; + return 0; } +int touch(const char *path) { + return touch_file(path, false, (usec_t) -1, (uid_t) -1, (gid_t) -1, 0); +} + char *unquote(const char *s, const char* quotes) { size_t l; assert(s); @@ -4282,7 +4335,7 @@ char* uid_to_name(uid_t uid) { if (p) return strdup(p->pw_name); - if (asprintf(&r, "%lu", (unsigned long) uid) < 0) + if (asprintf(&r, UID_FMT, uid) < 0) return NULL; return r; @@ -4299,7 +4352,7 @@ char* gid_to_name(gid_t gid) { if (p) return strdup(p->gr_name); - if (asprintf(&r, "%lu", (unsigned long) gid) < 0) + if (asprintf(&r, GID_FMT, gid) < 0) return NULL; return r; @@ -5444,21 +5497,25 @@ out: const char *draw_special_char(DrawSpecialChar ch) { static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = { + /* UTF-8 */ { - [DRAW_TREE_VERT] = "\342\224\202 ", /* │ */ + [DRAW_TREE_VERTICAL] = "\342\224\202 ", /* │ */ [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */ [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */ [DRAW_TREE_SPACE] = " ", /* */ - [DRAW_TRIANGULAR_BULLET] = "\342\200\243 ", /* ‣ */ - [DRAW_BLACK_CIRCLE] = "\342\227\217 ", /* ● */ + [DRAW_TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */ + [DRAW_BLACK_CIRCLE] = "\342\227\217", /* ● */ + [DRAW_ARROW] = "\342\206\222", /* → */ }, + /* ASCII fallback */ { - [DRAW_TREE_VERT] = "| ", + [DRAW_TREE_VERTICAL] = "| ", [DRAW_TREE_BRANCH] = "|-", [DRAW_TREE_RIGHT] = "`-", [DRAW_TREE_SPACE] = " ", - [DRAW_TRIANGULAR_BULLET] = "> ", - [DRAW_BLACK_CIRCLE] = "* ", + [DRAW_TRIANGULAR_BULLET] = ">", + [DRAW_BLACK_CIRCLE] = "*", + [DRAW_ARROW] = "->", } }; @@ -6070,60 +6127,93 @@ int container_get_leader(const char *machine, pid_t *pid) { return 0; } -int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *root_fd) { - _cleanup_close_ int pidnsfd = -1, mntnsfd = -1; - const char *pidns, *mntns, *root; - int rfd; +int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *root_fd) { + _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1; + int rfd = -1; assert(pid >= 0); - assert(pidns_fd); - assert(mntns_fd); - assert(root_fd); - mntns = procfs_file_alloca(pid, "ns/mnt"); - mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC); - if (mntnsfd < 0) - return -errno; + if (mntns_fd) { + const char *mntns; - pidns = procfs_file_alloca(pid, "ns/pid"); - pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC); - if (pidnsfd < 0) - return -errno; + mntns = procfs_file_alloca(pid, "ns/mnt"); + mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (mntnsfd < 0) + return -errno; + } - root = procfs_file_alloca(pid, "root"); - rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); - if (rfd < 0) - return -errno; + if (pidns_fd) { + const char *pidns; + + pidns = procfs_file_alloca(pid, "ns/pid"); + pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (pidnsfd < 0) + return -errno; + } + + if (netns_fd) { + const char *netns; + + netns = procfs_file_alloca(pid, "ns/net"); + netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (netnsfd < 0) + return -errno; + } - *pidns_fd = pidnsfd; - *mntns_fd = mntnsfd; - *root_fd = rfd; - pidnsfd = -1; - mntnsfd = -1; + if (root_fd) { + const char *root; + + root = procfs_file_alloca(pid, "root"); + rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + if (rfd < 0) + return -errno; + } + + if (pidns_fd) + *pidns_fd = pidnsfd; + + if (mntns_fd) + *mntns_fd = mntnsfd; + + if (netns_fd) + *netns_fd = netnsfd; + + if (root_fd) + *root_fd = rfd; + + pidnsfd = mntnsfd = netnsfd = -1; return 0; } -int namespace_enter(int pidns_fd, int mntns_fd, int root_fd) { - assert(pidns_fd >= 0); - assert(mntns_fd >= 0); - assert(root_fd >= 0); +int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd) { - if (setns(pidns_fd, CLONE_NEWPID) < 0) - return -errno; + if (pidns_fd >= 0) + if (setns(pidns_fd, CLONE_NEWPID) < 0) + return -errno; - if (setns(mntns_fd, CLONE_NEWNS) < 0) - return -errno; + if (mntns_fd >= 0) + if (setns(mntns_fd, CLONE_NEWNS) < 0) + return -errno; - if (fchdir(root_fd) < 0) - return -errno; + if (netns_fd >= 0) + if (setns(netns_fd, CLONE_NEWNET) < 0) + return -errno; - if (chroot(".") < 0) - return -errno; + if (root_fd >= 0) { + if (fchdir(root_fd) < 0) + return -errno; + + if (chroot(".") < 0) + return -errno; + } if (setresgid(0, 0, 0) < 0) return -errno; + if (setgroups(0, NULL) < 0) + return -errno; + if (setresuid(0, 0, 0) < 0) return -errno; @@ -6397,3 +6487,18 @@ void hexdump(FILE *f, const void *p, size_t s) { s -= 16; } } + +int update_reboot_param_file(const char *param) { + int r = 0; + + if (param) { + + r = write_string_file(REBOOT_PARAM_FILE, param); + if (r < 0) + log_error("Failed to write reboot param to " + REBOOT_PARAM_FILE": %s", strerror(-r)); + } else + unlink(REBOOT_PARAM_FILE); + + return r; +}