+static int node_symlink(const char *node, const char *slink)
+{
+ char target[PATH_SIZE] = "";
+ char buf[PATH_SIZE];
+ int i = 0;
+ int tail = 0;
+ int len;
+
+ /* use relative link */
+ while (node[i] && (node[i] == slink[i])) {
+ if (node[i] == '/')
+ tail = i+1;
+ i++;
+ }
+ while (slink[i] != '\0') {
+ if (slink[i] == '/')
+ strlcat(target, "../", sizeof(target));
+ i++;
+ }
+ strlcat(target, &node[tail], sizeof(target));
+
+ /* look if symlink already exists */
+ len = readlink(slink, buf, sizeof(buf));
+ if (len > 0) {
+ buf[len] = '\0';
+ if (strcmp(target, buf) == 0) {
+ info("preserving symlink '%s' to '%s'", slink, target);
+ selinux_setfilecon(slink, NULL, S_IFLNK);
+ goto exit;
+ }
+ info("link '%s' points to different target '%s', delete it", slink, buf);
+ unlink(slink);
+ }
+
+ /* create link */
+ info("creating symlink '%s' to '%s'", slink, target);
+ selinux_setfscreatecon(slink, NULL, S_IFLNK);
+ if (symlink(target, slink) != 0)
+ err("symlink(%s, %s) failed: %s", target, slink, strerror(errno));
+ selinux_resetfscreatecon();
+
+exit:
+ return 0;
+}
+