along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/inotify.h>
-#include <sys/epoll.h>
-#include <sys/ioctl.h>
#include <errno.h>
+#include <sys/epoll.h>
+#include <sys/inotify.h>
#include <unistd.h>
-#include "unit.h"
-#include "unit-name.h"
-#include "path.h"
-#include "mkdir.h"
+#include "bus-error.h"
+#include "bus-util.h"
#include "dbus-path.h"
-#include "special.h"
-#include "path-util.h"
+#include "fd-util.h"
+#include "fs-util.h"
+#include "glob-util.h"
#include "macro.h"
-#include "bus-util.h"
-#include "bus-error.h"
+#include "mkdir.h"
+#include "path.h"
+#include "special.h"
+#include "stat-util.h"
+#include "string-table.h"
+#include "string-util.h"
+#include "unit-name.h"
+#include "unit.h"
static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = {
[PATH_DEAD] = UNIT_INACTIVE,
if (r < 0)
goto fail;
+ (void) sd_event_source_set_description(s->event_source, "path");
+
/* This assumes the path was passed through path_kill_slashes()! */
for (slash = strchr(s->path, '/'); ; slash = strchr(slash+1, '/')) {
break;
}
- log_warning("Failed to add watch on %s: %s", s->path,
- errno == ENOSPC ? "too many watches" : strerror(-r));
- r = -errno;
+ r = log_warning_errno(errno, "Failed to add watch on %s: %s", s->path, errno == ENOSPC ? "too many watches" : strerror(-r));
if (cut)
*cut = tmp;
goto fail;
}
if (!exists) {
- log_error_errno(errno, "Failed to add watch on any of the components of %s: %m",
- s->path);
- r = -errno; /* either EACCESS or ENOENT */
+ r = log_error_errno(errno, "Failed to add watch on any of the components of %s: %m", s->path);
+ /* either EACCESS or ENOENT */
goto fail;
}
}
int path_spec_fd_event(PathSpec *s, uint32_t revents) {
- _cleanup_free_ uint8_t *buf = NULL;
+ union inotify_event_buffer buffer;
struct inotify_event *e;
- ssize_t k;
- int l;
+ ssize_t l;
int r = 0;
if (revents != EPOLLIN) {
return -EINVAL;
}
- if (ioctl(s->inotify_fd, FIONREAD, &l) < 0)
- return log_error_errno(errno, "FIONREAD failed: %m");
+ l = read(s->inotify_fd, &buffer, sizeof(buffer));
+ if (l < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ return 0;
- assert(l > 0);
-
- buf = malloc(l);
- if (!buf)
- return log_oom();
-
- k = read(s->inotify_fd, buf, l);
- if (k < 0)
return log_error_errno(errno, "Failed to read inotify event: %m");
+ }
- e = (struct inotify_event*) buf;
-
- while (k > 0) {
- size_t step;
-
+ FOREACH_INOTIFY_EVENT(e, buffer, l) {
if ((s->type == PATH_CHANGED || s->type == PATH_MODIFIED) &&
s->primary_wd == e->wd)
r = 1;
-
- step = sizeof(struct inotify_event) + e->len;
- assert(step <= (size_t) k);
-
- e = (struct inotify_event*) ((uint8_t*) e + step);
- k -= step;
}
return r;
return 0;
if (!p->specs) {
- log_unit_error(UNIT(p)->id,
- "%s lacks path setting. Refusing.", UNIT(p)->id);
+ log_unit_error(UNIT(p), "Path unit lacks path setting. Refusing.");
return -EINVAL;
}
assert(p);
- r = unit_add_dependency_by_name(UNIT(p), UNIT_BEFORE,
- SPECIAL_PATHS_TARGET, NULL, true);
+ if (!UNIT(p)->default_dependencies)
+ return 0;
+
+ r = unit_add_dependency_by_name(UNIT(p), UNIT_BEFORE, SPECIAL_PATHS_TARGET, NULL, true);
if (r < 0)
return r;
- if (UNIT(p)->manager->running_as == SYSTEMD_SYSTEM) {
- r = unit_add_two_dependencies_by_name(UNIT(p), UNIT_AFTER, UNIT_REQUIRES,
- SPECIAL_SYSINIT_TARGET, NULL, true);
+ if (UNIT(p)->manager->running_as == MANAGER_SYSTEM) {
+ r = unit_add_two_dependencies_by_name(UNIT(p), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
if (r < 0)
return r;
}
- return unit_add_two_dependencies_by_name(UNIT(p), UNIT_BEFORE, UNIT_CONFLICTS,
- SPECIAL_SHUTDOWN_TARGET, NULL, true);
+ return unit_add_two_dependencies_by_name(UNIT(p), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
}
static int path_load(Unit *u) {
if (r < 0)
return r;
- if (UNIT(p)->default_dependencies) {
- r = path_add_default_dependencies(p);
- if (r < 0)
- return r;
- }
+ r = path_add_default_dependencies(p);
+ if (r < 0)
+ return r;
}
return path_verify(p);
path_unwatch(p);
if (state != old_state)
- log_debug("%s changed %s -> %s",
- UNIT(p)->id,
- path_state_to_string(old_state),
- path_state_to_string(state));
+ log_unit_debug(UNIT(p), "Changed %s -> %s", path_state_to_string(old_state), path_state_to_string(state));
unit_notify(UNIT(p), state_translation_table[old_state], state_translation_table[state], true);
}
}
static void path_enter_running(Path *p) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(p);
if (unit_stop_pending(UNIT(p)))
return;
- r = manager_add_job(UNIT(p)->manager, JOB_START, UNIT_TRIGGER(UNIT(p)),
- JOB_REPLACE, true, &error, NULL);
+ r = manager_add_job(UNIT(p)->manager, JOB_START, UNIT_TRIGGER(UNIT(p)), JOB_REPLACE, &error, NULL);
if (r < 0)
goto fail;
return;
fail:
- log_warning("%s failed to queue unit startup job: %s",
- UNIT(p)->id, bus_error_message(&error, r));
+ log_unit_warning(UNIT(p), "Failed to queue unit startup job: %s", bus_error_message(&error, r));
path_enter_dead(p, PATH_FAILURE_RESOURCES);
}
if (recheck)
if (path_check_good(p, initial)) {
- log_debug("%s got triggered.", UNIT(p)->id);
+ log_unit_debug(UNIT(p), "Got triggered.");
path_enter_running(p);
return;
}
if (recheck)
if (path_check_good(p, false)) {
- log_debug("%s got triggered.", UNIT(p)->id);
+ log_unit_debug(UNIT(p), "Got triggered.");
path_enter_running(p);
return;
}
return;
fail:
- log_warning_errno(r, "%s failed to enter waiting state: %m", UNIT(p)->id);
+ log_unit_warning_errno(UNIT(p), r, "Failed to enter waiting state: %m");
path_enter_dead(p, PATH_FAILURE_RESOURCES);
}
p->result = PATH_SUCCESS;
path_enter_waiting(p, true, true);
- return 0;
+ return 1;
}
static int path_stop(Unit *u) {
assert(p->state == PATH_WAITING || p->state == PATH_RUNNING);
path_enter_dead(p, PATH_SUCCESS);
- return 0;
+ return 1;
}
static int path_serialize(Unit *u, FILE *f, FDSet *fds) {
state = path_state_from_string(value);
if (state < 0)
- log_debug("Failed to parse state value %s", value);
+ log_unit_debug(u, "Failed to parse state value: %s", value);
else
p->deserialized_state = state;
f = path_result_from_string(value);
if (f < 0)
- log_debug("Failed to parse result value %s", value);
+ log_unit_debug(u, "Failed to parse result value: %s", value);
else if (f != PATH_SUCCESS)
p->result = f;
} else
- log_debug("Unknown serialization key '%s'", key);
+ log_unit_debug(u, "Unknown serialization key: %s", key);
return 0;
}
if (p->state == PATH_RUNNING &&
UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
- log_unit_debug(UNIT(p)->id,
- "%s got notified about unit deactivation.",
- UNIT(p)->id);
+ log_unit_debug(UNIT(p), "Got notified about unit deactivation.");
/* Hmm, so inotify was triggered since the
* last activation, so I guess we need to
p->result = PATH_SUCCESS;
}
-static const char* const path_state_table[_PATH_STATE_MAX] = {
- [PATH_DEAD] = "dead",
- [PATH_WAITING] = "waiting",
- [PATH_RUNNING] = "running",
- [PATH_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(path_state, PathState);
-
static const char* const path_type_table[_PATH_TYPE_MAX] = {
[PATH_EXISTS] = "PathExists",
[PATH_EXISTS_GLOB] = "PathExistsGlob",
.reset_failed = path_reset_failed,
- .bus_interface = "org.freedesktop.systemd1.Path",
.bus_vtable = bus_path_vtable
};