chiark
/
gitweb
/
~ianmdlvl
/
elogind.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
tmpfiles: don't allow label_fix to print ENOENT when we want to ignore it
[elogind.git]
/
src
/
tmpfiles
/
tmpfiles.c
diff --git
a/src/tmpfiles/tmpfiles.c
b/src/tmpfiles/tmpfiles.c
index 5eca82ad26c423c3ca7320eb20eecb9e98c83de6..bff95271f526e5ab160c94f69834b4914a5c2e63 100644
(file)
--- a/
src/tmpfiles/tmpfiles.c
+++ b/
src/tmpfiles/tmpfiles.c
@@
-51,6
+51,8
@@
#include "set.h"
#include "conf-files.h"
#include "capability.h"
#include "set.h"
#include "conf-files.h"
#include "capability.h"
+#include "specifier.h"
+#include "build.h"
/* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
* them in the file system. This is intended to be used to create
/* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
* them in the file system. This is intended to be used to create
@@
-68,6
+70,7
@@
typedef enum ItemType {
CREATE_SYMLINK = 'L',
CREATE_CHAR_DEVICE = 'c',
CREATE_BLOCK_DEVICE = 'b',
CREATE_SYMLINK = 'L',
CREATE_CHAR_DEVICE = 'c',
CREATE_BLOCK_DEVICE = 'b',
+ ADJUST_MODE = 'm',
/* These ones take globs */
IGNORE_PATH = 'x',
/* These ones take globs */
IGNORE_PATH = 'x',
@@
-104,6
+107,7
@@
static Set *unix_sockets = NULL;
static bool arg_create = false;
static bool arg_clean = false;
static bool arg_remove = false;
static bool arg_create = false;
static bool arg_clean = false;
static bool arg_remove = false;
+static bool arg_boot = false;
static char **include_prefixes = NULL;
static char **exclude_prefixes = NULL;
static char **include_prefixes = NULL;
static char **exclude_prefixes = NULL;
@@
-256,8
+260,8
@@
static int dir_cleanup(
dev_t rootdev,
bool mountpoint,
int maxdepth,
dev_t rootdev,
bool mountpoint,
int maxdepth,
- bool keep_this_level)
-{
+ bool keep_this_level)
{
+
struct dirent *dent;
struct timespec times[2];
bool deleted = false;
struct dirent *dent;
struct timespec times[2];
bool deleted = false;
@@
-273,12
+277,15
@@
static int dir_cleanup(
continue;
if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
continue;
if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
+ if (errno == ENOENT)
+ continue;
- if (errno != ENOENT) {
+ /* FUSE, NFS mounts, SELinux might return EACCES */
+ if (errno == EACCES)
+ log_debug("stat(%s/%s) failed: %m", p, dent->d_name);
+ else
log_error("stat(%s/%s) failed: %m", p, dent->d_name);
log_error("stat(%s/%s) failed: %m", p, dent->d_name);
- r = -errno;
- }
-
+ r = -errno;
continue;
}
continue;
}
@@
-354,7
+361,7
@@
static int dir_cleanup(
continue;
if (i->type != IGNORE_DIRECTORY_PATH || !streq(dent->d_name, p)) {
continue;
if (i->type != IGNORE_DIRECTORY_PATH || !streq(dent->d_name, p)) {
- log_debug("rmdir '%s'
\n
", sub_path);
+ log_debug("rmdir '%s'", sub_path);
if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
if (errno != ENOENT && errno != ENOTEMPTY) {
if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
if (errno != ENOENT && errno != ENOTEMPTY) {
@@
-402,7
+409,7
@@
static int dir_cleanup(
if (age >= cutoff)
continue;
if (age >= cutoff)
continue;
- log_debug("unlink '%s'
\n
", sub_path);
+ log_debug("unlink '%s'", sub_path);
if (unlinkat(dirfd(d), dent->d_name, 0) < 0) {
if (errno != ENOENT) {
if (unlinkat(dirfd(d), dent->d_name, 0) < 0) {
if (errno != ENOENT) {
@@
-428,12
+435,14
@@
finish:
return r;
}
return r;
}
-static int item_set_perms
(Item *i, const char *path
) {
+static int item_set_perms
_full(Item *i, const char *path, bool ignore_enoent
) {
/* not using i->path directly because it may be a glob */
if (i->mode_set)
if (chmod(path, i->mode) < 0) {
/* 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 (errno != ENOENT || !ignore_enoent) {
+ log_error("chmod(%s) failed: %m", path);
+ return -errno;
+ }
}
if (i->uid_set || i->gid_set)
}
if (i->uid_set || i->gid_set)
@@
-441,16
+450,24
@@
static int item_set_perms(Item *i, const char *path) {
i->uid_set ? i->uid : (uid_t) -1,
i->gid_set ? i->gid : (gid_t) -1) < 0) {
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;
+ if (errno != ENOENT || !ignore_enoent) {
+ log_error("chown(%s) failed: %m", path);
+ return -errno;
+ }
}
}
- return label_fix(path, false, false);
+ return label_fix(path, ignore_enoent, false);
+}
+
+static int item_set_perms(Item *i, const char *path) {
+ return item_set_perms_full(i, path, false);
}
static int write_one_file(Item *i, const char *path) {
}
static int write_one_file(Item *i, const char *path) {
- int r, e, fd, flags;
+ int e, flags;
+ int fd = -1;
struct stat st;
struct stat st;
+ int r = 0;
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 :
i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC : 0;
@@
-524,15
+541,15
@@
static int recursive_relabel_children(Item *i, const char *path) {
for (;;) {
struct dirent *de;
for (;;) {
struct dirent *de;
- union dirent_storage buf;
bool is_dir;
int r;
_cleanup_free_ char *entry_path = NULL;
bool is_dir;
int r;
_cleanup_free_ char *entry_path = NULL;
- r = readdir_r(d, &buf.de, &de);
- if (r != 0) {
+ errno = 0;
+ de = readdir(d);
+ if (!de && errno != 0) {
if (ret == 0)
if (ret == 0)
- ret = -
r
;
+ ret = -
errno
;
break;
}
break;
}
@@
-622,8
+639,9
@@
static int glob_item(Item *i, int (*action)(Item *, const char *)) {
}
static int create_item(Item *i) {
}
static int create_item(Item *i) {
- int
r,
e;
+ int e;
struct stat st;
struct stat st;
+ int r = 0;
assert(i);
assert(i);
@@
-641,6
+659,7
@@
static int create_item(Item *i) {
if (r < 0)
return r;
break;
if (r < 0)
return r;
break;
+
case WRITE_FILE:
r = glob_item(i, write_one_file);
if (r < 0)
case WRITE_FILE:
r = glob_item(i, write_one_file);
if (r < 0)
@@
-648,6
+667,13
@@
static int create_item(Item *i) {
break;
break;
+ case ADJUST_MODE:
+ r = item_set_perms_full(i, i->path, true);
+ if (r < 0)
+ return r;
+
+ break;
+
case TRUNCATE_DIRECTORY:
case CREATE_DIRECTORY:
case TRUNCATE_DIRECTORY:
case CREATE_DIRECTORY:
@@
-818,6
+844,7
@@
static int remove_item_instance(Item *i, const char *instance) {
case RELABEL_PATH:
case RECURSIVE_RELABEL_PATH:
case WRITE_FILE:
case RELABEL_PATH:
case RECURSIVE_RELABEL_PATH:
case WRITE_FILE:
+ case ADJUST_MODE:
break;
case REMOVE_PATH:
break;
case REMOVE_PATH:
@@
-863,6
+890,7
@@
static int remove_item(Item *i) {
case RELABEL_PATH:
case RECURSIVE_RELABEL_PATH:
case WRITE_FILE:
case RELABEL_PATH:
case RECURSIVE_RELABEL_PATH:
case WRITE_FILE:
+ case ADJUST_MODE:
break;
case REMOVE_PATH:
break;
case REMOVE_PATH:
@@
-972,10
+1000,7
@@
static void item_free(Item *i) {
free(i);
}
free(i);
}
-static inline void item_freep(Item **i) {
- if (*i)
- item_free(*i);
-}
+DEFINE_TRIVIAL_CLEANUP_FUNC(Item*, item_free);
#define _cleanup_item_free_ _cleanup_(item_freep)
static bool item_equal(Item *a, Item *b) {
#define _cleanup_item_free_ _cleanup_(item_freep)
static bool item_equal(Item *a, Item *b) {
@@
-1038,10
+1063,19
@@
static bool should_include_path(const char *path) {
}
static int parse_line(const char *fname, unsigned line, const char *buffer) {
}
static int parse_line(const char *fname, unsigned line, const char *buffer) {
+
+ static const Specifier specifier_table[] = {
+ { 'm', specifier_machine_id, NULL },
+ { 'b', specifier_boot_id, NULL },
+ { 'H', specifier_host_name, NULL },
+ { 'v', specifier_kernel_release, NULL },
+ {}
+ };
+
_cleanup_item_free_ Item *i = NULL;
Item *existing;
_cleanup_free_ char
_cleanup_item_free_ Item *i = NULL;
Item *existing;
_cleanup_free_ char
- *
mode = NULL, *user = NULL, *group = NULL, *age
= NULL;
+ *
action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path
= NULL;
char type;
Hashmap *h;
int r, n = -1;
char type;
Hashmap *h;
int r, n = -1;
@@
-1050,14
+1084,10
@@
static int parse_line(const char *fname, unsigned line, const char *buffer) {
assert(line >= 1);
assert(buffer);
assert(line >= 1);
assert(buffer);
- i = new0(Item, 1);
- if (!i)
- return log_oom();
-
r = sscanf(buffer,
r = sscanf(buffer,
- "%
c
%ms %ms %ms %ms %ms %n",
- &
type
,
- &
i->
path,
+ "%
ms
%ms %ms %ms %ms %ms %n",
+ &
action
,
+ &path,
&mode,
&user,
&group,
&mode,
&user,
&group,
@@
-1068,6
+1098,24
@@
static int parse_line(const char *fname, unsigned line, const char *buffer) {
return -EIO;
}
return -EIO;
}
+ if (strlen(action) > 2 || (strlen(action) > 1 && action[1] != '!')) {
+ log_error("[%s:%u] Unknown modifier '%s'", fname, line, action);
+ return -EINVAL;
+ } else if (strlen(action) > 1 && !arg_boot)
+ return 0;
+
+ type = action[0];
+
+ i = new0(Item, 1);
+ if (!i)
+ return log_oom();
+
+ r = specifier_printf(path, specifier_table, NULL, &i->path);
+ if (r < 0) {
+ log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
+ return r;
+ }
+
if (n >= 0) {
n += strspn(buffer+n, WHITESPACE);
if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
if (n >= 0) {
n += strspn(buffer+n, WHITESPACE);
if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
@@
-1090,6
+1138,7
@@
static int parse_line(const char *fname, unsigned line, const char *buffer) {
case RECURSIVE_REMOVE_PATH:
case RELABEL_PATH:
case RECURSIVE_RELABEL_PATH:
case RECURSIVE_REMOVE_PATH:
case RELABEL_PATH:
case RECURSIVE_RELABEL_PATH:
+ case ADJUST_MODE:
break;
case CREATE_SYMLINK:
break;
case CREATE_SYMLINK:
@@
-1224,9
+1273,11
@@
static int help(void) {
printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
"Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
" -h --help Show this help\n"
printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
"Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
" -h --help Show this help\n"
+ " --version Show package version\n"
" --create Create marked files/directories\n"
" --clean Clean up marked directories\n"
" --remove Remove marked files/directories\n"
" --create Create marked files/directories\n"
" --clean Clean up marked directories\n"
" --remove Remove marked files/directories\n"
+ " --boot Execute actions only safe at boot\n"
" --prefix=PATH Only apply rules that apply to paths with the specified prefix\n"
" --exclude-prefix=PATH Ignore rules that apply to paths with the specified prefix\n",
program_invocation_short_name);
" --prefix=PATH Only apply rules that apply to paths with the specified prefix\n"
" --exclude-prefix=PATH Ignore rules that apply to paths with the specified prefix\n",
program_invocation_short_name);
@@
-1237,21
+1288,25
@@
static int help(void) {
static int parse_argv(int argc, char *argv[]) {
enum {
static int parse_argv(int argc, char *argv[]) {
enum {
+ ARG_VERSION = 0x100,
ARG_CREATE,
ARG_CLEAN,
ARG_REMOVE,
ARG_CREATE,
ARG_CLEAN,
ARG_REMOVE,
+ ARG_BOOT,
ARG_PREFIX,
ARG_EXCLUDE_PREFIX,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
ARG_PREFIX,
ARG_EXCLUDE_PREFIX,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
{ "create", no_argument, NULL, ARG_CREATE },
{ "clean", no_argument, NULL, ARG_CLEAN },
{ "remove", no_argument, NULL, ARG_REMOVE },
{ "create", no_argument, NULL, ARG_CREATE },
{ "clean", no_argument, NULL, ARG_CLEAN },
{ "remove", no_argument, NULL, ARG_REMOVE },
+ { "boot", no_argument, NULL, ARG_BOOT },
{ "prefix", required_argument, NULL, ARG_PREFIX },
{ "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
{ "prefix", required_argument, NULL, ARG_PREFIX },
{ "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
- {
NULL, 0, NULL, 0
}
+ {}
};
int c;
};
int c;
@@
-1264,7
+1319,11
@@
static int parse_argv(int argc, char *argv[]) {
switch (c) {
case 'h':
switch (c) {
case 'h':
- help();
+ return help();
+
+ case ARG_VERSION:
+ puts(PACKAGE_STRING);
+ puts(SYSTEMD_FEATURES);
return 0;
case ARG_CREATE:
return 0;
case ARG_CREATE:
@@
-1279,6
+1338,10
@@
static int parse_argv(int argc, char *argv[]) {
arg_remove = true;
break;
arg_remove = true;
break;
+ case ARG_BOOT:
+ arg_boot = true;
+ break;
+
case ARG_PREFIX:
if (strv_extend(&include_prefixes, optarg) < 0)
return log_oom();
case ARG_PREFIX:
if (strv_extend(&include_prefixes, optarg) < 0)
return log_oom();
@@
-1293,8
+1356,7
@@
static int parse_argv(int argc, char *argv[]) {
return -EINVAL;
default:
return -EINVAL;
default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
+ assert_not_reached("Unhandled option");
}
}
}
}
@@
-1307,11
+1369,12
@@
static int parse_argv(int argc, char *argv[]) {
}
static int read_config_file(const char *fn, bool ignore_enoent) {
}
static int read_config_file(const char *fn, bool ignore_enoent) {
- FILE *f;
- unsigned v = 0;
- int r;
+ _cleanup_fclose_ FILE *f = NULL;
+ char line[LINE_MAX];
Iterator iterator;
Iterator iterator;
+ unsigned v = 0;
Item *i;
Item *i;
+ int r;
assert(fn);
assert(fn);
@@
-1324,23
+1387,19
@@
static int read_config_file(const char *fn, bool ignore_enoent) {
return r;
}
return r;
}
- log_debug("apply: %s\n", fn);
- for (;;) {
- char line[LINE_MAX], *l;
+ FOREACH_LINE(line, f, break) {
+ char *l;
int k;
int k;
- if (!(fgets(line, sizeof(line), f)))
- break;
-
v++;
l = strstrip(line);
if (*l == '#' || *l == 0)
continue;
v++;
l = strstrip(line);
if (*l == '#' || *l == 0)
continue;
- if ((k = parse_line(fn, v, l)) < 0)
-
if (
r == 0)
-
r = k;
+ k = parse_line(fn, v, l);
+
if (k < 0 &&
r == 0)
+ r = k;
}
/* we have to determine age parameter for each entry of type X */
}
/* we have to determine age parameter for each entry of type X */
@@
-1377,8
+1436,6
@@
static int read_config_file(const char *fn, bool ignore_enoent) {
r = -EIO;
}
r = -EIO;
}
- fclose(f);
-
return r;
}
return r;
}