--- I'm not sure if this can be actually as useful as I envisioned. At least in case of systemd.spec there's a lot of special-casing required, which partially destroys the usefulness of this. Configuration for "normal" packages will hopefully be more straighforward.
I made the switch name generic, so that other "transforms" can be added later without complicating the command-line api. Zbyszek src/tmpfiles/tmpfiles.c | 144 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 107 insertions(+), 37 deletions(-) diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 6e36dc7..008bc16 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -101,6 +101,10 @@ typedef struct Item { bool keep_first_level:1; } Item; +enum { + TRANSFORM_RPM = 1, +}; + static Hashmap *items = NULL, *globs = NULL; static Set *unix_sockets = NULL; @@ -108,6 +112,7 @@ static bool arg_create = false; static bool arg_clean = false; static bool arg_remove = false; static bool arg_boot = false; +static int arg_transform = 0; static char **include_prefixes = NULL; static char **exclude_prefixes = NULL; @@ -125,7 +130,13 @@ static const char conf_file_dirs[] = #define MAX_DEPTH 256 static bool needs_glob(ItemType t) { - return t == IGNORE_PATH || t == IGNORE_DIRECTORY_PATH || t == REMOVE_PATH || t == RECURSIVE_REMOVE_PATH || t == RELABEL_PATH || t == RECURSIVE_RELABEL_PATH; + return IN_SET(t, + IGNORE_PATH, + IGNORE_DIRECTORY_PATH, + REMOVE_PATH, + RECURSIVE_REMOVE_PATH, + RELABEL_PATH, + RECURSIVE_RELABEL_PATH); } static struct Item* find_glob(Hashmap *h, const char *match) { @@ -972,22 +983,55 @@ static int clean_item(Item *i) { return r; } +static int transform_item(Item *i, int transform) { + assert(i); + assert(transform == TRANSFORM_RPM); + + switch (i->type) { + + case IGNORE_PATH: + case IGNORE_DIRECTORY_PATH: + case REMOVE_PATH: + case RECURSIVE_REMOVE_PATH: + case ADJUST_MODE: + case TRUNCATE_DIRECTORY: + case RELABEL_PATH: + case RECURSIVE_RELABEL_PATH: + log_debug("%s ignored.", i->path); + return 0; + + case CREATE_FILE: + case TRUNCATE_FILE: + case WRITE_FILE: + case CREATE_FIFO: + case CREATE_SYMLINK: + case CREATE_BLOCK_DEVICE: + case CREATE_CHAR_DEVICE: + printf("%%ghost %s\n", i->path); + break; + + case CREATE_DIRECTORY: + printf("%%ghost %%dir %s\n", i->path); + break; + } + + return 0; +} + static int process_item(Item *i) { - int r, q, p; + int r, q, p, s; assert(i); r = arg_create ? create_item(i) : 0; q = arg_remove ? remove_item(i) : 0; p = arg_clean ? clean_item(i) : 0; + s = arg_transform ? transform_item(i, arg_transform) : 0; - if (r < 0) - return r; - - if (q < 0) - return q; - - return p; + return r < 0 ? r : + q < 0 ? q : + p < 0 ? p : + s; } static void item_free(Item *i) { @@ -1270,14 +1314,15 @@ 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" - " --version Show package version\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", + " -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" + " --boot Execute actions only safe at boot\n" + " --transform=rpm Create files list suitable for RPM %%files section\n" + " --prefix=PATH Only apply rules that match the specified prefix\n" + " --exclude-prefix=PATH Ignore rules that match the specified prefix\n", program_invocation_short_name); return 0; @@ -1291,19 +1336,21 @@ static int parse_argv(int argc, char *argv[]) { ARG_CLEAN, ARG_REMOVE, ARG_BOOT, + ARG_TRANSFORM, 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 }, - { "boot", no_argument, NULL, ARG_BOOT }, - { "prefix", required_argument, NULL, ARG_PREFIX }, - { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX }, + { "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 }, + { "transform", required_argument, NULL, ARG_TRANSFORM }, + { "boot", no_argument, NULL, ARG_BOOT }, + { "prefix", required_argument, NULL, ARG_PREFIX }, + { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX }, {} }; @@ -1336,6 +1383,16 @@ static int parse_argv(int argc, char *argv[]) { arg_remove = true; break; + case ARG_TRANSFORM: + if (streq(optarg, "rpm")) { + arg_transform = TRANSFORM_RPM; + arg_boot = true; + } else { + log_error("Unknown transformation '%s'", optarg); + return -EINVAL; + } + break; + case ARG_BOOT: arg_boot = true; break; @@ -1358,31 +1415,44 @@ static int parse_argv(int argc, char *argv[]) { } } - if (!arg_clean && !arg_create && !arg_remove) { - log_error("You need to specify at least one of --clean, --create or --remove."); + if ((arg_clean || arg_create || arg_remove) + !!arg_transform != 1) { + log_error("You must specify at least one of --clean/--create/--remove, or only --transform."); + return -EINVAL; + } + + if (arg_transform && optind >= argc) { + log_error("Configuration file must be specified with --transform"); return -EINVAL; } return 1; } -static int read_config_file(const char *fn, bool ignore_enoent) { +static int read_config_file(const char *fn, bool ignore_enoent, bool real_path) { _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; Iterator iterator; unsigned v = 0; Item *i; - int r; + int r = 0; assert(fn); - r = search_and_fopen_nulstr(fn, "re", conf_file_dirs, &f); - if (r < 0) { - if (ignore_enoent && r == -ENOENT) - return 0; + if (real_path) { + f = fopen(fn, "re"); + if (!f) { + log_error("Failed to open '%s': %m", fn); + return -errno; + } + } else { + r = search_and_fopen_nulstr(fn, "re", conf_file_dirs, &f); + if (r < 0) { + if (ignore_enoent && r == -ENOENT) + return 0; - log_error("Failed to open '%s', ignoring: %s", fn, strerror(-r)); - return r; + log_error("Failed to open '%s', ignoring: %s", fn, strerror(-r)); + return r; + } } FOREACH_LINE(line, f, break) { @@ -1468,7 +1538,7 @@ int main(int argc, char *argv[]) { int j; for (j = optind; j < argc; j++) { - k = read_config_file(argv[j], false); + k = read_config_file(argv[j], false, !!arg_transform); if (k < 0 && r == 0) r = k; } @@ -1484,7 +1554,7 @@ int main(int argc, char *argv[]) { } STRV_FOREACH(f, files) { - k = read_config_file(*f, true); + k = read_config_file(*f, true, false); if (k < 0 && r == 0) r = k; } -- 1.8.5.3 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel