X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=unit.c;h=dbdd7e663e5783c020f0638071a5d13ad8fa4033;hb=0ae97ec11506cce808232abd0979e20aed2fd625;hp=c722717fe66045b411fd1da243e50aa35f38bc5e;hpb=0301abf48ed3be921c33d409c73b554435cf6378;p=elogind.git diff --git a/unit.c b/unit.c index c722717fe..dbdd7e663 100644 --- a/unit.c +++ b/unit.c @@ -44,7 +44,7 @@ UnitType unit_name_to_type(const char *n) { "0123456789" \ "abcdefghijklmnopqrstuvwxyz" \ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ - "-_" + "-_.\\" bool unit_name_is_valid(const char *n) { UnitType t; @@ -62,6 +62,9 @@ bool unit_name_is_valid(const char *n) { if (!(e = strrchr(n, '.'))) return false; + if (e == n) + return false; + for (i = n; i < e; i++) if (!strchr(VALID_CHARS, *i)) return false; @@ -152,6 +155,21 @@ int unit_add_name(Unit *u, const char *text) { return 0; } +int unit_choose_id(Unit *u, const char *name) { + char *s; + + assert(u); + assert(name); + + /* Selects one of the names of this unit as the id */ + + if (!(s = set_get(u->meta.names, (char*) name))) + return -ENOENT; + + u->meta.id = s; + return 0; +} + void unit_add_to_load_queue(Unit *u) { assert(u); @@ -240,7 +258,8 @@ static int ensure_merge(Set **s, Set *other) { 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; @@ -368,7 +387,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { /* Common implementation for multiple backends */ int unit_load_fragment_and_dropin(Unit *u) { - int r; + int r, ret; assert(u); @@ -376,11 +395,13 @@ int unit_load_fragment_and_dropin(Unit *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) { @@ -627,33 +648,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(w->type == WATCH_FD && w->unit == u); + assert_se(epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0); - assert_se(epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_DEL, fd, NULL) >= 0 || errno == ENOENT); + w->fd = -1; + w->type = WATCH_INVALID; + w->unit = NULL; } int unit_watch_pid(Unit *u, pid_t pid) { @@ -670,25 +702,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; } @@ -711,16 +740,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: @@ -730,16 +764,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) { @@ -812,6 +851,19 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other) { return 0; } +int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name) { + Unit *other; + int r; + + if ((r = manager_load_unit(u->meta.manager, name, &other)) < 0) + return r; + + if ((r = unit_add_dependency(u, d, other)) < 0) + return r; + + return 0; +} + const char *unit_path(void) { char *e; @@ -850,3 +902,42 @@ int set_unit_path(const char *p) { return 0; } + +char *unit_name_escape_path(const char *path, const char *suffix) { + char *r, *t; + const char *f; + size_t a, b; + + assert(path); + assert(suffix); + + /* Takes a path and a util suffix and makes a nice unit name + * of it, escaping all weird chars on the way. + * + * / becomes _, and all chars not alloweed in a unit name get + * escaped as \xFF, including the _ and the \ itself, of + * course. This escaping is hence reversible. + */ + + a = strlen(path); + b = strlen(suffix); + + if (!(r = new(char, a*4+b+1))) + return NULL; + + for (f = path, t = r; *f; f++) { + if (*f == '/') + *(t++) = '_'; + else if (*f == '_' || *f == '\\' || !strchr(VALID_CHARS, *f)) { + *(t++) = '\\'; + *(t++) = 'x'; + *(t++) = hexchar(*f > 4); + *(t++) = hexchar(*f); + } else + *(t++) = *f; + } + + memcpy(t, suffix, b+1); + + return r; +}