X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Futil.c;h=6fa9dec3a6532cf4de57ba8b554c1bda1de3680a;hp=8f70c0f28a143de8611a020f704c3caf81023fd5;hb=bb00e604097fba830af1dc078d78aff278dfcd37;hpb=3ba686c107b2b33e706f59432584875a4152d19a diff --git a/src/util.c b/src/util.c index 8f70c0f28..6fa9dec3a 100644 --- a/src/util.c +++ b/src/util.c @@ -44,6 +44,8 @@ #include #include #include +#include +#include #include "macro.h" #include "util.h" @@ -444,12 +446,12 @@ int get_parent_of_pid(pid_t pid, pid_t *_ppid) { int r; FILE *f; char fn[132], line[256], *p; - long long unsigned ppid; + long unsigned ppid; assert(pid >= 0); assert(_ppid); - assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%llu/stat", (unsigned long long) pid) < (int) (sizeof(fn)-1)); + assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1)); fn[sizeof(fn)-1] = 0; if (!(f = fopen(fn, "r"))) @@ -474,11 +476,11 @@ int get_parent_of_pid(pid_t pid, pid_t *_ppid) { if (sscanf(p, " " "%*c " /* state */ - "%llu ", /* ppid */ + "%lu ", /* ppid */ &ppid) != 1) return -EIO; - if ((long long unsigned) (pid_t) ppid != ppid) + if ((long unsigned) (pid_t) ppid != ppid) return -ERANGE; *_ppid = (pid_t) ppid; @@ -550,7 +552,7 @@ int get_process_name(pid_t pid, char **name) { assert(pid >= 1); assert(name); - if (asprintf(&p, "/proc/%llu/comm", (unsigned long long) pid) < 0) + if (asprintf(&p, "/proc/%lu/comm", (unsigned long) pid) < 0) return -ENOMEM; r = read_one_line_file(p, name); @@ -891,6 +893,53 @@ int mkdir_p(const char *path, mode_t mode) { return 0; } +int rmdir_parents(const char *path, const char *stop) { + size_t l; + int r = 0; + + assert(path); + assert(stop); + + l = strlen(path); + + /* Skip trailing slashes */ + while (l > 0 && path[l-1] == '/') + l--; + + while (l > 0) { + char *t; + + /* Skip last component */ + while (l > 0 && path[l-1] != '/') + l--; + + /* Skip trailing slashes */ + while (l > 0 && path[l-1] == '/') + l--; + + if (l <= 0) + break; + + if (!(t = strndup(path, l))) + return -ENOMEM; + + if (path_startswith(stop, t)) { + free(t); + return 0; + } + + r = rmdir(t); + free(t); + + if (r < 0) + if (errno != ENOENT) + return -errno; + } + + return 0; +} + + char hexchar(int x) { static const char table[16] = "0123456789abcdef"; @@ -1450,7 +1499,7 @@ char *format_timestamp(char *buf, size_t l, usec_t t) { if (t <= 0) return NULL; - sec = (time_t) t / USEC_PER_SEC; + sec = (time_t) (t / USEC_PER_SEC); if (strftime(buf, l, "%a, %d %b %Y %H:%M:%S %z", localtime_r(&sec, &tm)) <= 0) return NULL; @@ -1962,7 +2011,7 @@ int close_pipe(int p[]) { return a < 0 ? a : b; } -ssize_t loop_read(int fd, void *buf, size_t nbytes) { +ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) { uint8_t *p; ssize_t n = 0; @@ -1976,10 +2025,10 @@ ssize_t loop_read(int fd, void *buf, size_t nbytes) { if ((k = read(fd, p, nbytes)) <= 0) { - if (errno == EINTR) + if (k < 0 && errno == EINTR) continue; - if (errno == EAGAIN) { + if (k < 0 && errno == EAGAIN && do_poll) { struct pollfd pollfd; zero(pollfd); @@ -2010,6 +2059,54 @@ ssize_t loop_read(int fd, void *buf, size_t nbytes) { return n; } +ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) { + const uint8_t *p; + ssize_t n = 0; + + assert(fd >= 0); + assert(buf); + + p = buf; + + while (nbytes > 0) { + ssize_t k; + + if ((k = write(fd, p, nbytes)) <= 0) { + + if (k < 0 && errno == EINTR) + continue; + + if (k < 0 && errno == EAGAIN && do_poll) { + struct pollfd pollfd; + + zero(pollfd); + pollfd.fd = fd; + pollfd.events = POLLOUT; + + if (poll(&pollfd, 1, -1) < 0) { + if (errno == EINTR) + continue; + + return n > 0 ? n : -errno; + } + + if (pollfd.revents != POLLOUT) + return n > 0 ? n : -EIO; + + continue; + } + + return n > 0 ? n : (k < 0 ? -errno : 0); + } + + p += k; + nbytes -= k; + n += k; + } + + return n; +} + int path_is_mount_point(const char *t) { struct stat a, b; char *copy; @@ -2180,7 +2277,7 @@ unsigned long long random_ull(void) { if ((fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY)) < 0) goto fallback; - r = loop_read(fd, &ull, sizeof(ull)); + r = loop_read(fd, &ull, sizeof(ull), true); close_nointr_nofail(fd); if (r != sizeof(ull)) @@ -2205,6 +2302,80 @@ void rename_process(const char name[8]) { strncpy(program_invocation_name, name, strlen(program_invocation_name)); } +void sigset_add_many(sigset_t *ss, ...) { + va_list ap; + int sig; + + assert(ss); + + va_start(ap, ss); + while ((sig = va_arg(ap, int)) > 0) + assert_se(sigaddset(ss, sig) == 0); + va_end(ap); +} + +char* gethostname_malloc(void) { + struct utsname u; + + assert_se(uname(&u) >= 0); + + if (u.nodename[0]) + return strdup(u.nodename); + + return strdup(u.sysname); +} + +char* getlogname_malloc(void) { + uid_t uid; + long bufsize; + char *buf, *name; + struct passwd pwbuf, *pw = NULL; + struct stat st; + + if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0) + uid = st.st_uid; + else + uid = getuid(); + + /* Shortcut things to avoid NSS lookups */ + if (uid == 0) + return strdup("root"); + + if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) <= 0) + bufsize = 4096; + + if (!(buf = malloc(bufsize))) + return NULL; + + if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw) { + name = strdup(pw->pw_name); + free(buf); + return name; + } + + free(buf); + + if (asprintf(&name, "%lu", (unsigned long) uid) < 0) + return NULL; + + return name; +} + +char *getttyname_malloc(void) { + char path[PATH_MAX], *p; + + if (ttyname_r(STDIN_FILENO, path, sizeof(path)) < 0) + return strdup("unknown"); + + char_array_0(path); + + p = path; + if (startswith(path, "/dev/")) + p += 5; + + return strdup(p); +} + static const char *const ioprio_class_table[] = { [IOPRIO_CLASS_NONE] = "none", [IOPRIO_CLASS_RT] = "realtime",