#include <sys/capability.h>
#include <sys/time.h>
#include <linux/rtc.h>
+#include <glob.h>
#include "macro.h"
#include "util.h"
return 0;
}
+int parse_uid(const char *s, uid_t* ret_uid) {
+ unsigned long ul = 0;
+ uid_t uid;
+ int r;
+
+ assert(s);
+ assert(ret_uid);
+
+ if ((r = safe_atolu(s, &ul)) < 0)
+ return r;
+
+ uid = (uid_t) ul;
+
+ if ((unsigned long) uid != ul)
+ return -ERANGE;
+
+ *ret_uid = uid;
+ return 0;
+}
+
int safe_atou(const char *s, unsigned *ret_u) {
char *x = NULL;
unsigned long l;
assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
char_array_0(fn);
- if (!(f = fopen(fn, "r")))
+ if (!(f = fopen(fn, "re")))
return -errno;
if (!(fgets(line, sizeof(line), f))) {
assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
char_array_0(fn);
- if (!(f = fopen(fn, "r")))
+ if (!(f = fopen(fn, "re")))
return -errno;
if (!(fgets(line, sizeof(line), f))) {
if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
return -ENOMEM;
- f = fopen(p, "r");
+ f = fopen(p, "re");
free(p);
if (!f)
return 0;
}
+int readlink_and_canonicalize(const char *p, char **r) {
+ char *t, *s;
+ int j;
+
+ assert(p);
+ assert(r);
+
+ j = readlink_and_make_absolute(p, &t);
+ if (j < 0)
+ return j;
+
+ s = canonicalize_file_name(t);
+ if (s) {
+ free(t);
+ *r = s;
+ } else
+ *r = t;
+
+ path_kill_slashes(*r);
+
+ return 0;
+}
+
int parent_of_path(const char *path, char **_r) {
const char *e, *a = NULL, *b = NULL, *p;
char *r;
int r = 0, fd;
struct sigaction sa_old, sa_new;
- if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY)) < 0)
+ if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY|O_CLOEXEC)) < 0)
return -errno;
/* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
if (r < 0 || s < 0 || t < 0)
return -errno;
+ fd_cloexec(STDIN_FILENO, false);
+ fd_cloexec(STDOUT_FILENO, false);
+ fd_cloexec(STDERR_FILENO, false);
+
return 0;
}
}
int wait_for_terminate(pid_t pid, siginfo_t *status) {
+ siginfo_t dummy;
+
assert(pid >= 1);
- assert(status);
+
+ if (!status)
+ status = &dummy;
for (;;) {
zero(*status);
return false;
}
+int null_or_empty_path(const char *fn) {
+ struct stat st;
+
+ assert(fn);
+
+ if (stat(fn, &st) < 0)
+ return -errno;
+
+ return null_or_empty(&st);
+}
+
DIR *xopendirat(int fd, const char *name, int flags) {
int nfd;
DIR *d;
return 1;
}
- if ((f = fopen("/proc/self/cgroup", "r"))) {
+ if ((f = fopen("/proc/self/cgroup", "re"))) {
for (;;) {
char line[LINE_MAX], *p;
static int files_add(Hashmap *h, const char *path, const char *suffix) {
DIR *dir;
- struct dirent *de;
+ struct dirent buffer, *de;
int r = 0;
dir = opendir(path);
return -errno;
}
- for (de = readdir(dir); de; de = readdir(dir)) {
+ for (;;) {
+ int k;
char *p, *f;
- const char *base;
+
+ k = readdir_r(dir, &buffer, &de);
+ if (k != 0) {
+ r = -k;
+ goto finish;
+ }
+
+ if (!de)
+ break;
if (!file_is_conf(de, suffix))
continue;
free(p);
log_debug("found: %s\n", f);
- base = f + strlen(path) + 1;
- if (hashmap_put(h, base, f) <= 0)
+ if (hashmap_put(h, file_name_from_path(f), f) <= 0)
free(f);
}
return local;
}
-int hwclock_apply_localtime_delta(void) {
+int hwclock_apply_localtime_delta(int *min) {
const struct timeval *tv_null = NULL;
struct timespec ts;
struct tm *tm;
*/
if (settimeofday(tv_null, &tz) < 0)
return -errno;
-
- return minuteswest;
+ if (min)
+ *min = minuteswest;
+ return 0;
}
int hwclock_reset_localtime_delta(void) {
return 0;
}
+int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home) {
+ struct passwd *p;
+ unsigned long lu;
+
+ assert(username);
+ assert(*username);
+ assert(uid);
+ assert(gid);
+ assert(home);
+
+ /* We enforce some special rules for uid=0: in order to avoid
+ * NSS lookups for root we hardcode its data. */
+
+ if (streq(*username, "root") || streq(*username, "0")) {
+ *username = "root";
+ *uid = 0;
+ *gid = 0;
+ *home = "/root";
+ return 0;
+ }
+
+ if (safe_atolu(*username, &lu) >= 0) {
+ errno = 0;
+ p = getpwuid((uid_t) lu);
+
+ /* If there are multiple users with the same id, make
+ * sure to leave $USER to the configured value instead
+ * of the first occurrence in the database. However if
+ * the uid was configured by a numeric uid, then let's
+ * pick the real username from /etc/passwd. */
+ if (p)
+ *username = p->pw_name;
+ } else {
+ errno = 0;
+ p = getpwnam(*username);
+ }
+
+ if (!p)
+ return errno != 0 ? -errno : -ESRCH;
+
+ *uid = p->pw_uid;
+ *gid = p->pw_gid;
+ *home = p->pw_dir;
+ return 0;
+}
+
+int glob_exists(const char *path) {
+ glob_t g;
+ int r, k;
+
+ assert(path);
+
+ zero(g);
+ errno = 0;
+ k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
+
+ if (k == GLOB_NOMATCH)
+ r = 0;
+ else if (k == GLOB_NOSPACE)
+ r = -ENOMEM;
+ else if (k == 0)
+ r = !strv_isempty(g.gl_pathv);
+ else
+ r = errno ? -errno : -EIO;
+
+ globfree(&g);
+
+ return r;
+}
+
+int dirent_ensure_type(DIR *d, struct dirent *de) {
+ struct stat st;
+
+ assert(d);
+ assert(de);
+
+ if (de->d_type != DT_UNKNOWN)
+ return 0;
+
+ if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
+ return -errno;
+
+ de->d_type =
+ S_ISREG(st.st_mode) ? DT_REG :
+ S_ISDIR(st.st_mode) ? DT_DIR :
+ S_ISLNK(st.st_mode) ? DT_LNK :
+ S_ISFIFO(st.st_mode) ? DT_FIFO :
+ S_ISSOCK(st.st_mode) ? DT_SOCK :
+ S_ISCHR(st.st_mode) ? DT_CHR :
+ S_ISBLK(st.st_mode) ? DT_BLK :
+ DT_UNKNOWN;
+
+ return 0;
+}
+
+int in_search_path(const char *path, char **search) {
+ char **i, *parent;
+ int r;
+
+ r = parent_of_path(path, &parent);
+ if (r < 0)
+ return r;
+
+ r = 0;
+
+ STRV_FOREACH(i, search) {
+ if (path_equal(parent, *i)) {
+ r = 1;
+ break;
+ }
+ }
+
+ free(parent);
+
+ return r;
+}
+
+int get_files_in_directory(const char *path, char ***list) {
+ DIR *d;
+ int r = 0;
+ unsigned n = 0;
+ char **l = NULL;
+
+ assert(path);
+ assert(list);
+
+ d = opendir(path);
+ for (;;) {
+ struct dirent buffer, *de;
+ int k;
+
+ k = readdir_r(d, &buffer, &de);
+ if (k != 0) {
+ r = -k;
+ goto finish;
+ }
+
+ if (!de)
+ break;
+
+ dirent_ensure_type(d, de);
+
+ if (!dirent_is_file(de))
+ continue;
+
+ if ((unsigned) r >= n) {
+ char **t;
+
+ n = MAX(16, 2*r);
+ t = realloc(l, sizeof(char*) * n);
+ if (!t) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ l = t;
+ }
+
+ assert((unsigned) r < n);
+
+ l[r] = strdup(de->d_name);
+ if (!l[r]) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ l[++r] = NULL;
+ }
+
+finish:
+ if (d)
+ closedir(d);
+
+ if (r >= 0)
+ *list = l;
+ else
+ strv_free(l);
+
+ return r;
+}
+
static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime",