Commit dc1bfde5 authored by Beniamino Galvani's avatar Beniamino Galvani

systemd: update code from upstream (2017-08-09)

This is a direct dump from systemd git on 2017-08-09, git commit
c7f6ca9379279affa8f22d15fa13063491f86a49.

======

SYSTEMD_DIR=../systemd
COMMIT=c7f6ca9379279affa8f22d15fa13063491f86a49

(
  cd "$SYSTEMD_DIR"
  git checkout "$COMMIT"
  git reset --hard
  git clean -fdx
)

git ls-files :/src/systemd/src/ | xargs -d '\n' rm -f

nm_copy_sd() {
    mkdir -p "./src/systemd/$(dirname "$1")"
    cp "$SYSTEMD_DIR/$1" "./src/systemd/$1"
}

nm_copy_sd "src/basic/alloc-util.c"
nm_copy_sd "src/basic/alloc-util.h"
nm_copy_sd "src/basic/async.h"
nm_copy_sd "src/basic/escape.c"
nm_copy_sd "src/basic/escape.h"
nm_copy_sd "src/basic/ether-addr-util.c"
nm_copy_sd "src/basic/ether-addr-util.h"
nm_copy_sd "src/basic/extract-word.c"
nm_copy_sd "src/basic/extract-word.h"
nm_copy_sd "src/basic/fileio.c"
nm_copy_sd "src/basic/fileio.h"
nm_copy_sd "src/basic/fd-util.c"
nm_copy_sd "src/basic/fd-util.h"
nm_copy_sd "src/basic/fs-util.c"
nm_copy_sd "src/basic/fs-util.h"
nm_copy_sd "src/basic/hash-funcs.c"
nm_copy_sd "src/basic/hash-funcs.h"
nm_copy_sd "src/basic/hashmap.c"
nm_copy_sd "src/basic/hashmap.h"
nm_copy_sd "src/basic/hexdecoct.c"
nm_copy_sd "src/basic/hexdecoct.h"
nm_copy_sd "src/basic/hostname-util.c"
nm_copy_sd "src/basic/hostname-util.h"
nm_copy_sd "src/basic/in-addr-util.c"
nm_copy_sd "src/basic/in-addr-util.h"
nm_copy_sd "src/basic/io-util.c"
nm_copy_sd "src/basic/io-util.h"
nm_copy_sd "src/basic/list.h"
nm_copy_sd "src/basic/log.h"
nm_copy_sd "src/basic/macro.h"
nm_copy_sd "src/basic/mempool.h"
nm_copy_sd "src/basic/mempool.c"
nm_copy_sd "src/basic/parse-util.c"
nm_copy_sd "src/basic/parse-util.h"
nm_copy_sd "src/basic/path-util.c"
nm_copy_sd "src/basic/path-util.h"
nm_copy_sd "src/basic/prioq.h"
nm_copy_sd "src/basic/prioq.c"
nm_copy_sd "src/basic/process-util.h"
nm_copy_sd "src/basic/process-util.c"
nm_copy_sd "src/basic/random-util.c"
nm_copy_sd "src/basic/random-util.h"
nm_copy_sd "src/basic/refcnt.h"
nm_copy_sd "src/basic/set.h"
nm_copy_sd "src/basic/signal-util.h"
nm_copy_sd "src/basic/siphash24.c"
nm_copy_sd "src/basic/siphash24.h"
nm_copy_sd "src/basic/socket-util.c"
nm_copy_sd "src/basic/socket-util.h"
nm_copy_sd "src/basic/sparse-endian.h"
nm_copy_sd "src/basic/stdio-util.h"
nm_copy_sd "src/basic/string-table.c"
nm_copy_sd "src/basic/string-table.h"
nm_copy_sd "src/basic/string-util.c"
nm_copy_sd "src/basic/string-util.h"
nm_copy_sd "src/basic/strv.c"
nm_copy_sd "src/basic/strv.h"
nm_copy_sd "src/basic/time-util.c"
nm_copy_sd "src/basic/time-util.h"
nm_copy_sd "src/basic/umask-util.h"
nm_copy_sd "src/basic/unaligned.h"
nm_copy_sd "src/basic/utf8.c"
nm_copy_sd "src/basic/utf8.h"
nm_copy_sd "src/basic/util.c"
nm_copy_sd "src/basic/util.h"
nm_copy_sd "src/libsystemd-network/arp-util.c"
nm_copy_sd "src/libsystemd-network/arp-util.h"
nm_copy_sd "src/libsystemd-network/dhcp6-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp6-lease-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp6-network.c"
nm_copy_sd "src/libsystemd-network/dhcp6-option.c"
nm_copy_sd "src/libsystemd-network/dhcp6-protocol.h"
nm_copy_sd "src/libsystemd-network/dhcp-identifier.c"
nm_copy_sd "src/libsystemd-network/dhcp-identifier.h"
nm_copy_sd "src/libsystemd-network/dhcp-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp-lease-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp-network.c"
nm_copy_sd "src/libsystemd-network/dhcp-option.c"
nm_copy_sd "src/libsystemd-network/dhcp-packet.c"
nm_copy_sd "src/libsystemd-network/dhcp-protocol.h"
nm_copy_sd "src/libsystemd-network/lldp-internal.h"
nm_copy_sd "src/libsystemd-network/lldp-neighbor.c"
nm_copy_sd "src/libsystemd-network/lldp-neighbor.h"
nm_copy_sd "src/libsystemd-network/lldp-network.c"
nm_copy_sd "src/libsystemd-network/lldp-network.h"
nm_copy_sd "src/libsystemd-network/network-internal.c"
nm_copy_sd "src/libsystemd-network/network-internal.h"
nm_copy_sd "src/libsystemd-network/sd-dhcp6-client.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp6-lease.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp-client.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp-lease.c"
nm_copy_sd "src/libsystemd-network/sd-ipv4ll.c"
nm_copy_sd "src/libsystemd-network/sd-ipv4acd.c"
nm_copy_sd "src/libsystemd-network/sd-lldp.c"
nm_copy_sd "src/libsystemd/sd-event/sd-event.c"
nm_copy_sd "src/libsystemd/sd-id128/id128-util.c"
nm_copy_sd "src/libsystemd/sd-id128/id128-util.h"
nm_copy_sd "src/libsystemd/sd-id128/sd-id128.c"
nm_copy_sd "src/shared/dns-domain.c"
nm_copy_sd "src/shared/dns-domain.h"
nm_copy_sd "src/systemd/_sd-common.h"
nm_copy_sd "src/systemd/sd-dhcp6-client.h"
nm_copy_sd "src/systemd/sd-dhcp6-lease.h"
nm_copy_sd "src/systemd/sd-dhcp-client.h"
nm_copy_sd "src/systemd/sd-dhcp-lease.h"
nm_copy_sd "src/systemd/sd-event.h"
nm_copy_sd "src/systemd/sd-ndisc.h"
nm_copy_sd "src/systemd/sd-id128.h"
nm_copy_sd "src/systemd/sd-ipv4acd.h"
nm_copy_sd "src/systemd/sd-ipv4ll.h"
nm_copy_sd "src/systemd/sd-lldp.h"
parent cd5ef1ed
......@@ -25,16 +25,31 @@
#include "util.h"
void* memdup(const void *p, size_t l) {
void *r;
void *ret;
assert(p);
assert(l == 0 || p);
ret = malloc(l);
if (!ret)
return NULL;
memcpy(ret, p, l);
return ret;
}
void* memdup_suffix0(const void*p, size_t l) {
void *ret;
assert(l == 0 || p);
/* The same as memdup() but place a safety NUL byte after the allocated memory */
r = malloc(l);
if (!r)
ret = malloc(l + 1);
if (!ret)
return NULL;
memcpy(r, p, l);
return r;
*((uint8_t*) mempcpy(ret, p, l)) = 0;
return ret;
}
void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
......
......@@ -36,6 +36,8 @@
#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
#define newdup_suffix0(t, p, n) ((t*) memdup_suffix0_multiply(p, sizeof(t), (n)))
#define malloc0(n) (calloc(1, (n)))
static inline void *mfree(void *memory) {
......@@ -52,6 +54,7 @@ static inline void *mfree(void *memory) {
})
void* memdup(const void *p, size_t l) _alloc_(2);
void* memdup_suffix0(const void*p, size_t l) _alloc_(2);
static inline void freep(void *p) {
free(*(void**) p);
......@@ -84,6 +87,13 @@ _alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, si
return memdup(p, size * need);
}
_alloc_(2, 3) static inline void *memdup_suffix0_multiply(const void *p, size_t size, size_t need) {
if (size_multiply_overflow(size, need))
return NULL;
return memdup_suffix0(p, size * need);
}
void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size);
void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
......
......@@ -314,7 +314,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
/* Undoes C style string escaping, and optionally prefixes it. */
pl = prefix ? strlen(prefix) : 0;
pl = strlen_ptr(prefix);
r = new(char, pl+length+1);
if (!r)
......@@ -441,10 +441,16 @@ char *octescape(const char *s, size_t len) {
}
static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad, bool escape_tab_nl) {
assert(bad);
for (; *s; s++) {
if (escape_tab_nl && IN_SET(*s, '\n', '\t')) {
*(t++) = '\\';
*(t++) = *s == '\n' ? 'n' : 't';
continue;
}
if (*s == '\\' || strchr(bad, *s))
*(t++) = '\\';
......@@ -461,20 +467,21 @@ char *shell_escape(const char *s, const char *bad) {
if (!r)
return NULL;
t = strcpy_backslash_escaped(r, s, bad);
t = strcpy_backslash_escaped(r, s, bad, false);
*t = 0;
return r;
}
char *shell_maybe_quote(const char *s) {
char* shell_maybe_quote(const char *s, EscapeStyle style) {
const char *p;
char *r, *t;
assert(s);
/* Encloses a string in double quotes if necessary to make it
* OK as shell string. */
/* Encloses a string in quotes if necessary to make it OK as a shell
* string. Note that we treat benign UTF-8 characters as needing
* escaping too, but that should be OK. */
for (p = s; *p; p++)
if (*p <= ' ' ||
......@@ -485,17 +492,30 @@ char *shell_maybe_quote(const char *s) {
if (!*p)
return strdup(s);
r = new(char, 1+strlen(s)*2+1+1);
r = new(char, (style == ESCAPE_POSIX) + 1 + strlen(s)*2 + 1 + 1);
if (!r)
return NULL;
t = r;
*(t++) = '"';
if (style == ESCAPE_BACKSLASH)
*(t++) = '"';
else if (style == ESCAPE_POSIX) {
*(t++) = '$';
*(t++) = '\'';
} else
assert_not_reached("Bad EscapeStyle");
t = mempcpy(t, s, p - s);
t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE);
if (style == ESCAPE_BACKSLASH)
t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE, false);
else
t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE_POSIX, true);
*(t++)= '"';
if (style == ESCAPE_BACKSLASH)
*(t++) = '"';
else
*(t++) = '\'';
*t = 0;
return r;
......
......@@ -31,13 +31,30 @@
/* What characters are special in the shell? */
/* must be escaped outside and inside double-quotes */
#define SHELL_NEED_ESCAPE "\"\\`$"
/* can be escaped or double-quoted */
#define SHELL_NEED_QUOTES SHELL_NEED_ESCAPE GLOB_CHARS "'()<>|&;"
/* Those that can be escaped or double-quoted.
*
* Stricly speaking, ! does not need to be escaped, except in interactive
* mode, but let's be extra nice to the user and quote ! in case this
* output is ever used in interactive mode. */
#define SHELL_NEED_QUOTES SHELL_NEED_ESCAPE GLOB_CHARS "'()<>|&;!"
/* Note that we assume control characters would need to be escaped too in
* addition to the "special" characters listed here, if they appear in the
* string. Current users disallow control characters. Also '"' shall not
* be escaped.
*/
#define SHELL_NEED_ESCAPE_POSIX "\\\'"
typedef enum UnescapeFlags {
UNESCAPE_RELAX = 1,
} UnescapeFlags;
typedef enum EscapeStyle {
ESCAPE_BACKSLASH = 1,
ESCAPE_POSIX = 2,
} EscapeStyle;
char *cescape(const char *s);
char *cescape_length(const char *s, size_t n);
size_t cescape_char(char c, char *buf);
......@@ -51,4 +68,4 @@ char *xescape(const char *s, const char *bad);
char *octescape(const char *s, size_t len);
char *shell_escape(const char *s, const char *bad);
char *shell_maybe_quote(const char *s);
char* shell_maybe_quote(const char *s, EscapeStyle style);
......@@ -31,6 +31,7 @@
#include "missing.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "socket-util.h"
#include "stdio-util.h"
#include "util.h"
......@@ -282,7 +283,7 @@ int same_fd(int a, int b) {
return true;
/* Try to use kcmp() if we have it. */
pid = getpid();
pid = getpid_cached();
r = kcmp(pid, pid, KCMP_FILE, a, b);
if (r == 0)
return true;
......
......@@ -41,6 +41,7 @@
#include "missing.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "random-util.h"
#include "stdio-util.h"
#include "string-util.h"
......@@ -823,29 +824,29 @@ static void write_env_var(FILE *f, const char *v) {
p = strchr(v, '=');
if (!p) {
/* Fallback */
fputs(v, f);
fputc('\n', f);
fputs_unlocked(v, f);
fputc_unlocked('\n', f);
return;
}
p++;
fwrite(v, 1, p-v, f);
fwrite_unlocked(v, 1, p-v, f);
if (string_has_cc(p, NULL) || chars_intersect(p, WHITESPACE SHELL_NEED_QUOTES)) {
fputc('\"', f);
fputc_unlocked('\"', f);
for (; *p; p++) {
if (strchr(SHELL_NEED_ESCAPE, *p))
fputc('\\', f);
fputc_unlocked('\\', f);
fputc(*p, f);
fputc_unlocked(*p, f);
}
fputc('\"', f);
fputc_unlocked('\"', f);
} else
fputs(p, f);
fputs_unlocked(p, f);
fputc('\n', f);
fputc_unlocked('\n', f);
}
int write_env_file(const char *fname, char **l) {
......@@ -1399,7 +1400,7 @@ int open_serialization_fd(const char *ident) {
if (fd < 0) {
const char *path;
path = getpid() == 1 ? "/run/systemd" : "/tmp";
path = getpid_cached() == 1 ? "/run/systemd" : "/tmp";
fd = open_tmpfile_unlinkable(path, O_RDWR|O_CLOEXEC);
if (fd < 0)
return fd;
......
......@@ -307,7 +307,7 @@ int fd_warn_permissions(const char *path, int fd) {
if (st.st_mode & 0002)
log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
if (getpid() == 1 && (st.st_mode & 0044) != 0044)
if (getpid_cached() == 1 && (st.st_mode & 0044) != 0044)
log_warning("Configuration file %s is marked world-inaccessible. This has no effect as configuration data is accessible via APIs without restrictions. Proceeding anyway.", path);
return 0;
......
......@@ -25,6 +25,7 @@
#include "alloc-util.h"
#include "hexdecoct.h"
#include "macro.h"
#include "string-util.h"
#include "util.h"
char octchar(int x) {
......@@ -569,7 +570,7 @@ static int base64_append_width(char **prefix, int plen,
lines = (len + width - 1) / width;
slen = sep ? strlen(sep) : 0;
slen = strlen_ptr(sep);
t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
if (!t)
return -ENOMEM;
......
......@@ -196,8 +196,11 @@ bool is_gateway_hostname(const char *hostname) {
* synthetic "gateway" host. */
return
strcaseeq(hostname, "gateway") ||
strcaseeq(hostname, "gateway.");
strcaseeq(hostname, "_gateway") || strcaseeq(hostname, "_gateway.")
#if ENABLE_COMPAT_GATEWAY_HOSTNAME
|| strcaseeq(hostname, "gateway") || strcaseeq(hostname, "gateway.")
#endif
;
}
int sethostname_idempotent(const char *s) {
......
......@@ -30,6 +30,7 @@
#include "sd-id128.h"
#include "macro.h"
#include "process-util.h"
typedef enum LogRealm {
LOG_REALM_SYSTEMD,
......@@ -86,6 +87,11 @@ int log_get_max_level_realm(LogRealm realm) _pure_;
#define log_get_max_level() \
log_get_max_level_realm(LOG_REALM)
/* Functions below that open and close logs or configure logging based on the
* environment should not be called from library code — this is always a job
* for the application itself.
*/
int log_open(void);
void log_close(void);
void log_forget_fds(void);
......@@ -242,7 +248,7 @@ void log_assert_failed_return_realm(
#define log_notice(...) log_full(LOG_NOTICE, __VA_ARGS__)
#define log_warning(...) log_full(LOG_WARNING, __VA_ARGS__)
#define log_error(...) log_full(LOG_ERR, __VA_ARGS__)
#define log_emergency(...) log_full(getpid() == 1 ? LOG_EMERG : LOG_ERR, __VA_ARGS__)
#define log_emergency(...) log_full(getpid_cached() == 1 ? LOG_EMERG : LOG_ERR, __VA_ARGS__)
/* Logging triggered by an errno-like error */
#define log_debug_errno(error, ...) log_full_errno(LOG_DEBUG, error, __VA_ARGS__)
......@@ -250,7 +256,7 @@ void log_assert_failed_return_realm(
#define log_notice_errno(error, ...) log_full_errno(LOG_NOTICE, error, __VA_ARGS__)
#define log_warning_errno(error, ...) log_full_errno(LOG_WARNING, error, __VA_ARGS__)
#define log_error_errno(error, ...) log_full_errno(LOG_ERR, error, __VA_ARGS__)
#define log_emergency_errno(error, ...) log_full_errno(getpid() == 1 ? LOG_EMERG : LOG_ERR, error, __VA_ARGS__)
#define log_emergency_errno(error, ...) log_full_errno(getpid_cached() == 1 ? LOG_EMERG : LOG_ERR, error, __VA_ARGS__)
#ifdef LOG_TRACE
# define log_trace(...) log_debug(__VA_ARGS__)
......
......@@ -59,7 +59,7 @@ int parse_pid(const char *s, pid_t* ret_pid) {
if ((unsigned long) pid != ul)
return -ERANGE;
if (pid <= 0)
if (!pid_is_valid(pid))
return -ERANGE;
*ret_pid = pid;
......@@ -589,3 +589,18 @@ int parse_ip_port(const char *s, uint16_t *ret) {
return 0;
}
int parse_dev(const char *s, dev_t *ret) {
unsigned x, y;
dev_t d;
if (sscanf(s, "%u:%u", &x, &y) != 2)
return -EINVAL;
d = makedev(x, y);
if ((unsigned) major(d) != x || (unsigned) minor(d) != y)
return -EINVAL;
*ret = d;
return 0;
}
......@@ -30,6 +30,7 @@
#define MODE_INVALID ((mode_t) -1)
int parse_boolean(const char *v) _pure_;
int parse_dev(const char *s, dev_t *ret);
int parse_pid(const char *s, pid_t* ret_pid);
int parse_mode(const char *s, mode_t *ret);
int parse_ifindex(const char *s, int *ret);
......
......@@ -442,8 +442,8 @@ bool path_equal(const char *a, const char *b) {
return path_compare(a, b) == 0;
}
bool path_equal_or_files_same(const char *a, const char *b) {
return path_equal(a, b) || files_same(a, b) > 0;
bool path_equal_or_files_same(const char *a, const char *b, int flags) {
return path_equal(a, b) || files_same(a, b, flags) > 0;
}
char* path_join(const char *root, const char *path, const char *rest) {
......
......@@ -46,7 +46,7 @@ char* path_kill_slashes(char *path);
char* path_startswith(const char *path, const char *prefix) _pure_;
int path_compare(const char *a, const char *b) _pure_;
bool path_equal(const char *a, const char *b) _pure_;
bool path_equal_or_files_same(const char *a, const char *b);
bool path_equal_or_files_same(const char *a, const char *b, int flags);
char* path_join(const char *root, const char *path, const char *rest);
static inline bool path_equal_ptr(const char *a, const char *b) {
......
This diff is collapsed.
#pragma once
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <alloca.h>
#include <signal.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/types.h>
#include "format-util.h"
#include "ioprio.h"
#include "macro.h"
#define procfs_file_alloca(pid, field) \
({ \
pid_t _pid_ = (pid); \
const char *_r_; \
if (_pid_ == 0) { \
_r_ = ("/proc/self/" field); \
} else { \
_r_ = alloca(strlen("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \
} \
_r_; \
})
int get_process_state(pid_t pid);
int get_process_comm(pid_t pid, char **name);
int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line);
int get_process_exe(pid_t pid, char **name);
int get_process_uid(pid_t pid, uid_t *uid);
int get_process_gid(pid_t pid, gid_t *gid);
int get_process_capeff(pid_t pid, char **capeff);
int get_process_cwd(pid_t pid, char **cwd);
int get_process_root(pid_t pid, char **root);
int get_process_environ(pid_t pid, char **environ);
int get_process_ppid(pid_t pid, pid_t *ppid);
int wait_for_terminate(pid_t pid, siginfo_t *status);
int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code);
void sigkill_wait(pid_t pid);
void sigkill_waitp(pid_t *pid);
int kill_and_sigcont(pid_t pid, int sig);
int rename_process(const char name[]);
int is_kernel_thread(pid_t pid);
int getenv_for_pid(pid_t pid, const char *field, char **_value);
bool pid_is_alive(pid_t pid);
bool pid_is_unwaited(pid_t pid);
int pid_from_same_root_fs(pid_t pid);
bool is_main_thread(void);
noreturn void freeze(void);
bool oom_score_adjust_is_valid(int oa);
#ifndef PERSONALITY_INVALID
/* personality(7) documents that 0xffffffffUL is used for querying the
* current personality, hence let's use that here as error
* indicator. */
#define PERSONALITY_INVALID 0xffffffffLU
#endif
unsigned long personality_from_string(const char *p);
const char *personality_to_string(unsigned long);
int ioprio_class_to_string_alloc(int i, char **s);
int ioprio_class_from_string(const char *s);
const char *sigchld_code_to_string(int i) _const_;
int sigchld_code_from_string(const char *s) _pure_;
int sched_policy_to_string_alloc(int i, char **s);
int sched_policy_from_string(const char *s);
#define PTR_TO_PID(p) ((pid_t) ((uintptr_t) p))
#define PID_TO_PTR(p) ((void*) ((uintptr_t) p))
void valgrind_summary_hack(void);
int pid_compare_func(const void *a, const void *b);
static inline bool nice_is_valid(int n) {
return n >= PRIO_MIN && n < PRIO_MAX;
}
static inline bool ioprio_class_is_valid(int i) {
return IN_SET(i, IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE);
}
static inline bool ioprio_priority_is_valid(int i) {
return i >= 0 && i < IOPRIO_BE_NR;
}
static inline bool pid_is_valid(pid_t p) {
return p > 0;
}
int ioprio_parse_priority(const char *s, int *ret);
pid_t getpid_cached(void);
......@@ -42,53 +42,59 @@
#include "random-util.h"
#include "time-util.h"
int dev_urandom(void *p, size_t n) {
int acquire_random_bytes(void *p, size_t n, bool high_quality_required) {
static int have_syscall = -1;
_cleanup_close_ int fd = -1;
unsigned already_done = 0;
int r;
/* 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 our usual usecases
* of seeding the hash functions for hashtable */
/* Gathers some randomness from the kernel. This call will never block. If
* high_quality_required, it will always return some data from the kernel,
* regardless of whether the random pool is fully initialized or not.
* Otherwise, it will return success if at least some random bytes were
* successfully acquired, and an error if the kernel has no entropy whatsover
* for us. */
/* 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) {
/* Use the getrandom() syscall unless we know we don't have it. */
if (have_syscall != 0) {
r = getrandom(p, n, GRND_NONBLOCK);
if (r == (int) n) {
if (r > 0) {
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;
if ((size_t) r == n)
return 0;
if (!high_quality_required) {
/* Fill in the remaining bytes using pseudorandom values */
pseudorandom_bytes((uint8_t*) p + r, n - r);
return 0;
}
already_done = r;
} else if (errno == ENOSYS)
/* We lack the syscall, continue with reading from /dev/urandom. */
have_syscall = false;
else if (errno == EAGAIN) {
/* The kernel has no entropy whatsoever. Let's remember to
* use the syscall the next time again though.
*
* If high_quality_required is false, return an error so that
* random_bytes() can produce some pseudorandom
* bytes. Otherwise, fall back to /dev/urandom, which we know
* is empty, but the kernel will produce some bytes for us on
* a best-effort basis. */
have_syscall = true;
if (!high_quality_required)
return -ENODATA;
} else
/* too short read? */
return -ENODATA;
return -errno;
}
fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0)
return errno == ENOENT ? -ENOSYS : -errno;