X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Futil.c;h=ba86d206150cc92e0b43954d12dfb6d21404e1e6;hb=f32d2db140150b9d38684a699c9875b6e24ca27c;hp=30b0364b64cb7e0edf3d7803a7322ac0d758fdb7;hpb=42646a8bf24be2c9280554c9d8540c67c835b3c4;p=elogind.git diff --git a/src/shared/util.c b/src/shared/util.c index 30b0364b6..ba86d2061 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -695,7 +695,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; @@ -2074,7 +2074,7 @@ int acquire_terminal( * ended our handle will be dead. It's important that * we do this after sleeping, so that we don't enter * an endless loop. */ - safe_close(fd); + fd = safe_close(fd); } safe_close(notify); @@ -2466,14 +2466,53 @@ char* dirname_malloc(const char *path) { } int dev_urandom(void *p, size_t n) { - _cleanup_close_ int fd; + static int have_syscall = -1; + int r, fd; ssize_t k; + /* Gathers some randomness from the kernel. This call will + * never block, and will always return some data from the + * kernel, regardless if the random pool is fully initialized + * or not. It thus makes no guarantee for the quality of the + * returned entropy, but is good enough for or usual usecases + * of seeding the hash functions for hashtable */ + + /* Use the getrandom() syscall unless we know we don't have + * it, or when the requested size is too large for it. */ + if (have_syscall != 0 || (size_t) (int) n != n) { + r = getrandom(p, n, GRND_NONBLOCK); + if (r == (int) n) { + have_syscall = true; + return 0; + } + + if (r < 0) { + if (errno == ENOSYS) + /* we lack the syscall, continue with + * reading from /dev/urandom */ + have_syscall = false; + else if (errno == EAGAIN) + /* not enough entropy for now. Let's + * remember to use the syscall the + * next time, again, but also read + * from /dev/urandom for now, which + * doesn't care about the current + * amount of entropy. */ + have_syscall = true; + else + return -errno; + } else + /* too short read? */ + return -EIO; + } + fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return errno == ENOENT ? -ENOSYS : -errno; k = loop_read(fd, p, n, true); + safe_close(fd); + if (k < 0) return (int) k; if ((size_t) k != n) @@ -2482,8 +2521,36 @@ int dev_urandom(void *p, size_t n) { return 0; } -void random_bytes(void *p, size_t n) { +void initialize_srand(void) { static bool srand_called = false; + unsigned x; +#ifdef HAVE_SYS_AUXV_H + void *auxv; +#endif + + if (srand_called) + return; + + x = 0; + +#ifdef HAVE_SYS_AUXV_H + /* The kernel provides us with a bit of entropy in auxv, so + * let's try to make use of that to seed the pseudo-random + * generator. It's better than nothing... */ + + auxv = (void*) getauxval(AT_RANDOM); + if (auxv) + x ^= *(unsigned*) auxv; +#endif + + x ^= (unsigned) now(CLOCK_REALTIME); + x ^= (unsigned) gettid(); + + srand(x); + srand_called = true; +} + +void random_bytes(void *p, size_t n) { uint8_t *q; int r; @@ -2494,28 +2561,7 @@ void random_bytes(void *p, size_t n) { /* If some idiot made /dev/urandom unavailable to us, he'll * get a PRNG instead. */ - if (!srand_called) { - unsigned x = 0; - -#ifdef HAVE_SYS_AUXV_H - /* The kernel provides us with a bit of entropy in - * auxv, so let's try to make use of that to seed the - * pseudo-random generator. It's better than - * nothing... */ - - void *auxv; - - auxv = (void*) getauxval(AT_RANDOM); - if (auxv) - x ^= *(unsigned*) auxv; -#endif - - x ^= (unsigned) now(CLOCK_REALTIME); - x ^= (unsigned) gettid(); - - srand(x); - srand_called = true; - } + initialize_srand(); for (q = p; q < (uint8_t*) p + n; q ++) *q = rand(); @@ -3133,7 +3179,8 @@ char *replace_env(const char *format, char **env) { case CURLY: if (*e == '{') { - if (!(k = strnappend(r, word, e-word-1))) + k = strnappend(r, word, e-word-1); + if (!k) goto fail; free(r); @@ -3143,7 +3190,8 @@ char *replace_env(const char *format, char **env) { state = VARIABLE; } else if (*e == '$') { - if (!(k = strnappend(r, word, e-word))) + k = strnappend(r, word, e-word); + if (!k) goto fail; free(r); @@ -3175,7 +3223,8 @@ char *replace_env(const char *format, char **env) { } } - if (!(k = strnappend(r, word, e-word))) + k = strnappend(r, word, e-word); + if (!k) goto fail; free(r); @@ -3273,7 +3322,7 @@ unsigned columns(void) { c = 0; e = getenv("COLUMNS"); if (e) - safe_atoi(e, &c); + (void) safe_atoi(e, &c); if (c <= 0) c = fd_columns(STDOUT_FILENO); @@ -3307,7 +3356,7 @@ unsigned lines(void) { l = 0; e = getenv("LINES"); if (e) - safe_atou(e, &l); + (void) safe_atou(e, &l); if (l <= 0) l = fd_lines(STDOUT_FILENO); @@ -6097,27 +6146,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; @@ -6130,51 +6180,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 */ @@ -6933,13 +6967,24 @@ int is_symlink(const char *path) { if (lstat(path, &info) < 0) return -errno; - if (S_ISLNK(info.st_mode)) - return 1; + return !!S_ISLNK(info.st_mode); +} - return 0; +int is_dir(const char* path, bool follow) { + struct stat st; + int r; + + if (follow) + r = stat(path, &st); + else + r = lstat(path, &st); + if (r < 0) + return -errno; + + 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; @@ -6998,8 +7043,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; @@ -7010,9 +7058,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; @@ -7026,8 +7076,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; @@ -7053,8 +7106,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; @@ -7114,7 +7170,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; @@ -7164,3 +7220,23 @@ int free_and_strdup(char **p, const char *s) { return 0; } + +int sethostname_idempotent(const char *s) { + int r; + char buf[HOST_NAME_MAX + 1] = {}; + + assert(s); + + r = gethostname(buf, sizeof(buf)); + if (r < 0) + return -errno; + + if (streq(buf, s)) + return 0; + + r = sethostname(s, strlen(s)); + if (r < 0) + return -errno; + + return 1; +}