path.c revision e2f3b44cfc8864bfea7c77ff4c383ce9b535f27e
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch/***
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch This file is part of systemd.
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen Copyright 2010 Lennart Poettering
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch systemd is free software; you can redistribute it and/or modify it
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch under the terms of the GNU General Public License as published by
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch the Free Software Foundation; either version 2 of the License, or
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch (at your option) any later version.
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch systemd is distributed in the hope that it will be useful, but
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch WITHOUT ANY WARRANTY; without even the implied warranty of
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch General Public License for more details.
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch You should have received a copy of the GNU General Public License
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch along with systemd; If not, see <http://www.gnu.org/licenses/>.
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch***/
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include <sys/inotify.h>
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include <sys/epoll.h>
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include <sys/ioctl.h>
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include <errno.h>
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include <unistd.h>
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "unit.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "unit-name.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "path.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "dbus-path.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "special.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "bus-errors.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic const UnitActiveState state_translation_table[_PATH_STATE_MAX] = {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch [PATH_DEAD] = UNIT_INACTIVE,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch [PATH_WAITING] = UNIT_ACTIVE,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch [PATH_RUNNING] = UNIT_ACTIVE,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch [PATH_FAILED] = UNIT_FAILED
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch};
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void path_unwatch_one(Path *p, PathSpec *s) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (s->inotify_fd < 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch unit_unwatch_fd(UNIT(p), &s->watch);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch close_nointr_nofail(s->inotify_fd);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch s->inotify_fd = -1;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Boschstatic void path_done(Unit *u) {
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch Path *p = PATH(u);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch PathSpec *s;
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch while ((s = p->specs)) {
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch path_unwatch_one(p, s);
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch LIST_REMOVE(PathSpec, spec, p->specs, s);
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch free(s->path);
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch free(s);
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch }
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch}
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschint path_add_one_mount_link(Path *p, Mount *m) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch PathSpec *s;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch int r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch assert(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(m);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (p->meta.load_state != UNIT_LOADED ||
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch m->meta.load_state != UNIT_LOADED)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch LIST_FOREACH(spec, s, p->specs) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (!path_startswith(s->path, m->where))
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch continue;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((r = unit_add_two_dependencies(UNIT(p), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true)) < 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic int path_add_mount_links(Path *p) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch Meta *other;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch int r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen assert(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch LIST_FOREACH(units_per_type, other, p->meta.manager->units_per_type[UNIT_MOUNT])
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((r = path_add_one_mount_link(p, (Mount*) other)) < 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic int path_verify(Path *p) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen if (p->meta.load_state != UNIT_LOADED)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (!p->specs) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch log_error("%s lacks path setting. Refusing.", p->meta.id);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return -EINVAL;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return 0;
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic int path_add_default_dependencies(Path *p) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch int r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (p->meta.manager->running_as == MANAGER_SYSTEM) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((r = unit_add_dependency_by_name(UNIT(p), UNIT_BEFORE, SPECIAL_BASIC_TARGET, NULL, true)) < 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((r = unit_add_two_dependencies_by_name(UNIT(p), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true)) < 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return unit_add_two_dependencies_by_name(UNIT(p), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic int path_load(Unit *u) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch Path *p = PATH(u);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch int r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(u);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(u->meta.load_state == UNIT_STUB);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((r = unit_load_fragment_and_dropin(u)) < 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (u->meta.load_state == UNIT_LOADED) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch if (!p->unit)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((r = unit_load_related_unit(u, ".service", &p->unit)))
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((r = unit_add_dependency(u, UNIT_BEFORE, p->unit, true)) < 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((r = path_add_mount_links(p)) < 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (p->meta.default_dependencies)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((r = path_add_default_dependencies(p)) < 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return path_verify(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void path_dump(Unit *u, FILE *f, const char *prefix) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch Path *p = PATH(u);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch PathSpec *s;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(f);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch fprintf(f,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch "%sPath State: %s\n"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch "%sUnit: %s\n",
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch prefix, path_state_to_string(p->state),
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch prefix, p->unit->meta.id);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch LIST_FOREACH(spec, s, p->specs)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch fprintf(f,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch "%s%s: %s\n",
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch prefix,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_type_to_string(s->type),
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch s->path);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic int path_watch_one(Path *p, PathSpec *s) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch static const int flags_table[_PATH_TYPE_MAX] = {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch [PATH_EXISTS] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch [PATH_CHANGED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch [PATH_DIRECTORY_NOT_EMPTY] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch };
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch bool exists = false;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch char *k, *slash;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch int r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(s);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_unwatch_one(p, s);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (!(k = strdup(s->path)))
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return -ENOMEM;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((s->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC)) < 0) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch r = -errno;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch goto fail;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (unit_watch_fd(UNIT(p), s->inotify_fd, EPOLLIN, &s->watch) < 0) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch r = -errno;
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen goto fail;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((s->primary_wd = inotify_add_watch(s->inotify_fd, k, flags_table[s->type])) >= 0)
639bb36b12b9f9bb54c8bb1be50eac623622f8a0Timo Sirainen exists = true;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch do {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch int flags;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* This assumes the path was passed through path_kill_slashes()! */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (!(slash = strrchr(k, '/')))
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch break;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* Trim the path at the last slash. Keep the slash if it's the root dir. */
639bb36b12b9f9bb54c8bb1be50eac623622f8a0Timo Sirainen slash[slash == k] = 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch flags = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (!exists)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch flags |= IN_CREATE | IN_MOVED_TO;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (inotify_add_watch(s->inotify_fd, k, flags) >= 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch exists = true;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch } while (slash != k);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return 0;
639bb36b12b9f9bb54c8bb1be50eac623622f8a0Timo Sirainen
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschfail:
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch free(k);
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_unwatch_one(p, s);
639bb36b12b9f9bb54c8bb1be50eac623622f8a0Timo Sirainen return r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void path_unwatch(Path *p) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch PathSpec *s;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch LIST_FOREACH(spec, s, p->specs)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_unwatch_one(p, s);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
639bb36b12b9f9bb54c8bb1be50eac623622f8a0Timo Sirainen
4351efdddced25735d629496f6c68c9d0cfb896aTimo Sirainenstatic int path_watch(Path *p) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch int r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch PathSpec *s;
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen assert(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch LIST_FOREACH(spec, s, p->specs)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((r = path_watch_one(p, s)) < 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch return 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
0e702716169a158b87d08e21d1a128eb99e23fa1Phil Carmody
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void path_set_state(Path *p, PathState state) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch PathState old_state;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch old_state = p->state;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch p->state = state;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (state != PATH_WAITING &&
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch (state != PATH_RUNNING || p->inotify_triggered))
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_unwatch(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (state != old_state)
639bb36b12b9f9bb54c8bb1be50eac623622f8a0Timo Sirainen log_debug("%s changed %s -> %s",
0e702716169a158b87d08e21d1a128eb99e23fa1Phil Carmody p->meta.id,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_state_to_string(old_state),
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_state_to_string(state));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch unit_notify(UNIT(p), state_translation_table[old_state], state_translation_table[state], true);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void path_enter_waiting(Path *p, bool initial, bool recheck);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic int path_coldplug(Unit *u) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch Path *p = PATH(u);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(p->state == PATH_DEAD);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (p->deserialized_state != p->state) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (p->deserialized_state == PATH_WAITING ||
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch p->deserialized_state == PATH_RUNNING)
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch path_enter_waiting(p, true, true);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch else
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_set_state(p, p->deserialized_state);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void path_enter_dead(Path *p, bool success) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (!success)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch p->failure = true;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_set_state(p, p->failure ? PATH_FAILED : PATH_DEAD);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void path_enter_running(Path *p) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch int r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch DBusError error;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch dbus_error_init(&error);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* Don't start job if we are supposed to go down */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (p->meta.job && p->meta.job->type == JOB_STOP)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((r = manager_add_job(p->meta.manager, JOB_START, p->unit, JOB_REPLACE, true, &error, NULL)) < 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch goto fail;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch p->inotify_triggered = false;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((r = path_watch(p)) < 0)
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch goto fail;
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch path_set_state(p, PATH_RUNNING);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschfail:
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch log_warning("%s failed to queue unit startup job: %s", p->meta.id, bus_error(&error, r));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_enter_dead(p, false);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch dbus_error_free(&error);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void path_enter_waiting(Path *p, bool initial, bool recheck) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch PathSpec *s;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch int r;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch bool good = false;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (!recheck)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch goto waiting;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch LIST_FOREACH(spec, s, p->specs) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch switch (s->type) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch case PATH_EXISTS:
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch good = access(s->path, F_OK) >= 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch break;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch case PATH_DIRECTORY_NOT_EMPTY: {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch int k;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch k = dir_is_empty(s->path);
f3cf2f02155c4bac23fd50f0de96c0cae9c46478Stephan Bosch good = !(k == -ENOENT || k > 0);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch break;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch case PATH_CHANGED: {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch bool b;
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch b = access(s->path, F_OK) >= 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch good = !initial && b != s->previous_exists;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch s->previous_exists = b;
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch break;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch default:
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (good)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch break;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (good) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch log_debug("%s got triggered.", p->meta.id);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_enter_running(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschwaiting:
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((r = path_watch(p)) < 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch goto fail;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_set_state(p, PATH_WAITING);
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch return;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschfail:
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch log_warning("%s failed to enter waiting state: %s", p->meta.id, strerror(-r));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_enter_dead(p, false);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic int path_start(Unit *u) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch Path *p = PATH(u);
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(p->state == PATH_DEAD || p->state == PATH_FAILED);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch if (p->unit->meta.load_state != UNIT_LOADED)
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen return -ENOENT;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch p->failure = false;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_enter_waiting(p, true, true);
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch return 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic int path_stop(Unit *u) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch Path *p = PATH(u);
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch assert(p);
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch assert(p->state == PATH_WAITING || p->state == PATH_RUNNING);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_enter_dead(p, true);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic int path_serialize(Unit *u, FILE *f, FDSet *fds) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch Path *p = PATH(u);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(u);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(f);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(fds);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch unit_serialize_item(u, f, "state", path_state_to_string(p->state));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic int path_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch Path *p = PATH(u);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(u);
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen assert(key);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(value);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(fds);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (streq(key, "state")) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch PathState state;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((state = path_state_from_string(value)) < 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch log_debug("Failed to parse state value %s", value);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch else
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch p->deserialized_state = state;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch } else
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch log_debug("Unknown serialization key '%s'", key);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return 0;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic UnitActiveState path_active_state(Unit *u) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(u);
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return state_translation_table[PATH(u)->state];
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic const char *path_sub_state_to_string(Unit *u) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(u);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return path_state_to_string(PATH(u)->state);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
f3cf2f02155c4bac23fd50f0de96c0cae9c46478Stephan Bosch Path *p = PATH(u);
f3cf2f02155c4bac23fd50f0de96c0cae9c46478Stephan Bosch int l;
f3cf2f02155c4bac23fd50f0de96c0cae9c46478Stephan Bosch ssize_t k;
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen uint8_t *buf = NULL;
f3cf2f02155c4bac23fd50f0de96c0cae9c46478Stephan Bosch struct inotify_event *e;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch PathSpec *s;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch bool changed;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(p);
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch assert(fd >= 0);
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch if (p->state != PATH_WAITING &&
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch p->state != PATH_RUNNING)
009217abb57a24a4076092e8e4e165545747839eStephan Bosch return;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* log_debug("inotify wakeup on %s.", u->meta.id); */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (events != EPOLLIN) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch log_error("Got Invalid poll event on inotify.");
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch goto fail;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
009217abb57a24a4076092e8e4e165545747839eStephan Bosch
009217abb57a24a4076092e8e4e165545747839eStephan Bosch LIST_FOREACH(spec, s, p->specs)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (s->inotify_fd == fd)
009217abb57a24a4076092e8e4e165545747839eStephan Bosch break;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch
009217abb57a24a4076092e8e4e165545747839eStephan Bosch if (!s) {
009217abb57a24a4076092e8e4e165545747839eStephan Bosch log_error("Got event on unknown fd.");
009217abb57a24a4076092e8e4e165545747839eStephan Bosch goto fail;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (ioctl(fd, FIONREAD, &l) < 0) {
009217abb57a24a4076092e8e4e165545747839eStephan Bosch log_error("FIONREAD failed: %s", strerror(errno));
009217abb57a24a4076092e8e4e165545747839eStephan Bosch goto fail;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
009217abb57a24a4076092e8e4e165545747839eStephan Bosch if (!(buf = malloc(l))) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch log_error("Failed to allocate buffer: %s", strerror(-ENOMEM));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch goto fail;
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch }
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((k = read(fd, buf, l)) < 0) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch log_error("Failed to read inotify event: %s", strerror(-errno));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch goto fail;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* If we are already running, then remember that one event was
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch * dispatched so that we restart the service only if something
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch * actually changed on disk */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch p->inotify_triggered = true;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch e = (struct inotify_event*) buf;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch changed = false;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch while (k > 0) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch size_t step;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (s->type == PATH_CHANGED && s->primary_wd == e->wd)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch changed = true;
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch step = sizeof(struct inotify_event) + e->len;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(step <= (size_t) k);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch e = (struct inotify_event*) ((uint8_t*) e + step);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch k -= step;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (changed)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_enter_running(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch else
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_enter_waiting(p, false, true);
f3cf2f02155c4bac23fd50f0de96c0cae9c46478Stephan Bosch
f3cf2f02155c4bac23fd50f0de96c0cae9c46478Stephan Bosch free(buf);
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch
bcd6c13936df11167350ac86598a781dce9038c3Stephan Boschfail:
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch free(buf);
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch path_enter_dead(p, false);
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch}
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch
bcd6c13936df11167350ac86598a781dce9038c3Stephan Boschvoid path_unit_notify(Unit *u, UnitActiveState new_state) {
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch char *n;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch int r;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch Iterator i;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (u->meta.type == UNIT_PATH)
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch return;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch SET_FOREACH(n, u->meta.names, i) {
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch char *k;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch Unit *t;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch Path *p;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch if (!(k = unit_name_change_suffix(n, ".path"))) {
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch r = -ENOMEM;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch goto fail;
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch }
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch
bcd6c13936df11167350ac86598a781dce9038c3Stephan Bosch t = manager_get_unit(u->meta.manager, k);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch free(k);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (!t)
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch continue;
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch if (t->meta.load_state != UNIT_LOADED)
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch continue;
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch p = PATH(t);
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch if (p->unit != u)
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch continue;
3ec5378aadaa699c38b2e02be30aae1add36eb7cTimo Sirainen
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch if (p->state == PATH_RUNNING && new_state == UNIT_INACTIVE) {
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch log_debug("%s got notified about unit deactivation.", p->meta.id);
df70bf8c997cd91452cdb3a5c2e20605d30446d2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* Hmm, so inotify was triggered since the
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch * last activation, so I guess we need to
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch * recheck what is going on. */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_enter_waiting(p, false, p->inotify_triggered);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschfail:
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch log_error("Failed find path unit: %s", strerror(-r));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void path_reset_failed(Unit *u) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch Path *p = PATH(u);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch assert(p);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (p->state == PATH_FAILED)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch path_set_state(p, PATH_DEAD);
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch p->failure = false;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic const char* const path_state_table[_PATH_STATE_MAX] = {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch [PATH_DEAD] = "dead",
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch [PATH_WAITING] = "waiting",
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch [PATH_RUNNING] = "running",
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch [PATH_FAILED] = "failed"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch};
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan BoschDEFINE_STRING_TABLE_LOOKUP(path_state, PathState);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic const char* const path_type_table[_PATH_TYPE_MAX] = {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch [PATH_EXISTS] = "PathExists",
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch [PATH_CHANGED] = "PathChanged",
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch [PATH_DIRECTORY_NOT_EMPTY] = "DirectoryNotEmpty"
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen};
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch
7a545edbd1fca7a330bcb4a807002373ee18762aStephan BoschDEFINE_STRING_TABLE_LOOKUP(path_type, PathType);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Boschconst UnitVTable path_vtable = {
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch .suffix = ".path",
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch .done = path_done,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch .load = path_load,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch .coldplug = path_coldplug,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch .dump = path_dump,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch .start = path_start,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch .stop = path_stop,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch .serialize = path_serialize,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch .deserialize_item = path_deserialize_item,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch .active_state = path_active_state,
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch .sub_state_to_string = path_sub_state_to_string,
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch .fd_event = path_fd_event,
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch .reset_failed = path_reset_failed,
05262e3132642bbdc4a8087c17b0903cf2ff22d2Stephan Bosch
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch .bus_interface = "org.freedesktop.systemd1.Path",
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch .bus_message_handler = bus_path_message_handler
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch};
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch