+static void chrooted_cleanuplockeddirs(const gchar *pathname)
+{
+DIR *dir;
+struct dirent *dirent;
+
+ if (!(dir=opendir(pathname))) {
+ if (errno!=ENOTDIR)
+ fatal("Cannot opendir(\"%s\") to delete leftover sandbox files: %m",pathname);
+ /* errno==ENOTDIR, a regular file */
+ if (unlink(pathname))
+ fatal("Cannot unlink(\"%s\") to delete leftover sandbox files: %m",pathname);
+ return;
+ }
+ while (errno=0,(dirent=readdir(dir))) {
+gchar *dirent_path;
+int direntfd;
+
+ if (!strcmp(dirent->d_name,".") || !strcmp(dirent->d_name,".."))
+ continue;
+ dirent_path=g_strdup_printf("%s/%s",pathname,dirent->d_name);
+ if (-1==(direntfd=open(dirent_path,O_RDONLY))) {
+ if (errno==ENOENT) /* It could disappear in the meantime. */
+ goto next_dirent_free_dirent_path;
+ fatal("Cannot open(\"%s\") as the child directory during delete of leftover sandbox files: %m",dirent_path);
+ }
+ if (flock(direntfd,LOCK_EX|LOCK_NB)) {
+ if (errno==EWOULDBLOCK) /* Valid directory in use. */
+ goto next_dirent_close_direntfd;
+ fatal("Cannot flock(\"%s\",LOCK_EX|LOCK_NB) child directory during delete of leftover sandbox files: %m",dirent_path);
+ }
+ chrooted_unlink_recursive(dirent_path);
+next_dirent_close_direntfd:
+ if (close(direntfd))
+ fatal("Cannot close(\"%s\") child directory during delete of leftover sandbox files: %m",dirent_path);
+next_dirent_free_dirent_path:
+ g_free(dirent_path);
+ }
+ if (errno)
+ fatal("Cannot readdir(\"%s\") during delete of leftover sandbox files: %m",pathname);
+ if (closedir(dir))
+ fatal("Cannot closedir(\"%s\") during delete of leftover sandbox files: %m",pathname);
+}
+
+static void chrooted_createdir(const gchar *dir,uid_t uid,gid_t gid,gboolean lock)