X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Ftmpfiles%2Ftmpfiles.c;h=68cfa55ce9cee09e96985c76ac2390cfbe5140f7;hb=abee28c56d523e55751b0c007d0bf812cc285c00;hp=0c1c2b17f4ebc2f45108b9f9f2373232bea52f0e;hpb=2e78fa79bbaebb358d2657c397180d2d08d69b12;p=elogind.git diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 0c1c2b17f..68cfa55ce 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -494,20 +494,19 @@ static int item_set_perms(Item *i, const char *path) { } static int write_one_file(Item *i, const char *path) { - int flags; - int fd = -1; + _cleanup_close_ int fd = -1; + int flags, r = 0; struct stat st; - int r = 0; assert(i); assert(path); - flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND : - i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC : 0; + flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW : + i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0; - RUN_WITH_UMASK(0) { + RUN_WITH_UMASK(0000) { label_context_set(path, S_IFREG); - fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY|O_NOFOLLOW, i->mode); + fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode); label_context_clear(); } @@ -525,22 +524,19 @@ static int write_one_file(Item *i, const char *path) { size_t l; unescaped = cunescape(i->argument); - if (unescaped == NULL) { - safe_close(fd); + if (!unescaped) return log_oom(); - } l = strlen(unescaped); n = write(fd, unescaped, l); if (n < 0 || (size_t) n < l) { log_error("Failed to write file %s: %s", path, n < 0 ? strerror(-n) : "Short write"); - safe_close(fd); return n < 0 ? n : -EIO; } } - safe_close(fd); + fd = safe_close(fd); if (stat(path, &st) < 0) { log_error("stat(%s) failed: %m", path); @@ -671,10 +667,29 @@ static int create_item(Item *i) { break; case COPY_FILES: - r = copy_tree(i->argument, i->path); + r = copy_tree(i->argument, i->path, false); if (r < 0) { - log_error("Failed to copy files: %s", strerror(-r)); - return r; + struct stat a, b; + + if (r != -EEXIST) { + log_error("Failed to copy files to %s: %s", i->path, strerror(-r)); + return -r; + } + + if (stat(i->argument, &a) < 0) { + log_error("stat(%s) failed: %m", i->argument); + return -errno; + } + + if (stat(i->path, &b) < 0) { + log_error("stat(%s) failed: %m", i->path); + return -errno; + } + + if ((a.st_mode ^ b.st_mode) & S_IFMT) { + log_debug("Can't copy to %s, file exists already and is of different type", i->path); + return 0; + } } r = item_set_perms(i, i->path); @@ -695,22 +710,24 @@ static int create_item(Item *i) { RUN_WITH_UMASK(0000) { mkdir_parents_label(i->path, 0755); - r = mkdir(i->path, i->mode); + r = mkdir_label(i->path, i->mode); } - if (r < 0 && errno != EEXIST) { - log_error("Failed to create directory %s: %m", i->path); - return -errno; - } + if (r < 0) { + if (r != -EEXIST) { + log_error("Failed to create directory %s: %s", i->path, strerror(-r)); + return r; + } - if (stat(i->path, &st) < 0) { - log_error("stat(%s) failed: %m", i->path); - return -errno; - } + if (stat(i->path, &st) < 0) { + log_error("stat(%s) failed: %m", i->path); + return -errno; + } - if (!S_ISDIR(st.st_mode)) { - log_error("%s is not a directory.", i->path); - return -EEXIST; + if (!S_ISDIR(st.st_mode)) { + log_debug("%s already exists and is not a directory.", i->path); + return 0; + } } r = item_set_perms(i, i->path); @@ -721,25 +738,42 @@ static int create_item(Item *i) { case CREATE_FIFO: - label_context_set(i->path, S_IFIFO); RUN_WITH_UMASK(0000) { + label_context_set(i->path, S_IFIFO); r = mkfifo(i->path, i->mode); + label_context_clear(); } - label_context_clear(); - if (r < 0 && errno != EEXIST) { - log_error("Failed to create fifo %s: %m", i->path); - return -errno; - } + if (r < 0) { + if (errno != EEXIST) { + log_error("Failed to create fifo %s: %m", i->path); + return -errno; + } - if (stat(i->path, &st) < 0) { - log_error("stat(%s) failed: %m", i->path); - return -errno; - } + if (stat(i->path, &st) < 0) { + log_error("stat(%s) failed: %m", i->path); + return -errno; + } + + if (!S_ISFIFO(st.st_mode)) { + + if (i->force) { - if (!S_ISFIFO(st.st_mode)) { - log_error("%s is not a fifo.", i->path); - return -EEXIST; + RUN_WITH_UMASK(0000) { + label_context_set(i->path, S_IFIFO); + r = mkfifo_atomic(i->path, i->mode); + label_context_clear(); + } + + if (r < 0) { + log_error("Failed to create fifo %s: %s", i->path, strerror(-r)); + return r; + } + } else { + log_debug("%s is not a fifo.", i->path); + return 0; + } + } } r = item_set_perms(i, i->path); @@ -771,11 +805,13 @@ static int create_item(Item *i) { label_context_clear(); if (r < 0) { - log_error("symlink(%s, %s) failed: %m", i->argument, i->path); - return -errno; + log_error("symlink(%s, %s) failed: %s", i->argument, i->path, strerror(-r)); + return r; } - } else + } else { log_debug("%s is not a symlink or does not point to the correct path.", i->path); + return 0; + } } } @@ -795,7 +831,7 @@ static int create_item(Item *i) { return 0; } - file_type = (i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR); + file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR; RUN_WITH_UMASK(0000) { label_context_set(i->path, file_type); @@ -814,16 +850,31 @@ static int create_item(Item *i) { log_error("Failed to create device node %s: %m", i->path); return -errno; } - } - if (stat(i->path, &st) < 0) { - log_error("stat(%s) failed: %m", i->path); - return -errno; - } + if (stat(i->path, &st) < 0) { + log_error("stat(%s) failed: %m", i->path); + return -errno; + } - if ((st.st_mode & S_IFMT) != file_type) { - log_error("%s is not a device node.", i->path); - return -EEXIST; + if ((st.st_mode & S_IFMT) != file_type) { + + if (i->force) { + + RUN_WITH_UMASK(0000) { + label_context_set(i->path, file_type); + r = mknod_atomic(i->path, i->mode | file_type, i->major_minor); + label_context_clear(); + } + + if (r < 0) { + log_error("Failed to create device node %s: %s", i->path, strerror(-r)); + return r; + } + } else { + log_debug("%s is not a device node.", i->path); + return 0; + } + } } r = item_set_perms(i, i->path); @@ -1198,10 +1249,10 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { case CREATE_SYMLINK: if (!i->argument) { - log_error("[%s:%u] Symlink file requires argument.", fname, line); - return -EBADMSG; + i->argument = strappend("/usr/share/factory", i->path); + if (!i->argument) + return log_oom(); } - break; case WRITE_FILE: @@ -1213,8 +1264,9 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { case COPY_FILES: if (!i->argument) { - log_error("[%s:%u] Copy files requires argument.", fname, line); - return -EBADMSG; + i->argument = strappend("/usr/share/factory", i->path); + if (!i->argument) + return log_oom(); } if (!path_is_absolute(i->argument)) {