mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-09-06 17:14:02 +00:00
systemd: merge branch systemd into master
This commit is contained in:
commit
d577888d8f
|
@ -1355,6 +1355,8 @@ src_libsystemd_nm_la_SOURCES = \
|
|||
src/systemd/src/basic/socket-util.c \
|
||||
src/systemd/src/basic/socket-util.h \
|
||||
src/systemd/src/basic/sparse-endian.h \
|
||||
src/systemd/src/basic/stat-util.c \
|
||||
src/systemd/src/basic/stat-util.h \
|
||||
src/systemd/src/basic/stdio-util.h \
|
||||
src/systemd/src/basic/string-table.c \
|
||||
src/systemd/src/basic/string-table.h \
|
||||
|
|
|
@ -142,6 +142,8 @@ G_STMT_START { \
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#define VALGRIND 0
|
||||
|
||||
static inline pid_t
|
||||
raw_getpid (void) {
|
||||
#if defined(__alpha__)
|
||||
|
|
|
@ -18,9 +18,17 @@
|
|||
|
||||
#define new0(t, n) ((t*) calloc((n), sizeof(t)))
|
||||
|
||||
#define newa(t, n) ((t*) alloca(sizeof(t)*(n)))
|
||||
#define newa(t, n) \
|
||||
({ \
|
||||
assert(!size_multiply_overflow(sizeof(t), n)); \
|
||||
(t*) alloca(sizeof(t)*(n)); \
|
||||
})
|
||||
|
||||
#define newa0(t, n) ((t*) alloca0(sizeof(t)*(n)))
|
||||
#define newa0(t, n) \
|
||||
({ \
|
||||
assert(!size_multiply_overflow(sizeof(t), n)); \
|
||||
(t*) alloca0(sizeof(t)*(n)); \
|
||||
})
|
||||
|
||||
#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit)
|
|||
/* C++11 style 16bit unicode */
|
||||
|
||||
int a[4];
|
||||
unsigned i;
|
||||
size_t i;
|
||||
uint32_t c;
|
||||
|
||||
if (length != (size_t) -1 && length < 5)
|
||||
|
@ -217,7 +217,7 @@ int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit)
|
|||
/* C++11 style 32bit unicode */
|
||||
|
||||
int a[8];
|
||||
unsigned i;
|
||||
size_t i;
|
||||
char32_t c;
|
||||
|
||||
if (length != (size_t) -1 && length < 9)
|
||||
|
|
|
@ -35,19 +35,23 @@ char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR
|
|||
return buffer;
|
||||
}
|
||||
|
||||
bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) {
|
||||
int ether_addr_compare(const void *a, const void *b) {
|
||||
assert(a);
|
||||
assert(b);
|
||||
|
||||
return a->ether_addr_octet[0] == b->ether_addr_octet[0] &&
|
||||
a->ether_addr_octet[1] == b->ether_addr_octet[1] &&
|
||||
a->ether_addr_octet[2] == b->ether_addr_octet[2] &&
|
||||
a->ether_addr_octet[3] == b->ether_addr_octet[3] &&
|
||||
a->ether_addr_octet[4] == b->ether_addr_octet[4] &&
|
||||
a->ether_addr_octet[5] == b->ether_addr_octet[5];
|
||||
return memcmp(a, b, ETH_ALEN);
|
||||
}
|
||||
|
||||
int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset) {
|
||||
static void ether_addr_hash_func(const void *p, struct siphash *state) {
|
||||
siphash24_compress(p, sizeof(struct ether_addr), state);
|
||||
}
|
||||
|
||||
const struct hash_ops ether_addr_hash_ops = {
|
||||
.hash = ether_addr_hash_func,
|
||||
.compare = ether_addr_compare
|
||||
};
|
||||
|
||||
int ether_addr_from_string(const char *s, struct ether_addr *ret) {
|
||||
size_t pos = 0, n, field;
|
||||
char sep = '\0';
|
||||
const char *hex = HEXDIGITS, *hexoff;
|
||||
|
@ -86,31 +90,35 @@ int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset
|
|||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
s += strspn(s, WHITESPACE);
|
||||
sep = s[strspn(s, hex)];
|
||||
if (sep == '\n')
|
||||
return -EINVAL;
|
||||
if (!strchr(":.-", sep))
|
||||
return -EINVAL;
|
||||
|
||||
if (sep == '.') {
|
||||
uint16_t shorts[3] = { 0 };
|
||||
|
||||
parse_fields(shorts);
|
||||
|
||||
if (s[pos] != '\0')
|
||||
return -EINVAL;
|
||||
|
||||
for (n = 0; n < ELEMENTSOF(shorts); n++) {
|
||||
ret->ether_addr_octet[2*n] = ((shorts[n] & (uint16_t)0xff00) >> 8);
|
||||
ret->ether_addr_octet[2*n + 1] = (shorts[n] & (uint16_t)0x00ff);
|
||||
}
|
||||
} else {
|
||||
struct ether_addr out = { .ether_addr_octet = { 0 } };
|
||||
|
||||
} else if (IN_SET(sep, ':', '-')) {
|
||||
struct ether_addr out = ETHER_ADDR_NULL;
|
||||
|
||||
parse_fields(out.ether_addr_octet);
|
||||
|
||||
if (s[pos] != '\0')
|
||||
return -EINVAL;
|
||||
|
||||
for (n = 0; n < ELEMENTSOF(out.ether_addr_octet); n++)
|
||||
ret->ether_addr_octet[n] = out.ether_addr_octet[n];
|
||||
}
|
||||
|
||||
if (offset)
|
||||
*offset = pos;
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -10,13 +10,18 @@
|
|||
#include <net/ethernet.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "hash-funcs.h"
|
||||
|
||||
#define ETHER_ADDR_FORMAT_STR "%02X%02X%02X%02X%02X%02X"
|
||||
#define ETHER_ADDR_FORMAT_VAL(x) (x).ether_addr_octet[0], (x).ether_addr_octet[1], (x).ether_addr_octet[2], (x).ether_addr_octet[3], (x).ether_addr_octet[4], (x).ether_addr_octet[5]
|
||||
|
||||
#define ETHER_ADDR_TO_STRING_MAX (3*6)
|
||||
char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]);
|
||||
|
||||
bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b);
|
||||
int ether_addr_compare(const void *a, const void *b);
|
||||
static inline bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) {
|
||||
return ether_addr_compare(a, b) == 0;
|
||||
}
|
||||
|
||||
#define ETHER_ADDR_NULL ((const struct ether_addr){})
|
||||
|
||||
|
@ -24,4 +29,6 @@ static inline bool ether_addr_is_null(const struct ether_addr *addr) {
|
|||
return ether_addr_equal(addr, ÐER_ADDR_NULL);
|
||||
}
|
||||
|
||||
int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset);
|
||||
int ether_addr_from_string(const char *s, struct ether_addr *ret);
|
||||
|
||||
extern const struct hash_ops ether_addr_hash_ops;
|
||||
|
|
|
@ -87,8 +87,8 @@ void safe_close_pair(int p[]) {
|
|||
p[1] = safe_close(p[1]);
|
||||
}
|
||||
|
||||
void close_many(const int fds[], unsigned n_fd) {
|
||||
unsigned i;
|
||||
void close_many(const int fds[], size_t n_fd) {
|
||||
size_t i;
|
||||
|
||||
assert(fds || n_fd <= 0);
|
||||
|
||||
|
@ -181,8 +181,8 @@ int fd_cloexec(int fd, bool cloexec) {
|
|||
}
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
_pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
|
||||
unsigned i;
|
||||
_pure_ static bool fd_in_set(int fd, const int fdset[], size_t n_fdset) {
|
||||
size_t i;
|
||||
|
||||
assert(n_fdset == 0 || fdset);
|
||||
|
||||
|
@ -193,7 +193,7 @@ _pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
|
|||
return false;
|
||||
}
|
||||
|
||||
int close_all_fds(const int except[], unsigned n_except) {
|
||||
int close_all_fds(const int except[], size_t n_except) {
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
struct dirent *de;
|
||||
int r = 0;
|
||||
|
@ -202,15 +202,22 @@ int close_all_fds(const int except[], unsigned n_except) {
|
|||
|
||||
d = opendir("/proc/self/fd");
|
||||
if (!d) {
|
||||
int fd;
|
||||
struct rlimit rl;
|
||||
int fd, max_fd;
|
||||
|
||||
/* When /proc isn't available (for example in chroots)
|
||||
* the fallback is brute forcing through the fd
|
||||
/* When /proc isn't available (for example in chroots) the fallback is brute forcing through the fd
|
||||
* table */
|
||||
|
||||
assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
|
||||
for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
|
||||
|
||||
if (rl.rlim_max == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Let's take special care if the resource limit is set to unlimited, or actually larger than the range
|
||||
* of 'int'. Let's avoid implicit overflows. */
|
||||
max_fd = (rl.rlim_max == RLIM_INFINITY || rl.rlim_max > INT_MAX) ? INT_MAX : (int) (rl.rlim_max - 1);
|
||||
|
||||
for (fd = 3; fd >= 0; fd = fd < max_fd ? fd + 1 : -1) {
|
||||
int q;
|
||||
|
||||
if (fd_in_set(fd, except, n_except))
|
||||
|
|
|
@ -29,7 +29,7 @@ static inline int safe_close_above_stdio(int fd) {
|
|||
return safe_close(fd);
|
||||
}
|
||||
|
||||
void close_many(const int fds[], unsigned n_fd);
|
||||
void close_many(const int fds[], size_t n_fd);
|
||||
|
||||
int fclose_nointr(FILE *f);
|
||||
FILE* safe_fclose(FILE *f);
|
||||
|
@ -59,7 +59,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
|
|||
int fd_nonblock(int fd, bool nonblock);
|
||||
int fd_cloexec(int fd, bool cloexec);
|
||||
|
||||
int close_all_fds(const int except[], unsigned n_except);
|
||||
int close_all_fds(const int except[], size_t n_except);
|
||||
|
||||
int same_fd(int a, int b);
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ int write_string_stream_ts(
|
|||
struct timespec *ts) {
|
||||
|
||||
bool needs_nl;
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
assert(line);
|
||||
|
@ -77,6 +78,13 @@ int write_string_stream_ts(
|
|||
if (fputc('\n', f) == EOF)
|
||||
return -errno;
|
||||
|
||||
if (flags & WRITE_STRING_FILE_SYNC)
|
||||
r = fflush_sync_and_check(f);
|
||||
else
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ts) {
|
||||
struct timespec twice[2] = {*ts, *ts};
|
||||
|
||||
|
@ -84,10 +92,7 @@ int write_string_stream_ts(
|
|||
return -errno;
|
||||
}
|
||||
|
||||
if (flags & WRITE_STRING_FILE_SYNC)
|
||||
return fflush_sync_and_check(f);
|
||||
else
|
||||
return fflush_and_check(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_string_file_atomic(
|
||||
|
|
|
@ -248,6 +248,21 @@ int fchmod_umask(int fd, mode_t m) {
|
|||
}
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
int fchmod_opath(int fd, mode_t m) {
|
||||
char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
|
||||
|
||||
/* This function operates also on fd that might have been opened with
|
||||
* O_PATH. Indeed fchmodat() doesn't have the AT_EMPTY_PATH flag like
|
||||
* fchownat() does. */
|
||||
|
||||
xsprintf(procfs_path, "/proc/self/fd/%i", fd);
|
||||
|
||||
if (chmod(procfs_path, m) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fd_warn_permissions(const char *path, int fd) {
|
||||
struct stat st;
|
||||
|
||||
|
@ -911,25 +926,12 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
|
|||
return exists;
|
||||
|
||||
chased_one:
|
||||
|
||||
if (ret) {
|
||||
char *c;
|
||||
|
||||
if (done) {
|
||||
if (todo) {
|
||||
c = strjoin(done, todo);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
} else
|
||||
c = TAKE_PTR(done);
|
||||
} else {
|
||||
if (todo)
|
||||
c = strdup(todo);
|
||||
else
|
||||
c = strdup("/");
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
}
|
||||
c = strjoin(strempty(done), todo);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = c;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ int readlink_and_make_absolute(const char *p, char **r);
|
|||
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
|
||||
|
||||
int fchmod_umask(int fd, mode_t mode);
|
||||
int fchmod_opath(int fd, mode_t m);
|
||||
|
||||
int fd_warn_permissions(const char *path, int fd);
|
||||
|
||||
|
|
|
@ -283,7 +283,7 @@ static const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = {
|
|||
},
|
||||
};
|
||||
|
||||
#ifdef VALGRIND
|
||||
#if VALGRIND
|
||||
__attribute__((destructor)) static void cleanup_pools(void) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
int r;
|
||||
|
|
|
@ -79,33 +79,69 @@ char *hexmem(const void *p, size_t l) {
|
|||
return r;
|
||||
}
|
||||
|
||||
int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
|
||||
_cleanup_free_ uint8_t *r = NULL;
|
||||
uint8_t *z;
|
||||
const char *x;
|
||||
static int unhex_next(const char **p, size_t *l) {
|
||||
int r;
|
||||
|
||||
assert(mem);
|
||||
assert(len);
|
||||
assert(p);
|
||||
assert(l);
|
||||
|
||||
/* Find the next non-whitespace character, and decode it. We
|
||||
* greedily skip all preceeding and all following whitespace. */
|
||||
|
||||
for (;;) {
|
||||
if (*l == 0)
|
||||
return -EPIPE;
|
||||
|
||||
if (!strchr(WHITESPACE, **p))
|
||||
break;
|
||||
|
||||
/* Skip leading whitespace */
|
||||
(*p)++, (*l)--;
|
||||
}
|
||||
|
||||
r = unhexchar(**p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (;;) {
|
||||
(*p)++, (*l)--;
|
||||
|
||||
if (*l == 0 || !strchr(WHITESPACE, **p))
|
||||
break;
|
||||
|
||||
/* Skip following whitespace */
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
|
||||
_cleanup_free_ uint8_t *buf = NULL;
|
||||
const char *x;
|
||||
uint8_t *z;
|
||||
|
||||
assert(ret);
|
||||
assert(ret_len);
|
||||
assert(p || l == 0);
|
||||
|
||||
if (l == (size_t) -1)
|
||||
l = strlen(p);
|
||||
|
||||
if (l % 2 != 0)
|
||||
return -EINVAL;
|
||||
|
||||
z = r = malloc((l + 1) / 2 + 1);
|
||||
if (!r)
|
||||
/* Note that the calculation of memory size is an upper boundary, as we ignore whitespace while decoding */
|
||||
buf = malloc((l + 1) / 2 + 1);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
for (x = p; x < p + l; x += 2) {
|
||||
for (x = p, z = buf;;) {
|
||||
int a, b;
|
||||
|
||||
a = unhexchar(x[0]);
|
||||
a = unhex_next(&x, &l);
|
||||
if (a == -EPIPE) /* End of string */
|
||||
break;
|
||||
if (a < 0)
|
||||
return a;
|
||||
|
||||
b = unhexchar(x[1]);
|
||||
b = unhex_next(&x, &l);
|
||||
if (b < 0)
|
||||
return b;
|
||||
|
||||
|
@ -114,8 +150,8 @@ int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
|
|||
|
||||
*z = 0;
|
||||
|
||||
*mem = TAKE_PTR(r);
|
||||
*len = (l + 1) / 2;
|
||||
*ret_len = (size_t) (z - buf);
|
||||
*ret = TAKE_PTR(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -184,7 +220,7 @@ char *base32hexmem(const void *p, size_t l, bool padding) {
|
|||
|
||||
for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
|
||||
/* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
|
||||
x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
|
||||
* x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
|
||||
*(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
|
||||
*(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
|
||||
*(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
|
||||
|
@ -284,7 +320,7 @@ int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_l
|
|||
}
|
||||
|
||||
/* a group of eight input bytes needs five output bytes, in case of
|
||||
padding we need to add some extra bytes */
|
||||
* padding we need to add some extra bytes */
|
||||
len = (l / 8) * 5;
|
||||
|
||||
switch (l % 8) {
|
||||
|
@ -312,7 +348,7 @@ int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_l
|
|||
|
||||
for (x = p; x < p + (l / 8) * 8; x += 8) {
|
||||
/* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
|
||||
e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
|
||||
* e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
|
||||
a = unbase32hexchar(x[0]);
|
||||
if (a < 0)
|
||||
return -EINVAL;
|
||||
|
@ -668,7 +704,7 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
|
|||
l = strlen(p);
|
||||
|
||||
/* A group of four input bytes needs three output bytes, in case of padding we need to add two or three extra
|
||||
bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
|
||||
* bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
|
||||
len = (l / 4) * 3 + (l % 4 != 0 ? (l % 4) - 1 : 0);
|
||||
|
||||
buf = malloc(len + 1);
|
||||
|
@ -736,9 +772,7 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
|
|||
|
||||
*z = 0;
|
||||
|
||||
if (ret_size)
|
||||
*ret_size = (size_t) (z - buf);
|
||||
|
||||
*ret_size = (size_t) (z - buf);
|
||||
*ret = TAKE_PTR(buf);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -28,9 +28,8 @@ int fd_wait_for_event(int fd, int event, usec_t timeout);
|
|||
|
||||
ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length);
|
||||
|
||||
static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) {
|
||||
unsigned j;
|
||||
size_t r = 0;
|
||||
static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, size_t n) {
|
||||
size_t j, r = 0;
|
||||
|
||||
for (j = 0; j < n; j++)
|
||||
r += i[j].iov_len;
|
||||
|
@ -38,8 +37,8 @@ static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) {
|
|||
return r;
|
||||
}
|
||||
|
||||
static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
|
||||
unsigned j;
|
||||
static inline size_t IOVEC_INCREMENT(struct iovec *i, size_t n, size_t k) {
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < n; j++) {
|
||||
size_t sub;
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
|
||||
struct pool {
|
||||
struct pool *next;
|
||||
unsigned n_tiles;
|
||||
unsigned n_used;
|
||||
size_t n_tiles;
|
||||
size_t n_used;
|
||||
};
|
||||
|
||||
void* mempool_alloc_tile(struct mempool *mp) {
|
||||
unsigned i;
|
||||
size_t i;
|
||||
|
||||
/* When a tile is released we add it to the list and simply
|
||||
* place the next pointer at its offset 0. */
|
||||
|
@ -40,8 +40,7 @@ void* mempool_alloc_tile(struct mempool *mp) {
|
|||
|
||||
if (_unlikely_(!mp->first_pool) ||
|
||||
_unlikely_(mp->first_pool->n_used >= mp->first_pool->n_tiles)) {
|
||||
unsigned n;
|
||||
size_t size;
|
||||
size_t size, n;
|
||||
struct pool *p;
|
||||
|
||||
n = mp->first_pool ? mp->first_pool->n_tiles : 0;
|
||||
|
@ -79,7 +78,7 @@ void mempool_free_tile(struct mempool *mp, void *p) {
|
|||
mp->freelist = p;
|
||||
}
|
||||
|
||||
#ifdef VALGRIND
|
||||
#if VALGRIND
|
||||
|
||||
void mempool_drop(struct mempool *mp) {
|
||||
struct pool *p = mp->first_pool;
|
||||
|
|
|
@ -30,6 +30,6 @@ static struct mempool pool_name = { \
|
|||
}
|
||||
|
||||
|
||||
#ifdef VALGRIND
|
||||
#if VALGRIND
|
||||
void mempool_drop(struct mempool *mp);
|
||||
#endif
|
||||
|
|
|
@ -13,12 +13,14 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "errno-list.h"
|
||||
#include "extract-word.h"
|
||||
#include "locale-util.h"
|
||||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
#include "parse-util.h"
|
||||
#include "process-util.h"
|
||||
#include "string-util.h"
|
||||
|
@ -96,6 +98,30 @@ int parse_ifindex(const char *s, int *ret) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int parse_mtu(int family, const char *s, uint32_t *ret) {
|
||||
uint64_t u;
|
||||
size_t m;
|
||||
int r;
|
||||
|
||||
r = parse_size(s, 1024, &u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (u > UINT32_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
if (family == AF_INET6)
|
||||
m = IPV6_MIN_MTU; /* This is 1280 */
|
||||
else
|
||||
m = IPV4_MIN_MTU; /* For all other protocols, including 'unspecified' we assume the IPv4 minimal MTU */
|
||||
|
||||
if (u < m)
|
||||
return -ERANGE;
|
||||
|
||||
*ret = (uint32_t) u;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_size(const char *t, uint64_t base, uint64_t *size) {
|
||||
|
||||
/* Soo, sometimes we want to parse IEC binary suffixes, and
|
||||
|
@ -655,4 +681,21 @@ int parse_dev(const char *s, dev_t *ret) {
|
|||
*ret = d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_oom_score_adjust(const char *s, int *ret) {
|
||||
int r, v;
|
||||
|
||||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
r = safe_atoi(s, &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (v < OOM_SCORE_ADJ_MIN || v > OOM_SCORE_ADJ_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
*ret = v;
|
||||
return 0;
|
||||
}
|
||||
#endif /* NM_IGNORED */
|
||||
|
|
|
@ -22,6 +22,7 @@ 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);
|
||||
int parse_mtu(int family, const char *s, uint32_t *ret);
|
||||
|
||||
int parse_size(const char *t, uint64_t base, uint64_t *size);
|
||||
int parse_range(const char *t, unsigned *lower, unsigned *upper);
|
||||
|
@ -117,3 +118,5 @@ int parse_percent(const char *p);
|
|||
int parse_nice(const char *p, int *ret);
|
||||
|
||||
int parse_ip_port(const char *s, uint16_t *ret);
|
||||
|
||||
int parse_oom_score_adjust(const char *s, int *ret);
|
||||
|
|
|
@ -690,11 +690,12 @@ int parse_path_argument_and_warn(const char *path, bool suppress_root, char **ar
|
|||
return log_error_errno(r, "Failed to parse path \"%s\" and make it absolute: %m", path);
|
||||
|
||||
path_kill_slashes(p);
|
||||
if (suppress_root && path_equal(p, "/"))
|
||||
if (suppress_root && empty_or_root(p))
|
||||
p = mfree(p);
|
||||
|
||||
free(*arg);
|
||||
*arg = p;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -166,3 +166,6 @@ static inline const char *skip_dev_prefix(const char *p) {
|
|||
}
|
||||
|
||||
bool empty_or_root(const char *root);
|
||||
static inline const char *empty_to_root(const char *path) {
|
||||
return isempty(path) ? "/" : path;
|
||||
}
|
||||
|
|
|
@ -885,7 +885,7 @@ int getenv_for_pid(pid_t pid, const char *field, char **ret) {
|
|||
|
||||
do {
|
||||
char line[LINE_MAX];
|
||||
unsigned i;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(line)-1; i++) {
|
||||
int c;
|
||||
|
@ -1384,9 +1384,9 @@ int safe_fork_full(
|
|||
return 0;
|
||||
}
|
||||
|
||||
int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *ret_pid, const char *path, ...) {
|
||||
int fork_agent(const char *name, const int except[], size_t n_except, pid_t *ret_pid, const char *path, ...) {
|
||||
bool stdout_is_tty, stderr_is_tty;
|
||||
unsigned n, i;
|
||||
size_t n, i;
|
||||
va_list ap;
|
||||
char **l;
|
||||
int r;
|
||||
|
@ -1442,7 +1442,7 @@ int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *r
|
|||
va_end(ap);
|
||||
|
||||
/* Allocate strv */
|
||||
l = alloca(sizeof(char *) * (n + 1));
|
||||
l = newa(char*, n + 1);
|
||||
|
||||
/* Fill in arguments */
|
||||
va_start(ap, path);
|
||||
|
@ -1454,6 +1454,15 @@ int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *r
|
|||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int set_oom_score_adjust(int value) {
|
||||
char t[DECIMAL_STR_MAX(int)];
|
||||
|
||||
sprintf(t, "%i", value);
|
||||
|
||||
return write_string_file("/proc/self/oom_score_adj", t,
|
||||
WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_DISABLE_BUFFER);
|
||||
}
|
||||
|
||||
static const char *const ioprio_class_table[] = {
|
||||
[IOPRIO_CLASS_NONE] = "none",
|
||||
[IOPRIO_CLASS_RT] = "realtime",
|
||||
|
|
|
@ -173,7 +173,9 @@ static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret_pid) {
|
|||
return safe_fork_full(name, NULL, 0, flags, ret_pid);
|
||||
}
|
||||
|
||||
int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *pid, const char *path, ...);
|
||||
int fork_agent(const char *name, const int except[], size_t n_except, pid_t *pid, const char *path, ...);
|
||||
|
||||
int set_oom_score_adjust(int value);
|
||||
|
||||
#if SIZEOF_PID_T == 4
|
||||
/* The highest possibly (theoretic) pid_t value on this architecture. */
|
||||
|
|
|
@ -37,7 +37,7 @@ 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;
|
||||
size_t already_done = 0;
|
||||
int r;
|
||||
|
||||
/* Gathers some randomness from the kernel. This call will never block. If
|
||||
|
|
|
@ -136,5 +136,3 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free);
|
|||
|
||||
#define _cleanup_set_free_ _cleanup_(set_freep)
|
||||
#define _cleanup_set_free_free_ _cleanup_(set_free_freep)
|
||||
|
||||
int set_make(Set **ret, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS, void *add, ...);
|
||||
|
|
|
@ -24,8 +24,6 @@ int sigprocmask_many(int how, sigset_t *old, ...);
|
|||
const char *signal_to_string(int i) _const_;
|
||||
int signal_from_string(const char *s) _pure_;
|
||||
|
||||
int signal_from_string_try_harder(const char *s);
|
||||
|
||||
void nop_signal_handler(int sig);
|
||||
|
||||
static inline void block_signals_reset(sigset_t *ss) {
|
||||
|
|
292
src/systemd/src/basic/stat-util.c
Normal file
292
src/systemd/src/basic/stat-util.c
Normal file
|
@ -0,0 +1,292 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2010-2012 Lennart Poettering
|
||||
***/
|
||||
|
||||
#include "nm-sd-adapt.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/magic.h>
|
||||
#include <sched.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "dirent-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
int is_symlink(const char *path) {
|
||||
struct stat info;
|
||||
|
||||
assert(path);
|
||||
|
||||
if (lstat(path, &info) < 0)
|
||||
return -errno;
|
||||
|
||||
return !!S_ISLNK(info.st_mode);
|
||||
}
|
||||
|
||||
int is_dir(const char* path, bool follow) {
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
|
||||
if (follow)
|
||||
r = stat(path, &st);
|
||||
else
|
||||
r = lstat(path, &st);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
return !!S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
int is_device_node(const char *path) {
|
||||
struct stat info;
|
||||
|
||||
assert(path);
|
||||
|
||||
if (lstat(path, &info) < 0)
|
||||
return -errno;
|
||||
|
||||
return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode));
|
||||
}
|
||||
|
||||
int dir_is_empty(const char *path) {
|
||||
_cleanup_closedir_ DIR *d;
|
||||
struct dirent *de;
|
||||
|
||||
d = opendir(path);
|
||||
if (!d)
|
||||
return -errno;
|
||||
|
||||
FOREACH_DIRENT(de, d, return -errno)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool null_or_empty(struct stat *st) {
|
||||
assert(st);
|
||||
|
||||
if (S_ISREG(st->st_mode) && st->st_size <= 0)
|
||||
return true;
|
||||
|
||||
/* We don't want to hardcode the major/minor of /dev/null,
|
||||
* hence we do a simpler "is this a device node?" check. */
|
||||
|
||||
if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int null_or_empty_path(const char *fn) {
|
||||
struct stat st;
|
||||
|
||||
assert(fn);
|
||||
|
||||
if (stat(fn, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
return null_or_empty(&st);
|
||||
}
|
||||
|
||||
int null_or_empty_fd(int fd) {
|
||||
struct stat st;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
return null_or_empty(&st);
|
||||
}
|
||||
|
||||
int path_is_read_only_fs(const char *path) {
|
||||
struct statvfs st;
|
||||
|
||||
assert(path);
|
||||
|
||||
if (statvfs(path, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (st.f_flag & ST_RDONLY)
|
||||
return true;
|
||||
|
||||
/* On NFS, statvfs() might not reflect whether we can actually
|
||||
* write to the remote share. Let's try again with
|
||||
* access(W_OK) which is more reliable, at least sometimes. */
|
||||
if (access(path, W_OK) < 0 && errno == EROFS)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int path_is_os_tree(const char *path) {
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
|
||||
/* Does the path exist at all? If not, generate an error immediately. This is useful so that a missing root dir
|
||||
* always results in -ENOENT, and we can properly distuingish the case where the whole root doesn't exist from
|
||||
* the case where just the os-release file is missing. */
|
||||
if (laccess(path, F_OK) < 0)
|
||||
return -errno;
|
||||
|
||||
/* We use /usr/lib/os-release as flag file if something is an OS */
|
||||
r = chase_symlinks("/usr/lib/os-release", path, CHASE_PREFIX_ROOT, NULL);
|
||||
if (r == -ENOENT) {
|
||||
|
||||
/* Also check for the old location in /etc, just in case. */
|
||||
r = chase_symlinks("/etc/os-release", path, CHASE_PREFIX_ROOT, NULL);
|
||||
if (r == -ENOENT)
|
||||
return 0; /* We got nothing */
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int files_same(const char *filea, const char *fileb, int flags) {
|
||||
struct stat a, b;
|
||||
|
||||
assert(filea);
|
||||
assert(fileb);
|
||||
|
||||
if (fstatat(AT_FDCWD, filea, &a, flags) < 0)
|
||||
return -errno;
|
||||
|
||||
if (fstatat(AT_FDCWD, fileb, &b, flags) < 0)
|
||||
return -errno;
|
||||
|
||||
return a.st_dev == b.st_dev &&
|
||||
a.st_ino == b.st_ino;
|
||||
}
|
||||
|
||||
bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
|
||||
assert(s);
|
||||
assert_cc(sizeof(statfs_f_type_t) >= sizeof(s->f_type));
|
||||
|
||||
return F_TYPE_EQUAL(s->f_type, magic_value);
|
||||
}
|
||||
|
||||
int fd_is_fs_type(int fd, statfs_f_type_t magic_value) {
|
||||
struct statfs s;
|
||||
|
||||
if (fstatfs(fd, &s) < 0)
|
||||
return -errno;
|
||||
|
||||
return is_fs_type(&s, magic_value);
|
||||
}
|
||||
|
||||
int path_is_fs_type(const char *path, statfs_f_type_t magic_value) {
|
||||
_cleanup_close_ int fd = -1;
|
||||
|
||||
fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
return fd_is_fs_type(fd, magic_value);
|
||||
}
|
||||
|
||||
bool is_temporary_fs(const struct statfs *s) {
|
||||
return is_fs_type(s, TMPFS_MAGIC) ||
|
||||
is_fs_type(s, RAMFS_MAGIC);
|
||||
}
|
||||
|
||||
bool is_network_fs(const struct statfs *s) {
|
||||
return is_fs_type(s, CIFS_MAGIC_NUMBER) ||
|
||||
is_fs_type(s, CODA_SUPER_MAGIC) ||
|
||||
is_fs_type(s, NCP_SUPER_MAGIC) ||
|
||||
is_fs_type(s, NFS_SUPER_MAGIC) ||
|
||||
is_fs_type(s, SMB_SUPER_MAGIC) ||
|
||||
is_fs_type(s, V9FS_MAGIC) ||
|
||||
is_fs_type(s, AFS_SUPER_MAGIC) ||
|
||||
is_fs_type(s, OCFS2_SUPER_MAGIC);
|
||||
}
|
||||
|
||||
int fd_is_temporary_fs(int fd) {
|
||||
struct statfs s;
|
||||
|
||||
if (fstatfs(fd, &s) < 0)
|
||||
return -errno;
|
||||
|
||||
return is_temporary_fs(&s);
|
||||
}
|
||||
|
||||
int fd_is_network_fs(int fd) {
|
||||
struct statfs s;
|
||||
|
||||
if (fstatfs(fd, &s) < 0)
|
||||
return -errno;
|
||||
|
||||
return is_network_fs(&s);
|
||||
}
|
||||
|
||||
int fd_is_network_ns(int fd) {
|
||||
int r;
|
||||
|
||||
r = fd_is_fs_type(fd, NSFS_MAGIC);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = ioctl(fd, NS_GET_NSTYPE);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
return r == CLONE_NEWNET;
|
||||
}
|
||||
|
||||
int path_is_temporary_fs(const char *path) {
|
||||
_cleanup_close_ int fd = -1;
|
||||
|
||||
fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
return fd_is_temporary_fs(fd);
|
||||
}
|
||||
#endif /* NM_IGNORED */
|
||||
|
||||
int stat_verify_regular(const struct stat *st) {
|
||||
assert(st);
|
||||
|
||||
/* Checks whether the specified stat() structure refers to a regular file. If not returns an appropriate error
|
||||
* code. */
|
||||
|
||||
if (S_ISDIR(st->st_mode))
|
||||
return -EISDIR;
|
||||
|
||||
if (S_ISLNK(st->st_mode))
|
||||
return -ELOOP;
|
||||
|
||||
if (!S_ISREG(st->st_mode))
|
||||
return -EBADFD;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fd_verify_regular(int fd) {
|
||||
struct stat st;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
return stat_verify_regular(&st);
|
||||
}
|
67
src/systemd/src/basic/stat-util.h
Normal file
67
src/systemd/src/basic/stat-util.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2010-2012 Lennart Poettering
|
||||
***/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statfs.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/vfs.h>
|
||||
|
||||
#include "macro.h"
|
||||
|
||||
int is_symlink(const char *path);
|
||||
int is_dir(const char *path, bool follow);
|
||||
int is_device_node(const char *path);
|
||||
|
||||
int dir_is_empty(const char *path);
|
||||
|
||||
static inline int dir_is_populated(const char *path) {
|
||||
int r;
|
||||
r = dir_is_empty(path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return !r;
|
||||
}
|
||||
|
||||
bool null_or_empty(struct stat *st) _pure_;
|
||||
int null_or_empty_path(const char *fn);
|
||||
int null_or_empty_fd(int fd);
|
||||
|
||||
int path_is_read_only_fs(const char *path);
|
||||
int path_is_os_tree(const char *path);
|
||||
|
||||
int files_same(const char *filea, const char *fileb, int flags);
|
||||
|
||||
/* The .f_type field of struct statfs is really weird defined on
|
||||
* different archs. Let's give its type a name. */
|
||||
typedef typeof(((struct statfs*)NULL)->f_type) statfs_f_type_t;
|
||||
|
||||
bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) _pure_;
|
||||
int fd_is_fs_type(int fd, statfs_f_type_t magic_value);
|
||||
int path_is_fs_type(const char *path, statfs_f_type_t magic_value);
|
||||
|
||||
bool is_temporary_fs(const struct statfs *s) _pure_;
|
||||
bool is_network_fs(const struct statfs *s) _pure_;
|
||||
|
||||
int fd_is_temporary_fs(int fd);
|
||||
int fd_is_network_fs(int fd);
|
||||
|
||||
int fd_is_network_ns(int fd);
|
||||
|
||||
int path_is_temporary_fs(const char *path);
|
||||
|
||||
/* Because statfs.t_type can be int on some architectures, we have to cast
|
||||
* the const magic to the type, otherwise the compiler warns about
|
||||
* signed/unsigned comparison, because the magic can be 32 bit unsigned.
|
||||
*/
|
||||
#define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b)
|
||||
|
||||
int stat_verify_regular(const struct stat *st);
|
||||
int fd_verify_regular(int fd);
|
|
@ -23,6 +23,7 @@
|
|||
#include "terminal-util.h"
|
||||
#include "utf8.h"
|
||||
#include "util.h"
|
||||
#include "fileio.h"
|
||||
|
||||
int strcmp_ptr(const char *a, const char *b) {
|
||||
|
||||
|
@ -700,7 +701,8 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
|
|||
enum {
|
||||
STATE_OTHER,
|
||||
STATE_ESCAPE,
|
||||
STATE_BRACKET
|
||||
STATE_CSI,
|
||||
STATE_CSO,
|
||||
} state = STATE_OTHER;
|
||||
char *obuf = NULL;
|
||||
size_t osz = 0, isz, shift[2] = {};
|
||||
|
@ -709,7 +711,17 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
|
|||
assert(ibuf);
|
||||
assert(*ibuf);
|
||||
|
||||
/* Strips ANSI color and replaces TABs by 8 spaces */
|
||||
/* This does three things:
|
||||
*
|
||||
* 1. Replaces TABs by 8 spaces
|
||||
* 2. Strips ANSI color sequences (a subset of CSI), i.e. ESC '[' … 'm' sequences
|
||||
* 3. Strips ANSI operating system sequences (CSO), i.e. ESC ']' … BEL sequences
|
||||
*
|
||||
* Everything else will be left as it is. In particular other ANSI sequences are left as they are, as are any
|
||||
* other special characters. Truncated ANSI sequences are left-as is too. This call is supposed to suppress the
|
||||
* most basic formatting noise, but nothing else.
|
||||
*
|
||||
* Why care for CSO sequences? Well, to undo what terminal_urlify() and friends generate. */
|
||||
|
||||
isz = _isz ? *_isz : strlen(*ibuf);
|
||||
|
||||
|
@ -744,8 +756,11 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
|
|||
fputc('\x1B', f);
|
||||
advance_offsets(i - *ibuf, highlight, shift, 1);
|
||||
break;
|
||||
} else if (*i == '[') {
|
||||
state = STATE_BRACKET;
|
||||
} else if (*i == '[') { /* ANSI CSI */
|
||||
state = STATE_CSI;
|
||||
begin = i + 1;
|
||||
} else if (*i == ']') { /* ANSI CSO */
|
||||
state = STATE_CSO;
|
||||
begin = i + 1;
|
||||
} else {
|
||||
fputc('\x1B', f);
|
||||
|
@ -756,10 +771,10 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
|
|||
|
||||
break;
|
||||
|
||||
case STATE_BRACKET:
|
||||
case STATE_CSI:
|
||||
|
||||
if (i >= *ibuf + isz || /* EOT */
|
||||
(!(*i >= '0' && *i <= '9') && !IN_SET(*i, ';', 'm'))) {
|
||||
if (i >= *ibuf + isz || /* EOT … */
|
||||
!strchr("01234567890;m", *i)) { /* … or invalid chars in sequence */
|
||||
fputc('\x1B', f);
|
||||
fputc('[', f);
|
||||
advance_offsets(i - *ibuf, highlight, shift, 2);
|
||||
|
@ -767,11 +782,26 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
|
|||
i = begin-1;
|
||||
} else if (*i == 'm')
|
||||
state = STATE_OTHER;
|
||||
|
||||
break;
|
||||
|
||||
case STATE_CSO:
|
||||
|
||||
if (i >= *ibuf + isz || /* EOT … */
|
||||
(*i != '\a' && (uint8_t) *i < 32U) || (uint8_t) *i > 126U) { /* … or invalid chars in sequence */
|
||||
fputc('\x1B', f);
|
||||
fputc(']', f);
|
||||
advance_offsets(i - *ibuf, highlight, shift, 2);
|
||||
state = STATE_OTHER;
|
||||
i = begin-1;
|
||||
} else if (*i == '\a')
|
||||
state = STATE_OTHER;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ferror(f)) {
|
||||
if (fflush_and_check(f) < 0) {
|
||||
fclose(f);
|
||||
return mfree(obuf);
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ static inline const char *empty_to_null(const char *p) {
|
|||
return isempty(p) ? NULL : p;
|
||||
}
|
||||
|
||||
static inline const char *strdash_if_empty(const char *str) {
|
||||
static inline const char *empty_to_dash(const char *str) {
|
||||
return isempty(str) ? "-" : str;
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ char *strjoin_real(const char *x, ...) _sentinel_;
|
|||
const char *_appendees_[] = { a, __VA_ARGS__ }; \
|
||||
char *_d_, *_p_; \
|
||||
size_t _len_ = 0; \
|
||||
unsigned _i_; \
|
||||
size_t _i_; \
|
||||
for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \
|
||||
_len_ += strlen(_appendees_[_i_]); \
|
||||
_p_ = _d_ = alloca(_len_ + 1); \
|
||||
|
|
|
@ -109,8 +109,8 @@ char **strv_copy(char * const *l) {
|
|||
return r;
|
||||
}
|
||||
|
||||
unsigned strv_length(char * const *l) {
|
||||
unsigned n = 0;
|
||||
size_t strv_length(char * const *l) {
|
||||
size_t n = 0;
|
||||
|
||||
if (!l)
|
||||
return 0;
|
||||
|
@ -123,8 +123,8 @@ unsigned strv_length(char * const *l) {
|
|||
|
||||
char **strv_new_ap(const char *x, va_list ap) {
|
||||
const char *s;
|
||||
char **a;
|
||||
unsigned n = 0, i = 0;
|
||||
_cleanup_strv_free_ char **a = NULL;
|
||||
size_t n = 0, i = 0;
|
||||
va_list aq;
|
||||
|
||||
/* As a special trick we ignore all listed strings that equal
|
||||
|
@ -154,7 +154,7 @@ char **strv_new_ap(const char *x, va_list ap) {
|
|||
if (x != STRV_IGNORE) {
|
||||
a[i] = strdup(x);
|
||||
if (!a[i])
|
||||
goto fail;
|
||||
return NULL;
|
||||
i++;
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ char **strv_new_ap(const char *x, va_list ap) {
|
|||
|
||||
a[i] = strdup(s);
|
||||
if (!a[i])
|
||||
goto fail;
|
||||
return NULL;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
@ -173,11 +173,7 @@ char **strv_new_ap(const char *x, va_list ap) {
|
|||
|
||||
a[i] = NULL;
|
||||
|
||||
return a;
|
||||
|
||||
fail:
|
||||
strv_free(a);
|
||||
return NULL;
|
||||
return TAKE_PTR(a);
|
||||
}
|
||||
|
||||
char **strv_new(const char *x, ...) {
|
||||
|
@ -259,7 +255,7 @@ int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
|
|||
char **strv_split(const char *s, const char *separator) {
|
||||
const char *word, *state;
|
||||
size_t l;
|
||||
unsigned n, i;
|
||||
size_t n, i;
|
||||
char **r;
|
||||
|
||||
assert(s);
|
||||
|
@ -289,7 +285,7 @@ char **strv_split(const char *s, const char *separator) {
|
|||
|
||||
char **strv_split_newlines(const char *s) {
|
||||
char **l;
|
||||
unsigned n;
|
||||
size_t n;
|
||||
|
||||
assert(s);
|
||||
|
||||
|
@ -384,7 +380,7 @@ char *strv_join(char **l, const char *separator) {
|
|||
|
||||
int strv_push(char ***l, char *value) {
|
||||
char **c;
|
||||
unsigned n, m;
|
||||
size_t n, m;
|
||||
|
||||
if (!value)
|
||||
return 0;
|
||||
|
@ -409,7 +405,7 @@ int strv_push(char ***l, char *value) {
|
|||
|
||||
int strv_push_pair(char ***l, char *a, char *b) {
|
||||
char **c;
|
||||
unsigned n, m;
|
||||
size_t n, m;
|
||||
|
||||
if (!a && !b)
|
||||
return 0;
|
||||
|
@ -435,9 +431,9 @@ int strv_push_pair(char ***l, char *a, char *b) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int strv_insert(char ***l, unsigned position, char *value) {
|
||||
int strv_insert(char ***l, size_t position, char *value) {
|
||||
char **c;
|
||||
unsigned n, m, i;
|
||||
size_t n, m, i;
|
||||
|
||||
if (!value)
|
||||
return 0;
|
||||
|
@ -605,7 +601,7 @@ char **strv_parse_nulstr(const char *s, size_t l) {
|
|||
*/
|
||||
|
||||
const char *p;
|
||||
unsigned c = 0, i = 0;
|
||||
size_t c = 0, i = 0;
|
||||
char **v;
|
||||
|
||||
assert(s || l <= 0);
|
||||
|
@ -769,7 +765,7 @@ int strv_extendf(char ***l, const char *format, ...) {
|
|||
}
|
||||
|
||||
char **strv_reverse(char **l) {
|
||||
unsigned n, i;
|
||||
size_t n, i;
|
||||
|
||||
n = strv_length(l);
|
||||
if (n <= 1)
|
||||
|
|
|
@ -32,7 +32,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free_erase);
|
|||
void strv_clear(char **l);
|
||||
|
||||
char **strv_copy(char * const *l);
|
||||
unsigned strv_length(char * const *l) _pure_;
|
||||
size_t strv_length(char * const *l) _pure_;
|
||||
|
||||
int strv_extend_strv(char ***a, char **b, bool filter_duplicates);
|
||||
int strv_extend_strv_concat(char ***a, char **b, const char *suffix);
|
||||
|
@ -41,7 +41,7 @@ int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
|
|||
int strv_extend_front(char ***l, const char *value);
|
||||
int strv_push(char ***l, char *value);
|
||||
int strv_push_pair(char ***l, char *a, char *b);
|
||||
int strv_insert(char ***l, unsigned position, char *value);
|
||||
int strv_insert(char ***l, size_t position, char *value);
|
||||
|
||||
static inline int strv_push_prepend(char ***l, char *value) {
|
||||
return strv_insert(l, 0, value);
|
||||
|
@ -113,7 +113,7 @@ void strv_print(char **l);
|
|||
if (!first) \
|
||||
_l = (char**) &first; \
|
||||
else { \
|
||||
unsigned _n; \
|
||||
size_t _n; \
|
||||
va_list _ap; \
|
||||
\
|
||||
_n = 1; \
|
||||
|
|
|
@ -23,11 +23,13 @@
|
|||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "io-util.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "time-util.h"
|
||||
|
@ -438,7 +440,7 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
|
|||
{ "us", 1 },
|
||||
};
|
||||
|
||||
unsigned i;
|
||||
size_t i;
|
||||
char *p = buf;
|
||||
bool something = false;
|
||||
|
||||
|
@ -617,10 +619,9 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
|
|||
time_t x;
|
||||
usec_t x_usec, plus = 0, minus = 0, ret;
|
||||
int r, weekday = -1, dst = -1;
|
||||
unsigned i;
|
||||
size_t i;
|
||||
|
||||
/*
|
||||
* Allowed syntaxes:
|
||||
/* Allowed syntaxes:
|
||||
*
|
||||
* 2012-09-22 16:34:22
|
||||
* 2012-09-22 16:34 (seconds will be set to 0)
|
||||
|
@ -634,7 +635,6 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
|
|||
* +5min
|
||||
* -5days
|
||||
* @2147483647 (seconds since epoch)
|
||||
*
|
||||
*/
|
||||
|
||||
assert(t);
|
||||
|
@ -693,10 +693,10 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
|
|||
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. */
|
||||
* 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++) {
|
||||
|
||||
|
@ -882,7 +882,7 @@ int parse_timestamp(const char *t, usec_t *usec) {
|
|||
int r;
|
||||
|
||||
last_space = strrchr(t, ' ');
|
||||
if (last_space != NULL && timezone_is_valid(last_space + 1))
|
||||
if (last_space != NULL && timezone_is_valid(last_space + 1, LOG_DEBUG))
|
||||
tz = last_space + 1;
|
||||
|
||||
if (!tz || endswith_no_case(t, " UTC"))
|
||||
|
@ -908,10 +908,10 @@ int parse_timestamp(const char *t, usec_t *usec) {
|
|||
tzset();
|
||||
|
||||
/* If there is a timezone that matches the tzname fields, leave the parsing to the implementation.
|
||||
* Otherwise just cut it off */
|
||||
* Otherwise just cut it off. */
|
||||
with_tz = !STR_IN_SET(tz, tzname[0], tzname[1]);
|
||||
|
||||
/*cut off the timezone if we dont need it*/
|
||||
/* Cut off the timezone if we dont need it. */
|
||||
if (with_tz)
|
||||
t = strndupa(t, last_space - t);
|
||||
|
||||
|
@ -965,7 +965,7 @@ static char* extract_multiplier(char *p, usec_t *multiplier) {
|
|||
{ "us", 1ULL },
|
||||
{ "µs", 1ULL },
|
||||
};
|
||||
unsigned i;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(table); i++) {
|
||||
char *e;
|
||||
|
@ -1139,8 +1139,8 @@ int parse_nsec(const char *t, nsec_t *nsec) {
|
|||
|
||||
for (;;) {
|
||||
long long l, z = 0;
|
||||
size_t n = 0, i;
|
||||
char *e;
|
||||
unsigned i, n = 0;
|
||||
|
||||
p += strspn(p, WHITESPACE);
|
||||
|
||||
|
@ -1281,10 +1281,12 @@ int get_timezones(char ***ret) {
|
|||
}
|
||||
#endif /* NM_IGNORED */
|
||||
|
||||
bool timezone_is_valid(const char *name) {
|
||||
bool timezone_is_valid(const char *name, int log_level) {
|
||||
bool slash = false;
|
||||
const char *p, *t;
|
||||
struct stat st;
|
||||
_cleanup_close_ int fd = -1;
|
||||
char buf[4];
|
||||
int r;
|
||||
|
||||
if (isempty(name))
|
||||
return false;
|
||||
|
@ -1313,11 +1315,30 @@ bool timezone_is_valid(const char *name) {
|
|||
return false;
|
||||
|
||||
t = strjoina("/usr/share/zoneinfo/", name);
|
||||
if (stat(t, &st) < 0)
|
||||
return false;
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
fd = open(t, O_RDONLY|O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
log_full_errno(log_level, errno, "Failed to open timezone file '%s': %m", t);
|
||||
return false;
|
||||
}
|
||||
|
||||
r = fd_verify_regular(fd);
|
||||
if (r < 0) {
|
||||
log_full_errno(log_level, r, "Timezone file '%s' is not a regular file: %m", t);
|
||||
return false;
|
||||
}
|
||||
|
||||
r = loop_read_exact(fd, buf, 4, false);
|
||||
if (r < 0) {
|
||||
log_full_errno(log_level, r, "Failed to read from timezone file '%s': %m", t);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Magic from tzfile(5) */
|
||||
if (memcmp(buf, "TZif", 4) != 0) {
|
||||
log_full(log_level, "Timezone file '%s' has wrong magic bytes", t);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1389,7 +1410,7 @@ int get_timezone(char **tz) {
|
|||
if (!e)
|
||||
return -EINVAL;
|
||||
|
||||
if (!timezone_is_valid(e))
|
||||
if (!timezone_is_valid(e, LOG_DEBUG))
|
||||
return -EINVAL;
|
||||
|
||||
z = strdup(e);
|
||||
|
|
|
@ -128,7 +128,7 @@ int parse_nsec(const char *t, nsec_t *nsec);
|
|||
bool ntp_synced(void);
|
||||
|
||||
int get_timezones(char ***l);
|
||||
bool timezone_is_valid(const char *name);
|
||||
bool timezone_is_valid(const char *name, int log_level);
|
||||
|
||||
bool clock_boottime_supported(void);
|
||||
bool clock_supported(clockid_t clock);
|
||||
|
|
|
@ -86,7 +86,7 @@ int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_i
|
|||
#if 0 /* NM_IGNORED */
|
||||
/* name is a pointer to memory in the udev_device struct, so must
|
||||
have the same scope */
|
||||
_cleanup_udev_device_unref_ struct udev_device *device = NULL;
|
||||
_cleanup_(udev_device_unrefp) struct udev_device *device = NULL;
|
||||
#else /* NM_IGNORED */
|
||||
char name_buf[IF_NAMESIZE];
|
||||
#endif /* NM_IGNORED */
|
||||
|
@ -96,7 +96,7 @@ int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_i
|
|||
#if 0 /* NM_IGNORED */
|
||||
if (detect_container() <= 0) {
|
||||
/* not in a container, udev will be around */
|
||||
_cleanup_udev_unref_ struct udev *udev;
|
||||
_cleanup_(udev_unrefp) struct udev *udev;
|
||||
char ifindex_str[2 + DECIMAL_STR_MAX(int)];
|
||||
|
||||
udev = udev_new();
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "alloc-util.h"
|
||||
#include "utf8.h"
|
||||
#include "strv.h"
|
||||
|
||||
#include "dhcp-internal.h"
|
||||
|
||||
|
@ -37,6 +38,34 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
|
|||
*offset += 1;
|
||||
break;
|
||||
|
||||
case SD_DHCP_OPTION_USER_CLASS: {
|
||||
size_t len = 0;
|
||||
char **s;
|
||||
|
||||
STRV_FOREACH(s, (char **) optval)
|
||||
len += strlen(*s) + 1;
|
||||
|
||||
if (size < *offset + len + 2)
|
||||
return -ENOBUFS;
|
||||
|
||||
options[*offset] = code;
|
||||
options[*offset + 1] = len;
|
||||
*offset += 2;
|
||||
|
||||
STRV_FOREACH(s, (char **) optval) {
|
||||
len = strlen(*s);
|
||||
|
||||
if (len > 255)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
options[*offset] = len;
|
||||
|
||||
memcpy_safe(&options[*offset + 1], *s, len);
|
||||
*offset += len + 1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (size < *offset + optlen + 2)
|
||||
return -ENOBUFS;
|
||||
|
|
|
@ -86,7 +86,7 @@ static bool net_condition_test_strv(char * const *raw_patterns,
|
|||
/* If the patterns begin with "!", edit it out and negate the test. */
|
||||
if (raw_patterns[0][0] == '!') {
|
||||
char **patterns;
|
||||
unsigned i, length;
|
||||
size_t i, length;
|
||||
|
||||
length = strv_length(raw_patterns) + 1; /* Include the NULL. */
|
||||
patterns = newa(char*, length);
|
||||
|
@ -100,7 +100,7 @@ static bool net_condition_test_strv(char * const *raw_patterns,
|
|||
return string && strv_fnmatch(raw_patterns, string, 0);
|
||||
}
|
||||
|
||||
bool net_match_config(const struct ether_addr *match_mac,
|
||||
bool net_match_config(Set *match_mac,
|
||||
char * const *match_paths,
|
||||
char * const *match_drivers,
|
||||
char * const *match_types,
|
||||
|
@ -132,7 +132,7 @@ bool net_match_config(const struct ether_addr *match_mac,
|
|||
if (match_arch && condition_test(match_arch) <= 0)
|
||||
return false;
|
||||
|
||||
if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
|
||||
if (match_mac && dev_mac && !set_contains(match_mac, dev_mac))
|
||||
return false;
|
||||
|
||||
if (!net_condition_test_strv(match_paths, dev_path))
|
||||
|
@ -284,10 +284,9 @@ int config_parse_hwaddr(const char *unit,
|
|||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_free_ struct ether_addr *n = NULL;
|
||||
struct ether_addr **hwaddr = data;
|
||||
struct ether_addr *n;
|
||||
const char *start;
|
||||
size_t offset;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
|
@ -299,17 +298,86 @@ int config_parse_hwaddr(const char *unit,
|
|||
if (!n)
|
||||
return log_oom();
|
||||
|
||||
start = rvalue + strspn(rvalue, WHITESPACE);
|
||||
r = ether_addr_from_string(start, n, &offset);
|
||||
|
||||
if (r || (start[offset + strspn(start + offset, WHITESPACE)] != '\0')) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue);
|
||||
free(n);
|
||||
r = ether_addr_from_string(rvalue, n);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Not a valid MAC address, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(*hwaddr);
|
||||
*hwaddr = n;
|
||||
*hwaddr = TAKE_PTR(n);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_hwaddrs(const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_set_free_free_ Set *s = NULL;
|
||||
const char *p = rvalue;
|
||||
Set **hwaddrs = data;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
/* Empty assignment resets the list */
|
||||
*hwaddrs = set_free_free(*hwaddrs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s = set_new(ðer_addr_hash_ops);
|
||||
if (!s)
|
||||
return log_oom();
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
_cleanup_free_ struct ether_addr *n = NULL;
|
||||
|
||||
r = extract_first_word(&p, &word, NULL, 0);
|
||||
if (r == 0)
|
||||
break;
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = new(struct ether_addr, 1);
|
||||
if (!n)
|
||||
return log_oom();
|
||||
|
||||
r = ether_addr_from_string(word, n);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring: %s", word);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = set_put(s, n);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
if (r > 0)
|
||||
n = NULL; /* avoid cleanup */
|
||||
}
|
||||
|
||||
r = set_ensure_allocated(hwaddrs, ðer_addr_hash_ops);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = set_move(*hwaddrs, s);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -592,14 +660,3 @@ int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t siz
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int deserialize_dhcp_option(void **data, size_t *data_len, const char *string) {
|
||||
assert(data);
|
||||
assert(data_len);
|
||||
assert(string);
|
||||
|
||||
if (strlen(string) % 2)
|
||||
return -EINVAL;
|
||||
|
||||
return unhexmem(string, strlen(string), (void **)data, data_len);
|
||||
}
|
||||
|
|
|
@ -12,12 +12,13 @@
|
|||
#include "sd-dhcp-lease.h"
|
||||
|
||||
#include "condition.h"
|
||||
#include "set.h"
|
||||
#include "udev.h"
|
||||
|
||||
#define LINK_BRIDGE_PORT_PRIORITY_INVALID 128
|
||||
#define LINK_BRIDGE_PORT_PRIORITY_MAX 63
|
||||
|
||||
bool net_match_config(const struct ether_addr *match_mac,
|
||||
bool net_match_config(Set *match_mac,
|
||||
char * const *match_path,
|
||||
char * const *match_driver,
|
||||
char * const *match_type,
|
||||
|
@ -42,6 +43,10 @@ int config_parse_hwaddr(const char *unit, const char *filename, unsigned line,
|
|||
const char *section, unsigned section_line, const char *lvalue,
|
||||
int ltype, const char *rvalue, void *data, void *userdata);
|
||||
|
||||
int config_parse_hwaddrs(const char *unit, const char *filename, unsigned line,
|
||||
const char *section, unsigned section_line, const char *lvalue,
|
||||
int ltype, const char *rvalue, void *data, void *userdata);
|
||||
|
||||
int config_parse_ifnames(const char *unit, const char *filename, unsigned line,
|
||||
const char *section, unsigned section_line, const char *lvalue,
|
||||
int ltype, const char *rvalue, void *data, void *userdata);
|
||||
|
@ -73,5 +78,5 @@ struct sd_dhcp_route;
|
|||
void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size);
|
||||
int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string);
|
||||
|
||||
/* It is not necessary to add deserialize_dhcp_option(). Use unhexmem() instead. */
|
||||
int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size);
|
||||
int deserialize_dhcp_option(void **data, size_t *data_len, const char *string);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "random-util.h"
|
||||
#include "string-util.h"
|
||||
#include "util.h"
|
||||
#include "strv.h"
|
||||
|
||||
#define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
|
||||
#define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
|
||||
|
@ -85,6 +86,7 @@ struct sd_dhcp_client {
|
|||
size_t client_id_len;
|
||||
char *hostname;
|
||||
char *vendor_class_identifier;
|
||||
char **user_class;
|
||||
uint32_t mtu;
|
||||
uint32_t xid;
|
||||
usec_t start_time;
|
||||
|
@ -445,6 +447,26 @@ int sd_dhcp_client_set_vendor_class_identifier(
|
|||
return free_and_strdup(&client->vendor_class_identifier, vci);
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_user_class(
|
||||
sd_dhcp_client *client,
|
||||
const char* const* user_class) {
|
||||
|
||||
_cleanup_strv_free_ char **s = NULL;
|
||||
char **p;
|
||||
|
||||
STRV_FOREACH(p, (char **) user_class)
|
||||
if (strlen(*p) > 255)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
s = strv_copy((char **) user_class);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
client->user_class = TAKE_PTR(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_client_port(
|
||||
sd_dhcp_client *client,
|
||||
uint16_t port) {
|
||||
|
@ -768,6 +790,15 @@ static int client_send_discover(sd_dhcp_client *client) {
|
|||
return r;
|
||||
}
|
||||
|
||||
if (client->user_class) {
|
||||
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
|
||||
SD_DHCP_OPTION_USER_CLASS,
|
||||
strv_length(client->user_class),
|
||||
client->user_class);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
|
||||
SD_DHCP_OPTION_END, 0, NULL);
|
||||
if (r < 0)
|
||||
|
@ -1923,6 +1954,7 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
|
|||
free(client->req_opts);
|
||||
free(client->hostname);
|
||||
free(client->vendor_class_identifier);
|
||||
client->user_class = strv_free(client->user_class);
|
||||
return mfree(client);
|
||||
}
|
||||
|
||||
|
|
|
@ -223,7 +223,7 @@ int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes) {
|
|||
}
|
||||
|
||||
int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains) {
|
||||
unsigned r;
|
||||
size_t r;
|
||||
|
||||
assert_return(lease, -EINVAL);
|
||||
assert_return(domains, -EINVAL);
|
||||
|
@ -669,7 +669,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!timezone_is_valid(tz)) {
|
||||
if (!timezone_is_valid(tz, LOG_DEBUG)) {
|
||||
log_debug_errno(r, "Timezone is not valid, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
@ -1195,13 +1195,13 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
|
|||
}
|
||||
|
||||
if (client_id_hex) {
|
||||
r = deserialize_dhcp_option(&lease->client_id, &lease->client_id_len, client_id_hex);
|
||||
r = unhexmem(client_id_hex, (size_t) -1, &lease->client_id, &lease->client_id_len);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse client ID %s, ignoring: %m", client_id_hex);
|
||||
}
|
||||
|
||||
if (vendor_specific_hex) {
|
||||
r = deserialize_dhcp_option(&lease->vendor_specific, &lease->vendor_specific_len, vendor_specific_hex);
|
||||
r = unhexmem(vendor_specific_hex, (size_t) -1, &lease->vendor_specific, &lease->vendor_specific_len);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex);
|
||||
}
|
||||
|
@ -1213,7 +1213,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
|
|||
if (!options[i])
|
||||
continue;
|
||||
|
||||
r = deserialize_dhcp_option(&data, &len, options[i]);
|
||||
r = unhexmem(options[i], (size_t) -1, &data, &len);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to parse private DHCP option %s, ignoring: %m", options[i]);
|
||||
continue;
|
||||
|
|
|
@ -250,8 +250,7 @@ int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
|
|||
if (r < 0)
|
||||
return 0;
|
||||
|
||||
strv_free(lease->domains);
|
||||
lease->domains = domains;
|
||||
strv_free_and_replace(lease->domains, domains);
|
||||
lease->domains_count = r;
|
||||
|
||||
return r;
|
||||
|
@ -310,8 +309,7 @@ int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
|
|||
if (r < 0)
|
||||
return 0;
|
||||
|
||||
lease->ntp_fqdn = strv_free(lease->ntp_fqdn);
|
||||
lease->ntp_fqdn = servers;
|
||||
strv_free_and_replace(lease->ntp_fqdn, servers);
|
||||
lease->ntp_fqdn_count = r;
|
||||
|
||||
break;
|
||||
|
|
|
@ -404,15 +404,15 @@ static int neighbor_compare_func(const void *a, const void *b) {
|
|||
|
||||
static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||
sd_lldp *lldp = userdata;
|
||||
int r, q;
|
||||
int r;
|
||||
|
||||
r = lldp_make_space(lldp, 0);
|
||||
if (r < 0)
|
||||
return log_lldp_errno(r, "Failed to make space: %m");
|
||||
|
||||
q = lldp_start_timer(lldp, NULL);
|
||||
if (q < 0)
|
||||
return log_lldp_errno(q, "Failed to restart timer: %m");
|
||||
r = lldp_start_timer(lldp, NULL);
|
||||
if (r < 0)
|
||||
return log_lldp_errno(r, "Failed to restart timer: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -82,6 +82,7 @@ enum {
|
|||
SD_DHCP_OPTION_REBINDING_T2_TIME = 59,
|
||||
SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60,
|
||||
SD_DHCP_OPTION_CLIENT_IDENTIFIER = 61,
|
||||
SD_DHCP_OPTION_USER_CLASS = 77,
|
||||
SD_DHCP_OPTION_FQDN = 81,
|
||||
SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100,
|
||||
SD_DHCP_OPTION_NEW_TZDB_TIMEZONE = 101,
|
||||
|
@ -154,6 +155,9 @@ int sd_dhcp_client_set_hostname(
|
|||
int sd_dhcp_client_set_vendor_class_identifier(
|
||||
sd_dhcp_client *client,
|
||||
const char *vci);
|
||||
int sd_dhcp_client_set_user_class(
|
||||
sd_dhcp_client *client,
|
||||
const char* const *user_class);
|
||||
int sd_dhcp_client_get_lease(
|
||||
sd_dhcp_client *client,
|
||||
sd_dhcp_lease **ret);
|
||||
|
|
Loading…
Reference in a new issue