Close all fds for the daemon for compatibility with usermount(8).
authorshort <>
Fri, 29 Aug 2003 12:43:17 +0000 (12:43 +0000)
committershort <>
Fri, 29 Aug 2003 12:43:17 +0000 (12:43 +0000)
lufsd/daemon.c

index 89df831..2b3d6a8 100644 (file)
@@ -29,6 +29,7 @@
 #include <pwd.h>
 #include <errno.h>
 #include <time.h>
+#include <dirent.h>
 
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -96,6 +97,50 @@ tempsock(char *base, char *name){
     return sock;
 }
 
+/* From captive/src/libcaptive/sandbox/split.c/captive_sandbox_fd_closeup(): */
+#define g_return_if_fail(cond) do { if (!(cond)) { ERROR("FAIL: " #cond ); return; } } while (0)
+#define g_assert(cond) do { if (!(cond)) ERROR("FAIL: " #cond ); } while (0)
+static void fd_closeup(int fd_first_to_delete,int exception)
+{
+DIR *dir;
+int errint;
+int dir_fd;
+struct dirent *dirent;
+
+       dir=opendir("/proc/self/fd/");
+       g_return_if_fail(dir!=NULL);
+       dir_fd=dirfd(dir);
+       g_return_if_fail(dir_fd!=-1);
+
+       while (errno=0,(dirent=readdir(dir))) {
+long dirent_fd;
+char *endptr;
+
+               if (0
+                               || !strcmp(dirent->d_name,".")
+                               || !strcmp(dirent->d_name,".."))
+                       continue;
+               dirent_fd=strtol(dirent->d_name,&endptr,10 /* base */);
+               g_assert(dirent_fd>=0 && (!endptr || !*endptr));
+               if (dirent_fd<fd_first_to_delete || dirent_fd==dir_fd || dirent_fd==exception)
+                       continue;
+
+               errint=close(dirent_fd);
+               g_assert(errint==0);
+               errno=0;
+               errint=close(dirent_fd);
+               g_assert(errint==-1); g_assert(errno==EBADF);
+               }
+       g_return_if_fail(errno==0);     /* check for EOF */
+
+       errint=closedir(dir);
+       g_return_if_fail(errint==0);
+       errno=0;
+       close(dir_fd); g_assert(errno==EBADF);  /* just a bit of paranoia; it should be already closed by closedir() */
+}
+#undef g_return_if_fail
+#undef g_assert
+
 int
 main(int argc, char **argv){
     char *service, *mountpoint, *odata;
@@ -110,6 +155,14 @@ main(int argc, char **argv){
     setlinebuf(stdout);
     setlinebuf(stderr);
 
+    /* Close all fds as we will later fork(2) and at least usermount(8) waits
+     * for child finish by select(2) on fd left open for mount(8). We can be
+     * called as external program from mount(8). Close even STD* fds as
+     * usermount(8) uses STDERR for its pipe watching.
+     */
+    /* FIXME: 'quiet' option has no meaning now. */
+    fd_closeup(3,-1);
+
     if((argc < 5) || (strcmp(argv[3], "-o")) ){
        ERROR("Usage: %s none <mount-point> -o [options, ...]", argv[0]);
        exit(1);
@@ -181,7 +234,8 @@ main(int argc, char **argv){
 
            free(nopts);
 
-           if(quiet){
+           /* FIXME: 'quiet' option has no meaning now; check fd_closeup(). */
+           if(1 || quiet){
                int stdfd;
 
                TRACE("going dumb...");