Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/librumphijack Properly implement fcntl commands: F_DUPFD...



details:   https://anonhg.NetBSD.org/src/rev/816ec7bda934
branches:  trunk
changeset: 762091:816ec7bda934
user:      pooka <pooka%NetBSD.org@localhost>
date:      Tue Feb 15 13:59:28 2011 +0000

description:
Properly implement fcntl commands: F_DUPFD, F_CLOSEM, F_MAXFD

diffstat:

 lib/librumphijack/hijack.c |  173 ++++++++++++++++++++++++++++++++------------
 1 files changed, 125 insertions(+), 48 deletions(-)

diffs (265 lines):

diff -r baf0d6d3f9c9 -r 816ec7bda934 lib/librumphijack/hijack.c
--- a/lib/librumphijack/hijack.c        Tue Feb 15 12:06:22 2011 +0000
+++ b/lib/librumphijack/hijack.c        Tue Feb 15 13:59:28 2011 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: hijack.c,v 1.39 2011/02/14 14:56:23 pooka Exp $       */
+/*      $NetBSD: hijack.c,v 1.40 2011/02/15 13:59:28 pooka Exp $       */
 
 /*-
  * Copyright (c) 2011 Antti Kantee.  All Rights Reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: hijack.c,v 1.39 2011/02/14 14:56:23 pooka Exp $");
+__RCSID("$NetBSD: hijack.c,v 1.40 2011/02/15 13:59:28 pooka Exp $");
 
 #define __ssp_weak_name(fun) _hijack_ ## fun
 
@@ -142,8 +142,12 @@
 int    (*host_daemon)(int, int);
 int    (*host_execve)(const char *, char *const[], char *const[]);
 
-static unsigned dup2mask;
-#define ISDUP2D(fd) ((fd < 32) && (1<<(fd) & dup2mask))
+static uint32_t dup2mask;
+#define ISDUP2D(fd) (((fd) < 32) && (1<<(fd) & dup2mask))
+#define SETDUP2(fd) \
+    do { if ((fd) < 32) dup2mask |= (1<<(fd)); } while (/*CONSTCOND*/0)
+#define CLRDUP2(fd) \
+    do { if ((fd) < 32) dup2mask &= ~(1<<(fd)); } while (/*CONSTCOND*/0)
 
 //#define DEBUGJACK
 #ifdef DEBUGJACK
@@ -277,13 +281,12 @@
        }
 
        if (getenv_r("RUMPHIJACK__DUP2MASK", buf, sizeof(buf)) == 0) {
-               dup2mask = atoi(buf);
+               dup2mask = strtoul(buf, NULL, 10);
        }
 }
 
 /* XXX: need runtime selection.  low for now due to FD_SETSIZE */
 #define HIJACK_FDOFF 128
-#define HIJACK_ASSERT 128 /* XXX */
 static int
 fd_rump2host(int fd)
 {
@@ -313,8 +316,33 @@
        return ISDUP2D(fd) || fd >= HIJACK_FDOFF;
 }
 
-#define assertfd(_fd_) assert(ISDUP2D(_fd_) || (_fd_) >= HIJACK_ASSERT)
-#undef HIJACK_FDOFF
+#define assertfd(_fd_) assert(ISDUP2D(_fd_) || (_fd_) >= HIJACK_FDOFF)
+
+static int
+dodup(int oldd, int minfd)
+{
+       int (*op_fcntl)(int, int, ...);
+       int newd;
+       int isrump;
+
+       DPRINTF(("dup -> %d (minfd %d)\n", oldd, minfd));
+       if (fd_isrump(oldd)) {
+               op_fcntl = GETSYSCALL(rump, FCNTL);
+               oldd = fd_host2rump(oldd);
+               isrump = 1;
+       } else {
+               op_fcntl = GETSYSCALL(host, FCNTL);
+               isrump = 0;
+       }
+
+       newd = op_fcntl(oldd, F_DUPFD, minfd);
+
+       if (isrump)
+               newd = fd_rump2host(newd);
+       DPRINTF(("dup <- %d\n", newd));
+
+       return newd;
+}
 
 int __socket30(int, int, int);
 int
@@ -388,31 +416,99 @@
        return rv;
 }
 
-
-/* TODO: support F_DUPFD, F_CLOSEM, F_MAXFD */
+#include <syslog.h>
 int
 fcntl(int fd, int cmd, ...)
 {
        int (*op_fcntl)(int, int, ...);
        va_list ap;
-       int rv;
+       int rv, minfd, i;
+
+       DPRINTF(("fcntl -> %d (cmd %d)\n", fd, cmd));
 
-       DPRINTF(("fcntl -> %d\n", fd));
-       if (fd_isrump(fd)) {
-               fd = fd_host2rump(fd);
-               op_fcntl = GETSYSCALL(rump, FCNTL);
-       } else {
-               op_fcntl = GETSYSCALL(host, FCNTL);
-               if (cmd == F_CLOSEM)
-                       if (rumpclient__closenotify(&fd,
+       switch (cmd) {
+       case F_DUPFD:
+               va_start(ap, cmd);
+               minfd = va_arg(ap, int);
+               va_end(ap);
+               return dodup(fd, minfd);
+
+       case F_CLOSEM:
+               /*
+                * So, if fd < HIJACKOFF, we want to do a host closem.
+                */
+
+               if (fd < HIJACK_FDOFF) {
+                       int closemfd = fd;
+
+                       if (rumpclient__closenotify(&closemfd,
                            RUMPCLIENT_CLOSE_FCLOSEM) == -1)
                                return -1;
-       }
+                       op_fcntl = GETSYSCALL(host, FCNTL);
+                       rv = op_fcntl(closemfd, cmd);
+                       if (rv)
+                               return rv;
+               }
+
+               /*
+                * Additionally, we want to do a rump closem, but only
+                * for the file descriptors not within the dup2mask.
+                */
+
+               /* why don't we offer fls()? */
+               for (i = 31; i >= 0; i--) {
+                       if (dup2mask & 1<<i)
+                               break;
+               }
+               
+               if (fd >= HIJACK_FDOFF)
+                       fd -= HIJACK_FDOFF;
+               else
+                       fd = 0;
+               fd = MAX(i+1, fd);
+
+               /* hmm, maybe we should close rump fd's not within dup2mask? */
+
+               return rump_sys_fcntl(fd, F_CLOSEM);
 
-       va_start(ap, cmd);
-       rv = op_fcntl(fd, cmd, va_arg(ap, void *));
-       va_end(ap);
-       return rv;
+       case F_MAXFD:
+               /*
+                * For maxfd, if there's a rump kernel fd, return
+                * it hostified.  Otherwise, return host's MAXFD
+                * return value.
+                */
+               if ((rv = rump_sys_fcntl(fd, F_MAXFD)) != -1) {
+                       /*
+                        * This might go a little wrong in case
+                        * of dup2 to [012], but I'm not sure if
+                        * there's a justification for tracking
+                        * that info.  Consider e.g.
+                        * dup2(rumpfd, 2) followed by rump_sys_open()
+                        * returning 1.  We should return 1+HIJACKOFF,
+                        * not 2+HIJACKOFF.  However, if [01] is not
+                        * open, the correct return value is 2.
+                        */
+                       return fd_rump2host(fd);
+               } else {
+                       op_fcntl = GETSYSCALL(host, FCNTL);
+                       return op_fcntl(fd, F_MAXFD);
+               }
+               /*NOTREACHED*/
+
+       default:
+               if (fd_isrump(fd)) {
+                       fd = fd_host2rump(fd);
+                       op_fcntl = GETSYSCALL(rump, FCNTL);
+               } else {
+                       op_fcntl = GETSYSCALL(host, FCNTL);
+               }
+
+               va_start(ap, cmd);
+               rv = op_fcntl(fd, cmd, va_arg(ap, void *));
+               va_end(ap);
+               return rv;
+       }
+       /*NOTREACHED*/
 }
 
 int
@@ -431,7 +527,7 @@
                op_close = GETSYSCALL(rump, CLOSE);
                rv = op_close(fd);
                if (rv == 0 && undup2)
-                       dup2mask &= ~(1 << fd);
+                       CLRDUP2(fd);
        } else {
                if (rumpclient__closenotify(&fd, RUMPCLIENT_CLOSE_CLOSE) == -1)
                        return -1;
@@ -481,7 +577,7 @@
                oldd = fd_host2rump(oldd);
                rv = rump_sys_dup2(oldd, newd);
                if (rv != -1)
-                       dup2mask |= 1<<newd;
+                       SETDUP2(newd);
        } else {
                host_dup2 = syscalls[DUALCALL_DUP2].bs_host;
                if (rumpclient__closenotify(&newd, RUMPCLIENT_CLOSE_DUP2) == -1)
@@ -495,27 +591,8 @@
 int
 dup(int oldd)
 {
-       int (*op_dup)(int);
-       int newd;
-       int isrump;
 
-       DPRINTF(("dup -> %d\n", oldd));
-       if (fd_isrump(oldd)) {
-               op_dup = GETSYSCALL(rump, DUP);
-               oldd = fd_host2rump(oldd);
-               isrump = 1;
-       } else {
-               op_dup = GETSYSCALL(host, DUP);
-               isrump = 0;
-       }
-
-       newd = op_dup(oldd);
-
-       if (isrump)
-               newd = fd_rump2host(newd);
-       DPRINTF(("dup <- %d\n", newd));
-
-       return newd;
+       return dodup(oldd, 0);
 }
 
 /*
@@ -576,7 +653,7 @@
        char *dup2str;
        int rv;
 
-       snprintf(buf, sizeof(buf), "RUMPHIJACK__DUP2MASK=%d", dup2mask);
+       snprintf(buf, sizeof(buf), "RUMPHIJACK__DUP2MASK=%u", dup2mask);
        dup2str = malloc(strlen(buf)+1);
        if (dup2str == NULL)
                return ENOMEM;
@@ -953,7 +1030,7 @@
                ev = &changelist[i];
                if (ev->filter == EVFILT_READ || ev->filter == EVFILT_WRITE ||
                    ev->filter == EVFILT_VNODE) {
-                       if (fd_isrump(ev->ident))
+                       if (fd_isrump((int)ev->ident))
                                return ENOTSUP;
                }
        }



Home | Main Index | Thread Index | Old Index