Permalink
Browse files

tmpfiles: introduce create_device()

  • Loading branch information...
fbuihuu committed Apr 12, 2018
1 parent 16ba55a commit 074bd73fd36a6379d10d41c307223706b0ef300d
Showing with 75 additions and 69 deletions.
  1. +75 −69 src/tmpfiles/tmpfiles.c
@@ -1511,6 +1511,79 @@ static int copy_files(Item *i) {
return fd_set_perms(i, fd, NULL);
}

typedef enum {
CREATION_NORMAL,
CREATION_EXISTING,
CREATION_FORCE,
_CREATION_MODE_MAX,
_CREATION_MODE_INVALID = -1
} CreationMode;

static const char *creation_mode_verb_table[_CREATION_MODE_MAX] = {
[CREATION_NORMAL] = "Created",
[CREATION_EXISTING] = "Found existing",
[CREATION_FORCE] = "Created replacement",
};

DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(creation_mode_verb, CreationMode);

static int create_device(Item *i, mode_t file_type) {
CreationMode creation;
struct stat st;
int r;

assert(i);
assert(IN_SET(file_type, S_IFBLK, S_IFCHR));

RUN_WITH_UMASK(0000) {
mac_selinux_create_file_prepare(i->path, file_type);
r = mknod(i->path, i->mode | file_type, i->major_minor);
mac_selinux_create_file_clear();
}

if (r < 0) {
if (errno == EPERM) {
log_debug("We lack permissions, possibly because of cgroup configuration; "
"skipping creation of device node %s.", i->path);
return 0;
}

if (errno != EEXIST)
return log_error_errno(errno, "Failed to create device node %s: %m", i->path);

if (lstat(i->path, &st) < 0)
return log_error_errno(errno, "stat(%s) failed: %m", i->path);

if ((st.st_mode & S_IFMT) != file_type) {

if (i->force) {

RUN_WITH_UMASK(0000) {
mac_selinux_create_file_prepare(i->path, file_type);
r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
mac_selinux_create_file_clear();
}

if (r < 0)
return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
creation = CREATION_FORCE;
} else {
log_debug("%s is not a device node.", i->path);
return 0;
}
} else
creation = CREATION_EXISTING;
} else
creation = CREATION_NORMAL;

log_debug("%s %s device node \"%s\" %u:%u.",
creation_mode_verb_to_string(creation),
i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
i->path, major(i->mode), minor(i->mode));

return path_set_perms(i, i->path);
}

typedef int (*action_t)(Item *, const char *);
typedef int (*fdaction_t)(Item *, int fd, const struct stat *st);

@@ -1623,22 +1696,6 @@ static int glob_item_recursively(Item *i, fdaction_t action) {
return r;
}

typedef enum {
CREATION_NORMAL,
CREATION_EXISTING,
CREATION_FORCE,
_CREATION_MODE_MAX,
_CREATION_MODE_INVALID = -1
} CreationMode;

static const char *creation_mode_verb_table[_CREATION_MODE_MAX] = {
[CREATION_NORMAL] = "Created",
[CREATION_EXISTING] = "Found existing",
[CREATION_FORCE] = "Created replacement",
};

DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(creation_mode_verb, CreationMode);

static int create_item(Item *i) {
struct stat st;
int r = 0;
@@ -1870,9 +1927,7 @@ static int create_item(Item *i) {
}

case CREATE_BLOCK_DEVICE:
case CREATE_CHAR_DEVICE: {
mode_t file_type;

case CREATE_CHAR_DEVICE:
if (have_effective_cap(CAP_MKNOD) == 0) {
/* In a container we lack CAP_MKNOD. We
shouldn't attempt to create the device node in
@@ -1886,60 +1941,11 @@ static int create_item(Item *i) {
RUN_WITH_UMASK(0000)
(void) mkdir_parents_label(i->path, 0755);

file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;

RUN_WITH_UMASK(0000) {
mac_selinux_create_file_prepare(i->path, file_type);
r = mknod(i->path, i->mode | file_type, i->major_minor);
mac_selinux_create_file_clear();
}

if (r < 0) {
if (errno == EPERM) {
log_debug("We lack permissions, possibly because of cgroup configuration; "
"skipping creation of device node %s.", i->path);
return 0;
}

if (errno != EEXIST)
return log_error_errno(errno, "Failed to create device node %s: %m", i->path);

if (lstat(i->path, &st) < 0)
return log_error_errno(errno, "stat(%s) failed: %m", i->path);

if ((st.st_mode & S_IFMT) != file_type) {

if (i->force) {

RUN_WITH_UMASK(0000) {
mac_selinux_create_file_prepare(i->path, file_type);
r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
mac_selinux_create_file_clear();
}

if (r < 0)
return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
creation = CREATION_FORCE;
} else {
log_debug("%s is not a device node.", i->path);
return 0;
}
} else
creation = CREATION_EXISTING;
} else
creation = CREATION_NORMAL;

log_debug("%s %s device node \"%s\" %u:%u.",
creation_mode_verb_to_string(creation),
i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
i->path, major(i->mode), minor(i->mode));

r = path_set_perms(i, i->path);
r = create_device(i, i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR);
if (r < 0)
return r;

break;
}

case ADJUST_MODE:
case RELABEL_PATH:

0 comments on commit 074bd73

Please sign in to comment.