if (!(e = strrchr(n, '.')))
return false;
+ if (e == n)
+ return false;
+
for (i = n; i < e; i++)
if (!strchr(VALID_CHARS, *i))
return false;
return 0;
}
-/* FIXME: Does not rollback on failure! */
+/* FIXME: Does not rollback on failure! Needs to fix special unit
+ * pointers. Needs to merge names and dependencies properly.*/
int unit_merge(Unit *u, Unit *other) {
int r;
UnitDependency d;
/* Common implementation for multiple backends */
int unit_load_fragment_and_dropin(Unit *u) {
- int r;
+ int r, ret;
assert(u);
if ((r = unit_load_fragment(u)) < 0)
return r;
+ ret = r > 0;
+
/* Load drop-in directory data */
if ((r = unit_load_dropin(u)) < 0)
return r;
- return 0;
+ return ret;
}
int unit_load(Unit *u) {
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) {
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;
}
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:
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) {