X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=unit.c;h=e6e5574312161668f8b7133010cd815bc2267d85;hp=15401e24fe0660cd3540b146e00b84ffcf439715;hb=acbb02252a38214ecba3aa8a5c9b3669f9c9317e;hpb=87f0e418cf2c58b3201d06a60e3696ec672d2662 diff --git a/unit.c b/unit.c index 15401e24f..e6e557431 100644 --- a/unit.c +++ b/unit.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include "set.h" #include "unit.h" @@ -206,6 +208,7 @@ void unit_free(Unit *u) { bidi_set_free(u, u->meta.dependencies[d]); free(u->meta.description); + free(u->meta.load_path); while ((t = set_steal_first(u->meta.names))) free(t); @@ -338,6 +341,9 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { prefix, load_state_table[u->meta.load_state], prefix, active_state_table[unit_active_state(u)]); + if (u->meta.load_path) + fprintf(f, "%s\tLoad Path: %s\n", prefix, u->meta.load_path); + SET_FOREACH(t, u->meta.names, i) fprintf(f, "%s\tName: %s\n", prefix, t); @@ -621,33 +627,44 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) { retroactively_stop_dependencies(u); } -int unit_watch_fd(Unit *u, int fd, uint32_t events) { +int unit_watch_fd(Unit *u, int fd, uint32_t events, Watch *w) { struct epoll_event ev; assert(u); assert(fd >= 0); + assert(w); + assert(w->type == WATCH_INVALID || (w->type == WATCH_FD && w->fd == fd && w->unit == u)); zero(ev); - ev.data.fd = fd; - ev.data.ptr = u; - ev.data.u32 = MANAGER_FD; + ev.data.ptr = w; ev.events = events; - if (epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) >= 0) - return 0; + if (epoll_ctl(u->meta.manager->epoll_fd, + w->type == WATCH_INVALID ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, + fd, + &ev) < 0) + return -errno; - if (errno == EEXIST) - if (epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_MOD, fd, &ev) >= 0) - return 0; + w->fd = fd; + w->type = WATCH_FD; + w->unit = u; - return -errno; + return 0; } -void unit_unwatch_fd(Unit *u, int fd) { +void unit_unwatch_fd(Unit *u, Watch *w) { assert(u); - assert(fd >= 0); + assert(w); + + if (w->type == WATCH_INVALID) + return; - assert_se(epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_DEL, fd, NULL) >= 0 || errno == ENOENT); + assert(w->type == WATCH_FD && w->unit == u); + assert_se(epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0); + + w->fd = -1; + w->type = WATCH_INVALID; + w->unit = NULL; } int unit_watch_pid(Unit *u, pid_t pid) { @@ -664,25 +681,22 @@ void unit_unwatch_pid(Unit *u, pid_t pid) { hashmap_remove(u->meta.manager->watch_pids, UINT32_TO_PTR(pid)); } -int unit_watch_timer(Unit *u, usec_t delay, int *id) { - struct epoll_event ev; - int fd; +int unit_watch_timer(Unit *u, usec_t delay, Watch *w) { struct itimerspec its; - int flags; + int flags, fd; bool ours; assert(u); - assert(id); + assert(w); + assert(w->type == WATCH_INVALID || (w->type == WATCH_TIMER && w->unit == u)); /* This will try to reuse the old timer if there is one */ - if (*id >= 0) { + if (w->type == WATCH_TIMER) { ours = false; - fd = *id; - + fd = w->fd; } else { ours = true; - if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) return -errno; } @@ -705,16 +719,21 @@ int unit_watch_timer(Unit *u, usec_t delay, int *id) { if (timerfd_settime(fd, flags, &its, NULL) < 0) goto fail; - zero(ev); - ev.data.fd = fd; - ev.data.ptr = u; - ev.data.u32 = MANAGER_TIMER; - ev.events = POLLIN; + if (w->type == WATCH_INVALID) { + struct epoll_event ev; - if (epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) - goto fail; + zero(ev); + ev.data.ptr = w; + ev.events = POLLIN; + + if (epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) + goto fail; + } + + w->fd = fd; + w->type = WATCH_TIMER; + w->unit = u; - *id = fd; return 0; fail: @@ -724,16 +743,21 @@ fail: return -errno; } -void unit_unwatch_timer(Unit *u, int *id) { +void unit_unwatch_timer(Unit *u, Watch *w) { assert(u); - assert(id); + assert(w); - if (*id < 0) + if (w->type == WATCH_INVALID) return; - assert_se(epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_DEL, *id, NULL) >= 0); - assert_se(close_nointr(*id) == 0); - *id = -1; + assert(w->type == WATCH_TIMER && w->unit == u); + + assert_se(epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0); + assert_se(close_nointr(w->fd) == 0); + + w->fd = -1; + w->type = WATCH_INVALID; + w->unit = NULL; } bool unit_job_is_applicable(Unit *u, JobType j) { @@ -805,3 +829,42 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other) { return 0; } + +const char *unit_path(void) { + char *e; + + if ((e = getenv("UNIT_PATH"))) + if (path_is_absolute(e)) + return e; + + return UNIT_PATH; +} + +int set_unit_path(const char *p) { + char *cwd, *c; + int r; + + /* This is mostly for debug purposes */ + + if (path_is_absolute(p)) { + if (!(c = strdup(p))) + return -ENOMEM; + } else { + if (!(cwd = get_current_dir_name())) + return -errno; + + r = asprintf(&c, "%s/%s", cwd, p); + free(cwd); + + if (r < 0) + return -ENOMEM; + } + + if (setenv("UNIT_PATH", c, 0) < 0) { + r = -errno; + free(c); + return r; + } + + return 0; +}