#include <langinfo.h>
#include <locale.h>
#include <libgen.h>
+#undef basename
#include "macro.h"
#include "util.h"
/* Split a string into words, but consider strings enclosed in '' and
* "" as words even if they include spaces. */
char *split_quoted(const char *c, size_t *l, char **state) {
- char *current, *e;
+ const char *current, *e;
bool escaped = false;
- current = *state ? *state : (char*) c;
+ assert(c);
+ assert(l);
+ assert(state);
- if (!*current || *c == 0)
- return NULL;
+ current = *state ? *state : c;
current += strspn(current, WHITESPACE);
- if (*current == '\'') {
+ if (*current == 0)
+ return NULL;
+
+ else if (*current == '\'') {
current ++;
for (e = current; *e; e++) {
}
*l = e-current;
- *state = *e == 0 ? e : e+1;
+ *state = (char*) (*e == 0 ? e : e+1);
+
} else if (*current == '\"') {
current ++;
}
*l = e-current;
- *state = *e == 0 ? e : e+1;
+ *state = (char*) (*e == 0 ? e : e+1);
+
} else {
for (e = current; *e; e++) {
if (escaped)
break;
}
*l = e-current;
- *state = e;
+ *state = (char*) e;
}
return (char*) current;
f = fopen(p, "re");
if (!f)
- return -errno;
+ return errno == ENOENT ? -ESRCH : -errno;
if (!fgets(line, sizeof(line), f)) {
if (ferror(f))
int get_process_comm(pid_t pid, char **name) {
const char *p;
+ int r;
assert(name);
assert(pid >= 0);
else
p = procfs_file_alloca(pid, "comm");
- return read_one_line_file(p, name);
+ r = read_one_line_file(p, name);
+ if (r == -ENOENT)
+ return -ESRCH;
+
+ return r;
}
int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
r = readlink_malloc(p, name);
if (r < 0)
- return r;
+ return r == -ENOENT ? -ESRCH : r;
d = endswith(*name, " (deleted)");
if (d)
return r;
}
-char *bus_path_escape(const char *s) {
- char *r, *t;
- const char *f;
-
- assert(s);
-
- /* Escapes all chars that D-Bus' object path cannot deal
- * with. Can be reversed with bus_path_unescape(). We special
- * case the empty string. */
-
- if (*s == 0)
- return strdup("_");
-
- r = new(char, strlen(s)*3 + 1);
- if (!r)
- return NULL;
-
- for (f = s, t = r; *f; f++) {
-
- /* Escape everything that is not a-zA-Z0-9. We also
- * escape 0-9 if it's the first character */
-
- if (!(*f >= 'A' && *f <= 'Z') &&
- !(*f >= 'a' && *f <= 'z') &&
- !(f > s && *f >= '0' && *f <= '9')) {
- *(t++) = '_';
- *(t++) = hexchar(*f >> 4);
- *(t++) = hexchar(*f);
- } else
- *(t++) = *f;
- }
-
- *t = 0;
-
- return r;
-}
-
-char *bus_path_unescape(const char *f) {
- char *r, *t;
-
- assert(f);
-
- /* Special case for the empty string */
- if (streq(f, "_"))
- return strdup("");
-
- r = new(char, strlen(f) + 1);
- if (!r)
- return NULL;
-
- for (t = r; *f; f++) {
-
- if (*f == '_') {
- int a, b;
-
- if ((a = unhexchar(f[1])) < 0 ||
- (b = unhexchar(f[2])) < 0) {
- /* Invalid escape code, let's take it literal then */
- *(t++) = '_';
- } else {
- *(t++) = (char) ((a << 4) | b);
- f += 2;
- }
- } else
- *(t++) = *f;
- }
-
- *t = 0;
-
- return r;
-}
-
char *ascii_strlower(char *t) {
char *p;
assert(r);
k = ttyname_r(fd, path, sizeof(path));
- if (k != 0)
+ if (k > 0)
return -k;
char_array_0(path);
char line[LINE_MAX], *p;
unsigned long ttynr;
const char *fn;
- int k;
assert(pid >= 0);
- assert(d);
if (pid == 0)
fn = "/proc/self/stat";
if (!f)
return -errno;
- if (!fgets(line, sizeof(line), f)) {
- k = feof(f) ? -EIO : -errno;
- return k;
- }
+ if (!fgets(line, sizeof(line), f))
+ return feof(f) ? -EIO : -errno;
p = strrchr(line, ')');
if (!p)
if (major(ttynr) == 0 && minor(ttynr) == 0)
return -ENOENT;
- *d = (dev_t) ttynr;
+ if (d)
+ *d = (dev_t) ttynr;
+
return 0;
}
if (!t)
return -ENOMEM;
- fn = path_get_file_name(path);
- k = fn-path;
+ fn = basename(path);
+ k = fn - path;
memcpy(t, path, k);
t[k] = '.';
stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
if (!t)
return -ENOMEM;
- fn = path_get_file_name(to);
+ fn = basename(to);
k = fn-to;
memcpy(t, to, k);
t[k] = '.';
goto out;
}
- if(streq(set, "UTF-8")) {
+ if (streq(set, "UTF-8")) {
cached_answer = true;
goto out;
}
return search_and_fopen_internal(path, mode, s, _f);
}
-int create_tmp_dir(char template[], char** dir_name) {
- int r = 0;
- char *d = NULL, *dt;
-
- assert(dir_name);
-
- RUN_WITH_UMASK(0077) {
- d = mkdtemp(template);
- }
- if (!d) {
- log_error("Can't create directory %s: %m", template);
- return -errno;
- }
-
- dt = strjoin(d, "/tmp", NULL);
- if (!dt) {
- r = log_oom();
- goto fail3;
- }
-
- RUN_WITH_UMASK(0000) {
- r = mkdir(dt, 0777);
- }
- if (r < 0) {
- log_error("Can't create directory %s: %m", dt);
- r = -errno;
- goto fail2;
- }
- log_debug("Created temporary directory %s", dt);
-
- r = chmod(dt, 0777 | S_ISVTX);
- if (r < 0) {
- log_error("Failed to chmod %s: %m", dt);
- r = -errno;
- goto fail1;
- }
- log_debug("Set sticky bit on %s", dt);
-
- *dir_name = dt;
-
- return 0;
-fail1:
- rmdir(dt);
-fail2:
- free(dt);
-fail3:
- rmdir(template);
- return r;
-}
-
char *strextend(char **x, ...) {
va_list ap;
size_t f, l;
size_t a;
void *q;
+ assert(p);
+ assert(allocated);
+
if (*allocated >= need)
return *p;
a = MAX(64u, need * 2);
+
+ /* check for overflows */
+ if (a < need)
+ return NULL;
+
q = realloc(*p, a);
if (!q)
return NULL;
return q;
}
+void* greedy_realloc0(void **p, size_t *allocated, size_t need) {
+ size_t prev;
+ uint8_t *q;
+
+ assert(p);
+ assert(allocated);
+
+ prev = *allocated;
+
+ q = greedy_realloc(p, allocated, need);
+ if (!q)
+ return NULL;
+
+ if (*allocated > prev)
+ memset(&q[prev], 0, *allocated - prev);
+
+ return q;
+}
+
bool id128_is_valid(const char *s) {
size_t i, l;
return 1;
FOREACH_WORD_QUOTED(w, l, line, state)
- if (l == 23 && memcmp(w, "systemd.restore_state=0", 23))
+ if (l == 23 && strneq(w, "systemd.restore_state=0", 23))
return 0;
return 1;
return 1;
}
+
+int container_get_leader(const char *machine, pid_t *pid) {
+ _cleanup_free_ char *s = NULL, *class = NULL;
+ const char *p;
+ pid_t leader;
+ int r;
+
+ assert(machine);
+ assert(pid);
+
+ p = strappenda("/run/systemd/machines/", machine);
+ r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
+ if (r == -ENOENT)
+ return -EHOSTDOWN;
+ if (r < 0)
+ return r;
+ if (!s)
+ return -EIO;
+
+ if (!streq_ptr(class, "container"))
+ return -EIO;
+
+ r = parse_pid(s, &leader);
+ if (r < 0)
+ return r;
+ if (leader <= 1)
+ return -EIO;
+
+ *pid = leader;
+ return 0;
+}
+
+int namespace_open(pid_t pid, int *namespace_fd, int *root_fd) {
+ _cleanup_close_ int nsfd = -1;
+ const char *ns, *root;
+ int rfd;
+
+ assert(pid >= 0);
+ assert(namespace_fd);
+ assert(root_fd);
+
+ ns = procfs_file_alloca(pid, "ns/mnt");
+ nsfd = open(ns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
+ if (nsfd < 0)
+ return -errno;
+
+ root = procfs_file_alloca(pid, "root");
+ rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
+ if (rfd < 0)
+ return -errno;
+
+ *namespace_fd = nsfd;
+ *root_fd = rfd;
+ nsfd = -1;
+
+ return 0;
+}
+
+int namespace_enter(int namespace_fd, int root_fd) {
+ assert(namespace_fd >= 0);
+ assert(root_fd >= 0);
+
+ if (setns(namespace_fd, CLONE_NEWNS) < 0)
+ return -errno;
+
+ if (fchdir(root_fd) < 0)
+ return -errno;
+
+ if (chroot(".") < 0)
+ return -errno;
+
+ if (setresgid(0, 0, 0) < 0)
+ return -errno;
+
+ if (setresuid(0, 0, 0) < 0)
+ return -errno;
+
+ return 0;
+}