From 8092a428d40ac682df9e80c36988043854579679 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 7 Jul 2011 02:07:39 +0200 Subject: path,unit: support globbing in conditions and path units --- src/condition.c | 6 ++++++ src/condition.h | 1 + src/load-fragment.c | 12 +++++++----- src/path.c | 8 +++++++- src/path.h | 1 + src/util.c | 25 +++++++++++++++++++++++++ src/util.h | 2 ++ 7 files changed, 49 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/condition.c b/src/condition.c index a520e43436..76ee0370d2 100644 --- a/src/condition.c +++ b/src/condition.c @@ -34,6 +34,8 @@ Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) { Condition *c; + assert(type < _CONDITION_TYPE_MAX); + if (!(c = new0(Condition, 1))) return NULL; @@ -148,6 +150,9 @@ bool condition_test(Condition *c) { case CONDITION_PATH_EXISTS: return (access(c->parameter, F_OK) >= 0) == !c->negate; + case CONDITION_PATH_EXISTS_GLOB: + return (glob_exists(c->parameter) > 0) == !c->negate; + case CONDITION_PATH_IS_DIRECTORY: { struct stat st; @@ -231,6 +236,7 @@ void condition_dump_list(Condition *first, FILE *f, const char *prefix) { static const char* const condition_type_table[_CONDITION_TYPE_MAX] = { [CONDITION_PATH_EXISTS] = "ConditionPathExists", + [CONDITION_PATH_EXISTS_GLOB] = "ConditionPathExistsGlob", [CONDITION_PATH_IS_DIRECTORY] = "ConditionPathIsDirectory", [CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty", [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine", diff --git a/src/condition.h b/src/condition.h index 84028028c4..ff896a793a 100644 --- a/src/condition.h +++ b/src/condition.h @@ -28,6 +28,7 @@ typedef enum ConditionType { CONDITION_PATH_EXISTS, + CONDITION_PATH_EXISTS_GLOB, CONDITION_PATH_IS_DIRECTORY, CONDITION_DIRECTORY_NOT_EMPTY, CONDITION_KERNEL_COMMAND_LINE, diff --git a/src/load-fragment.c b/src/load-fragment.c index 8f39839986..05e60bf8fd 100644 --- a/src/load-fragment.c +++ b/src/load-fragment.c @@ -1999,12 +1999,13 @@ static int load_from_path(Unit *u, const char *path) { { "IgnoreOnIsolate", config_parse_bool, 0, &u->meta.ignore_on_isolate, "Unit" }, { "IgnoreOnSnapshot", config_parse_bool, 0, &u->meta.ignore_on_snapshot, "Unit" }, { "JobTimeoutSec", config_parse_usec, 0, &u->meta.job_timeout, "Unit" }, - { "ConditionPathExists", config_parse_condition_path, CONDITION_PATH_EXISTS, u, "Unit" }, - { "ConditionPathIsDirectory", config_parse_condition_path, CONDITION_PATH_IS_DIRECTORY, u, "Unit" }, - { "ConditionDirectoryNotEmpty", config_parse_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, u, "Unit" }, + { "ConditionPathExists", config_parse_condition_path, CONDITION_PATH_EXISTS, u, "Unit" }, + { "ConditionPathExistsGlob", config_parse_condition_path, CONDITION_PATH_EXISTS_GLOB, u, "Unit" }, + { "ConditionPathIsDirectory", config_parse_condition_path, CONDITION_PATH_IS_DIRECTORY, u, "Unit" }, + { "ConditionDirectoryNotEmpty", config_parse_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, u, "Unit" }, { "ConditionKernelCommandLine", config_parse_condition_string, CONDITION_KERNEL_COMMAND_LINE, u, "Unit" }, - { "ConditionVirtualization", config_parse_condition_string, CONDITION_VIRTUALIZATION, u, "Unit" }, - { "ConditionSecurity", config_parse_condition_string, CONDITION_SECURITY, u, "Unit" }, + { "ConditionVirtualization", config_parse_condition_string, CONDITION_VIRTUALIZATION, u, "Unit" }, + { "ConditionSecurity", config_parse_condition_string, CONDITION_SECURITY, u, "Unit" }, { "ConditionNull", config_parse_condition_null, 0, u, "Unit" }, { "PIDFile", config_parse_path_printf, 0, &u->service.pid_file, "Service" }, @@ -2094,6 +2095,7 @@ static int load_from_path(Unit *u, const char *path) { { "Unit", config_parse_timer_unit, 0, &u->timer, "Timer" }, { "PathExists", config_parse_path_spec, 0, &u->path, "Path" }, + { "PathExistsGlob", config_parse_path_spec, 0, &u->path, "Path" }, { "PathChanged", config_parse_path_spec, 0, &u->path, "Path" }, { "DirectoryNotEmpty", config_parse_path_spec, 0, &u->path, "Path" }, { "Unit", config_parse_path_unit, 0, &u->path, "Path" }, diff --git a/src/path.c b/src/path.c index 1c20dcfed6..200fc2bdcb 100644 --- a/src/path.c +++ b/src/path.c @@ -197,6 +197,7 @@ static void path_dump(Unit *u, FILE *f, const char *prefix) { static int path_watch_one(Path *p, PathSpec *s) { static const int flags_table[_PATH_TYPE_MAX] = { [PATH_EXISTS] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB, + [PATH_EXISTS_GLOB] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB, [PATH_CHANGED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO, [PATH_DIRECTORY_NOT_EMPTY] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO }; @@ -367,6 +368,10 @@ static bool path_check_good(Path *p, bool initial) { good = access(s->path, F_OK) >= 0; break; + case PATH_EXISTS_GLOB: + good = glob_exists(s->path) > 0; + break; + case PATH_DIRECTORY_NOT_EMPTY: { int k; @@ -438,7 +443,7 @@ static void path_mkdir(Path *p) { LIST_FOREACH(spec, s, p->specs) { int r; - if (s->type == PATH_EXISTS) + if (s->type == PATH_EXISTS || s->type == PATH_EXISTS_GLOB) continue; if ((r = mkdir_p(s->path, p->directory_mode)) < 0) @@ -672,6 +677,7 @@ DEFINE_STRING_TABLE_LOOKUP(path_state, PathState); static const char* const path_type_table[_PATH_TYPE_MAX] = { [PATH_EXISTS] = "PathExists", + [PATH_EXISTS_GLOB] = "PathExistsGlob", [PATH_CHANGED] = "PathChanged", [PATH_DIRECTORY_NOT_EMPTY] = "DirectoryNotEmpty" }; diff --git a/src/path.h b/src/path.h index 8ba0ce6890..116fc63ff7 100644 --- a/src/path.h +++ b/src/path.h @@ -38,6 +38,7 @@ typedef enum PathState { typedef enum PathType { PATH_EXISTS, + PATH_EXISTS_GLOB, PATH_DIRECTORY_NOT_EMPTY, PATH_CHANGED, _PATH_TYPE_MAX, diff --git a/src/util.c b/src/util.c index 344b869c8c..356b4f9de2 100644 --- a/src/util.c +++ b/src/util.c @@ -53,6 +53,7 @@ #include #include #include +#include #include "macro.h" #include "util.h" @@ -5238,6 +5239,30 @@ int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **h return 0; } +int glob_exists(const char *path) { + glob_t g; + int r, k; + + assert(path); + + zero(g); + errno = 0; + k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g); + + if (k == GLOB_NOMATCH) + r = 0; + else if (k == GLOB_NOSPACE) + r = -ENOMEM; + else if (k == 0) + r = !strv_isempty(g.gl_pathv); + else + r = errno ? -errno : -EIO; + + globfree(&g); + + return r; +} + static const char *const ioprio_class_table[] = { [IOPRIO_CLASS_NONE] = "none", [IOPRIO_CLASS_RT] = "realtime", diff --git a/src/util.h b/src/util.h index 411efae933..b8bbd23e8c 100644 --- a/src/util.h +++ b/src/util.h @@ -447,6 +447,8 @@ int socket_from_display(const char *display, char **path); int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home); +int glob_exists(const char *path); + #define NULSTR_FOREACH(i, l) \ for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1) -- cgit v1.2.3-54-g00ecf