/* These ones take globs */
IGNORE_PATH = 'x',
REMOVE_PATH = 'r',
- RECURSIVE_REMOVE_PATH = 'R'
+ RECURSIVE_REMOVE_PATH = 'R',
+ RELABEL_PATH = 'z',
+ RECURSIVE_RELABEL_PATH = 'Z'
} ItemType;
typedef struct Item {
#define MAX_DEPTH 256
static bool needs_glob(ItemType t) {
- return t == IGNORE_PATH || t == REMOVE_PATH || t == RECURSIVE_REMOVE_PATH;
+ return t == IGNORE_PATH || t == REMOVE_PATH || t == RECURSIVE_REMOVE_PATH || t == RELABEL_PATH || t == RECURSIVE_RELABEL_PATH;
}
static struct Item* find_glob(Hashmap *h, const char *match) {
/* We maintain a cache of the sockets we found in
* /proc/net/unix to speed things up a little. */
- if (!(unix_sockets = set_new(string_hash_func, string_compare_func)))
+ unix_sockets = set_new(string_hash_func, string_compare_func);
+ if (!unix_sockets)
return;
- if (!(f = fopen("/proc/net/unix", "re")))
+ f = fopen("/proc/net/unix", "re");
+ if (!f)
return;
- if (!(fgets(line, sizeof(line), f)))
+ /* Skip header */
+ if (!fgets(line, sizeof(line), f))
goto fail;
for (;;) {
char *p, *s;
int k;
- if (!(fgets(line, sizeof(line), f)))
+ if (!fgets(line, sizeof(line), f))
break;
truncate_nl(line);
- if (strlen(line) < 53)
+ p = strchr(line, ':');
+ if (!p)
+ continue;
+
+ if (strlen(p) < 37)
continue;
- p = line + 53;
+ p += 37;
p += strspn(p, WHITESPACE);
- p += strcspn(p, WHITESPACE);
+ p += strcspn(p, WHITESPACE); /* skip one more word */
p += strspn(p, WHITESPACE);
if (*p != '/')
continue;
- if (!(s = strdup(p)))
+ s = strdup(p);
+ if (!s)
goto fail;
path_kill_slashes(s);
- if ((k = set_put(unix_sockets, s)) < 0) {
+ k = set_put(unix_sockets, s);
+ if (k < 0) {
free(s);
if (k != -EEXIST)
return r;
}
+static int item_set_perms(Item *i, const char *path) {
+ /* not using i->path directly because it may be a glob */
+ if (i->mode_set)
+ if (chmod(path, i->mode) < 0) {
+ log_error("chmod(%s) failed: %m", path);
+ return -errno;
+ }
+
+ if (i->uid_set || i->gid_set)
+ if (chown(path,
+ i->uid_set ? i->uid : (uid_t) -1,
+ i->gid_set ? i->gid : (gid_t) -1) < 0) {
+
+ log_error("chown(%s) failed: %m", path);
+ return -errno;
+ }
+
+ return label_fix(path, false);
+}
+
+static int recursive_relabel_children(Item *i, const char *path) {
+ DIR *d;
+ int ret = 0;
+
+ /* This returns the first error we run into, but nevertheless
+ * tries to go on */
+
+ d = opendir(path);
+ if (!d)
+ return errno == ENOENT ? 0 : -errno;
+
+ for (;;) {
+ struct dirent buf, *de;
+ bool is_dir;
+ int r;
+ char *entry_path;
+
+ r = readdir_r(d, &buf, &de);
+ if (r != 0) {
+ if (ret == 0)
+ ret = -r;
+ break;
+ }
+
+ if (!de)
+ break;
+
+ if (streq(de->d_name, ".") || streq(de->d_name, ".."))
+ continue;
+
+ if (asprintf(&entry_path, "%s/%s", path, de->d_name) < 0) {
+ if (ret == 0)
+ ret = -ENOMEM;
+ continue;
+ }
+
+ if (de->d_type == DT_UNKNOWN) {
+ struct stat st;
+
+ if (lstat(entry_path, &st) < 0) {
+ if (ret == 0 && errno != ENOENT)
+ ret = -errno;
+ free(entry_path);
+ continue;
+ }
+
+ is_dir = S_ISDIR(st.st_mode);
+
+ } else
+ is_dir = de->d_type == DT_DIR;
+
+ r = item_set_perms(i, entry_path);
+ if (r < 0) {
+ if (ret == 0 && r != -ENOENT)
+ ret = r;
+ free(entry_path);
+ continue;
+ }
+
+ if (is_dir) {
+ r = recursive_relabel_children(i, entry_path);
+ if (r < 0 && ret == 0)
+ ret = r;
+ }
+
+ free(entry_path);
+ }
+
+ closedir(d);
+
+ return ret;
+}
+
+static int recursive_relabel(Item *i, const char *path) {
+ int r;
+ struct stat st;
+
+ r = item_set_perms(i, path);
+ if (r < 0)
+ return r;
+
+ if (lstat(path, &st) < 0)
+ return -errno;
+
+ if (S_ISDIR(st.st_mode))
+ r = recursive_relabel_children(i, path);
+
+ return r;
+}
+
static int glob_item(Item *i, int (*action)(Item *, const char *)) {
int r = 0, k;
glob_t g;
return r;
}
-static int item_set_perms(Item *i) {
- if (i->mode_set)
- if (chmod(i->path, i->mode) < 0) {
- log_error("chmod(%s) failed: %m", i->path);
- return -errno;
- }
-
- if (i->uid_set || i->gid_set)
- if (chown(i->path,
- i->uid_set ? i->uid : (uid_t) -1,
- i->gid_set ? i->gid : (gid_t) -1) < 0) {
-
- log_error("chown(%s) failed: %m", i->path);
- return -errno;
- }
-
- return label_fix(i->path, false);
-}
-
static int create_item(Item *i) {
int r;
mode_t u;
return -EEXIST;
}
- r = item_set_perms(i);
+ r = item_set_perms(i, i->path);
if (r < 0)
return r;
return -EEXIST;
}
- r = item_set_perms(i);
+ r = item_set_perms(i, i->path);
if (r < 0)
return r;
return -EEXIST;
}
- r = item_set_perms(i);
+ r = item_set_perms(i, i->path);
if (r < 0)
return r;
break;
+
+ case RELABEL_PATH:
+
+ r = glob_item(i, item_set_perms);
+ if (r < 0)
+ return 0;
+ break;
+
+ case RECURSIVE_RELABEL_PATH:
+
+ r = glob_item(i, recursive_relabel);
+ if (r < 0)
+ return r;
}
log_debug("%s created successfully.", i->path);
case CREATE_DIRECTORY:
case CREATE_FIFO:
case IGNORE_PATH:
+ case RELABEL_PATH:
+ case RECURSIVE_RELABEL_PATH:
break;
case REMOVE_PATH:
case CREATE_DIRECTORY:
case CREATE_FIFO:
case IGNORE_PATH:
+ case RELABEL_PATH:
+ case RECURSIVE_RELABEL_PATH:
break;
case REMOVE_PATH:
r = -EIO;
goto finish;
}
- i->type = type;
- if (i->type != CREATE_FILE &&
- i->type != TRUNCATE_FILE &&
- i->type != CREATE_DIRECTORY &&
- i->type != TRUNCATE_DIRECTORY &&
- i->type != CREATE_FIFO &&
- i->type != IGNORE_PATH &&
- i->type != REMOVE_PATH &&
- i->type != RECURSIVE_REMOVE_PATH) {
- log_error("[%s:%u] Unknown file type '%c'.", fname, line, i->type);
+ switch(type) {
+ case CREATE_FILE:
+ case TRUNCATE_FILE:
+ case CREATE_DIRECTORY:
+ case TRUNCATE_DIRECTORY:
+ case CREATE_FIFO:
+ case IGNORE_PATH:
+ case REMOVE_PATH:
+ case RECURSIVE_REMOVE_PATH:
+ case RELABEL_PATH:
+ case RECURSIVE_RELABEL_PATH:
+ break;
+ default:
+ log_error("[%s:%u] Unknown file type '%c'.", fname, line, type);
r = -EBADMSG;
goto finish;
}
+ i->type = type;
if (!path_is_absolute(i->path)) {
log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path);
Item *i;
Iterator iterator;
- if ((r = parse_argv(argc, argv)) <= 0)
+ r = parse_argv(argc, argv);
+ if (r <= 0)
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
log_set_target(LOG_TARGET_AUTO);