tmpfiles: take names of tmpfiles configuration files on the command line

This commit is contained in:
Lennart Poettering 2011-02-13 14:00:54 +01:00
parent eb0ca9ebff
commit fba6e68723
2 changed files with 88 additions and 67 deletions

2
TODO
View File

@ -126,8 +126,6 @@ Features:
* systemctl condrestart should return 0 if service isn't running * systemctl condrestart should return 0 if service isn't running
* tmpfiles: allow specification of .conf files on cmdline
* allow runtime changing of log level and target * allow runtime changing of log level and target
* automatically determine TERM= based on tty name even for /dev/console * automatically determine TERM= based on tty name even for /dev/console

View File

@ -85,6 +85,8 @@ static bool arg_create = false;
static bool arg_clean = false; static bool arg_clean = false;
static bool arg_remove = false; static bool arg_remove = false;
static const char *arg_prefix = NULL;
#define MAX_DEPTH 256 #define MAX_DEPTH 256
static bool needs_glob(int t) { static bool needs_glob(int t) {
@ -538,7 +540,7 @@ static void item_free(Item *i) {
free(i); free(i);
} }
static int parse_line(const char *fname, unsigned line, const char *buffer, const char *prefix) { static int parse_line(const char *fname, unsigned line, const char *buffer) {
Item *i; Item *i;
char *mode = NULL, *user = NULL, *group = NULL, *age = NULL; char *mode = NULL, *user = NULL, *group = NULL, *age = NULL;
int r; int r;
@ -590,7 +592,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer, cons
path_kill_slashes(i->path); path_kill_slashes(i->path);
if (prefix && !path_startswith(i->path, prefix)) { if (arg_prefix && !path_startswith(i->path, arg_prefix)) {
r = 0; r = 0;
goto finish; goto finish;
} }
@ -698,12 +700,13 @@ static int scandir_filter(const struct dirent *d) {
static int help(void) { static int help(void) {
printf("%s [OPTIONS...]\n\n" printf("%s [OPTIONS...] [CONFIGURATION FILE]\n\n"
"Create and clean up temporary directories.\n\n" "Create and clean up temporary files and directories.\n\n"
" -h --help Show this help\n" " -h --help Show this help\n"
" --create Create marked files/directories\n" " --create Create marked files/directories\n"
" --clean Clean up marked directories\n" " --clean Clean up marked directories\n"
" --remove Remove marked files/directories\n", " --remove Remove marked files/directories\n"
" --prefix=PATH Only apply rules that apply to paths\n",
program_invocation_short_name); program_invocation_short_name);
return 0; return 0;
@ -714,7 +717,8 @@ static int parse_argv(int argc, char *argv[]) {
enum { enum {
ARG_CREATE, ARG_CREATE,
ARG_CLEAN, ARG_CLEAN,
ARG_REMOVE ARG_REMOVE,
ARG_PREFIX
}; };
static const struct option options[] = { static const struct option options[] = {
@ -722,6 +726,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "create", no_argument, NULL, ARG_CREATE }, { "create", no_argument, NULL, ARG_CREATE },
{ "clean", no_argument, NULL, ARG_CLEAN }, { "clean", no_argument, NULL, ARG_CLEAN },
{ "remove", no_argument, NULL, ARG_REMOVE }, { "remove", no_argument, NULL, ARG_REMOVE },
{ "prefix", required_argument, NULL, ARG_PREFIX },
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
}; };
@ -750,6 +755,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_remove = true; arg_remove = true;
break; break;
case ARG_PREFIX:
arg_prefix = optarg;
break;
case '?': case '?':
return -EINVAL; return -EINVAL;
@ -760,28 +769,66 @@ static int parse_argv(int argc, char *argv[]) {
} }
if (!arg_clean && !arg_create && !arg_remove) { if (!arg_clean && !arg_create && !arg_remove) {
help(); log_error("You need to specify at leat one of --clean, --create or --remove.");
return -EINVAL; return -EINVAL;
} }
return 1; return 1;
} }
static int read_config_file(const char *fn, bool ignore_enoent) {
FILE *f;
unsigned v = 0;
int r = 0;
assert(fn);
if (!(f = fopen(fn, "re"))) {
if (ignore_enoent && errno == ENOENT)
return 0;
log_error("Failed to open %s: %m", fn);
return -errno;
}
for (;;) {
char line[LINE_MAX], *l;
int k;
if (!(fgets(line, sizeof(line), f)))
break;
v++;
l = strstrip(line);
if (*l == '#' || *l == 0)
continue;
if ((k = parse_line(fn, v, l)) < 0)
if (r == 0)
r = k;
}
if (ferror(f)) {
log_error("Failed to read from file %s: %m", fn);
if (r == 0)
r = -EIO;
}
fclose(f);
return r;
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
struct dirent **de = NULL; int r;
int r, n, j;
const char *prefix = NULL;
Item *i; Item *i;
Iterator iterator; Iterator iterator;
if ((r = parse_argv(argc, argv)) <= 0) if ((r = parse_argv(argc, argv)) <= 0)
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
if (optind < argc)
prefix = argv[optind];
else
prefix = "/";
log_set_target(LOG_TARGET_AUTO); log_set_target(LOG_TARGET_AUTO);
log_parse_environment(); log_parse_environment();
log_open(); log_open();
@ -797,75 +844,51 @@ int main(int argc, char *argv[]) {
goto finish; goto finish;
} }
if ((n = scandir("/etc/tmpfiles.d/", &de, scandir_filter, alphasort)) < 0) {
if (errno == ENOENT)
r = EXIT_SUCCESS;
else {
log_error("Failed to enumerate /etc/tmpfiles.d/ files: %m");
r = EXIT_FAILURE;
}
goto finish;
}
r = EXIT_SUCCESS; r = EXIT_SUCCESS;
for (j = 0; j < n; j++) { if (optind < argc) {
int k; int j;
char *fn;
FILE *f;
unsigned v;
k = asprintf(&fn, "/etc/tmpfiles.d/%s", de[j]->d_name); for (j = optind; j < argc; j++)
free(de[j]); if (read_config_file(argv[j], false) < 0)
r = EXIT_FAILURE;
if (k < 0) { } else {
log_error("Failed to allocate file name."); int n, j;
r = EXIT_FAILURE; struct dirent **de = NULL;
continue;
}
if (!(f = fopen(fn, "re"))) { if ((n = scandir("/etc/tmpfiles.d/", &de, scandir_filter, alphasort)) < 0) {
if (errno != ENOENT) { if (errno != ENOENT) {
log_error("Failed to open %s: %m", fn); log_error("Failed to enumerate /etc/tmpfiles.d/ files: %m");
r = EXIT_FAILURE; r = EXIT_FAILURE;
} }
free(fn); goto finish;
continue;
} }
v = 0; for (j = 0; j < n; j++) {
for (;;) { int k;
char line[LINE_MAX], *l; char *fn;
if (!(fgets(line, sizeof(line), f))) k = asprintf(&fn, "/etc/tmpfiles.d/%s", de[j]->d_name);
break; free(de[j]);
v++; if (k < 0) {
log_error("Failed to allocate file name.");
l = strstrip(line);
if (*l == '#' || *l == 0)
continue;
if (parse_line(fn, v, l, prefix) < 0)
r = EXIT_FAILURE; r = EXIT_FAILURE;
continue;
}
if (read_config_file(fn, true) < 0)
r = EXIT_FAILURE;
free(fn);
} }
if (ferror(f)) { free(de);
r = EXIT_FAILURE;
log_error("Failed to read from file %s: %m", fn);
}
free(fn);
fclose(f);
} }
free(de);
HASHMAP_FOREACH(i, globs, iterator) HASHMAP_FOREACH(i, globs, iterator)
if (process_item(i) < 0) if (process_item(i) < 0)
r = EXIT_FAILURE; r = EXIT_FAILURE;