mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-04-18 02:40:40 +02:00
systemd: update code from upstream
This is a direct dump from systemd git on 2016-08-11, git commit
9c5077fed42dc3cd2517a7ab816babef549dd079.
======
SYSTEMD_DIR=../systemd
COMMIT=9c5077fed42dc3cd2517a7ab816babef549dd079
(
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/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"
This commit is contained in:
parent
21e3aa91d8
commit
5507dd68ca
25 changed files with 763 additions and 219 deletions
|
|
@ -186,6 +186,12 @@ int fd_cloexec(int fd, bool cloexec) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void stdio_unset_cloexec(void) {
|
||||
fd_cloexec(STDIN_FILENO, false);
|
||||
fd_cloexec(STDOUT_FILENO, false);
|
||||
fd_cloexec(STDERR_FILENO, false);
|
||||
}
|
||||
|
||||
_pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
|
||||
unsigned i;
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
|
|||
|
||||
int fd_nonblock(int fd, bool nonblock);
|
||||
int fd_cloexec(int fd, bool cloexec);
|
||||
void stdio_unset_cloexec(void);
|
||||
|
||||
int close_all_fds(const int except[], unsigned n_except);
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@
|
|||
#include "umask-util.h"
|
||||
#include "utf8.h"
|
||||
|
||||
#define READ_FULL_BYTES_MAX (4U*1024U*1024U)
|
||||
|
||||
int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
|
||||
|
||||
assert(f);
|
||||
|
|
@ -230,7 +232,7 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
|
|||
if (S_ISREG(st.st_mode)) {
|
||||
|
||||
/* Safety check */
|
||||
if (st.st_size > 4*1024*1024)
|
||||
if (st.st_size > READ_FULL_BYTES_MAX)
|
||||
return -E2BIG;
|
||||
|
||||
/* Start with the right file size, but be prepared for
|
||||
|
|
@ -245,26 +247,31 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
|
|||
char *t;
|
||||
size_t k;
|
||||
|
||||
t = realloc(buf, n+1);
|
||||
t = realloc(buf, n + 1);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
|
||||
buf = t;
|
||||
k = fread(buf + l, 1, n - l, f);
|
||||
if (k > 0)
|
||||
l += k;
|
||||
|
||||
if (k <= 0) {
|
||||
if (ferror(f))
|
||||
return -errno;
|
||||
if (ferror(f))
|
||||
return -errno;
|
||||
|
||||
if (feof(f))
|
||||
break;
|
||||
}
|
||||
|
||||
l += k;
|
||||
n *= 2;
|
||||
/* We aren't expecting fread() to return a short read outside
|
||||
* of (error && eof), assert buffer is full and enlarge buffer.
|
||||
*/
|
||||
assert(l == n);
|
||||
|
||||
/* Safety check */
|
||||
if (n > 4*1024*1024)
|
||||
if (n >= READ_FULL_BYTES_MAX)
|
||||
return -E2BIG;
|
||||
|
||||
n = MIN(n * 2, READ_FULL_BYTES_MAX);
|
||||
}
|
||||
|
||||
buf[l] = 0;
|
||||
|
|
@ -1067,7 +1074,7 @@ int fflush_and_check(FILE *f) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* This is much like like mkostemp() but is subject to umask(). */
|
||||
/* This is much like mkostemp() but is subject to umask(). */
|
||||
int mkostemp_safe(char *pattern, int flags) {
|
||||
_cleanup_umask_ mode_t u = 0;
|
||||
int fd;
|
||||
|
|
@ -1161,8 +1168,8 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
|
|||
char *t, *x;
|
||||
uint64_t u;
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
assert(p);
|
||||
assert(ret);
|
||||
|
||||
/* Turns this:
|
||||
|
|
@ -1171,6 +1178,12 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
|
|||
* /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
|
||||
*/
|
||||
|
||||
if (!p) {
|
||||
r = tmp_dir(&p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!extra)
|
||||
extra = "";
|
||||
|
||||
|
|
@ -1257,9 +1270,13 @@ int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space)
|
|||
|
||||
int open_tmpfile_unlinkable(const char *directory, int flags) {
|
||||
char *p;
|
||||
int fd;
|
||||
int fd, r;
|
||||
|
||||
assert(directory);
|
||||
if (!directory) {
|
||||
r = tmp_dir(&directory);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Returns an unlinked temporary file that cannot be linked into the file system anymore */
|
||||
|
||||
|
|
@ -1354,3 +1371,44 @@ int link_tmpfile(int fd, const char *path, const char *target) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_nul_string(FILE *f, char **ret) {
|
||||
_cleanup_free_ char *x = NULL;
|
||||
size_t allocated = 0, n = 0;
|
||||
|
||||
assert(f);
|
||||
assert(ret);
|
||||
|
||||
/* Reads a NUL-terminated string from the specified file. */
|
||||
|
||||
for (;;) {
|
||||
int c;
|
||||
|
||||
if (!GREEDY_REALLOC(x, allocated, n+2))
|
||||
return -ENOMEM;
|
||||
|
||||
c = fgetc(f);
|
||||
if (c == 0) /* Terminate at NUL byte */
|
||||
break;
|
||||
if (c == EOF) {
|
||||
if (ferror(f))
|
||||
return -errno;
|
||||
break; /* Terminate at EOF */
|
||||
}
|
||||
|
||||
x[n++] = (char) c;
|
||||
}
|
||||
|
||||
if (x)
|
||||
x[n] = 0;
|
||||
else {
|
||||
x = new0(char, 1);
|
||||
if (!x)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*ret = x;
|
||||
x = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,3 +86,5 @@ int open_tmpfile_unlinkable(const char *directory, int flags);
|
|||
int open_tmpfile_linkable(const char *target, int flags, char **ret_path);
|
||||
|
||||
int link_tmpfile(int fd, const char *path, const char *target);
|
||||
|
||||
int read_nul_string(FILE *f, char **ret);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "mkdir.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
|
|
@ -495,6 +496,94 @@ int get_files_in_directory(const char *path, char ***list) {
|
|||
return n;
|
||||
}
|
||||
|
||||
static int getenv_tmp_dir(const char **ret_path) {
|
||||
const char *n;
|
||||
int r, ret = 0;
|
||||
|
||||
assert(ret_path);
|
||||
|
||||
/* We use the same order of environment variables python uses in tempfile.gettempdir():
|
||||
* https://docs.python.org/3/library/tempfile.html#tempfile.gettempdir */
|
||||
FOREACH_STRING(n, "TMPDIR", "TEMP", "TMP") {
|
||||
const char *e;
|
||||
|
||||
e = secure_getenv(n);
|
||||
if (!e)
|
||||
continue;
|
||||
if (!path_is_absolute(e)) {
|
||||
r = -ENOTDIR;
|
||||
goto next;
|
||||
}
|
||||
if (!path_is_safe(e)) {
|
||||
r = -EPERM;
|
||||
goto next;
|
||||
}
|
||||
|
||||
r = is_dir(e, true);
|
||||
if (r < 0)
|
||||
goto next;
|
||||
if (r == 0) {
|
||||
r = -ENOTDIR;
|
||||
goto next;
|
||||
}
|
||||
|
||||
*ret_path = e;
|
||||
return 1;
|
||||
|
||||
next:
|
||||
/* Remember first error, to make this more debuggable */
|
||||
if (ret >= 0)
|
||||
ret = r;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*ret_path = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tmp_dir_internal(const char *def, const char **ret) {
|
||||
const char *e;
|
||||
int r, k;
|
||||
|
||||
assert(def);
|
||||
assert(ret);
|
||||
|
||||
r = getenv_tmp_dir(&e);
|
||||
if (r > 0) {
|
||||
*ret = e;
|
||||
return 0;
|
||||
}
|
||||
|
||||
k = is_dir(def, true);
|
||||
if (k == 0)
|
||||
k = -ENOTDIR;
|
||||
if (k < 0)
|
||||
return r < 0 ? r : k;
|
||||
|
||||
*ret = def;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int var_tmp_dir(const char **ret) {
|
||||
|
||||
/* Returns the location for "larger" temporary files, that is backed by physical storage if available, and thus
|
||||
* even might survive a boot: /var/tmp. If $TMPDIR (or related environment variables) are set, its value is
|
||||
* returned preferably however. Note that both this function and tmp_dir() below are affected by $TMPDIR,
|
||||
* making it a variable that overrides all temporary file storage locations. */
|
||||
|
||||
return tmp_dir_internal("/var/tmp", ret);
|
||||
}
|
||||
|
||||
int tmp_dir(const char **ret) {
|
||||
|
||||
/* Similar to var_tmp_dir() above, but returns the location for "smaller" temporary files, which is usually
|
||||
* backed by an in-memory file system: /tmp. */
|
||||
|
||||
return tmp_dir_internal("/tmp", ret);
|
||||
}
|
||||
|
||||
int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
|
||||
char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
|
||||
int r;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@ int mkfifo_atomic(const char *path, mode_t mode);
|
|||
|
||||
int get_files_in_directory(const char *path, char ***list);
|
||||
|
||||
int tmp_dir(const char **ret);
|
||||
int var_tmp_dir(const char **ret);
|
||||
|
||||
#define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1)
|
||||
|
||||
#define FOREACH_INOTIFY_EVENT(e, buffer, sz) \
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "extract-word.h"
|
||||
#include "macro.h"
|
||||
#include "parse-util.h"
|
||||
#include "process-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
int parse_boolean(const char *v) {
|
||||
|
|
@ -533,7 +534,7 @@ int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int parse_percent(const char *p) {
|
||||
int parse_percent_unbounded(const char *p) {
|
||||
const char *pc, *n;
|
||||
unsigned v;
|
||||
int r;
|
||||
|
|
@ -546,8 +547,30 @@ int parse_percent(const char *p) {
|
|||
r = safe_atou(n, &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (v > 100)
|
||||
return -ERANGE;
|
||||
|
||||
return (int) v;
|
||||
}
|
||||
|
||||
int parse_percent(const char *p) {
|
||||
int v;
|
||||
|
||||
v = parse_percent_unbounded(p);
|
||||
if (v > 100)
|
||||
return -ERANGE;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
int parse_nice(const char *p, int *ret) {
|
||||
int n, r;
|
||||
|
||||
r = safe_atoi(p, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!nice_is_valid(n))
|
||||
return -ERANGE;
|
||||
|
||||
*ret = n;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,4 +106,7 @@ int safe_atod(const char *s, double *ret_d);
|
|||
|
||||
int parse_fractional_part_u(const char **s, size_t digits, unsigned *res);
|
||||
|
||||
int parse_percent_unbounded(const char *p);
|
||||
int parse_percent(const char *p);
|
||||
|
||||
int parse_nice(const char *p, int *ret);
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@
|
|||
#include "hashmap.h"
|
||||
#include "macro.h"
|
||||
|
||||
Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
#define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
#define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
|
||||
static inline Set *set_free(Set *s) {
|
||||
internal_hashmap_free(HASHMAP_BASE(s));
|
||||
|
|
@ -42,8 +42,8 @@ static inline Set *set_copy(Set *s) {
|
|||
return (Set*) internal_hashmap_copy(HASHMAP_BASE(s));
|
||||
}
|
||||
|
||||
int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
#define set_ensure_allocated(h, ops) internal_set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
#define set_ensure_allocated(h, ops) internal_set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
|
||||
int set_put(Set *s, const void *key);
|
||||
/* no set_update */
|
||||
|
|
|
|||
|
|
@ -1046,3 +1046,17 @@ int flush_accept(int fd) {
|
|||
close(cfd);
|
||||
}
|
||||
}
|
||||
|
||||
struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length) {
|
||||
struct cmsghdr *cmsg;
|
||||
|
||||
assert(mh);
|
||||
|
||||
CMSG_FOREACH(cmsg, mh)
|
||||
if (cmsg->cmsg_level == level &&
|
||||
cmsg->cmsg_type == type &&
|
||||
(length == (socklen_t) -1 || length == cmsg->cmsg_len))
|
||||
return cmsg;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,6 +142,8 @@ int flush_accept(int fd);
|
|||
#define CMSG_FOREACH(cmsg, mh) \
|
||||
for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg)))
|
||||
|
||||
struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length);
|
||||
|
||||
/* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */
|
||||
#define SOCKADDR_UN_LEN(sa) \
|
||||
({ \
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "gunicode.h"
|
||||
|
|
@ -323,6 +324,14 @@ char ascii_tolower(char x) {
|
|||
return x;
|
||||
}
|
||||
|
||||
char ascii_toupper(char x) {
|
||||
|
||||
if (x >= 'a' && x <= 'z')
|
||||
return x - 'a' + 'A';
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
char *ascii_strlower(char *t) {
|
||||
char *p;
|
||||
|
||||
|
|
@ -334,6 +343,17 @@ char *ascii_strlower(char *t) {
|
|||
return t;
|
||||
}
|
||||
|
||||
char *ascii_strupper(char *t) {
|
||||
char *p;
|
||||
|
||||
assert(t);
|
||||
|
||||
for (p = t; *p; p++)
|
||||
*p = ascii_toupper(*p);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
char *ascii_strlower_n(char *t, size_t n) {
|
||||
size_t i;
|
||||
|
||||
|
|
@ -803,25 +823,20 @@ int free_and_strdup(char **p, const char *s) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
/*
|
||||
* Pointer to memset is volatile so that compiler must de-reference
|
||||
* the pointer and can't assume that it points to any function in
|
||||
* particular (such as memset, which it then might further "optimize")
|
||||
* This approach is inspired by openssl's crypto/mem_clr.c.
|
||||
*/
|
||||
typedef void *(*memset_t)(void *,int,size_t);
|
||||
|
||||
static volatile memset_t memset_func = memset;
|
||||
|
||||
void* memory_erase(void *p, size_t l) {
|
||||
volatile uint8_t* x = (volatile uint8_t*) p;
|
||||
|
||||
/* This basically does what memset() does, but hopefully isn't
|
||||
* optimized away by the compiler. One of those days, when
|
||||
* glibc learns memset_s() we should replace this call by
|
||||
* memset_s(), but until then this has to do. */
|
||||
|
||||
for (; l > 0; l--)
|
||||
*(x++) = 'x';
|
||||
|
||||
return p;
|
||||
return memset_func(p, 'x', l);
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
char* string_erase(char *x) {
|
||||
|
||||
if (!x)
|
||||
|
|
|
|||
|
|
@ -137,6 +137,9 @@ char ascii_tolower(char x);
|
|||
char *ascii_strlower(char *s);
|
||||
char *ascii_strlower_n(char *s, size_t n);
|
||||
|
||||
char ascii_toupper(char x);
|
||||
char *ascii_strupper(char *s);
|
||||
|
||||
int ascii_strcasecmp_n(const char *a, const char *b, size_t n);
|
||||
int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m);
|
||||
|
||||
|
|
|
|||
|
|
@ -638,6 +638,17 @@ char **strv_remove(char **l, const char *s) {
|
|||
}
|
||||
|
||||
char **strv_parse_nulstr(const char *s, size_t l) {
|
||||
/* l is the length of the input data, which will be split at NULs into
|
||||
* elements of the resulting strv. Hence, the number of items in the resulting strv
|
||||
* will be equal to one plus the number of NUL bytes in the l bytes starting at s,
|
||||
* unless s[l-1] is NUL, in which case the final empty string is not stored in
|
||||
* the resulting strv, and length is equal to the number of NUL bytes.
|
||||
*
|
||||
* Note that contrary to a normal nulstr which cannot contain empty strings, because
|
||||
* the input data is terminated by any two consequent NUL bytes, this parser accepts
|
||||
* empty strings in s.
|
||||
*/
|
||||
|
||||
const char *p;
|
||||
unsigned c = 0, i = 0;
|
||||
char **v;
|
||||
|
|
@ -700,6 +711,13 @@ char **strv_split_nulstr(const char *s) {
|
|||
}
|
||||
|
||||
int strv_make_nulstr(char **l, char **p, size_t *q) {
|
||||
/* A valid nulstr with two NULs at the end will be created, but
|
||||
* q will be the length without the two trailing NULs. Thus the output
|
||||
* string is a valid nulstr and can be iterated over using NULSTR_FOREACH,
|
||||
* and can also be parsed by strv_parse_nulstr as long as the length
|
||||
* is provided separately.
|
||||
*/
|
||||
|
||||
size_t n_allocated = 0, n = 0;
|
||||
_cleanup_free_ char *m = NULL;
|
||||
char **i;
|
||||
|
|
@ -712,7 +730,7 @@ int strv_make_nulstr(char **l, char **p, size_t *q) {
|
|||
|
||||
z = strlen(*i);
|
||||
|
||||
if (!GREEDY_REALLOC(m, n_allocated, n + z + 1))
|
||||
if (!GREEDY_REALLOC(m, n_allocated, n + z + 2))
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(m + n, *i, z + 1);
|
||||
|
|
@ -723,11 +741,14 @@ int strv_make_nulstr(char **l, char **p, size_t *q) {
|
|||
m = new0(char, 1);
|
||||
if (!m)
|
||||
return -ENOMEM;
|
||||
n = 0;
|
||||
}
|
||||
n = 1;
|
||||
} else
|
||||
/* make sure there is a second extra NUL at the end of resulting nulstr */
|
||||
m[n] = '\0';
|
||||
|
||||
assert(n > 0);
|
||||
*p = m;
|
||||
*q = n;
|
||||
*q = n - 1;
|
||||
|
||||
m = NULL;
|
||||
|
||||
|
|
@ -803,9 +824,8 @@ char **strv_reverse(char **l) {
|
|||
if (n <= 1)
|
||||
return l;
|
||||
|
||||
for (i = 0; i < n / 2; i++) {
|
||||
for (i = 0; i < n / 2; i++)
|
||||
SWAP_TWO(l[i], l[n-1-i]);
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
|
@ -876,7 +896,7 @@ int strv_extend_n(char ***l, const char *value, size_t n) {
|
|||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
/* Adds the value value n times to l */
|
||||
/* Adds the value n times to l */
|
||||
|
||||
k = strv_length(*l);
|
||||
|
||||
|
|
|
|||
|
|
@ -254,32 +254,95 @@ struct timeval *timeval_store(struct timeval *tv, usec_t u) {
|
|||
return tv;
|
||||
}
|
||||
|
||||
static char *format_timestamp_internal(char *buf, size_t l, usec_t t,
|
||||
bool utc, bool us) {
|
||||
static char *format_timestamp_internal(
|
||||
char *buf,
|
||||
size_t l,
|
||||
usec_t t,
|
||||
bool utc,
|
||||
bool us) {
|
||||
|
||||
/* The weekdays in non-localized (English) form. We use this instead of the localized form, so that our
|
||||
* generated timestamps may be parsed with parse_timestamp(), and always read the same. */
|
||||
static const char * const weekdays[] = {
|
||||
[0] = "Sun",
|
||||
[1] = "Mon",
|
||||
[2] = "Tue",
|
||||
[3] = "Wed",
|
||||
[4] = "Thu",
|
||||
[5] = "Fri",
|
||||
[6] = "Sat",
|
||||
};
|
||||
|
||||
struct tm tm;
|
||||
time_t sec;
|
||||
int k;
|
||||
size_t n;
|
||||
|
||||
assert(buf);
|
||||
assert(l > 0);
|
||||
|
||||
if (l <
|
||||
3 + /* week day */
|
||||
1 + 10 + /* space and date */
|
||||
1 + 8 + /* space and time */
|
||||
(us ? 1 + 6 : 0) + /* "." and microsecond part */
|
||||
1 + 1 + /* space and shortest possible zone */
|
||||
1)
|
||||
return NULL; /* Not enough space even for the shortest form. */
|
||||
if (t <= 0 || t == USEC_INFINITY)
|
||||
return NULL; /* Timestamp is unset */
|
||||
|
||||
sec = (time_t) (t / USEC_PER_SEC); /* Round down */
|
||||
if ((usec_t) sec != (t / USEC_PER_SEC))
|
||||
return NULL; /* overflow? */
|
||||
|
||||
if (!localtime_or_gmtime_r(&sec, &tm, utc))
|
||||
return NULL;
|
||||
|
||||
sec = (time_t) (t / USEC_PER_SEC);
|
||||
localtime_or_gmtime_r(&sec, &tm, utc);
|
||||
/* Start with the week day */
|
||||
assert((size_t) tm.tm_wday < ELEMENTSOF(weekdays));
|
||||
memcpy(buf, weekdays[tm.tm_wday], 4);
|
||||
|
||||
if (us)
|
||||
k = strftime(buf, l, "%a %Y-%m-%d %H:%M:%S", &tm);
|
||||
else
|
||||
k = strftime(buf, l, "%a %Y-%m-%d %H:%M:%S %Z", &tm);
|
||||
/* Add the main components */
|
||||
if (strftime(buf + 3, l - 3, " %Y-%m-%d %H:%M:%S", &tm) <= 0)
|
||||
return NULL; /* Doesn't fit */
|
||||
|
||||
if (k <= 0)
|
||||
return NULL;
|
||||
/* Append the microseconds part, if that's requested */
|
||||
if (us) {
|
||||
snprintf(buf + strlen(buf), l - strlen(buf), ".%06llu", (unsigned long long) (t % USEC_PER_SEC));
|
||||
if (strftime(buf + strlen(buf), l - strlen(buf), " %Z", &tm) <= 0)
|
||||
return NULL;
|
||||
n = strlen(buf);
|
||||
if (n + 8 > l)
|
||||
return NULL; /* Microseconds part doesn't fit. */
|
||||
|
||||
sprintf(buf + n, ".%06llu", (unsigned long long) (t % USEC_PER_SEC));
|
||||
}
|
||||
|
||||
/* Append the timezone */
|
||||
n = strlen(buf);
|
||||
if (utc) {
|
||||
/* If this is UTC then let's explicitly use the "UTC" string here, because gmtime_r() normally uses the
|
||||
* obsolete "GMT" instead. */
|
||||
if (n + 5 > l)
|
||||
return NULL; /* "UTC" doesn't fit. */
|
||||
|
||||
strcpy(buf + n, " UTC");
|
||||
|
||||
} else if (!isempty(tm.tm_zone)) {
|
||||
size_t tn;
|
||||
|
||||
/* An explicit timezone is specified, let's use it, if it fits */
|
||||
tn = strlen(tm.tm_zone);
|
||||
if (n + 1 + tn + 1 > l) {
|
||||
/* The full time zone does not fit in. Yuck. */
|
||||
|
||||
if (n + 1 + _POSIX_TZNAME_MAX + 1 > l)
|
||||
return NULL; /* Not even enough space for the POSIX minimum (of 6)? In that case, complain that it doesn't fit */
|
||||
|
||||
/* So the time zone doesn't fit in fully, but the caller passed enough space for the POSIX
|
||||
* minimum time zone length. In this case suppress the timezone entirely, in order not to dump
|
||||
* an overly long, hard to read string on the user. This should be safe, because the user will
|
||||
* assume the local timezone anyway if none is shown. And so does parse_timestamp(). */
|
||||
} else {
|
||||
buf[n++] = ' ';
|
||||
strcpy(buf + n, tm.tm_zone);
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
|
|
@ -539,12 +602,11 @@ int parse_timestamp(const char *t, usec_t *usec) {
|
|||
{ "Sat", 6 },
|
||||
};
|
||||
|
||||
const char *k;
|
||||
const char *utc;
|
||||
const char *k, *utc, *tzn = NULL;
|
||||
struct tm tm, copy;
|
||||
time_t x;
|
||||
usec_t x_usec, plus = 0, minus = 0, ret;
|
||||
int r, weekday = -1;
|
||||
int r, weekday = -1, dst = -1;
|
||||
unsigned i;
|
||||
|
||||
/*
|
||||
|
|
@ -609,15 +671,55 @@ int parse_timestamp(const char *t, usec_t *usec) {
|
|||
goto finish;
|
||||
}
|
||||
|
||||
/* See if the timestamp is suffixed with UTC */
|
||||
utc = endswith_no_case(t, " UTC");
|
||||
if (utc)
|
||||
t = strndupa(t, utc - t);
|
||||
else {
|
||||
const char *e = NULL;
|
||||
int j;
|
||||
|
||||
x = ret / USEC_PER_SEC;
|
||||
tzset();
|
||||
|
||||
/* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note that we only
|
||||
* support the local timezones here, nothing else. Not because we wouldn't want to, but simply because
|
||||
* there are no nice APIs available to cover this. By accepting the local time zone strings, we make
|
||||
* sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't
|
||||
* support arbitrary timezone specifications. */
|
||||
|
||||
for (j = 0; j <= 1; j++) {
|
||||
|
||||
if (isempty(tzname[j]))
|
||||
continue;
|
||||
|
||||
e = endswith_no_case(t, tzname[j]);
|
||||
if (!e)
|
||||
continue;
|
||||
if (e == t)
|
||||
continue;
|
||||
if (e[-1] != ' ')
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (IN_SET(j, 0, 1)) {
|
||||
/* Found one of the two timezones specified. */
|
||||
t = strndupa(t, e - t - 1);
|
||||
dst = j;
|
||||
tzn = tzname[j];
|
||||
}
|
||||
}
|
||||
|
||||
x = (time_t) (ret / USEC_PER_SEC);
|
||||
x_usec = 0;
|
||||
|
||||
assert_se(localtime_or_gmtime_r(&x, &tm, utc));
|
||||
tm.tm_isdst = -1;
|
||||
if (!localtime_or_gmtime_r(&x, &tm, utc))
|
||||
return -EINVAL;
|
||||
|
||||
tm.tm_isdst = dst;
|
||||
if (tzn)
|
||||
tm.tm_zone = tzn;
|
||||
|
||||
if (streq(t, "today")) {
|
||||
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
|
||||
|
|
@ -634,7 +736,6 @@ int parse_timestamp(const char *t, usec_t *usec) {
|
|||
goto from_tm;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(day_nr); i++) {
|
||||
size_t skip;
|
||||
|
||||
|
|
@ -727,7 +828,6 @@ parse_usec:
|
|||
return -EINVAL;
|
||||
|
||||
x_usec = add;
|
||||
|
||||
}
|
||||
|
||||
from_tm:
|
||||
|
|
|
|||
|
|
@ -68,7 +68,9 @@ typedef struct triple_timestamp {
|
|||
#define USEC_PER_YEAR ((usec_t) (31557600ULL*USEC_PER_SEC))
|
||||
#define NSEC_PER_YEAR ((nsec_t) (31557600ULL*NSEC_PER_SEC))
|
||||
|
||||
#define FORMAT_TIMESTAMP_MAX ((4*4+1)+11+9+4+1) /* weekdays can be unicode */
|
||||
/* We assume a maximum timezone length of 6. TZNAME_MAX is not defined on Linux, but glibc internally initializes this
|
||||
* to 6. Let's rely on that. */
|
||||
#define FORMAT_TIMESTAMP_MAX (3+1+10+1+8+1+6+1+6+1)
|
||||
#define FORMAT_TIMESTAMP_WIDTH 28 /* when outputting, assume this width */
|
||||
#define FORMAT_TIMESTAMP_RELATIVE_MAX 256
|
||||
#define FORMAT_TIMESPAN_MAX 64
|
||||
|
|
|
|||
|
|
@ -581,47 +581,6 @@ int on_ac_power(void) {
|
|||
return found_online || !found_offline;
|
||||
}
|
||||
|
||||
bool id128_is_valid(const char *s) {
|
||||
size_t i, l;
|
||||
|
||||
l = strlen(s);
|
||||
if (l == 32) {
|
||||
|
||||
/* Simple formatted 128bit hex string */
|
||||
|
||||
for (i = 0; i < l; i++) {
|
||||
char c = s[i];
|
||||
|
||||
if (!(c >= '0' && c <= '9') &&
|
||||
!(c >= 'a' && c <= 'z') &&
|
||||
!(c >= 'A' && c <= 'Z'))
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (l == 36) {
|
||||
|
||||
/* Formatted UUID */
|
||||
|
||||
for (i = 0; i < l; i++) {
|
||||
char c = s[i];
|
||||
|
||||
if ((i == 8 || i == 13 || i == 18 || i == 23)) {
|
||||
if (c != '-')
|
||||
return false;
|
||||
} else {
|
||||
if (!(c >= '0' && c <= '9') &&
|
||||
!(c >= 'a' && c <= 'z') &&
|
||||
!(c >= 'A' && c <= 'Z'))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int container_get_leader(const char *machine, pid_t *pid) {
|
||||
_cleanup_free_ char *s = NULL, *class = NULL;
|
||||
const char *p;
|
||||
|
|
@ -832,6 +791,61 @@ uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
|
|||
return r;
|
||||
}
|
||||
|
||||
uint64_t system_tasks_max(void) {
|
||||
|
||||
#if SIZEOF_PID_T == 4
|
||||
#define TASKS_MAX ((uint64_t) (INT32_MAX-1))
|
||||
#elif SIZEOF_PID_T == 2
|
||||
#define TASKS_MAX ((uint64_t) (INT16_MAX-1))
|
||||
#else
|
||||
#error "Unknown pid_t size"
|
||||
#endif
|
||||
|
||||
_cleanup_free_ char *value = NULL, *root = NULL;
|
||||
uint64_t a = TASKS_MAX, b = TASKS_MAX;
|
||||
|
||||
/* Determine the maximum number of tasks that may run on this system. We check three sources to determine this
|
||||
* limit:
|
||||
*
|
||||
* a) the maximum value for the pid_t type
|
||||
* b) the cgroups pids_max attribute for the system
|
||||
* c) the kernel's configure maximum PID value
|
||||
*
|
||||
* And then pick the smallest of the three */
|
||||
|
||||
if (read_one_line_file("/proc/sys/kernel/pid_max", &value) >= 0)
|
||||
(void) safe_atou64(value, &a);
|
||||
|
||||
if (cg_get_root_path(&root) >= 0) {
|
||||
value = mfree(value);
|
||||
|
||||
if (cg_get_attribute("pids", root, "pids.max", &value) >= 0)
|
||||
(void) safe_atou64(value, &b);
|
||||
}
|
||||
|
||||
return MIN3(TASKS_MAX,
|
||||
a <= 0 ? TASKS_MAX : a,
|
||||
b <= 0 ? TASKS_MAX : b);
|
||||
}
|
||||
|
||||
uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) {
|
||||
uint64_t t, m;
|
||||
|
||||
assert(max > 0);
|
||||
|
||||
/* Multiply the system's task value by the fraction v/max. Hence, if max==100 this calculates percentages
|
||||
* relative to the system's maximum number of tasks. Returns UINT64_MAX on overflow. */
|
||||
|
||||
t = system_tasks_max();
|
||||
assert(t > 0);
|
||||
|
||||
m = t * v;
|
||||
if (m / t != v) /* overflow? */
|
||||
return UINT64_MAX;
|
||||
|
||||
return m / max;
|
||||
}
|
||||
|
||||
int update_reboot_parameter_and_warn(const char *param) {
|
||||
int r;
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,10 @@ static inline const char* one_zero(bool b) {
|
|||
return b ? "1" : "0";
|
||||
}
|
||||
|
||||
static inline const char* enable_disable(bool b) {
|
||||
return b ? "enable" : "disable";
|
||||
}
|
||||
|
||||
void execute_directories(const char* const* directories, usec_t timeout, char *argv[]);
|
||||
|
||||
bool plymouth_running(void);
|
||||
|
|
@ -176,8 +180,6 @@ static inline unsigned log2u_round_up(unsigned x) {
|
|||
return log2u(x - 1) + 1;
|
||||
}
|
||||
|
||||
bool id128_is_valid(const char *s) _pure_;
|
||||
|
||||
int container_get_leader(const char *machine, pid_t *pid);
|
||||
|
||||
int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd);
|
||||
|
|
@ -186,6 +188,9 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
|
|||
uint64_t physical_memory(void);
|
||||
uint64_t physical_memory_scale(uint64_t v, uint64_t max);
|
||||
|
||||
uint64_t system_tasks_max(void);
|
||||
uint64_t system_tasks_max_scale(uint64_t v, uint64_t max);
|
||||
|
||||
int update_reboot_parameter_and_warn(const char *param);
|
||||
|
||||
int version(void);
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
|
|||
assert(n);
|
||||
|
||||
if (n->raw_size < sizeof(struct ether_header)) {
|
||||
log_lldp("Recieved truncated packet, ignoring.");
|
||||
log_lldp("Received truncated packet, ignoring.");
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -102,16 +102,16 @@ bool net_match_config(const struct ether_addr *match_mac,
|
|||
const char *dev_type,
|
||||
const char *dev_name) {
|
||||
|
||||
if (match_host && !condition_test(match_host))
|
||||
if (match_host && condition_test(match_host) <= 0)
|
||||
return false;
|
||||
|
||||
if (match_virt && !condition_test(match_virt))
|
||||
if (match_virt && condition_test(match_virt) <= 0)
|
||||
return false;
|
||||
|
||||
if (match_kernel && !condition_test(match_kernel))
|
||||
if (match_kernel && condition_test(match_kernel) <= 0)
|
||||
return false;
|
||||
|
||||
if (match_arch && !condition_test(match_arch))
|
||||
if (match_arch && condition_test(match_arch) <= 0)
|
||||
return false;
|
||||
|
||||
if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
|
||||
|
|
|
|||
|
|
@ -109,8 +109,8 @@ struct sd_event_source {
|
|||
int64_t priority;
|
||||
unsigned pending_index;
|
||||
unsigned prepare_index;
|
||||
unsigned pending_iteration;
|
||||
unsigned prepare_iteration;
|
||||
uint64_t pending_iteration;
|
||||
uint64_t prepare_iteration;
|
||||
|
||||
LIST_FIELDS(sd_event_source, sources);
|
||||
|
||||
|
|
@ -215,7 +215,7 @@ struct sd_event {
|
|||
|
||||
pid_t original_pid;
|
||||
|
||||
unsigned iteration;
|
||||
uint64_t iteration;
|
||||
triple_timestamp timestamp;
|
||||
int state;
|
||||
|
||||
|
|
@ -2874,3 +2874,11 @@ _public_ int sd_event_get_watchdog(sd_event *e) {
|
|||
|
||||
return e->watchdog;
|
||||
}
|
||||
|
||||
_public_ int sd_event_get_iteration(sd_event *e, uint64_t *ret) {
|
||||
assert_return(e, -EINVAL);
|
||||
assert_return(!event_pid_changed(e), -ECHILD);
|
||||
|
||||
*ret = e->iteration;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
194
src/systemd/src/libsystemd/sd-id128/id128-util.c
Normal file
194
src/systemd/src/libsystemd/sd-id128/id128-util.c
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2016 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 <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "fd-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "id128-util.h"
|
||||
#include "io-util.h"
|
||||
#include "stdio-util.h"
|
||||
|
||||
char *id128_to_uuid_string(sd_id128_t id, char s[37]) {
|
||||
unsigned n, k = 0;
|
||||
|
||||
assert(s);
|
||||
|
||||
/* Similar to sd_id128_to_string() but formats the result as UUID instead of plain hex chars */
|
||||
|
||||
for (n = 0; n < 16; n++) {
|
||||
|
||||
if (IN_SET(n, 4, 6, 8, 10))
|
||||
s[k++] = '-';
|
||||
|
||||
s[k++] = hexchar(id.bytes[n] >> 4);
|
||||
s[k++] = hexchar(id.bytes[n] & 0xF);
|
||||
}
|
||||
|
||||
assert(k == 36);
|
||||
|
||||
s[k] = 0;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
bool id128_is_valid(const char *s) {
|
||||
size_t i, l;
|
||||
|
||||
assert(s);
|
||||
|
||||
l = strlen(s);
|
||||
if (l == 32) {
|
||||
|
||||
/* Plain formatted 128bit hex string */
|
||||
|
||||
for (i = 0; i < l; i++) {
|
||||
char c = s[i];
|
||||
|
||||
if (!(c >= '0' && c <= '9') &&
|
||||
!(c >= 'a' && c <= 'z') &&
|
||||
!(c >= 'A' && c <= 'Z'))
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (l == 36) {
|
||||
|
||||
/* Formatted UUID */
|
||||
|
||||
for (i = 0; i < l; i++) {
|
||||
char c = s[i];
|
||||
|
||||
if ((i == 8 || i == 13 || i == 18 || i == 23)) {
|
||||
if (c != '-')
|
||||
return false;
|
||||
} else {
|
||||
if (!(c >= '0' && c <= '9') &&
|
||||
!(c >= 'a' && c <= 'z') &&
|
||||
!(c >= 'A' && c <= 'Z'))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) {
|
||||
char buffer[36 + 2];
|
||||
ssize_t l;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(f < _ID128_FORMAT_MAX);
|
||||
|
||||
/* Reads an 128bit ID from a file, which may either be in plain format (32 hex digits), or in UUID format, both
|
||||
* optionally followed by a newline and nothing else. ID files should really be newline terminated, but if they
|
||||
* aren't that's OK too, following the rule of "Be conservative in what you send, be liberal in what you
|
||||
* accept". */
|
||||
|
||||
l = loop_read(fd, buffer, sizeof(buffer), false); /* we expect a short read of either 32/33 or 36/37 chars */
|
||||
if (l < 0)
|
||||
return (int) l;
|
||||
if (l == 0) /* empty? */
|
||||
return -ENOMEDIUM;
|
||||
|
||||
switch (l) {
|
||||
|
||||
case 33: /* plain UUID with trailing newline */
|
||||
if (buffer[32] != '\n')
|
||||
return -EINVAL;
|
||||
|
||||
/* fall through */
|
||||
case 32: /* plain UUID without trailing newline */
|
||||
if (f == ID128_UUID)
|
||||
return -EINVAL;
|
||||
|
||||
buffer[32] = 0;
|
||||
break;
|
||||
|
||||
case 37: /* RFC UUID with trailing newline */
|
||||
if (buffer[36] != '\n')
|
||||
return -EINVAL;
|
||||
|
||||
/* fall through */
|
||||
case 36: /* RFC UUID without trailing newline */
|
||||
if (f == ID128_PLAIN)
|
||||
return -EINVAL;
|
||||
|
||||
buffer[36] = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return sd_id128_from_string(buffer, ret);
|
||||
}
|
||||
|
||||
int id128_read(const char *p, Id128Format f, sd_id128_t *ret) {
|
||||
_cleanup_close_ int fd = -1;
|
||||
|
||||
fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
return id128_read_fd(fd, f, ret);
|
||||
}
|
||||
|
||||
int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) {
|
||||
char buffer[36 + 2];
|
||||
size_t sz;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(f < _ID128_FORMAT_MAX);
|
||||
|
||||
if (f != ID128_UUID) {
|
||||
sd_id128_to_string(id, buffer);
|
||||
buffer[32] = '\n';
|
||||
sz = 33;
|
||||
} else {
|
||||
id128_to_uuid_string(id, buffer);
|
||||
buffer[36] = '\n';
|
||||
sz = 37;
|
||||
}
|
||||
|
||||
r = loop_write(fd, buffer, sz, false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (do_sync) {
|
||||
if (fsync(fd) < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync) {
|
||||
_cleanup_close_ int fd = -1;
|
||||
|
||||
fd = open(p, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0444);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
return id128_write_fd(fd, f, id, do_sync);
|
||||
}
|
||||
45
src/systemd/src/libsystemd/sd-id128/id128-util.h
Normal file
45
src/systemd/src/libsystemd/sd-id128/id128-util.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2016 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 <stdbool.h>
|
||||
|
||||
#include "sd-id128.h"
|
||||
#include "macro.h"
|
||||
|
||||
char *id128_to_uuid_string(sd_id128_t id, char s[37]);
|
||||
|
||||
/* Like SD_ID128_FORMAT_STR, but formats as UUID, not in plain format */
|
||||
#define ID128_UUID_FORMAT_STR "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
|
||||
|
||||
bool id128_is_valid(const char *s) _pure_;
|
||||
|
||||
typedef enum Id128Format {
|
||||
ID128_ANY,
|
||||
ID128_PLAIN, /* formatted as 32 hex chars as-is */
|
||||
ID128_UUID, /* formatted as 36 character uuid string */
|
||||
_ID128_FORMAT_MAX,
|
||||
} Id128Format;
|
||||
|
||||
int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret);
|
||||
int id128_read(const char *p, Id128Format f, sd_id128_t *ret);
|
||||
|
||||
int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync);
|
||||
int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync);
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "fd-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "id128-util.h"
|
||||
#include "io-util.h"
|
||||
#include "macro.h"
|
||||
#include "random-util.h"
|
||||
|
|
@ -51,7 +52,6 @@ _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
|
|||
bool is_guid = false;
|
||||
|
||||
assert_return(s, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
for (n = 0, i = 0; n < 16;) {
|
||||
int a, b;
|
||||
|
|
@ -89,7 +89,43 @@ _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
|
|||
if (s[i] != 0)
|
||||
return -EINVAL;
|
||||
|
||||
*ret = t;
|
||||
if (ret)
|
||||
*ret = t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_id128_get_machine(sd_id128_t *ret) {
|
||||
static thread_local sd_id128_t saved_machine_id = {};
|
||||
int r;
|
||||
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
if (sd_id128_is_null(saved_machine_id)) {
|
||||
r = id128_read("/etc/machine-id", ID128_PLAIN, &saved_machine_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (sd_id128_is_null(saved_machine_id))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*ret = saved_machine_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_id128_get_boot(sd_id128_t *ret) {
|
||||
static thread_local sd_id128_t saved_boot_id = {};
|
||||
int r;
|
||||
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
if (sd_id128_is_null(saved_boot_id)) {
|
||||
r = id128_read("/proc/sys/kernel/random/boot_id", ID128_UUID, &saved_boot_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
*ret = saved_boot_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -106,106 +142,6 @@ static sd_id128_t make_v4_uuid(sd_id128_t id) {
|
|||
return id;
|
||||
}
|
||||
|
||||
_public_ int sd_id128_get_machine(sd_id128_t *ret) {
|
||||
static thread_local sd_id128_t saved_machine_id;
|
||||
static thread_local bool saved_machine_id_valid = false;
|
||||
_cleanup_close_ int fd = -1;
|
||||
char buf[33];
|
||||
unsigned j;
|
||||
sd_id128_t t;
|
||||
int r;
|
||||
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
if (saved_machine_id_valid) {
|
||||
*ret = saved_machine_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = open("/etc/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
r = loop_read_exact(fd, buf, 33, false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (buf[32] !='\n')
|
||||
return -EIO;
|
||||
|
||||
for (j = 0; j < 16; j++) {
|
||||
int a, b;
|
||||
|
||||
a = unhexchar(buf[j*2]);
|
||||
b = unhexchar(buf[j*2+1]);
|
||||
|
||||
if (a < 0 || b < 0)
|
||||
return -EIO;
|
||||
|
||||
t.bytes[j] = a << 4 | b;
|
||||
}
|
||||
|
||||
saved_machine_id = t;
|
||||
saved_machine_id_valid = true;
|
||||
|
||||
*ret = t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_id128_get_boot(sd_id128_t *ret) {
|
||||
static thread_local sd_id128_t saved_boot_id;
|
||||
static thread_local bool saved_boot_id_valid = false;
|
||||
_cleanup_close_ int fd = -1;
|
||||
char buf[36];
|
||||
unsigned j;
|
||||
sd_id128_t t;
|
||||
char *p;
|
||||
int r;
|
||||
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
if (saved_boot_id_valid) {
|
||||
*ret = saved_boot_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
r = loop_read_exact(fd, buf, 36, false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (j = 0, p = buf; j < 16; j++) {
|
||||
int a, b;
|
||||
|
||||
if (p >= buf + 35)
|
||||
return -EIO;
|
||||
|
||||
if (*p == '-') {
|
||||
p++;
|
||||
if (p >= buf + 35)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
a = unhexchar(p[0]);
|
||||
b = unhexchar(p[1]);
|
||||
|
||||
if (a < 0 || b < 0)
|
||||
return -EIO;
|
||||
|
||||
t.bytes[j] = a << 4 | b;
|
||||
|
||||
p += 2;
|
||||
}
|
||||
|
||||
saved_boot_id = t;
|
||||
saved_boot_id_valid = true;
|
||||
|
||||
*ret = t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_id128_randomize(sd_id128_t *ret) {
|
||||
sd_id128_t t;
|
||||
int r;
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ int sd_event_get_tid(sd_event *e, pid_t *tid);
|
|||
int sd_event_get_exit_code(sd_event *e, int *code);
|
||||
int sd_event_set_watchdog(sd_event *e, int b);
|
||||
int sd_event_get_watchdog(sd_event *e);
|
||||
int sd_event_get_iteration(sd_event *e, uint64_t *ret);
|
||||
|
||||
sd_event_source* sd_event_source_ref(sd_event_source *s);
|
||||
sd_event_source* sd_event_source_unref(sd_event_source *s);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue