X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=util.c;h=f3161bd7f3e888b4a4b34e8ded2b1a4fde652f13;hb=4fc935cad4026516035e16484fd359c778ec0acb;hp=6ed87a76262827cbb0e74cfbe370cb3736ae003e;hpb=ea4309869e75497ba6a97c540646cb66a157a4d9;p=elogind.git
diff --git a/util.c b/util.c
index 6ed87a762..f3161bd7f 100644
--- a/util.c
+++ b/util.c
@@ -1,5 +1,24 @@
/*-*- Mode: C; c-basic-offset: 8 -*-*/
+/***
+ 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 General Public License as published by
+ the Free Software Foundation; either version 2 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with systemd; If not, see .
+***/
+
#include
#include
#include
@@ -10,16 +29,36 @@
#include
#include
#include
+#include
+#include
+#include
+#include
+#include
#include "macro.h"
#include "util.h"
#include "ioprio.h"
#include "missing.h"
+#include "log.h"
+#include "strv.h"
+
+bool streq_ptr(const char *a, const char *b) {
-usec_t now(clockid_t clock) {
+ /* Like streq(), but tries to make sense of NULL pointers */
+
+ if (a && b)
+ return streq(a, b);
+
+ if (!a && !b)
+ return true;
+
+ return false;
+}
+
+usec_t now(clockid_t clock_id) {
struct timespec ts;
- assert_se(clock_gettime(clock, &ts) == 0);
+ assert_se(clock_gettime(clock_id, &ts) == 0);
return timespec_load(&ts);
}
@@ -249,7 +288,7 @@ int safe_atolli(const char *s, long long int *ret_lli) {
}
/* Split a string into words. */
-char *split_spaces(const char *c, size_t *l, char **state) {
+char *split(const char *c, size_t *l, const char *separator, char **state) {
char *current;
current = *state ? *state : (char*) c;
@@ -257,8 +296,8 @@ char *split_spaces(const char *c, size_t *l, char **state) {
if (!*current || *c == 0)
return NULL;
- current += strspn(current, WHITESPACE);
- *l = strcspn(current, WHITESPACE);
+ current += strspn(current, separator);
+ *l = strcspn(current, separator);
*state = current+*l;
return (char*) current;
@@ -301,6 +340,21 @@ char *split_quoted(const char *c, size_t *l, char **state) {
return (char*) current;
}
+char **split_path_and_make_absolute(const char *p) {
+ char **l;
+ assert(p);
+
+ if (!(l = strv_split(p, ":")))
+ return NULL;
+
+ if (!strv_path_make_absolute_cwd(l)) {
+ strv_free(l);
+ return NULL;
+ }
+
+ return l;
+}
+
int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
int r;
FILE *f;
@@ -371,7 +425,7 @@ finish:
int read_one_line_file(const char *fn, char **line) {
FILE *f;
int r;
- char t[64], *c;
+ char t[2048], *c;
assert(fn);
assert(line);
@@ -397,6 +451,33 @@ finish:
return r;
}
+char *truncate_nl(char *s) {
+ assert(s);
+
+ s[strcspn(s, NEWLINE)] = 0;
+ return s;
+}
+
+int get_process_name(pid_t pid, char **name) {
+ char *p;
+ int r;
+
+ assert(pid >= 1);
+ assert(name);
+
+ if (asprintf(&p, "/proc/%llu/comm", (unsigned long long) pid) < 0)
+ return -ENOMEM;
+
+ r = read_one_line_file(p, name);
+ free(p);
+
+ if (r < 0)
+ return r;
+
+ truncate_nl(*name);
+ return 0;
+}
+
char *strappend(const char *s, const char *suffix) {
size_t a, b;
char *r;
@@ -474,6 +555,9 @@ char *path_make_absolute(const char *p, const char *prefix) {
assert(p);
+ /* Makes every item in the list an absolute path by prepending
+ * the prefix, if specified and necessary */
+
if (path_is_absolute(p) || !prefix)
return strdup(p);
@@ -483,6 +567,46 @@ char *path_make_absolute(const char *p, const char *prefix) {
return r;
}
+char *path_make_absolute_cwd(const char *p) {
+ char *cwd, *r;
+
+ assert(p);
+
+ /* Similar to path_make_absolute(), but prefixes with the
+ * current working directory. */
+
+ if (path_is_absolute(p))
+ return strdup(p);
+
+ if (!(cwd = get_current_dir_name()))
+ return NULL;
+
+ r = path_make_absolute(p, cwd);
+ free(cwd);
+
+ return r;
+}
+
+char **strv_path_make_absolute_cwd(char **l) {
+ char **s;
+
+ /* Goes through every item in the string list and makes it
+ * absolute. This works in place and won't rollback any
+ * changes on failure. */
+
+ STRV_FOREACH(s, l) {
+ char *t;
+
+ if (!(t = path_make_absolute_cwd(*s)))
+ return NULL;
+
+ free(*s);
+ *s = t;
+ }
+
+ return l;
+}
+
int reset_all_signal_handlers(void) {
int sig;
@@ -503,7 +627,7 @@ int reset_all_signal_handlers(void) {
return -errno;
}
- return 0;
+ return 0;
}
char *strstrip(char *s) {
@@ -527,6 +651,23 @@ char *strstrip(char *s) {
}
+char *delete_chars(char *s, const char *bad) {
+ char *f, *t;
+
+ /* Drops all whitespace, regardless where in the string */
+
+ for (f = s, t = s; *f; f++) {
+ if (strchr(bad, *f))
+ continue;
+
+ *(t++) = *f;
+ }
+
+ *t = 0;
+
+ return s;
+}
+
char *file_in_same_dir(const char *path, const char *filename) {
char *e, *r;
size_t k;
@@ -554,6 +695,53 @@ char *file_in_same_dir(const char *path, const char *filename) {
return r;
}
+int mkdir_parents(const char *path, mode_t mode) {
+ const char *p, *e;
+
+ assert(path);
+
+ /* Creates every parent directory in the path except the last
+ * component. */
+
+ p = path + strspn(path, "/");
+ for (;;) {
+ int r;
+ char *t;
+
+ e = p + strcspn(p, "/");
+ p = e + strspn(e, "/");
+
+ /* Is this the last component? If so, then we're
+ * done */
+ if (*p == 0)
+ return 0;
+
+ if (!(t = strndup(path, e - path)))
+ return -ENOMEM;
+
+ r = mkdir(t, mode);
+
+ free(t);
+
+ if (r < 0 && errno != EEXIST)
+ return -errno;
+ }
+}
+
+int mkdir_p(const char *path, mode_t mode) {
+ int r;
+
+ /* Like mkdir -p */
+
+ if ((r = mkdir_parents(path, mode)) < 0)
+ return r;
+
+ if (mkdir(path, mode) < 0)
+ return -errno;
+
+ return 0;
+}
+
char hexchar(int x) {
static const char table[16] = "0123456789abcdef";
@@ -586,6 +774,18 @@ int unoctchar(char c) {
return -1;
}
+char decchar(int x) {
+ return '0' + (x % 10);
+}
+
+int undecchar(char c) {
+
+ if (c >= '0' && c <= '9')
+ return c - '0';
+
+ return -1;
+}
+
char *cescape(const char *s) {
char *r, *t;
const char *f;
@@ -788,8 +988,8 @@ char *xescape(const char *s, const char *bad) {
for (f = s, t = r; *f; f++) {
- if (*f < ' ' || *f >= 127 ||
- *f == '\\' || strchr(bad, *f)) {
+ if ((*f < ' ') || (*f >= 127) ||
+ (*f == '\\') || strchr(bad, *f)) {
*(t++) = '\\';
*(t++) = 'x';
*(t++) = hexchar(*f >> 4);
@@ -804,11 +1004,11 @@ char *xescape(const char *s, const char *bad) {
}
char *bus_path_escape(const char *s) {
- assert(s);
-
char *r, *t;
const char *f;
+ assert(s);
+
/* Escapes all chars that D-Bus' object path cannot deal
* with. Can be reverse with bus_path_unescape() */
@@ -833,11 +1033,11 @@ char *bus_path_escape(const char *s) {
}
char *bus_path_unescape(const char *s) {
- assert(s);
-
char *r, *t;
const char *f;
+ assert(s);
+
if (!(r = new(char, strlen(s)+1)))
return NULL;
@@ -931,16 +1131,167 @@ bool path_startswith(const char *path, const char *prefix) {
}
}
-char *ascii_strlower(char *path) {
+char *ascii_strlower(char *t) {
char *p;
- assert(path);
+ assert(t);
- for (p = path; *p; p++)
+ for (p = t; *p; p++)
if (*p >= 'A' && *p <= 'Z')
*p = *p - 'A' + 'a';
- return p;
+ return t;
+}
+
+bool ignore_file(const char *filename) {
+ assert(filename);
+
+ return
+ filename[0] == '.' ||
+ endswith(filename, "~") ||
+ endswith(filename, ".rpmnew") ||
+ endswith(filename, ".rpmsave") ||
+ endswith(filename, ".rpmorig") ||
+ endswith(filename, ".dpkg-old") ||
+ endswith(filename, ".dpkg-new") ||
+ endswith(filename, ".swp");
+}
+
+int fd_nonblock(int fd, bool nonblock) {
+ int flags;
+
+ assert(fd >= 0);
+
+ if ((flags = fcntl(fd, F_GETFL, 0)) < 0)
+ return -errno;
+
+ if (nonblock)
+ flags |= O_NONBLOCK;
+ else
+ flags &= ~O_NONBLOCK;
+
+ if (fcntl(fd, F_SETFL, flags) < 0)
+ return -errno;
+
+ return 0;
+}
+
+int fd_cloexec(int fd, bool cloexec) {
+ int flags;
+
+ assert(fd >= 0);
+
+ if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
+ return -errno;
+
+ if (cloexec)
+ flags |= FD_CLOEXEC;
+ else
+ flags &= ~FD_CLOEXEC;
+
+ if (fcntl(fd, F_SETFD, flags) < 0)
+ return -errno;
+
+ return 0;
+}
+
+int close_all_fds(const int except[], unsigned n_except) {
+ DIR *d;
+ struct dirent *de;
+ int r = 0;
+
+ if (!(d = opendir("/proc/self/fd")))
+ return -errno;
+
+ while ((de = readdir(d))) {
+ int fd = -1;
+
+ if (de->d_name[0] == '.')
+ continue;
+
+ if ((r = safe_atoi(de->d_name, &fd)) < 0)
+ goto finish;
+
+ if (fd < 3)
+ continue;
+
+ if (fd == dirfd(d))
+ continue;
+
+ if (except) {
+ bool found;
+ unsigned i;
+
+ found = false;
+ for (i = 0; i < n_except; i++)
+ if (except[i] == fd) {
+ found = true;
+ break;
+ }
+
+ if (found)
+ continue;
+ }
+
+ if ((r = close_nointr(fd)) < 0) {
+ /* Valgrind has its own FD and doesn't want to have it closed */
+ if (errno != EBADF)
+ goto finish;
+ }
+ }
+
+ r = 0;
+
+finish:
+ closedir(d);
+ return r;
+}
+
+bool chars_intersect(const char *a, const char *b) {
+ const char *p;
+
+ /* Returns true if any of the chars in a are in b. */
+ for (p = a; *p; p++)
+ if (strchr(b, *p))
+ return true;
+
+ return false;
+}
+
+char *format_timestamp(char *buf, size_t l, usec_t t) {
+ struct tm tm;
+ time_t sec;
+
+ assert(buf);
+ assert(l > 0);
+
+ if (t <= 0)
+ return NULL;
+
+ sec = (time_t) t / USEC_PER_SEC;
+
+ if (strftime(buf, l, "%a, %d %b %Y %H:%M:%S %z", localtime_r(&sec, &tm)) <= 0)
+ return NULL;
+
+ return buf;
+}
+
+bool fstype_is_network(const char *fstype) {
+ static const char * const table[] = {
+ "cifs",
+ "smbfs",
+ "ncpfs",
+ "nfs",
+ "nfs4"
+ };
+
+ unsigned i;
+
+ for (i = 0; i < ELEMENTSOF(table); i++)
+ if (streq(table[i], fstype))
+ return true;
+
+ return false;
}
static const char *const ioprio_class_table[] = {