X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Futil.c;h=eeced4769a2aa141af7e7ba76cdef193c7ecefad;hb=781fa93815fafd02b5287ef5781b92ef7b99973b;hp=39ce46adb4dd19c10d5522f0c61e6271c5ff0426;hpb=d1bddcec98551ea748f39a742a4cbcf9ea9254ef;p=elogind.git diff --git a/src/shared/util.c b/src/shared/util.c index 39ce46adb..eeced4769 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -363,6 +363,46 @@ int safe_atou8(const char *s, uint8_t *ret) { return 0; } +int safe_atou16(const char *s, uint16_t *ret) { + char *x = NULL; + unsigned long l; + + assert(s); + assert(ret); + + errno = 0; + l = strtoul(s, &x, 0); + + if (!x || x == s || *x || errno) + return errno > 0 ? -errno : -EINVAL; + + if ((unsigned long) (uint16_t) l != l) + return -ERANGE; + + *ret = (uint16_t) l; + return 0; +} + +int safe_atoi16(const char *s, int16_t *ret) { + char *x = NULL; + long l; + + assert(s); + assert(ret); + + errno = 0; + l = strtol(s, &x, 0); + + if (!x || x == s || *x || errno) + return errno > 0 ? -errno : -EINVAL; + + if ((long) (int16_t) l != l) + return -ERANGE; + + *ret = (int16_t) l; + return 0; +} + int safe_atollu(const char *s, long long unsigned *ret_llu) { char *x = NULL; unsigned long long l; @@ -695,7 +735,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char * } /* Kernel threads have no argv[] */ - if (r == NULL || r[0] == 0) { + if (isempty(r)) { _cleanup_free_ char *t = NULL; int h; @@ -893,6 +933,28 @@ int readlink_malloc(const char *p, char **ret) { return readlinkat_malloc(AT_FDCWD, p, ret); } +int readlink_value(const char *p, char **ret) { + _cleanup_free_ char *link = NULL; + char *value; + int r; + + r = readlink_malloc(p, &link); + if (r < 0) + return r; + + value = basename(link); + if (!value) + return -ENOENT; + + value = strdup(value); + if (!value) + return -ENOMEM; + + *ret = value; + + return 0; +} + int readlink_and_make_absolute(const char *p, char **r) { _cleanup_free_ char *target = NULL; char *k; @@ -2783,7 +2845,7 @@ int get_ctty(pid_t pid, dev_t *_devnr, char **r) { if (k < 0) return k; - snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr)); + sprintf(fn, "/dev/char/%u:%u", major(devnr), minor(devnr)); k = readlink_malloc(fn, &s); if (k < 0) { @@ -2941,6 +3003,19 @@ int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root return rm_rf_children_dangerous(fd, only_dirs, honour_sticky, root_dev); } +static int file_is_priv_sticky(const char *p) { + struct stat st; + + assert(p); + + if (lstat(p, &st) < 0) + return -errno; + + return + (st.st_uid == 0 || st.st_uid == getuid()) && + (st.st_mode & S_ISVTX); +} + static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bool honour_sticky, bool dangerous) { int fd, r; struct statfs s; @@ -3257,7 +3332,7 @@ char **replace_env_argv(char **argv, char **env) { if (e) { int r; - r = strv_split_quoted(&m, e); + r = strv_split_quoted(&m, e, true); if (r < 0) { ret[k] = NULL; strv_free(ret); @@ -3578,41 +3653,33 @@ char *unquote(const char *s, const char* quotes) { } char *normalize_env_assignment(const char *s) { - _cleanup_free_ char *name = NULL, *value = NULL, *p = NULL; - char *eq, *r; + _cleanup_free_ char *value = NULL; + const char *eq; + char *p, *name; eq = strchr(s, '='); if (!eq) { - char *t; + char *r, *t; r = strdup(s); if (!r) return NULL; t = strstrip(r); - if (t == r) - return r; + if (t != r) + memmove(r, t, strlen(t) + 1); - memmove(r, t, strlen(t) + 1); return r; } - name = strndup(s, eq - s); - if (!name) - return NULL; - - p = strdup(eq + 1); - if (!p) - return NULL; + name = strndupa(s, eq - s); + p = strdupa(eq + 1); value = unquote(strstrip(p), QUOTES); if (!value) return NULL; - if (asprintf(&r, "%s=%s", strstrip(name), value) < 0) - r = NULL; - - return r; + return strjoin(strstrip(name), "=", value, NULL); } int wait_for_terminate(pid_t pid, siginfo_t *status) { @@ -4829,19 +4896,6 @@ int block_get_whole_disk(dev_t d, dev_t *ret) { return -ENOENT; } -int file_is_priv_sticky(const char *p) { - struct stat st; - - assert(p); - - if (lstat(p, &st) < 0) - return -errno; - - return - (st.st_uid == 0 || st.st_uid == getuid()) && - (st.st_mode & S_ISVTX); -} - static const char *const ioprio_class_table[] = { [IOPRIO_CLASS_NONE] = "none", [IOPRIO_CLASS_RT] = "realtime", @@ -6146,27 +6200,28 @@ int split_pair(const char *s, const char *sep, char **l, char **r) { int shall_restore_state(void) { _cleanup_free_ char *line = NULL; - const char *word, *state; - size_t l; + const char *p; int r; r = proc_cmdline(&line); if (r < 0) return r; - if (r == 0) /* Container ... */ - return 1; r = 1; + p = line; - FOREACH_WORD_QUOTED(word, l, line, state) { + for (;;) { + _cleanup_free_ char *word = NULL; const char *e; - char n[l+1]; int k; - memcpy(n, word, l); - n[l] = 0; + k = unquote_first_word(&p, &word, true); + if (k < 0) + return k; + if (k == 0) + break; - e = startswith(n, "systemd.restore_state="); + e = startswith(word, "systemd.restore_state="); if (!e) continue; @@ -6179,51 +6234,35 @@ int shall_restore_state(void) { } int proc_cmdline(char **ret) { - int r; - - if (detect_container(NULL) > 0) { - char *buf = NULL, *p; - size_t sz = 0; - - r = read_full_file("/proc/1/cmdline", &buf, &sz); - if (r < 0) - return r; - - for (p = buf; p + 1 < buf + sz; p++) - if (*p == 0) - *p = ' '; - - *p = 0; - *ret = buf; - return 1; - } - - r = read_one_line_file("/proc/cmdline", ret); - if (r < 0) - return r; + assert(ret); - return 1; + if (detect_container(NULL) > 0) + return get_process_cmdline(1, 0, false, ret); + else + return read_one_line_file("/proc/cmdline", ret); } int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) { _cleanup_free_ char *line = NULL; - const char *w, *state; - size_t l; + const char *p; int r; assert(parse_item); r = proc_cmdline(&line); if (r < 0) - log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r)); - if (r <= 0) - return 0; + return r; - FOREACH_WORD_QUOTED(w, l, line, state) { - char word[l+1], *value; + p = line; + for (;;) { + _cleanup_free_ char *word = NULL; + char *value = NULL; - memcpy(word, w, l); - word[l] = 0; + r = unquote_first_word(&p, &word, true); + if (r < 0) + return r; + if (r == 0) + break; /* Filter out arguments that are intended only for the * initrd */ @@ -6999,7 +7038,7 @@ int is_dir(const char* path, bool follow) { return !!S_ISDIR(st.st_mode); } -int unquote_first_word(const char **p, char **ret) { +int unquote_first_word(const char **p, char **ret, bool relax) { _cleanup_free_ char *s = NULL; size_t allocated = 0, sz = 0; @@ -7058,8 +7097,11 @@ int unquote_first_word(const char **p, char **ret) { break; case VALUE_ESCAPE: - if (c == 0) + if (c == 0) { + if (relax) + goto finish; return -EINVAL; + } if (!GREEDY_REALLOC(s, allocated, sz+2)) return -ENOMEM; @@ -7070,9 +7112,11 @@ int unquote_first_word(const char **p, char **ret) { break; case SINGLE_QUOTE: - if (c == 0) + if (c == 0) { + if (relax) + goto finish; return -EINVAL; - else if (c == '\'') + } else if (c == '\'') state = VALUE; else if (c == '\\') state = SINGLE_QUOTE_ESCAPE; @@ -7086,8 +7130,11 @@ int unquote_first_word(const char **p, char **ret) { break; case SINGLE_QUOTE_ESCAPE: - if (c == 0) + if (c == 0) { + if (relax) + goto finish; return -EINVAL; + } if (!GREEDY_REALLOC(s, allocated, sz+2)) return -ENOMEM; @@ -7113,8 +7160,11 @@ int unquote_first_word(const char **p, char **ret) { break; case DOUBLE_QUOTE_ESCAPE: - if (c == 0) + if (c == 0) { + if (relax) + goto finish; return -EINVAL; + } if (!GREEDY_REALLOC(s, allocated, sz+2)) return -ENOMEM; @@ -7174,7 +7224,7 @@ int unquote_many_words(const char **p, ...) { l = newa0(char*, n); for (c = 0; c < n; c++) { - r = unquote_first_word(p, &l[c]); + r = unquote_first_word(p, &l[c], false); if (r < 0) { int j;