[systemd-devel] [RFC/PATCH] tmpfiles: implement --transform=rpm
Zbigniew Jędrzejewski-Szmek
zbyszek at in.waw.pl
Sat Mar 1 18:06:14 PST 2014
---
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
More information about the systemd-devel
mailing list