X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Futil.c;h=4b841491aa2a73e4d9ea79bca62d31ce0bc44bae;hb=8f33b5b8b3e85f9c3b00eb004e601f7a72fa6461;hp=d8d3f1a16d302f95305a90ab1ffe121e0fb43893;hpb=6edd7d0a09171ea5ae8e01b7b1cbcb0bdfbfeb16;p=elogind.git diff --git a/src/shared/util.c b/src/shared/util.c index d8d3f1a16..4b841491a 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -597,7 +597,8 @@ int write_one_line_file(const char *fn, const char *line) { assert(fn); assert(line); - if (!(f = fopen(fn, "we"))) + f = fopen(fn, "we"); + if (!f) return -errno; errno = 0; @@ -2948,12 +2949,20 @@ char* gethostname_malloc(void) { assert_se(uname(&u) >= 0); - if (u.nodename[0]) + if (!isempty(u.nodename) && !streq(u.nodename, "(none)")) return strdup(u.nodename); return strdup(u.sysname); } +bool hostname_is_set(void) { + struct utsname u; + + assert_se(uname(&u) >= 0); + + return !isempty(u.nodename) && !streq(u.nodename, "(none)"); +} + char* getlogname_malloc(void) { uid_t uid; long bufsize; @@ -3130,7 +3139,7 @@ int get_ctty(pid_t pid, dev_t *_devnr, char **r) { return 0; } -static int rm_rf_children(int fd, bool only_dirs, bool honour_sticky) { +int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) { DIR *d; int ret = 0; @@ -3139,7 +3148,8 @@ static int rm_rf_children(int fd, bool only_dirs, bool honour_sticky) { /* This returns the first error we run into, but nevertheless * tries to go on */ - if (!(d = fdopendir(fd))) { + d = fdopendir(fd); + if (!d) { close_nointr_nofail(fd); return errno == ENOENT ? 0 : -errno; @@ -3150,9 +3160,9 @@ static int rm_rf_children(int fd, bool only_dirs, bool honour_sticky) { bool is_dir, keep_around = false; int r; - if ((r = readdir_r(d, &buf, &de)) != 0) { - if (ret == 0) - ret = -r; + r = readdir_r(d, &buf, &de); + if (r != 0 && ret == 0) { + ret = -r; break; } @@ -3198,25 +3208,37 @@ static int rm_rf_children(int fd, bool only_dirs, bool honour_sticky) { if (is_dir) { int subdir_fd; - - subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); - if (subdir_fd < 0) { - if (ret == 0 && errno != ENOENT) - ret = -errno; - continue; + struct stat sb; + if (root_dev) { + if (fstatat(fd, de->d_name, &sb, AT_SYMLINK_NOFOLLOW)) { + if (ret == 0 && errno != ENOENT) + ret = -errno; + continue; + } } - if ((r = rm_rf_children(subdir_fd, only_dirs, honour_sticky)) < 0) { - if (ret == 0) - ret = r; - } + /* if root_dev is set, remove subdirectories only, if device is same as dir */ + if ((root_dev == NULL) || (sb.st_dev == root_dev->st_dev)) { - if (!keep_around) - if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) { + subdir_fd = openat(fd, de->d_name, + O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); + if (subdir_fd < 0) { if (ret == 0 && errno != ENOENT) ret = -errno; + continue; } + r = rm_rf_children(subdir_fd, only_dirs, honour_sticky, root_dev); + if (r < 0 && ret == 0) + ret = r; + + if (!keep_around) + if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) { + if (ret == 0 && errno != ENOENT) + ret = -errno; + } + } + } else if (!only_dirs && !keep_around) { if (unlinkat(fd, de->d_name, 0) < 0) { @@ -3237,19 +3259,20 @@ int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky assert(path); - if ((fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)) < 0) { + fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); + if (fd < 0) { if (errno != ENOTDIR) return -errno; if (delete_root && !only_dirs) - if (unlink(path) < 0) + if (unlink(path) < 0 && errno != ENOENT) return -errno; return 0; } - r = rm_rf_children(fd, only_dirs, honour_sticky); + r = rm_rf_children(fd, only_dirs, honour_sticky, NULL); if (delete_root) { @@ -3328,15 +3351,15 @@ cpu_set_t* cpu_set_malloc(unsigned *ncpus) { } void status_vprintf(const char *status, bool ellipse, const char *format, va_list ap) { - char *s = NULL, *spaces = NULL, *e; - int fd = -1, c; - size_t emax, sl, left; + char *s = NULL; + static const char status_indent[] = " "; /* "[" STATUS "] " */ + int fd = -1; struct iovec iovec[5]; int n = 0; assert(format); - /* This independent of logging, as status messages are + /* This is independent of logging, as status messages are * optional and go exclusively to the console. */ if (vasprintf(&s, format, ap) < 0) @@ -3347,15 +3370,19 @@ void status_vprintf(const char *status, bool ellipse, const char *format, va_lis goto finish; if (ellipse) { + char *e; + size_t emax, sl; + int c; + c = fd_columns(fd); if (c <= 0) c = 80; - if (status) { - sl = 2 + 6 + 1; /* " [" status "]" */ - emax = (size_t) c > sl ? c - sl - 1 : 0; - } else - emax = c - 1; + sl = status ? strlen(status_indent) : 0; + + emax = c - sl - 1; + if (emax < 3) + emax = 3; e = ellipsize(s, emax, 75); if (e) { @@ -3365,34 +3392,23 @@ void status_vprintf(const char *status, bool ellipse, const char *format, va_lis } zero(iovec); - IOVEC_SET_STRING(iovec[n++], s); - if (ellipse) { - sl = strlen(s); - left = emax > sl ? emax - sl : 0; - if (left > 0) { - spaces = malloc(left); - if (spaces) { - memset(spaces, ' ', left); - iovec[n].iov_base = spaces; - iovec[n].iov_len = left; - n++; - } - } + if (status) { + if (!isempty(status)) { + IOVEC_SET_STRING(iovec[n++], "["); + IOVEC_SET_STRING(iovec[n++], status); + IOVEC_SET_STRING(iovec[n++], "] "); + } else + IOVEC_SET_STRING(iovec[n++], status_indent); } - if (status) { - IOVEC_SET_STRING(iovec[n++], " ["); - IOVEC_SET_STRING(iovec[n++], status); - IOVEC_SET_STRING(iovec[n++], "]\n"); - } else - IOVEC_SET_STRING(iovec[n++], "\n"); + IOVEC_SET_STRING(iovec[n++], s); + IOVEC_SET_STRING(iovec[n++], "\n"); writev(fd, iovec, n); finish: free(s); - free(spaces); if (fd >= 0) close_nointr_nofail(fd); @@ -5590,3 +5606,58 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value) { return r; } + +int can_sleep(const char *type) { + char *p, *w, *state; + size_t l, k; + bool found = false; + int r; + + assert(type); + + r = read_one_line_file("/sys/power/state", &p); + if (r < 0) + return r == -ENOENT ? 0 : r; + + k = strlen(type); + + FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) { + if (l == k && strncmp(w, type, l) == 0) { + found = true; + break; + } + } + + free(p); + return found; +} + +bool is_valid_documentation_url(const char *url) { + assert(url); + + if (startswith(url, "http://") && url[7]) + return true; + + if (startswith(url, "https://") && url[8]) + return true; + + if (startswith(url, "file:") && url[5]) + return true; + + if (startswith(url, "info:") && url[5]) + return true; + + if (startswith(url, "man:") && url[4]) + return true; + + return false; +} + +bool in_initrd(void) { + static int saved = -1; + + if (saved < 0) + saved = access("/etc/initrd-release", F_OK) >= 0; + + return saved; +}