util.c revision 3b63d2d31d0850bd7a81ab9b468218d2c4c461e8
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen This file is part of systemd.
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen Copyright 2010 Lennart Poettering
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen systemd is free software; you can redistribute it and/or modify it
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen under the terms of the GNU General Public License as published by
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen the Free Software Foundation; either version 2 of the License, or
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen (at your option) any later version.
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen systemd is distributed in the hope that it will be useful, but
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen WITHOUT ANY WARRANTY; without even the implied warranty of
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen General Public License for more details.
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen You should have received a copy of the GNU General Public License
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen along with systemd; If not, see <http://www.gnu.org/licenses/>.
6656aefb42385b468dd96867118d049f945cbf81WaLyong Chobool streq_ptr(const char *a, const char *b) {
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen /* Like streq(), but tries to make sense of NULL pointers */
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen if (!a && !b)
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen return false;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmekdual_timestamp* dual_timestamp_get(dual_timestamp *ts) {
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poetteringusec_t timespec_load(const struct timespec *ts) {
6656aefb42385b468dd96867118d049f945cbf81WaLyong Chostruct timespec *timespec_store(struct timespec *ts, usec_t u) {
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Chostruct timeval *timeval_store(struct timeval *tv, usec_t u) {
6656aefb42385b468dd96867118d049f945cbf81WaLyong Chobool endswith(const char *s, const char *postfix) {
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return true;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return false;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Chobool startswith(const char *s, const char *prefix) {
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return true;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return false;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Chobool startswith_no_case(const char *s, const char *prefix) {
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return true;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return false;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho for(i = 0; i < pl; ++i) {
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return false;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return true;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmekbool first_word(const char *s, const char *word) {
8a188de9e0ea41509beda12084126d7a75ebe86eWaLyong Cho return true;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek return s[wl] == 0 ||
8b197c3a8a57c3f7c231b39e5660856fd9580c80Auke Kok /* like close_nointr() but cannot fail, and guarantees errno
23446f01480e1d6f72a03d71f9c67cbf34ddaf3bMichal Schmidt * is unchanged */
abbacb1defaaecb8d2477685f7bb3fabcf58585bNathaniel Chenvoid close_many(const int fds[], unsigned n_fd) {
abbacb1defaaecb8d2477685f7bb3fabcf58585bNathaniel Chen for (i = 0; i < n_fd; i++)
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmekint parse_boolean(const char *v) {
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek if (streq(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
e49d3c016751c03e544697656e8e596af8a664d7Łukasz Stelmach else if (streq(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
unsigned long ul;
assert(s);
return -ERANGE;
if (pid <= 0)
return -ERANGE;
char *x = NULL;
assert(s);
errno = 0;
l = strtoul(s, &x, 0);
if (!x || *x || errno)
return -ERANGE;
*ret_u = (unsigned) l;
char *x = NULL;
assert(s);
errno = 0;
l = strtol(s, &x, 0);
if (!x || *x || errno)
return -ERANGE;
*ret_i = (int) l;
char *x = NULL;
assert(s);
errno = 0;
l = strtoull(s, &x, 0);
if (!x || *x || errno)
*ret_llu = l;
char *x = NULL;
assert(s);
errno = 0;
l = strtoll(s, &x, 0);
if (!x || *x || errno)
*ret_lli = l;
char *current;
if (!*current || *c == 0)
return NULL;
return (char*) current;
char *current, *e;
bool escaped = false;
if (!*current || *c == 0)
return NULL;
current ++;
for (e = current; *e; e++) {
if (escaped)
escaped = false;
escaped = true;
*l = e-current;
current ++;
for (e = current; *e; e++) {
if (escaped)
escaped = false;
escaped = true;
*l = e-current;
for (e = current; *e; e++) {
if (escaped)
escaped = false;
escaped = true;
*l = e-current;
*state = e;
return (char*) current;
char **split_path_and_make_absolute(const char *p) {
assert(p);
return NULL;
if (!strv_path_make_absolute_cwd(l)) {
strv_free(l);
return NULL;
FILE *f;
long unsigned ppid;
assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
return -errno;
r = -errno;
fclose(f);
fclose(f);
return -EIO;
return -EIO;
return -ERANGE;
FILE *f;
return -errno;
r = -errno;
goto finish;
fclose(f);
FILE *f;
char t[LINE_MAX], *c;
return -errno;
if (!(fgets(t, sizeof(t), f))) {
r = -errno;
goto finish;
if (!(c = strdup(t))) {
r = -ENOMEM;
goto finish;
*line = c;
fclose(f);
FILE *f;
size_t n, l;
return -errno;
r = -errno;
goto finish;
size_t k;
r = -ENOMEM;
goto finish;
buf = t;
if (ferror(f)) {
r = -errno;
goto finish;
r = -E2BIG;
goto finish;
if (buf)
buf[l] = 0;
r = -errno;
goto finish;
fclose(f);
int parse_env_file(
const char *fname,
const char *separator, ...) {
char *contents, *p;
p = contents;
char **value;
size_t n;
v = strndup(p, n);
r = -ENOMEM;
goto fail;
free(v);
v = NULL;
*value = v;
if (!key)
fail:
char *truncate_nl(char *s) {
assert(s);
return -ENOMEM;
free(p);
bool space = false;
FILE *f;
return -ENOMEM;
free(p);
return -errno;
fclose(f);
return -ENOMEM;
if (isprint(c)) {
if (space) {
left--;
space = false;
left--;
space = true;
fclose(f);
free(r);
free(t);
return -ENOMEM;
*line = r;
size_t a;
if (!s && !suffix)
if (!suffix)
return strdup(s);
assert(s);
a = strlen(s);
return NULL;
memcpy(r, s, a);
int readlink_malloc(const char *p, char **r) {
assert(p);
assert(r);
ssize_t n;
if (!(c = new(char, l)))
return -ENOMEM;
free(c);
return ret;
free(c);
int readlink_and_make_absolute(const char *p, char **r) {
char *target, *k;
assert(p);
assert(r);
return -ENOMEM;
bool slash = false;
if (!*path)
return -EINVAL;
for (e = path; *e; e++) {
slash = true;
slash = false;
return -EINVAL;
if (p == path)
return -ENOMEM;
*_r = r;
char *file_name_from_path(const char *p) {
assert(p);
bool path_is_absolute(const char *p) {
assert(p);
bool is_path(const char *p) {
assert(p);
return strdup(p);
return NULL;
char *path_make_absolute_cwd(const char *p) {
char *cwd, *r;
assert(p);
if (path_is_absolute(p))
return strdup(p);
return NULL;
char **strv_path_make_absolute_cwd(char **l) {
STRV_FOREACH(s, l) {
if (!(t = path_make_absolute_cwd(*s)))
return NULL;
free(*s);
char **strv_path_canonicalize(char **l) {
bool enomem = false;
if (strv_isempty(l))
STRV_FOREACH(s, l) {
t = path_make_absolute_cwd(*s);
free(*s);
enomem = true;
errno = 0;
u = canonicalize_file_name(t);
free(t);
enomem = true;
l[k] = NULL;
if (enomem)
return NULL;
int reset_all_signal_handlers(void) {
int sig;
return -errno;
char *strstrip(char *s) {
char *e, *l = NULL;
size_t k;
return NULL;
return -errno;
return -errno;
return -errno;
return -ENOMEM;
free(t);
return -errno;
return -errno;
size_t l;
return -ENOMEM;
free(t);
r = rmdir(t);
free(t);
return -errno;
char hexchar(int x) {
int unhexchar(char c) {
char octchar(int x) {
int unoctchar(char c) {
char decchar(int x) {
int undecchar(char c) {
char *cescape(const char *s) {
assert(s);
return NULL;
*(t++) = octchar((unsigned char) *f);
assert(s);
for (f = s, t = r; f < s + length; f++) {
if ((a = unoctchar(f[0])) < 0 ||
goto finish;
char *cunescape(const char *s) {
return NULL;
*(t++) = hexchar(*f);
char *bus_path_escape(const char *s) {
assert(s);
return NULL;
*(t++) = hexchar(*f);
char *bus_path_unescape(const char *f) {
assert(f);
if (!(r = strdup(f)))
return NULL;
bool slash = false;
slash = true;
if (slash) {
slash = false;
return path;
size_t a, b;
if (*prefix == 0)
if (*path == 0)
path += a;
prefix += b;
bool path_equal(const char *a, const char *b) {
assert(a);
assert(b);
size_t j, k;
if (memcmp(a, b, j) != 0)
char *ascii_strlower(char *t) {
assert(t);
int flags;
return -errno;
if (nonblock)
return -errno;
int flags;
return -errno;
if (cloexec)
return -errno;
DIR *d;
return -errno;
goto finish;
if (except) {
bool found;
found = false;
for (i = 0; i < n_except; i++)
found = true;
if (found)
goto finish;
closedir(d);
bool chars_intersect(const char *a, const char *b) {
if (strchr(b, *p))
assert(l > 0);
return NULL;
return NULL;
return buf;
usec_t n, d;
return NULL;
if (d >= USEC_PER_YEAR)
(unsigned long long) (d / USEC_PER_YEAR),
else if (d >= USEC_PER_MONTH)
(unsigned long long) (d / USEC_PER_MONTH),
else if (d >= USEC_PER_WEEK)
(unsigned long long) (d / USEC_PER_WEEK),
(unsigned long long) (d / USEC_PER_HOUR));
else if (d >= USEC_PER_HOUR)
(unsigned long long) (d / USEC_PER_HOUR),
(unsigned long long) (d / USEC_PER_MINUTE));
else if (d >= USEC_PER_MINUTE)
(unsigned long long) (d / USEC_PER_MINUTE),
else if (d >= USEC_PER_SEC)
(unsigned long long) (d / USEC_PER_SEC));
else if (d >= USEC_PER_MSEC)
(unsigned long long) (d / USEC_PER_MSEC));
return buf;
const char *suffix;
} table[] = {
char *p = buf;
assert(l > 0);
return NULL;
size_t n;
k = snprintf(p, l, "%s%llu%s", p > buf ? " " : "", (unsigned long long) (t / table[i].usec), table[i].suffix);
return buf;
static const char * const table[] = {
int fd, r = 0;
return -errno;
if (vt < 0) {
return -errno;
r = -errno;
assert(f);
size_t k;
return -EIO;
if (need_nl)
*ret = c;
return -EIO;
return -EBADMSG;
if (need_nl)
*need_nl = false;
bool on_tty;
bool need_nl = true;
if (on_tty)
if (on_tty)
if (r == -EBADMSG) {
if (need_nl)
*ret = c;
long arg;
r = -errno;
goto finish;
r = -errno;
int fd, r;
return -errno;
return -errno;
return -ENOTTY;
return fd;
ssize_t l;
return -errno;
return -errno;
r = -errno;
goto fail;
r = -errno;
goto fail;
if (notify >= 0)
goto fail;
return -errno;
r = -errno;
goto fail;
ssize_t l;
struct inotify_event *e;
r = -errno;
goto fail;
r = -EIO;
goto fail;
l -= step;
if (notify >= 0)
return fd;
fail:
if (fd >= 0)
if (notify >= 0)
int release_terminal(void) {
int r = 0, fd;
return -errno;
r = -errno;
int r = 0, sig;
r = -errno;
r = -errno;
r = -errno;
r = -errno;
r = -errno;
int close_pipe(int p[]) {
assert(p);
a = close_nointr(p[0]);
uint8_t *p;
ssize_t n = 0;
p = buf;
while (nbytes > 0) {
ssize_t k;
return n > 0 ? n : -errno;
return n > 0 ? n : -EIO;
return n > 0 ? n : (k < 0 ? -errno : 0);
nbytes -= k;
const uint8_t *p;
ssize_t n = 0;
p = buf;
while (nbytes > 0) {
ssize_t k;
return n > 0 ? n : -errno;
return n > 0 ? n : -EIO;
return n > 0 ? n : (k < 0 ? -errno : 0);
nbytes -= k;
int path_is_mount_point(const char *t) {
struct stat a, b;
char *parent;
if (lstat(t, &a) < 0) {
return -errno;
return -errno;
const char *suffix;
} table[] = {
usec_t r = 0;
assert(t);
errno = 0;
if (errno != 0)
return -errno;
return -ERANGE;
return -EINVAL;
return -EINVAL;
*usec = r;
return -errno;
return status == 0;
DIR *d;
return -errno;
if (!de) {
closedir(d);
unsigned long long random_ull(void) {
int fd;
ssize_t r;
goto fallback;
if (r != sizeof(ull))
goto fallback;
return ull;
int sig;
char* gethostname_malloc(void) {
struct utsname u;
if (u.nodename[0])
char* getlogname_malloc(void) {
long bufsize;
if (uid == 0)
return NULL;
return name;
return NULL;
return name;
int getttyname_malloc(char **r) {
assert(r);
p = path;
if (!(c = strdup(p)))
return -ENOMEM;
DIR *d;
int ret = 0;
bool is_dir;
if (ret == 0)
ret = -r;
if (!de)
if (is_dir) {
int subdir_fd;
if (ret == 0)
ret = r;
} else if (!only_dirs) {
closedir(d);
return ret;
int fd;
return -errno;
return -errno;
if (delete_root)
r = -errno;
return -errno;
return -errno;
cpu_set_t *r;
if (!(r = CPU_ALLOC(n)))
return NULL;
if (ncpus)
*ncpus = n;
CPU_FREE(r);
return NULL;
char *s = NULL;
goto finish;
goto finish;
free(s);
if (fd >= 0)
void status_welcome(void) {
#if defined(TARGET_FEDORA)
truncate_nl(r);
free(r);
truncate_nl(r);
free(r);
truncate_nl(r);
free(r);
truncate_nl(r);
free(r);
WORD,
char *r = NULL, *k;
for (e = format; *e; e ++) {
switch (state) {
case WORD:
case CURLY:
goto fail;
free(r);
goto fail;
free(r);
case VARIABLE:
if (!(k = strappend(r, t)))
goto fail;
free(r);
goto fail;
free(r);
fail:
free(r);
return NULL;
return NULL;
if (!(m = strv_split_quoted(e))) {
r[k] = NULL;
strv_free(r);
return NULL;
m = NULL;
q = strv_length(m);
r[k] = NULL;
strv_free(r);
strv_free(m);
return NULL;
memcpy(r + k, m, q * sizeof(char*));
free(m);
strv_free(r);
return NULL;
r[k] = NULL;
int columns(void) {
if (parsed_columns > 0)
return parsed_columns;
if (parsed_columns <= 0) {
if (parsed_columns <= 0)
return parsed_columns;
int running_in_chroot(void) {
struct stat a, b;
zero(a);
zero(b);
return -errno;
return -errno;
size_t l, x;
assert(s);
l = strlen(s);
return strdup(s);
memcpy(r, s, x);
int fd;
return -errno;
size_t l;
assert(s);
return strdup(s);
return strdup(s);
return -errno;
return -EPROTO;
return -EPROTO;
return -EPROTO;
void freeze(void) {
pause();
static const char *const ioprio_class_table[] = {
static const char *const sigchld_code_table[] = {
static const char *const log_level_table[] = {
static const char* const sched_policy_table[] = {
static const char* const rlimit_table[] = {
static const char* const ip_tos_table[] = {
static const char *const signal_table[] = {
#ifdef SIGSTKFLT