]> Zhao Yanbai Git Server - minix.git/commitdiff
VFS: add support for F_DUPFD_CLOEXEC 31/3031/1
authorDavid van Moolenbroek <david@minix3.org>
Mon, 20 Jul 2015 13:55:10 +0000 (13:55 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Mon, 20 Jul 2015 13:55:10 +0000 (13:55 +0000)
Change-Id: Ibe422c6c99fe5fd1385884843ff9e15111810309

minix/lib/libc/sys/fcntl.c
minix/man/man2/fcntl.2
minix/servers/vfs/misc.c
minix/tests/test7.c
minix/usr.bin/trace/service/vfs.c

index e6f4e67862d3fedc725e25c273fc67c7da3dd888..8a243e5c19c29a4649a4290b0967a7f29722f2f0 100644 (file)
@@ -21,6 +21,7 @@ int fcntl(int fd, int cmd, ...)
   /* Adjust for the stupid cases. */
   switch(cmd) {
      case F_DUPFD:
+     case F_DUPFD_CLOEXEC:
      case F_SETFD:
      case F_SETFL:
      case F_SETNOSIGPIPE:
index bc49672a98277fe243bce9053073f1791f34dd45..7d75901818b786f420650cc4d72a442d7399a811 100644 (file)
@@ -37,6 +37,13 @@ or equal to
 .IR fd2 .
 .RE
 .SP
+.BI "fcntl(" fd ", F_DUPFD_CLOEXEC, int " fd2 ")"
+.RS
+As
+.BR F_DUPFD ,
+but the "close on exec" flag is set on the returned file descriptor.
+.RE
+.SP
 .BI "fcntl(" fd ", F_GETFD)"
 .RS
 Returns the file descriptor flags associated with file descriptor
index 429244c0b1918f58ecee9d88b5a8071d0726f967..9e426ce0e1e122101210c5ab1e9a5798d297376c 100644 (file)
@@ -116,11 +116,15 @@ int do_fcntl(void)
 
   switch (fcntl_req) {
     case F_DUPFD:
+    case F_DUPFD_CLOEXEC:
        /* This replaces the old dup() system call. */
        if (fcntl_argx < 0 || fcntl_argx >= OPEN_MAX) r = EINVAL;
        else if ((r = get_fd(fp, fcntl_argx, 0, &new_fd, NULL)) == OK) {
                f->filp_count++;
                fp->fp_filp[new_fd] = f;
+               assert(!FD_ISSET(new_fd, &fp->fp_cloexec_set));
+               if (fcntl_req == F_DUPFD_CLOEXEC)
+                       FD_SET(new_fd, &fp->fp_cloexec_set);
                r = new_fd;
        }
        break;
index c8b78f117d288ade0256cf6fa42183b7acd4f518..2443d148065e45e2bf0d2d863720322774544e3e 100644 (file)
@@ -213,8 +213,8 @@ void test7c()
 {
 /* Test fcntl(). */
 
-  int fd, m, s, newfd, newfd2;
-  struct stat stat1, stat2, stat3;
+  int fd, m, s, newfd, newfd2, newfd3, newfd4;
+  struct stat stat1, stat2, stat3, stat4, stat5;
 
   subtest = 3;
   errno = -100;
@@ -264,20 +264,42 @@ void test7c()
   if (fcntl(newfd2, F_GETFL) != (O_APPEND | m)) e(30); /* O_APPEND set */
   if (fcntl(fd, F_SETFD, 0) != 0) e(31);/* turn FD_CLOEXEC off */
 
-  /* Check if newfd and newfd2 are the same inode. */
+  /* Also test F_DUPFD_CLOEXEC. */
+  if ( (newfd3 = fcntl(fd, F_DUPFD_CLOEXEC, 0)) != 4) e(0);
+  if (fcntl(newfd3, F_GETFD) != FD_CLOEXEC) e(0); /* FD_CLOEXEC must be set */
+  if (close(newfd3) != 0) e(0);
+  if ( (newfd3 = fcntl(fd, F_DUPFD_CLOEXEC, 12)) != 12) e(0);
+  if (fcntl(newfd3, F_GETFD) != FD_CLOEXEC) e(0); /* FD_CLOEXEC must be set */
+  if ( (newfd4 = fcntl(newfd3, F_DUPFD, 0)) != 4) e(0);
+  if (fcntl(newfd4, F_GETFD) != 0) e(0);       /* FD_CLOEXEC must be unset */
+  if (close(newfd4) != 0) e(0);
+  if ( (newfd4 = fcntl(newfd3, F_DUPFD_CLOEXEC, 15)) != 15) e(0);
+  if (fcntl(newfd4, F_GETFD) != FD_CLOEXEC) e(0); /* FD_CLOEXEC must be set */
+  if (fcntl(newfd4, F_SETFD, 0) != 0) e(0);    /* turn FD_CLOEXEC off */
+  if (fcntl(newfd4, F_GETFD) != 0) e(0);       /* FD_CLOEXEC must be unset */
+
+  /* Check if all file descriptors are for the same inode. */
   if (fstat(fd, &stat1) != 0) e(32);
-  if (fstat(fd, &stat2) != 0) e(33);
-  if (fstat(fd, &stat3) != 0) e(34);
+  if (fstat(newfd, &stat2) != 0) e(33);
+  if (fstat(newfd2, &stat3) != 0) e(34);
+  if (fstat(newfd3, &stat4) != 0) e(0);
+  if (fstat(newfd4, &stat5) != 0) e(0);
   if (stat1.st_dev != stat2.st_dev) e(35);
   if (stat1.st_dev != stat3.st_dev) e(36);
+  if (stat1.st_dev != stat4.st_dev) e(0);
+  if (stat1.st_dev != stat5.st_dev) e(0);
   if (stat1.st_ino != stat2.st_ino) e(37);
   if (stat1.st_ino != stat3.st_ino) e(38);
+  if (stat1.st_ino != stat4.st_ino) e(0);
+  if (stat1.st_ino != stat5.st_ino) e(0);
 
   /* Now check on the FD_CLOEXEC flag.  Set it for fd (3) and newfd2 (10) */
-  if (fd != 3 || newfd2 != 10 || newfd != 6) e(39);
+  if (fd != 3 || newfd2 != 10 || newfd3 != 12 || newfd4 != 15 || newfd != 6)
+       e(39);
   if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) e(40);      /* close 3 on exec */
   if (fcntl(newfd2, F_SETFD, FD_CLOEXEC) != 0) e(41);  /* close 10 on exec */
   if (fcntl(newfd, F_SETFD, 0) != 0) e(42);            /* don't close 6 */
+  /* leave 12 and 15 as is */
   if (fork()) {
        wait(&s);               /* parent just waits */
        if (WEXITSTATUS(s) != 0) e(43);
@@ -630,12 +652,14 @@ void cloexec_test()
  * closed upon exec, we have to exec something.  The test is carried
  * out by forking, and then having the child exec test7 itself, but
  * with argument 0.  This is detected, and control comes here.
- * File descriptors 3 and 10 should be closed here, and 10 open.
+ * File descriptors 3, 10, and 12 should be closed here, and 6 and 15 open.
  */
 
   if (close(3) == 0) e(1001);  /* close should fail; it was closed on exec */
   if (close(6) != 0) e(1002);  /* close should succeed */
   if (close(10) == 0) e(1003); /* close should fail */
+  if (close(12) == 0) e(1004); /* close should fail */
+  if (close(15) != 0) e(1005); /* close should succeed */
   fflush(stdout);
   exit(0);
 }
index 71006c1cbe477cc763ec7a438fbb7f1314dbc5d7..12e9965ab35a69de90e70058f154d84a153c13b0 100644 (file)
@@ -603,6 +603,7 @@ vfs_fcntl_out(struct trace_proc * proc, const message * m_out)
 
        switch (m_out->m_lc_vfs_fcntl.cmd) {
        case F_DUPFD:
+       case F_DUPFD_CLOEXEC:
                put_fd(proc, "fd2", m_out->m_lc_vfs_fcntl.arg_int);
                break;
        case F_SETFD: