+ if (!sanitize_paths)
+ return do_stat(fname, stp);
+
+ mod_path = lp_path(module_id);
+ mod_path_len = strlen(mod_path);
+
+ for (i = 0; i < 16; i++) {
+#ifdef DEBUG
+ if (*fname == '/')
+ assert(strncmp(fname, mod_path, mod_path_len) == 0 && fname[mod_path_len] == '/');
+#endif
+ if (do_lstat(fname, stp) < 0)
+ return -1;
+ if (!S_ISLNK(stp->st_mode))
+ return 0;
+ if ((llen = readlink(fname, linkbuf, sizeof linkbuf - 1)) < 0)
+ return -1;
+ linkbuf[llen] = '\0';
+ if (*fname == '/')
+ fname += mod_path_len;
+ if (!(fname = sanitize_path(tmpbuf, fname, mod_path, curr_dir_depth, linkbuf)))
+ break;
+ }
+
+ return 0; /* Leave *stp set to the last symlink. */
+#else
+ return do_stat(fname, stp);
+#endif
+}
+
+void die_on_unsafe_path(char *path, int strip_filename)
+{
+#ifdef SUPPORT_LINKS
+ char *final_slash, *p;
+ STRUCT_STAT st;
+
+ if (!path)
+ return;
+ if (strip_filename) {
+ if (!(final_slash = strrchr(path, '/')))
+ return;
+ *final_slash = '\0';
+ } else
+ final_slash = NULL;
+
+ p = path;
+ if (*p == '/')
+ p += module_dirlen + 1;
+ while (*p) {
+ if ((p = strchr(p, '/')) != NULL)
+ *p = '\0';
+ if (safe_stat(path, &st) < 0) {
+ *p++ = '/';
+ goto done;
+ }
+ if (S_ISLNK(st.st_mode)) {
+ rprintf(FERROR, "Unsafe path: %s\n", path);
+ exit_cleanup(RERR_SYNTAX);
+ }
+ if (!p)
+ break;
+ *p++ = '/';
+ }
+
+ done:
+ if (final_slash)
+ *final_slash = '/';
+#endif
+}
+
+/* Like chdir(), but it keeps track of the current directory (in the