assert(p);
- LIST_FOREACH(units_per_type, other, p->meta.manager->units_per_type[UNIT_MOUNT])
+ LIST_FOREACH(units_by_type, other, p->meta.manager->units_by_type[UNIT_MOUNT])
if ((r = path_add_one_mount_link(p, (Mount*) other)) < 0)
return r;
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
};
unit_notify(UNIT(p), state_translation_table[old_state], state_translation_table[state], true);
}
-static void path_enter_waiting(Path *p, bool initial, bool recheck, bool skip_watch);
+static void path_enter_waiting(Path *p, bool initial, bool recheck);
static int path_coldplug(Unit *u) {
Path *p = PATH(u);
if (p->deserialized_state == PATH_WAITING ||
p->deserialized_state == PATH_RUNNING)
- path_enter_waiting(p, true, true, false);
+ path_enter_waiting(p, true, true);
else
path_set_state(p, p->deserialized_state);
}
dbus_error_free(&error);
}
-
-static void path_enter_waiting(Path *p, bool initial, bool recheck, bool skip_watch) {
+static bool path_check_good(Path *p, bool initial) {
PathSpec *s;
- int r;
bool good = false;
- if (!recheck)
- goto waiting;
+ assert(p);
LIST_FOREACH(spec, s, p->specs) {
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;
break;
}
- if (good) {
- log_debug("%s got triggered.", p->meta.id);
- path_enter_running(p);
- return;
- }
+ return good;
+}
-waiting:
- if (!skip_watch) {
- if ((r = path_watch(p)) < 0)
- goto fail;
+static void path_enter_waiting(Path *p, bool initial, bool recheck) {
+ int r;
- /* Hmm, so now we have created inotify watches, but the file
- * might have appeared/been removed by now, so we must
- * recheck */
- path_enter_waiting(p, false, true, true);
- return;
- }
+ if (recheck)
+ if (path_check_good(p, initial)) {
+ log_debug("%s got triggered.", p->meta.id);
+ path_enter_running(p);
+ return;
+ }
+
+ if ((r = path_watch(p)) < 0)
+ goto fail;
+
+ /* Hmm, so now we have created inotify watches, but the file
+ * might have appeared/been removed by now, so we must
+ * recheck */
+
+ if (recheck)
+ if (path_check_good(p, false)) {
+ log_debug("%s got triggered.", p->meta.id);
+ path_enter_running(p);
+ return;
+ }
path_set_state(p, PATH_WAITING);
return;
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)
path_mkdir(p);
p->failure = false;
- path_enter_waiting(p, true, true, false);
+ path_enter_waiting(p, true, true);
return 0;
}
goto fail;
}
+ assert(l > 0);
+
if (!(buf = malloc(l))) {
- log_error("Failed to allocate buffer: %s", strerror(-ENOMEM));
+ log_error("Failed to allocate buffer: %s", strerror(ENOMEM));
goto fail;
}
if (changed)
path_enter_running(p);
else
- path_enter_waiting(p, false, true, false);
+ path_enter_waiting(p, false, true);
free(buf);
/* Hmm, so inotify was triggered since the
* last activation, so I guess we need to
* recheck what is going on. */
- path_enter_waiting(p, false, p->inotify_triggered, false);
+ path_enter_waiting(p, false, p->inotify_triggered);
}
}
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"
};
const UnitVTable path_vtable = {
.suffix = ".path",
+ .sections =
+ "Unit\0"
+ "Path\0"
+ "Install\0",
.init = path_init,
.done = path_done,