diff --git a/src/confd/src/dagger.c b/src/confd/src/dagger.c index 9dfd3e28..a8aea6f5 100644 --- a/src/confd/src/dagger.c +++ b/src/confd/src/dagger.c @@ -87,10 +87,32 @@ FILE *dagger_fopen_net_exit(struct dagger *d, const char *node, enum netdag_exit return dagger_fopen_current(d, "exit", node, order, script); } -int dagger_add_dep(struct dagger *d, const char *depender, const char *dependee) +int dagger_add_dep(const struct dagger *d, const char *depender, const char *dependee) { - return systemf("ln -s ../%s %s/%d/dag/%s", dependee, - d->path, d->next, depender); + char link[strlen(d->path) + strlen(depender) + strlen(dependee) + 16]; + char target[strlen(dependee) + 16]; + char path[strlen(dependee) + 16]; + ssize_t len; + + /* + * Some callbacks may run twice, double check symlink, if it + * exists already and points to the same target, we're OK. + */ + snprintf(target, sizeof(target), "../%s", dependee); + snprintf(link, sizeof(link), "%s/%d/dag/%s/%s", d->path, d->next, depender, dependee); + + len = readlink(link, path, sizeof(path)); + if (len > 0) { + path[len] = 0; + if (strcmp(target, path)) { + ERROR("Dagger dependency already exists %s -> %s", target, path); + return errno = EEXIST; + } + + return 0; /* same, ignore */ + } + + return symlink(target, link); } int dagger_add_node(struct dagger *d, const char *node) diff --git a/src/confd/src/dagger.h b/src/confd/src/dagger.h index d98469b1..959aa8d6 100644 --- a/src/confd/src/dagger.h +++ b/src/confd/src/dagger.h @@ -21,7 +21,7 @@ FILE *dagger_fopen_next(struct dagger *d, const char *action, const char *node, FILE *dagger_fopen_current(struct dagger *d, const char *action, const char *node, unsigned char prio, const char *script); -int dagger_add_dep(struct dagger *d, const char *depender, const char *dependee); +int dagger_add_dep(const struct dagger *d, const char *depender, const char *dependee); int dagger_add_node(struct dagger *d, const char *node); int dagger_abandon(struct dagger *d); int dagger_evolve(struct dagger *d);