X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Futil.c;h=ee95a4b6f71c67bb7ff3f5c3e8ce736bfaa98113;hb=69adae5168da231c6cf319f708860954701b25ed;hp=8c1cf52c0a695c653b74b8a9cfd869a84e8d9178;hpb=32802361561403cb6441198c82d9c499e0513863;p=elogind.git diff --git a/src/shared/util.c b/src/shared/util.c index 8c1cf52c0..ee95a4b6f 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -558,7 +558,7 @@ const char* split(const char **state, size_t *l, const char *separator, bool quo *l = strcspn_escaped(current + 1, quotechars); if (current[*l + 1] == '\0' || (current[*l + 2] && !strchr(separator, current[*l + 2]))) { - /* right quote missing or garbage at the end*/ + /* right quote missing or garbage at the end */ *state = current; return NULL; } @@ -1436,7 +1436,7 @@ char *cunescape_length_with_prefix(const char *s, size_t length, const char *pre } case 0: - /* premature end of string.*/ + /* premature end of string. */ *(t++) = '\\'; goto finish; @@ -2100,9 +2100,9 @@ int acquire_terminal( assert(notify >= 0); for (;;) { - uint8_t inotify_buffer[sizeof(struct inotify_event) + FILENAME_MAX]; - ssize_t l; + uint8_t buffer[INOTIFY_EVENT_MAX] _alignas_(struct inotify_event); struct inotify_event *e; + ssize_t l; if (timeout != USEC_INFINITY) { usec_t n; @@ -2123,9 +2123,8 @@ int acquire_terminal( } } - l = read(notify, inotify_buffer, sizeof(inotify_buffer)); + l = read(notify, buffer, sizeof(buffer)); if (l < 0) { - if (errno == EINTR || errno == EAGAIN) continue; @@ -2133,21 +2132,11 @@ int acquire_terminal( goto fail; } - e = (struct inotify_event*) inotify_buffer; - - while (l > 0) { - size_t step; - + FOREACH_INOTIFY_EVENT(e, buffer, l) { if (e->wd != wd || !(e->mask & IN_CLOSE)) { r = -EIO; goto fail; } - - step = sizeof(struct inotify_event) + e->len; - assert(step <= (size_t) l); - - e = (struct inotify_event*) ((uint8_t*) e + step); - l -= step; } break; @@ -2279,21 +2268,25 @@ ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) { ssize_t k; k = read(fd, p, nbytes); - if (k < 0 && errno == EINTR) - continue; + if (k < 0) { + if (errno == EINTR) + continue; - if (k < 0 && errno == EAGAIN && do_poll) { + if (errno == EAGAIN && do_poll) { - /* We knowingly ignore any return value here, - * and expect that any error/EOF is reported - * via read() */ + /* We knowingly ignore any return value here, + * and expect that any error/EOF is reported + * via read() */ - fd_wait_for_event(fd, POLLIN, USEC_INFINITY); - continue; + fd_wait_for_event(fd, POLLIN, USEC_INFINITY); + continue; + } + + return n > 0 ? n : -errno; } - if (k <= 0) - return n > 0 ? n : (k < 0 ? -errno : 0); + if (k == 0) + return n; p += k; nbytes -= k; @@ -2303,39 +2296,42 @@ ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) { return n; } -ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) { +int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) { const uint8_t *p = buf; - ssize_t n = 0; assert(fd >= 0); assert(buf); + errno = 0; + while (nbytes > 0) { ssize_t k; k = write(fd, p, nbytes); - if (k < 0 && errno == EINTR) - continue; + if (k < 0) { + if (errno == EINTR) + continue; - if (k < 0 && errno == EAGAIN && do_poll) { + if (errno == EAGAIN && do_poll) { + /* We knowingly ignore any return value here, + * and expect that any error/EOF is reported + * via write() */ - /* We knowingly ignore any return value here, - * and expect that any error/EOF is reported - * via write() */ + fd_wait_for_event(fd, POLLOUT, USEC_INFINITY); + continue; + } - fd_wait_for_event(fd, POLLOUT, USEC_INFINITY); - continue; + return -errno; } - if (k <= 0) - return n > 0 ? n : (k < 0 ? -errno : 0); + if (k == 0) /* Can't really happen */ + return -EIO; p += k; nbytes -= k; - n += k; } - return n; + return 0; } int parse_size(const char *t, off_t base, off_t *size) { @@ -3670,7 +3666,7 @@ char *unquote(const char *s, const char* quotes) { /* This is rather stupid, simply removes the heading and * trailing quotes if there is one. Doesn't care about * escaping or anything. We should make this smarter one - * day...*/ + * day... */ l = strlen(s); if (l < 2) @@ -4292,15 +4288,15 @@ int fd_wait_for_event(int fd, int event, usec_t t) { int fopen_temporary(const char *path, FILE **_f, char **_temp_path) { FILE *f; char *t; - int fd; + int r, fd; assert(path); assert(_f); assert(_temp_path); - t = tempfn_xxxxxx(path); - if (!t) - return -ENOMEM; + r = tempfn_xxxxxx(path, &t); + if (r < 0) + return r; fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC); if (fd < 0) { @@ -4411,13 +4407,14 @@ int vt_disallocate(const char *name) { int symlink_atomic(const char *from, const char *to) { _cleanup_free_ char *t = NULL; + int r; assert(from); assert(to); - t = tempfn_random(to); - if (!t) - return -ENOMEM; + r = tempfn_random(to, &t); + if (r < 0) + return r; if (symlink(from, t) < 0) return -errno; @@ -4432,12 +4429,13 @@ int symlink_atomic(const char *from, const char *to) { int mknod_atomic(const char *path, mode_t mode, dev_t dev) { _cleanup_free_ char *t = NULL; + int r; assert(path); - t = tempfn_random(path); - if (!t) - return -ENOMEM; + r = tempfn_random(path, &t); + if (r < 0) + return r; if (mknod(t, mode, dev) < 0) return -errno; @@ -4452,12 +4450,13 @@ int mknod_atomic(const char *path, mode_t mode, dev_t dev) { int mkfifo_atomic(const char *path, mode_t mode) { _cleanup_free_ char *t = NULL; + int r; assert(path); - t = tempfn_random(path); - if (!t) - return -ENOMEM; + r = tempfn_random(path, &t); + if (r < 0) + return r; if (mkfifo(t, mode) < 0) return -errno; @@ -5569,7 +5568,7 @@ int get_shell(char **_s) { return 0; } -bool filename_is_safe(const char *p) { +bool filename_is_valid(const char *p) { if (isempty(p)) return false; @@ -6971,42 +6970,93 @@ int fflush_and_check(FILE *f) { return 0; } -char *tempfn_xxxxxx(const char *p) { +int tempfn_xxxxxx(const char *p, char **ret) { const char *fn; char *t; - size_t k; assert(p); + assert(ret); - t = new(char, strlen(p) + 1 + 6 + 1); - if (!t) - return NULL; + /* + * Turns this: + * /foo/bar/waldo + * + * Into this: + * /foo/bar/.waldoXXXXXX + */ fn = basename(p); - k = fn - p; + if (!filename_is_valid(fn)) + return -EINVAL; - strcpy(stpcpy(stpcpy(mempcpy(t, p, k), "."), fn), "XXXXXX"); + t = new(char, strlen(p) + 1 + 6 + 1); + if (!t) + return -ENOMEM; - return t; + strcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), "."), fn), "XXXXXX"); + + *ret = path_kill_slashes(t); + return 0; } -char *tempfn_random(const char *p) { +int tempfn_random(const char *p, char **ret) { const char *fn; char *t, *x; uint64_t u; - size_t k; unsigned i; assert(p); + assert(ret); + + /* + * Turns this: + * /foo/bar/waldo + * + * Into this: + * /foo/bar/.waldobaa2a261115984a9 + */ + + fn = basename(p); + if (!filename_is_valid(fn)) + return -EINVAL; t = new(char, strlen(p) + 1 + 16 + 1); if (!t) - return NULL; + return -ENOMEM; - fn = basename(p); - k = fn - p; + x = stpcpy(stpcpy(mempcpy(t, p, fn - p), "."), fn); - x = stpcpy(stpcpy(mempcpy(t, p, k), "."), fn); + u = random_u64(); + for (i = 0; i < 16; i++) { + *(x++) = hexchar(u & 0xF); + u >>= 4; + } + + *x = 0; + + *ret = path_kill_slashes(t); + return 0; +} + +int tempfn_random_child(const char *p, char **ret) { + char *t, *x; + uint64_t u; + unsigned i; + + assert(p); + assert(ret); + + /* Turns this: + * /foo/bar/waldo + * Into this: + * /foo/bar/waldo/.3c2b6219aa75d7d0 + */ + + t = new(char, strlen(p) + 2 + 16 + 1); + if (!t) + return -ENOMEM; + + x = stpcpy(stpcpy(t, p), "/."); u = random_u64(); for (i = 0; i < 16; i++) { @@ -7016,7 +7066,8 @@ char *tempfn_random(const char *p) { *x = 0; - return t; + *ret = path_kill_slashes(t); + return 0; } /* make sure the hostname is not "localhost" */