mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-10-27 18:55:09 +03:00
tmpfiles: take names of tmpfiles configuration files on the command line
This commit is contained in:
parent
eb0ca9ebff
commit
fba6e68723
2
TODO
2
TODO
@ -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
|
||||||
|
153
src/tmpfiles.c
153
src/tmpfiles.c
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user