#include <sched.h>
#include <sys/resource.h>
#include <linux/sched.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
#include "macro.h"
#include "util.h"
#include "ioprio.h"
#include "missing.h"
+#include "log.h"
+#include "strv.h"
-usec_t now(clockid_t clock) {
+bool streq_ptr(const char *a, const char *b) {
+
+ /* 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);
}
}
/* 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;
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;
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;
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);
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;
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);
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;
return -errno;
}
- return 0;
+ return 0;
}
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;
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";
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;
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);
}
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() */
}
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;
}
}
-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[] = {