mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
util-lib: split string parsing related calls from util.[ch] into parse-util.[ch]
This commit is contained in:
@@ -787,6 +787,8 @@ libbasic_la_SOURCES = \
|
||||
src/basic/string-util.h \
|
||||
src/basic/fd-util.c \
|
||||
src/basic/fd-util.h \
|
||||
src/basic/parse-util.c \
|
||||
src/basic/parse-util.h \
|
||||
src/basic/user-util.c \
|
||||
src/basic/user-util.h \
|
||||
src/basic/extract-word.c \
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "hashmap.h"
|
||||
#include "log.h"
|
||||
#include "pager.h"
|
||||
#include "parse-util.h"
|
||||
#include "special.h"
|
||||
#include "strv.h"
|
||||
#include "strxcpyx.h"
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "string-util.h"
|
||||
#include "udev-util.h"
|
||||
#include "util.h"
|
||||
#include "parse-util.h"
|
||||
|
||||
static struct udev_device *find_pci_or_platform_parent(struct udev_device *device) {
|
||||
struct udev_device *parent;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "macro.h"
|
||||
#include "parse-util.h"
|
||||
#include "process-util.h"
|
||||
#include "user-util.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -21,9 +21,10 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "cap-list.h"
|
||||
#include "missing.h"
|
||||
#include "parse-util.h"
|
||||
#include "util.h"
|
||||
|
||||
static const struct capability_name* lookup_capability(register const char *str, register unsigned int len);
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "fileio.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "parse-util.h"
|
||||
#include "util.h"
|
||||
|
||||
int have_effective_cap(int value) {
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "login-util.h"
|
||||
#include "macro.h"
|
||||
#include "mkdir.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "set.h"
|
||||
|
||||
@@ -20,9 +20,10 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "extract-word.h"
|
||||
#include "util.h"
|
||||
#include "cpu-set-util.h"
|
||||
#include "extract-word.h"
|
||||
#include "parse-util.h"
|
||||
#include "util.h"
|
||||
|
||||
cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
|
||||
cpu_set_t *c;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
***/
|
||||
|
||||
#include "fd-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "util.h"
|
||||
|
||||
int close_nointr(int fd) {
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "fd-util.h"
|
||||
#include "fdset.h"
|
||||
#include "macro.h"
|
||||
#include "parse-util.h"
|
||||
#include "set.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "string-util.h"
|
||||
#include "terminal-util.h"
|
||||
#include "util.h"
|
||||
#include "parse-util.h"
|
||||
|
||||
#define SNDBUF_SIZE (8*1024*1024)
|
||||
|
||||
|
||||
408
src/basic/parse-util.c
Normal file
408
src/basic/parse-util.c
Normal file
@@ -0,0 +1,408 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2010 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "parse-util.h"
|
||||
#include "string-util.h"
|
||||
#include "util.h"
|
||||
|
||||
int parse_boolean(const char *v) {
|
||||
assert(v);
|
||||
|
||||
if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
|
||||
return 1;
|
||||
else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
|
||||
return 0;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int parse_pid(const char *s, pid_t* ret_pid) {
|
||||
unsigned long ul = 0;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(ret_pid);
|
||||
|
||||
r = safe_atolu(s, &ul);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
pid = (pid_t) ul;
|
||||
|
||||
if ((unsigned long) pid != ul)
|
||||
return -ERANGE;
|
||||
|
||||
if (pid <= 0)
|
||||
return -ERANGE;
|
||||
|
||||
*ret_pid = pid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_mode(const char *s, mode_t *ret) {
|
||||
char *x;
|
||||
long l;
|
||||
|
||||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
errno = 0;
|
||||
l = strtol(s, &x, 8);
|
||||
if (errno != 0)
|
||||
return -errno;
|
||||
|
||||
if (!x || x == s || *x)
|
||||
return -EINVAL;
|
||||
if (l < 0 || l > 07777)
|
||||
return -ERANGE;
|
||||
|
||||
*ret = (mode_t) l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_size(const char *t, uint64_t base, uint64_t *size) {
|
||||
|
||||
/* Soo, sometimes we want to parse IEC binary suffixes, and
|
||||
* sometimes SI decimal suffixes. This function can parse
|
||||
* both. Which one is the right way depends on the
|
||||
* context. Wikipedia suggests that SI is customary for
|
||||
* hardware metrics and network speeds, while IEC is
|
||||
* customary for most data sizes used by software and volatile
|
||||
* (RAM) memory. Hence be careful which one you pick!
|
||||
*
|
||||
* In either case we use just K, M, G as suffix, and not Ki,
|
||||
* Mi, Gi or so (as IEC would suggest). That's because that's
|
||||
* frickin' ugly. But this means you really need to make sure
|
||||
* to document which base you are parsing when you use this
|
||||
* call. */
|
||||
|
||||
struct table {
|
||||
const char *suffix;
|
||||
unsigned long long factor;
|
||||
};
|
||||
|
||||
static const struct table iec[] = {
|
||||
{ "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
|
||||
{ "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
|
||||
{ "T", 1024ULL*1024ULL*1024ULL*1024ULL },
|
||||
{ "G", 1024ULL*1024ULL*1024ULL },
|
||||
{ "M", 1024ULL*1024ULL },
|
||||
{ "K", 1024ULL },
|
||||
{ "B", 1ULL },
|
||||
{ "", 1ULL },
|
||||
};
|
||||
|
||||
static const struct table si[] = {
|
||||
{ "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
|
||||
{ "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
|
||||
{ "T", 1000ULL*1000ULL*1000ULL*1000ULL },
|
||||
{ "G", 1000ULL*1000ULL*1000ULL },
|
||||
{ "M", 1000ULL*1000ULL },
|
||||
{ "K", 1000ULL },
|
||||
{ "B", 1ULL },
|
||||
{ "", 1ULL },
|
||||
};
|
||||
|
||||
const struct table *table;
|
||||
const char *p;
|
||||
unsigned long long r = 0;
|
||||
unsigned n_entries, start_pos = 0;
|
||||
|
||||
assert(t);
|
||||
assert(base == 1000 || base == 1024);
|
||||
assert(size);
|
||||
|
||||
if (base == 1000) {
|
||||
table = si;
|
||||
n_entries = ELEMENTSOF(si);
|
||||
} else {
|
||||
table = iec;
|
||||
n_entries = ELEMENTSOF(iec);
|
||||
}
|
||||
|
||||
p = t;
|
||||
do {
|
||||
unsigned long long l, tmp;
|
||||
double frac = 0;
|
||||
char *e;
|
||||
unsigned i;
|
||||
|
||||
p += strspn(p, WHITESPACE);
|
||||
if (*p == '-')
|
||||
return -ERANGE;
|
||||
|
||||
errno = 0;
|
||||
l = strtoull(p, &e, 10);
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
if (e == p)
|
||||
return -EINVAL;
|
||||
|
||||
if (*e == '.') {
|
||||
e++;
|
||||
|
||||
/* strtoull() itself would accept space/+/- */
|
||||
if (*e >= '0' && *e <= '9') {
|
||||
unsigned long long l2;
|
||||
char *e2;
|
||||
|
||||
l2 = strtoull(e, &e2, 10);
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
|
||||
/* Ignore failure. E.g. 10.M is valid */
|
||||
frac = l2;
|
||||
for (; e < e2; e++)
|
||||
frac /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
e += strspn(e, WHITESPACE);
|
||||
|
||||
for (i = start_pos; i < n_entries; i++)
|
||||
if (startswith(e, table[i].suffix))
|
||||
break;
|
||||
|
||||
if (i >= n_entries)
|
||||
return -EINVAL;
|
||||
|
||||
if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
|
||||
return -ERANGE;
|
||||
|
||||
tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
|
||||
if (tmp > ULLONG_MAX - r)
|
||||
return -ERANGE;
|
||||
|
||||
r += tmp;
|
||||
if ((unsigned long long) (uint64_t) r != r)
|
||||
return -ERANGE;
|
||||
|
||||
p = e + strlen(table[i].suffix);
|
||||
|
||||
start_pos = i + 1;
|
||||
|
||||
} while (*p);
|
||||
|
||||
*size = r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *format_bytes(char *buf, size_t l, uint64_t t) {
|
||||
unsigned i;
|
||||
|
||||
/* This only does IEC units so far */
|
||||
|
||||
static const struct {
|
||||
const char *suffix;
|
||||
uint64_t factor;
|
||||
} table[] = {
|
||||
{ "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
|
||||
{ "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
|
||||
{ "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
|
||||
{ "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
|
||||
{ "M", UINT64_C(1024)*UINT64_C(1024) },
|
||||
{ "K", UINT64_C(1024) },
|
||||
};
|
||||
|
||||
if (t == (uint64_t) -1)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(table); i++) {
|
||||
|
||||
if (t >= table[i].factor) {
|
||||
snprintf(buf, l,
|
||||
"%" PRIu64 ".%" PRIu64 "%s",
|
||||
t / table[i].factor,
|
||||
((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10),
|
||||
table[i].suffix);
|
||||
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(buf, l, "%" PRIu64 "B", t);
|
||||
|
||||
finish:
|
||||
buf[l-1] = 0;
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
int safe_atou(const char *s, unsigned *ret_u) {
|
||||
char *x = NULL;
|
||||
unsigned long l;
|
||||
|
||||
assert(s);
|
||||
assert(ret_u);
|
||||
|
||||
errno = 0;
|
||||
l = strtoul(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
|
||||
if ((unsigned long) (unsigned) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
*ret_u = (unsigned) l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int safe_atoi(const char *s, int *ret_i) {
|
||||
char *x = NULL;
|
||||
long l;
|
||||
|
||||
assert(s);
|
||||
assert(ret_i);
|
||||
|
||||
errno = 0;
|
||||
l = strtol(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
|
||||
if ((long) (int) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
*ret_i = (int) l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int safe_atollu(const char *s, long long unsigned *ret_llu) {
|
||||
char *x = NULL;
|
||||
unsigned long long l;
|
||||
|
||||
assert(s);
|
||||
assert(ret_llu);
|
||||
|
||||
errno = 0;
|
||||
l = strtoull(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno ? -errno : -EINVAL;
|
||||
|
||||
*ret_llu = l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int safe_atolli(const char *s, long long int *ret_lli) {
|
||||
char *x = NULL;
|
||||
long long l;
|
||||
|
||||
assert(s);
|
||||
assert(ret_lli);
|
||||
|
||||
errno = 0;
|
||||
l = strtoll(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno ? -errno : -EINVAL;
|
||||
|
||||
*ret_lli = l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int safe_atou8(const char *s, uint8_t *ret) {
|
||||
char *x = NULL;
|
||||
unsigned long l;
|
||||
|
||||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
errno = 0;
|
||||
l = strtoul(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
|
||||
if ((unsigned long) (uint8_t) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
*ret = (uint8_t) l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int safe_atou16(const char *s, uint16_t *ret) {
|
||||
char *x = NULL;
|
||||
unsigned long l;
|
||||
|
||||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
errno = 0;
|
||||
l = strtoul(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
|
||||
if ((unsigned long) (uint16_t) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
*ret = (uint16_t) l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int safe_atoi16(const char *s, int16_t *ret) {
|
||||
char *x = NULL;
|
||||
long l;
|
||||
|
||||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
errno = 0;
|
||||
l = strtol(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
|
||||
if ((long) (int16_t) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
*ret = (int16_t) l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int safe_atod(const char *s, double *ret_d) {
|
||||
char *x = NULL;
|
||||
double d = 0;
|
||||
locale_t loc;
|
||||
|
||||
assert(s);
|
||||
assert(ret_d);
|
||||
|
||||
loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
|
||||
if (loc == (locale_t) 0)
|
||||
return -errno;
|
||||
|
||||
errno = 0;
|
||||
d = strtod_l(s, &x, loc);
|
||||
|
||||
if (!x || x == s || *x || errno) {
|
||||
freelocale(loc);
|
||||
return errno ? -errno : -EINVAL;
|
||||
}
|
||||
|
||||
freelocale(loc);
|
||||
*ret_d = (double) d;
|
||||
return 0;
|
||||
}
|
||||
88
src/basic/parse-util.h
Normal file
88
src/basic/parse-util.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2010 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "macro.h"
|
||||
|
||||
int parse_boolean(const char *v) _pure_;
|
||||
int parse_pid(const char *s, pid_t* ret_pid);
|
||||
int parse_mode(const char *s, mode_t *ret);
|
||||
|
||||
int parse_size(const char *t, uint64_t base, uint64_t *size);
|
||||
|
||||
#define FORMAT_BYTES_MAX 8
|
||||
char *format_bytes(char *buf, size_t l, uint64_t t);
|
||||
|
||||
int safe_atou(const char *s, unsigned *ret_u);
|
||||
int safe_atoi(const char *s, int *ret_i);
|
||||
int safe_atollu(const char *s, unsigned long long *ret_u);
|
||||
int safe_atolli(const char *s, long long int *ret_i);
|
||||
|
||||
int safe_atou8(const char *s, uint8_t *ret);
|
||||
|
||||
int safe_atou16(const char *s, uint16_t *ret);
|
||||
int safe_atoi16(const char *s, int16_t *ret);
|
||||
|
||||
static inline int safe_atou32(const char *s, uint32_t *ret_u) {
|
||||
assert_cc(sizeof(uint32_t) == sizeof(unsigned));
|
||||
return safe_atou(s, (unsigned*) ret_u);
|
||||
}
|
||||
|
||||
static inline int safe_atoi32(const char *s, int32_t *ret_i) {
|
||||
assert_cc(sizeof(int32_t) == sizeof(int));
|
||||
return safe_atoi(s, (int*) ret_i);
|
||||
}
|
||||
|
||||
static inline int safe_atou64(const char *s, uint64_t *ret_u) {
|
||||
assert_cc(sizeof(uint64_t) == sizeof(unsigned long long));
|
||||
return safe_atollu(s, (unsigned long long*) ret_u);
|
||||
}
|
||||
|
||||
static inline int safe_atoi64(const char *s, int64_t *ret_i) {
|
||||
assert_cc(sizeof(int64_t) == sizeof(long long int));
|
||||
return safe_atolli(s, (long long int*) ret_i);
|
||||
}
|
||||
|
||||
#if LONG_MAX == INT_MAX
|
||||
static inline int safe_atolu(const char *s, unsigned long *ret_u) {
|
||||
assert_cc(sizeof(unsigned long) == sizeof(unsigned));
|
||||
return safe_atou(s, (unsigned*) ret_u);
|
||||
}
|
||||
static inline int safe_atoli(const char *s, long int *ret_u) {
|
||||
assert_cc(sizeof(long int) == sizeof(int));
|
||||
return safe_atoi(s, (int*) ret_u);
|
||||
}
|
||||
#else
|
||||
static inline int safe_atolu(const char *s, unsigned long *ret_u) {
|
||||
assert_cc(sizeof(unsigned long) == sizeof(unsigned long long));
|
||||
return safe_atollu(s, (unsigned long long*) ret_u);
|
||||
}
|
||||
static inline int safe_atoli(const char *s, long int *ret_u) {
|
||||
assert_cc(sizeof(long int) == sizeof(long long int));
|
||||
return safe_atolli(s, (long long int*) ret_u);
|
||||
}
|
||||
#endif
|
||||
|
||||
int safe_atod(const char *s, double *ret_d);
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "parse-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "string-util.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "signal-util.h"
|
||||
|
||||
int reset_all_signal_handlers(void) {
|
||||
static const struct sigaction sa = {
|
||||
.sa_handler = SIG_DFL,
|
||||
@@ -268,3 +268,7 @@ int signal_from_string_try_harder(const char *s) {
|
||||
|
||||
return signo;
|
||||
}
|
||||
|
||||
void nop_signal_handler(int sig) {
|
||||
/* nothing here */
|
||||
}
|
||||
|
||||
@@ -39,3 +39,5 @@ 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);
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "formats-util.h"
|
||||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "io-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "socket-util.h"
|
||||
|
||||
@@ -22,11 +22,12 @@
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#include "user-util.h"
|
||||
#include "macro.h"
|
||||
#include "util.h"
|
||||
#include "string-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "string-util.h"
|
||||
#include "user-util.h"
|
||||
#include "util.h"
|
||||
|
||||
bool uid_is_valid(uid_t uid) {
|
||||
|
||||
|
||||
388
src/basic/util.c
388
src/basic/util.c
@@ -89,6 +89,7 @@
|
||||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
#include "mkdir.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "random-util.h"
|
||||
@@ -133,201 +134,6 @@ int unlink_noerrno(const char *path) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_boolean(const char *v) {
|
||||
assert(v);
|
||||
|
||||
if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
|
||||
return 1;
|
||||
else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
|
||||
return 0;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int parse_pid(const char *s, pid_t* ret_pid) {
|
||||
unsigned long ul = 0;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(ret_pid);
|
||||
|
||||
r = safe_atolu(s, &ul);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
pid = (pid_t) ul;
|
||||
|
||||
if ((unsigned long) pid != ul)
|
||||
return -ERANGE;
|
||||
|
||||
if (pid <= 0)
|
||||
return -ERANGE;
|
||||
|
||||
*ret_pid = pid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int safe_atou(const char *s, unsigned *ret_u) {
|
||||
char *x = NULL;
|
||||
unsigned long l;
|
||||
|
||||
assert(s);
|
||||
assert(ret_u);
|
||||
|
||||
errno = 0;
|
||||
l = strtoul(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
|
||||
if ((unsigned long) (unsigned) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
*ret_u = (unsigned) l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int safe_atoi(const char *s, int *ret_i) {
|
||||
char *x = NULL;
|
||||
long l;
|
||||
|
||||
assert(s);
|
||||
assert(ret_i);
|
||||
|
||||
errno = 0;
|
||||
l = strtol(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
|
||||
if ((long) (int) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
*ret_i = (int) l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int safe_atou8(const char *s, uint8_t *ret) {
|
||||
char *x = NULL;
|
||||
unsigned long l;
|
||||
|
||||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
errno = 0;
|
||||
l = strtoul(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
|
||||
if ((unsigned long) (uint8_t) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
*ret = (uint8_t) l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int safe_atou16(const char *s, uint16_t *ret) {
|
||||
char *x = NULL;
|
||||
unsigned long l;
|
||||
|
||||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
errno = 0;
|
||||
l = strtoul(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
|
||||
if ((unsigned long) (uint16_t) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
*ret = (uint16_t) l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int safe_atoi16(const char *s, int16_t *ret) {
|
||||
char *x = NULL;
|
||||
long l;
|
||||
|
||||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
errno = 0;
|
||||
l = strtol(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
|
||||
if ((long) (int16_t) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
*ret = (int16_t) l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int safe_atollu(const char *s, long long unsigned *ret_llu) {
|
||||
char *x = NULL;
|
||||
unsigned long long l;
|
||||
|
||||
assert(s);
|
||||
assert(ret_llu);
|
||||
|
||||
errno = 0;
|
||||
l = strtoull(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno ? -errno : -EINVAL;
|
||||
|
||||
*ret_llu = l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int safe_atolli(const char *s, long long int *ret_lli) {
|
||||
char *x = NULL;
|
||||
long long l;
|
||||
|
||||
assert(s);
|
||||
assert(ret_lli);
|
||||
|
||||
errno = 0;
|
||||
l = strtoll(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno ? -errno : -EINVAL;
|
||||
|
||||
*ret_lli = l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int safe_atod(const char *s, double *ret_d) {
|
||||
char *x = NULL;
|
||||
double d = 0;
|
||||
locale_t loc;
|
||||
|
||||
assert(s);
|
||||
assert(ret_d);
|
||||
|
||||
loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
|
||||
if (loc == (locale_t) 0)
|
||||
return -errno;
|
||||
|
||||
errno = 0;
|
||||
d = strtod_l(s, &x, loc);
|
||||
|
||||
if (!x || x == s || *x || errno) {
|
||||
freelocale(loc);
|
||||
return errno ? -errno : -EINVAL;
|
||||
}
|
||||
|
||||
freelocale(loc);
|
||||
*ret_d = (double) d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int fchmod_umask(int fd, mode_t m) {
|
||||
mode_t u;
|
||||
int r;
|
||||
@@ -1195,134 +1001,6 @@ bool fstype_is_network(const char *fstype) {
|
||||
return nulstr_contains(table, fstype);
|
||||
}
|
||||
|
||||
int parse_size(const char *t, uint64_t base, uint64_t *size) {
|
||||
|
||||
/* Soo, sometimes we want to parse IEC binary suffixes, and
|
||||
* sometimes SI decimal suffixes. This function can parse
|
||||
* both. Which one is the right way depends on the
|
||||
* context. Wikipedia suggests that SI is customary for
|
||||
* hardware metrics and network speeds, while IEC is
|
||||
* customary for most data sizes used by software and volatile
|
||||
* (RAM) memory. Hence be careful which one you pick!
|
||||
*
|
||||
* In either case we use just K, M, G as suffix, and not Ki,
|
||||
* Mi, Gi or so (as IEC would suggest). That's because that's
|
||||
* frickin' ugly. But this means you really need to make sure
|
||||
* to document which base you are parsing when you use this
|
||||
* call. */
|
||||
|
||||
struct table {
|
||||
const char *suffix;
|
||||
unsigned long long factor;
|
||||
};
|
||||
|
||||
static const struct table iec[] = {
|
||||
{ "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
|
||||
{ "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
|
||||
{ "T", 1024ULL*1024ULL*1024ULL*1024ULL },
|
||||
{ "G", 1024ULL*1024ULL*1024ULL },
|
||||
{ "M", 1024ULL*1024ULL },
|
||||
{ "K", 1024ULL },
|
||||
{ "B", 1ULL },
|
||||
{ "", 1ULL },
|
||||
};
|
||||
|
||||
static const struct table si[] = {
|
||||
{ "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
|
||||
{ "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
|
||||
{ "T", 1000ULL*1000ULL*1000ULL*1000ULL },
|
||||
{ "G", 1000ULL*1000ULL*1000ULL },
|
||||
{ "M", 1000ULL*1000ULL },
|
||||
{ "K", 1000ULL },
|
||||
{ "B", 1ULL },
|
||||
{ "", 1ULL },
|
||||
};
|
||||
|
||||
const struct table *table;
|
||||
const char *p;
|
||||
unsigned long long r = 0;
|
||||
unsigned n_entries, start_pos = 0;
|
||||
|
||||
assert(t);
|
||||
assert(base == 1000 || base == 1024);
|
||||
assert(size);
|
||||
|
||||
if (base == 1000) {
|
||||
table = si;
|
||||
n_entries = ELEMENTSOF(si);
|
||||
} else {
|
||||
table = iec;
|
||||
n_entries = ELEMENTSOF(iec);
|
||||
}
|
||||
|
||||
p = t;
|
||||
do {
|
||||
unsigned long long l, tmp;
|
||||
double frac = 0;
|
||||
char *e;
|
||||
unsigned i;
|
||||
|
||||
p += strspn(p, WHITESPACE);
|
||||
if (*p == '-')
|
||||
return -ERANGE;
|
||||
|
||||
errno = 0;
|
||||
l = strtoull(p, &e, 10);
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
if (e == p)
|
||||
return -EINVAL;
|
||||
|
||||
if (*e == '.') {
|
||||
e++;
|
||||
|
||||
/* strtoull() itself would accept space/+/- */
|
||||
if (*e >= '0' && *e <= '9') {
|
||||
unsigned long long l2;
|
||||
char *e2;
|
||||
|
||||
l2 = strtoull(e, &e2, 10);
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
|
||||
/* Ignore failure. E.g. 10.M is valid */
|
||||
frac = l2;
|
||||
for (; e < e2; e++)
|
||||
frac /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
e += strspn(e, WHITESPACE);
|
||||
|
||||
for (i = start_pos; i < n_entries; i++)
|
||||
if (startswith(e, table[i].suffix))
|
||||
break;
|
||||
|
||||
if (i >= n_entries)
|
||||
return -EINVAL;
|
||||
|
||||
if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
|
||||
return -ERANGE;
|
||||
|
||||
tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
|
||||
if (tmp > ULLONG_MAX - r)
|
||||
return -ERANGE;
|
||||
|
||||
r += tmp;
|
||||
if ((unsigned long long) (uint64_t) r != r)
|
||||
return -ERANGE;
|
||||
|
||||
p = e + strlen(table[i].suffix);
|
||||
|
||||
start_pos = i + 1;
|
||||
|
||||
} while (*p);
|
||||
|
||||
*size = r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool is_device_path(const char *path) {
|
||||
|
||||
/* Returns true on paths that refer to a device, either in
|
||||
@@ -2300,45 +1978,6 @@ int prot_from_flags(int flags) {
|
||||
}
|
||||
}
|
||||
|
||||
char *format_bytes(char *buf, size_t l, uint64_t t) {
|
||||
unsigned i;
|
||||
|
||||
static const struct {
|
||||
const char *suffix;
|
||||
uint64_t factor;
|
||||
} table[] = {
|
||||
{ "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
|
||||
{ "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
|
||||
{ "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
|
||||
{ "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
|
||||
{ "M", UINT64_C(1024)*UINT64_C(1024) },
|
||||
{ "K", UINT64_C(1024) },
|
||||
};
|
||||
|
||||
if (t == (uint64_t) -1)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(table); i++) {
|
||||
|
||||
if (t >= table[i].factor) {
|
||||
snprintf(buf, l,
|
||||
"%" PRIu64 ".%" PRIu64 "%s",
|
||||
t / table[i].factor,
|
||||
((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10),
|
||||
table[i].suffix);
|
||||
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(buf, l, "%" PRIu64 "B", t);
|
||||
|
||||
finish:
|
||||
buf[l-1] = 0;
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
void* memdup(const void *p, size_t l) {
|
||||
void *r;
|
||||
|
||||
@@ -4111,27 +3750,6 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_mode(const char *s, mode_t *ret) {
|
||||
char *x;
|
||||
long l;
|
||||
|
||||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
errno = 0;
|
||||
l = strtol(s, &x, 8);
|
||||
if (errno != 0)
|
||||
return -errno;
|
||||
|
||||
if (!x || x == s || *x)
|
||||
return -EINVAL;
|
||||
if (l < 0 || l > 07777)
|
||||
return -ERANGE;
|
||||
|
||||
*ret = (mode_t) l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mount_move_root(const char *path) {
|
||||
assert(path);
|
||||
|
||||
@@ -4220,10 +3838,6 @@ int fgetxattr_malloc(int fd, const char *name, char **value) {
|
||||
}
|
||||
}
|
||||
|
||||
void nop_signal_handler(int sig) {
|
||||
/* nothing here */
|
||||
}
|
||||
|
||||
int version(void) {
|
||||
puts(PACKAGE_STRING "\n"
|
||||
SYSTEMD_FEATURES);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user