[BACK]Return to hijack.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / librumphijack

Annotation of src/lib/librumphijack/hijack.c, Revision 1.79

1.79    ! bouyer      1: /*      $NetBSD: hijack.c,v 1.78 2011/03/09 15:03:18 pooka Exp $       */
1.1       pooka       2:
                      3: /*-
                      4:  * Copyright (c) 2011 Antti Kantee.  All Rights Reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
                     16:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     18:  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     19:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     20:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     21:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     23:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     24:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     25:  * SUCH DAMAGE.
                     26:  */
                     27:
                     28: #include <sys/cdefs.h>
1.79    ! bouyer     29: __RCSID("$NetBSD: hijack.c,v 1.78 2011/03/09 15:03:18 pooka Exp $");
1.21      christos   30:
                     31: #define __ssp_weak_name(fun) _hijack_ ## fun
1.1       pooka      32:
                     33: #include <sys/param.h>
                     34: #include <sys/types.h>
1.10      pooka      35: #include <sys/event.h>
1.1       pooka      36: #include <sys/ioctl.h>
1.62      pooka      37: #include <sys/mman.h>
1.48      pooka      38: #include <sys/mount.h>
                     39: #include <sys/poll.h>
1.1       pooka      40: #include <sys/socket.h>
1.45      pooka      41: #include <sys/statvfs.h>
1.1       pooka      42:
                     43: #include <rump/rumpclient.h>
                     44: #include <rump/rump_syscalls.h>
                     45:
                     46: #include <assert.h>
                     47: #include <dlfcn.h>
                     48: #include <err.h>
                     49: #include <errno.h>
                     50: #include <fcntl.h>
                     51: #include <poll.h>
                     52: #include <pthread.h>
1.3       pooka      53: #include <signal.h>
1.1       pooka      54: #include <stdarg.h>
1.8       pooka      55: #include <stdbool.h>
1.1       pooka      56: #include <stdio.h>
                     57: #include <stdlib.h>
1.28      pooka      58: #include <string.h>
1.3       pooka      59: #include <time.h>
1.1       pooka      60: #include <unistd.h>
                     61:
1.64      pooka      62: #include "hijack.h"
                     63:
1.17      pooka      64: enum dualcall {
1.60      pooka      65:        DUALCALL_WRITE, DUALCALL_WRITEV, DUALCALL_PWRITE, DUALCALL_PWRITEV,
1.17      pooka      66:        DUALCALL_IOCTL, DUALCALL_FCNTL,
                     67:        DUALCALL_SOCKET, DUALCALL_ACCEPT, DUALCALL_BIND, DUALCALL_CONNECT,
                     68:        DUALCALL_GETPEERNAME, DUALCALL_GETSOCKNAME, DUALCALL_LISTEN,
                     69:        DUALCALL_RECVFROM, DUALCALL_RECVMSG,
                     70:        DUALCALL_SENDTO, DUALCALL_SENDMSG,
                     71:        DUALCALL_GETSOCKOPT, DUALCALL_SETSOCKOPT,
                     72:        DUALCALL_SHUTDOWN,
1.60      pooka      73:        DUALCALL_READ, DUALCALL_READV, DUALCALL_PREAD, DUALCALL_PREADV,
1.41      pooka      74:        DUALCALL_DUP2,
1.34      pooka      75:        DUALCALL_CLOSE,
1.17      pooka      76:        DUALCALL_POLLTS,
1.34      pooka      77:        DUALCALL_KEVENT,
1.45      pooka      78:        DUALCALL_STAT, DUALCALL_LSTAT, DUALCALL_FSTAT,
                     79:        DUALCALL_CHMOD, DUALCALL_LCHMOD, DUALCALL_FCHMOD,
                     80:        DUALCALL_CHOWN, DUALCALL_LCHOWN, DUALCALL_FCHOWN,
                     81:        DUALCALL_OPEN,
                     82:        DUALCALL_STATVFS1, DUALCALL_FSTATVFS1,
                     83:        DUALCALL_CHDIR, DUALCALL_FCHDIR,
                     84:        DUALCALL_LSEEK,
                     85:        DUALCALL_GETDENTS,
                     86:        DUALCALL_UNLINK, DUALCALL_SYMLINK, DUALCALL_READLINK,
                     87:        DUALCALL_RENAME,
                     88:        DUALCALL_MKDIR, DUALCALL_RMDIR,
                     89:        DUALCALL_UTIMES, DUALCALL_LUTIMES, DUALCALL_FUTIMES,
                     90:        DUALCALL_TRUNCATE, DUALCALL_FTRUNCATE,
                     91:        DUALCALL_FSYNC, DUALCALL_FSYNC_RANGE,
1.48      pooka      92:        DUALCALL_MOUNT, DUALCALL_UNMOUNT,
1.57      pooka      93:        DUALCALL___GETCWD,
1.60      pooka      94:        DUALCALL_CHFLAGS, DUALCALL_LCHFLAGS, DUALCALL_FCHFLAGS,
1.65      pooka      95:        DUALCALL_ACCESS,
1.68      pooka      96:        DUALCALL_MKNOD,
1.78      pooka      97:        DUALCALL___SYSCTL,
                     98:        DUALCALL_GETVFSSTAT, DUALCALL_NFSSVC,
                     99:        DUALCALL_GETFH, DUALCALL_FHOPEN, DUALCALL_FHSTAT, DUALCALL_FHSTATVFS1,
1.17      pooka     100:        DUALCALL__NUM
1.1       pooka     101: };
                    102:
1.8       pooka     103: #define RSYS_STRING(a) __STRING(a)
                    104: #define RSYS_NAME(a) RSYS_STRING(__CONCAT(RUMP_SYS_RENAME_,a))
                    105:
1.1       pooka     106: /*
1.14      pooka     107:  * Would be nice to get this automatically in sync with libc.
                    108:  * Also, this does not work for compat-using binaries!
                    109:  */
                    110: #if !__NetBSD_Prereq__(5,99,7)
1.29      pooka     111: #define REALSELECT select
                    112: #define REALPOLLTS pollts
1.34      pooka     113: #define REALKEVENT kevent
1.45      pooka     114: #define REALSTAT __stat30
                    115: #define REALLSTAT __lstat30
                    116: #define REALFSTAT __fstat30
                    117: #define REALUTIMES utimes
                    118: #define REALLUTIMES lutimes
                    119: #define REALFUTIMES futimes
1.68      pooka     120: #define REALMKNOD mknod
1.78      pooka     121: #define REALFHSTAT __fhstat40
1.14      pooka     122: #else
1.29      pooka     123: #define REALSELECT _sys___select50
                    124: #define REALPOLLTS _sys___pollts50
1.34      pooka     125: #define REALKEVENT _sys___kevent50
1.45      pooka     126: #define REALSTAT __stat50
                    127: #define REALLSTAT __lstat50
                    128: #define REALFSTAT __fstat50
                    129: #define REALUTIMES __utimes50
                    130: #define REALLUTIMES __lutimes50
1.69      pooka     131: #define REALFUTIMES __futimes50
1.68      pooka     132: #define REALMKNOD __mknod50
1.78      pooka     133: #define REALFHSTAT __fhstat50
1.17      pooka     134: #endif
1.31      pooka     135: #define REALREAD _sys_read
1.60      pooka     136: #define REALPREAD _sys_pread
                    137: #define REALPWRITE _sys_pwrite
1.45      pooka     138: #define REALGETDENTS __getdents30
1.48      pooka     139: #define REALMOUNT __mount50
1.78      pooka     140: #define REALGETFH __getfh30
                    141: #define REALFHOPEN __fhopen40
                    142: #define REALFHSTATVFS1 __fhstatvfs140
1.14      pooka     143:
1.29      pooka     144: int REALSELECT(int, fd_set *, fd_set *, fd_set *, struct timeval *);
                    145: int REALPOLLTS(struct pollfd *, nfds_t,
1.20      pooka     146:               const struct timespec *, const sigset_t *);
1.34      pooka     147: int REALKEVENT(int, const struct kevent *, size_t, struct kevent *, size_t,
                    148:               const struct timespec *);
1.31      pooka     149: ssize_t REALREAD(int, void *, size_t);
1.60      pooka     150: ssize_t REALPREAD(int, void *, size_t, off_t);
                    151: ssize_t REALPWRITE(int, const void *, size_t, off_t);
1.45      pooka     152: int REALSTAT(const char *, struct stat *);
                    153: int REALLSTAT(const char *, struct stat *);
                    154: int REALFSTAT(int, struct stat *);
                    155: int REALGETDENTS(int, char *, size_t);
                    156: int REALUTIMES(const char *, const struct timeval [2]);
                    157: int REALLUTIMES(const char *, const struct timeval [2]);
                    158: int REALFUTIMES(int, const struct timeval [2]);
1.48      pooka     159: int REALMOUNT(const char *, const char *, int, void *, size_t);
1.57      pooka     160: int __getcwd(char *, size_t);
1.68      pooka     161: int REALMKNOD(const char *, mode_t, dev_t);
1.78      pooka     162: int REALGETFH(const char *, void *, size_t *);
                    163: int REALFHOPEN(const void *, size_t, int);
                    164: int REALFHSTAT(const void *, size_t, struct stat *);
                    165: int REALFHSTATVFS1(const void *, size_t, struct statvfs *, int);
1.17      pooka     166:
                    167: #define S(a) __STRING(a)
                    168: struct sysnames {
                    169:        enum dualcall scm_callnum;
                    170:        const char *scm_hostname;
                    171:        const char *scm_rumpname;
                    172: } syscnames[] = {
                    173:        { DUALCALL_SOCKET,      "__socket30",   RSYS_NAME(SOCKET)       },
                    174:        { DUALCALL_ACCEPT,      "accept",       RSYS_NAME(ACCEPT)       },
                    175:        { DUALCALL_BIND,        "bind",         RSYS_NAME(BIND)         },
                    176:        { DUALCALL_CONNECT,     "connect",      RSYS_NAME(CONNECT)      },
                    177:        { DUALCALL_GETPEERNAME, "getpeername",  RSYS_NAME(GETPEERNAME)  },
                    178:        { DUALCALL_GETSOCKNAME, "getsockname",  RSYS_NAME(GETSOCKNAME)  },
                    179:        { DUALCALL_LISTEN,      "listen",       RSYS_NAME(LISTEN)       },
                    180:        { DUALCALL_RECVFROM,    "recvfrom",     RSYS_NAME(RECVFROM)     },
                    181:        { DUALCALL_RECVMSG,     "recvmsg",      RSYS_NAME(RECVMSG)      },
                    182:        { DUALCALL_SENDTO,      "sendto",       RSYS_NAME(SENDTO)       },
                    183:        { DUALCALL_SENDMSG,     "sendmsg",      RSYS_NAME(SENDMSG)      },
                    184:        { DUALCALL_GETSOCKOPT,  "getsockopt",   RSYS_NAME(GETSOCKOPT)   },
                    185:        { DUALCALL_SETSOCKOPT,  "setsockopt",   RSYS_NAME(SETSOCKOPT)   },
                    186:        { DUALCALL_SHUTDOWN,    "shutdown",     RSYS_NAME(SHUTDOWN)     },
1.31      pooka     187:        { DUALCALL_READ,        S(REALREAD),    RSYS_NAME(READ)         },
1.17      pooka     188:        { DUALCALL_READV,       "readv",        RSYS_NAME(READV)        },
1.60      pooka     189:        { DUALCALL_PREAD,       S(REALPREAD),   RSYS_NAME(PREAD)        },
                    190:        { DUALCALL_PREADV,      "preadv",       RSYS_NAME(PREADV)       },
1.17      pooka     191:        { DUALCALL_WRITE,       "write",        RSYS_NAME(WRITE)        },
                    192:        { DUALCALL_WRITEV,      "writev",       RSYS_NAME(WRITEV)       },
1.60      pooka     193:        { DUALCALL_PWRITE,      S(REALPWRITE),  RSYS_NAME(PWRITE)       },
                    194:        { DUALCALL_PWRITEV,     "pwritev",      RSYS_NAME(PWRITEV)      },
1.17      pooka     195:        { DUALCALL_IOCTL,       "ioctl",        RSYS_NAME(IOCTL)        },
                    196:        { DUALCALL_FCNTL,       "fcntl",        RSYS_NAME(FCNTL)        },
                    197:        { DUALCALL_DUP2,        "dup2",         RSYS_NAME(DUP2)         },
                    198:        { DUALCALL_CLOSE,       "close",        RSYS_NAME(CLOSE)        },
1.29      pooka     199:        { DUALCALL_POLLTS,      S(REALPOLLTS),  RSYS_NAME(POLLTS)       },
1.34      pooka     200:        { DUALCALL_KEVENT,      S(REALKEVENT),  RSYS_NAME(KEVENT)       },
1.45      pooka     201:        { DUALCALL_STAT,        S(REALSTAT),    RSYS_NAME(STAT)         },
                    202:        { DUALCALL_LSTAT,       S(REALLSTAT),   RSYS_NAME(LSTAT)        },
                    203:        { DUALCALL_FSTAT,       S(REALFSTAT),   RSYS_NAME(FSTAT)        },
                    204:        { DUALCALL_CHOWN,       "chown",        RSYS_NAME(CHOWN)        },
                    205:        { DUALCALL_LCHOWN,      "lchown",       RSYS_NAME(LCHOWN)       },
                    206:        { DUALCALL_FCHOWN,      "fchown",       RSYS_NAME(FCHOWN)       },
                    207:        { DUALCALL_CHMOD,       "chmod",        RSYS_NAME(CHMOD)        },
                    208:        { DUALCALL_LCHMOD,      "lchmod",       RSYS_NAME(LCHMOD)       },
                    209:        { DUALCALL_FCHMOD,      "fchmod",       RSYS_NAME(FCHMOD)       },
                    210:        { DUALCALL_UTIMES,      S(REALUTIMES),  RSYS_NAME(UTIMES)       },
                    211:        { DUALCALL_LUTIMES,     S(REALLUTIMES), RSYS_NAME(LUTIMES)      },
                    212:        { DUALCALL_FUTIMES,     S(REALFUTIMES), RSYS_NAME(FUTIMES)      },
                    213:        { DUALCALL_OPEN,        "open",         RSYS_NAME(OPEN)         },
                    214:        { DUALCALL_STATVFS1,    "statvfs1",     RSYS_NAME(STATVFS1)     },
                    215:        { DUALCALL_FSTATVFS1,   "fstatvfs1",    RSYS_NAME(FSTATVFS1)    },
                    216:        { DUALCALL_CHDIR,       "chdir",        RSYS_NAME(CHDIR)        },
                    217:        { DUALCALL_FCHDIR,      "fchdir",       RSYS_NAME(FCHDIR)       },
1.61      pooka     218:        { DUALCALL_LSEEK,       "lseek",        RSYS_NAME(LSEEK)        },
1.45      pooka     219:        { DUALCALL_GETDENTS,    "__getdents30", RSYS_NAME(GETDENTS)     },
                    220:        { DUALCALL_UNLINK,      "unlink",       RSYS_NAME(UNLINK)       },
                    221:        { DUALCALL_SYMLINK,     "symlink",      RSYS_NAME(SYMLINK)      },
                    222:        { DUALCALL_READLINK,    "readlink",     RSYS_NAME(READLINK)     },
                    223:        { DUALCALL_RENAME,      "rename",       RSYS_NAME(RENAME)       },
                    224:        { DUALCALL_MKDIR,       "mkdir",        RSYS_NAME(MKDIR)        },
                    225:        { DUALCALL_RMDIR,       "rmdir",        RSYS_NAME(RMDIR)        },
                    226:        { DUALCALL_TRUNCATE,    "truncate",     RSYS_NAME(TRUNCATE)     },
                    227:        { DUALCALL_FTRUNCATE,   "ftruncate",    RSYS_NAME(FTRUNCATE)    },
                    228:        { DUALCALL_FSYNC,       "fsync",        RSYS_NAME(FSYNC)        },
                    229:        { DUALCALL_FSYNC_RANGE, "fsync_range",  RSYS_NAME(FSYNC_RANGE)  },
1.48      pooka     230:        { DUALCALL_MOUNT,       S(REALMOUNT),   RSYS_NAME(MOUNT)        },
                    231:        { DUALCALL_UNMOUNT,     "unmount",      RSYS_NAME(UNMOUNT)      },
1.57      pooka     232:        { DUALCALL___GETCWD,    "__getcwd",     RSYS_NAME(__GETCWD)     },
1.60      pooka     233:        { DUALCALL_CHFLAGS,     "chflags",      RSYS_NAME(CHFLAGS)      },
                    234:        { DUALCALL_LCHFLAGS,    "lchflags",     RSYS_NAME(LCHFLAGS)     },
                    235:        { DUALCALL_FCHFLAGS,    "fchflags",     RSYS_NAME(FCHFLAGS)     },
1.65      pooka     236:        { DUALCALL_ACCESS,      "access",       RSYS_NAME(ACCESS)       },
1.68      pooka     237:        { DUALCALL_MKNOD,       S(REALMKNOD),   RSYS_NAME(MKNOD)        },
1.78      pooka     238:        { DUALCALL___SYSCTL,    "__sysctl",     RSYS_NAME(__SYSCTL)     },
                    239:        { DUALCALL_GETVFSSTAT,  "getvfsstat",   RSYS_NAME(GETVFSSTAT)   },
                    240:        { DUALCALL_NFSSVC,      "nfssvc",       RSYS_NAME(NFSSVC)       },
1.79    ! bouyer    241:        { DUALCALL_GETFH,       S(REALGETFH),   RSYS_NAME(GETFH)        },
        !           242:        { DUALCALL_FHOPEN,      S(REALFHOPEN),RSYS_NAME(FHOPEN) },
        !           243:        { DUALCALL_FHSTAT,      S(REALFHSTAT),RSYS_NAME(FHSTAT) },
        !           244:        { DUALCALL_FHSTATVFS1,  S(REALFHSTATVFS1),RSYS_NAME(FHSTATVFS1) },
1.17      pooka     245: };
                    246: #undef S
                    247:
                    248: struct bothsys {
                    249:        void *bs_host;
                    250:        void *bs_rump;
                    251: } syscalls[DUALCALL__NUM];
                    252: #define GETSYSCALL(which, name) syscalls[DUALCALL_##name].bs_##which
                    253:
1.71      pooka     254: static pid_t   (*host_fork)(void);
                    255: static int     (*host_daemon)(int, int);
                    256: static void *  (*host_mmap)(void *, size_t, int, int, int, off_t);
                    257:
1.75      pooka     258: /*
                    259:  * This tracks if our process is in a subdirectory of /rump.
                    260:  * It's preserved over exec.
                    261:  */
                    262: static bool pwdinrump;
                    263:
                    264: enum pathtype { PATH_HOST, PATH_RUMP, PATH_RUMPBLANKET };
                    265:
                    266: static bool            fd_isrump(int);
                    267: static enum pathtype   path_isrump(const char *);
1.71      pooka     268:
                    269: /*
                    270:  * Maintain a mapping table for the usual dup2 suspects.
1.74      pooka     271:  * Could use atomic ops to operate on dup2vec, but an application
                    272:  * racing there is not well-defined, so don't bother.
1.71      pooka     273:  */
                    274: /* note: you cannot change this without editing the env-passing code */
                    275: #define DUP2HIGH 2
                    276: static uint32_t dup2vec[DUP2HIGH+1];
                    277: #define DUP2BIT (1<<31)
                    278: #define DUP2ALIAS (1<<30)
                    279: #define DUP2FDMASK ((1<<30)-1)
                    280:
                    281: static bool
                    282: isdup2d(int fd)
                    283: {
                    284:
                    285:        return fd <= DUP2HIGH && fd >= 0 && dup2vec[fd] & DUP2BIT;
                    286: }
                    287:
                    288: static int
                    289: mapdup2(int hostfd)
                    290: {
                    291:
                    292:        _DIAGASSERT(isdup2d(hostfd));
                    293:        return dup2vec[hostfd] & DUP2FDMASK;
                    294: }
                    295:
                    296: static int
                    297: unmapdup2(int rumpfd)
                    298: {
                    299:        int i;
                    300:
                    301:        for (i = 0; i <= DUP2HIGH; i++) {
1.72      pooka     302:                if (dup2vec[i] & DUP2BIT &&
                    303:                    (dup2vec[i] & DUP2FDMASK) == (unsigned)rumpfd)
1.71      pooka     304:                        return i;
                    305:        }
                    306:        return -1;
                    307: }
                    308:
                    309: static void
                    310: setdup2(int hostfd, int rumpfd)
                    311: {
                    312:
                    313:        if (hostfd > DUP2HIGH) {
                    314:                _DIAGASSERT(0);
                    315:                return;
                    316:        }
                    317:
                    318:        dup2vec[hostfd] = DUP2BIT | DUP2ALIAS | rumpfd;
                    319: }
                    320:
                    321: static void
                    322: clrdup2(int hostfd)
                    323: {
                    324:
                    325:        if (hostfd > DUP2HIGH) {
                    326:                _DIAGASSERT(0);
                    327:                return;
                    328:        }
                    329:
                    330:        dup2vec[hostfd] = 0;
                    331: }
                    332:
                    333: static bool
                    334: killdup2alias(int rumpfd)
                    335: {
                    336:        int hostfd;
                    337:
                    338:        if ((hostfd = unmapdup2(rumpfd)) == -1)
                    339:                return false;
                    340:
                    341:        if (dup2vec[hostfd] & DUP2ALIAS) {
                    342:                dup2vec[hostfd] &= ~DUP2ALIAS;
                    343:                return true;
                    344:        }
                    345:        return false;
                    346: }
1.17      pooka     347:
                    348: //#define DEBUGJACK
                    349: #ifdef DEBUGJACK
                    350: #define DPRINTF(x) mydprintf x
                    351: static void
                    352: mydprintf(const char *fmt, ...)
                    353: {
                    354:        va_list ap;
                    355:
1.71      pooka     356:        if (isdup2d(STDERR_FILENO))
1.17      pooka     357:                return;
                    358:
                    359:        va_start(ap, fmt);
                    360:        vfprintf(stderr, fmt, ap);
                    361:        va_end(ap);
                    362: }
                    363:
1.71      pooka     364: static const char *
                    365: whichfd(int fd)
                    366: {
                    367:
                    368:        if (fd == -1)
                    369:                return "-1";
                    370:        else if (fd_isrump(fd))
                    371:                return "rump";
                    372:        else
                    373:                return "host";
                    374: }
                    375:
                    376: static const char *
                    377: whichpath(const char *path)
                    378: {
                    379:
                    380:        if (path_isrump(path))
                    381:                return "rump";
                    382:        else
                    383:                return "host";
                    384: }
                    385:
1.17      pooka     386: #else
                    387: #define DPRINTF(x)
1.14      pooka     388: #endif
                    389:
1.17      pooka     390: #define FDCALL(type, name, rcname, args, proto, vars)                  \
                    391: type name args                                                         \
                    392: {                                                                      \
                    393:        type (*fun) proto;                                              \
                    394:                                                                        \
1.71      pooka     395:        DPRINTF(("%s -> %d (%s)\n", __STRING(name), fd, whichfd(fd)));  \
1.17      pooka     396:        if (fd_isrump(fd)) {                                            \
                    397:                fun = syscalls[rcname].bs_rump;                         \
                    398:                fd = fd_host2rump(fd);                                  \
                    399:        } else {                                                        \
                    400:                fun = syscalls[rcname].bs_host;                         \
                    401:        }                                                               \
                    402:                                                                        \
                    403:        return fun vars;                                                \
                    404: }
                    405:
1.45      pooka     406: #define PATHCALL(type, name, rcname, args, proto, vars)                        \
                    407: type name args                                                         \
                    408: {                                                                      \
                    409:        type (*fun) proto;                                              \
1.75      pooka     410:        enum pathtype pt;                                               \
1.45      pooka     411:                                                                        \
1.71      pooka     412:        DPRINTF(("%s -> %s (%s)\n", __STRING(name), path,               \
                    413:            whichpath(path)));                                          \
1.75      pooka     414:        if ((pt = path_isrump(path)) != PATH_HOST) {                    \
1.45      pooka     415:                fun = syscalls[rcname].bs_rump;                         \
1.75      pooka     416:                if (pt == PATH_RUMP)                                    \
                    417:                        path = path_host2rump(path);                    \
1.45      pooka     418:        } else {                                                        \
                    419:                fun = syscalls[rcname].bs_host;                         \
                    420:        }                                                               \
                    421:                                                                        \
                    422:        return fun vars;                                                \
                    423: }
                    424:
1.78      pooka     425: #define VFSCALL(bit, type, name, rcname, args, proto, vars)            \
                    426: type name args                                                         \
                    427: {                                                                      \
                    428:        type (*fun) proto;                                              \
                    429:                                                                        \
                    430:        DPRINTF(("%s (0x%x, 0x%x)\n", __STRING(name), bit, vfsbits));   \
                    431:        if (vfsbits & bit) {                                            \
                    432:                fun = syscalls[rcname].bs_rump;                         \
                    433:        } else {                                                        \
                    434:                fun = syscalls[rcname].bs_host;                         \
                    435:        }                                                               \
                    436:                                                                        \
                    437:        return fun vars;                                                \
                    438: }
                    439:
1.14      pooka     440: /*
1.49      pooka     441:  * These variables are set from the RUMPHIJACK string and control
                    442:  * which operations can product rump kernel file descriptors.
                    443:  * This should be easily extendable for future needs.
                    444:  */
                    445: #define RUMPHIJACK_DEFAULT "path=/rump,socket=all:nolocal"
                    446: static bool rumpsockets[PF_MAX];
                    447: static const char *rumpprefix;
                    448: static size_t rumpprefixlen;
                    449:
                    450: static struct {
                    451:        int pf;
                    452:        const char *name;
                    453: } socketmap[] = {
1.51      pooka     454:        { PF_LOCAL, "local" },
1.49      pooka     455:        { PF_INET, "inet" },
                    456:        { PF_LINK, "link" },
1.55      pooka     457: #ifdef PF_OROUTE
1.56      pooka     458:        { PF_OROUTE, "oroute" },
                    459: #endif
1.49      pooka     460:        { PF_ROUTE, "route" },
                    461:        { PF_INET6, "inet6" },
1.55      pooka     462: #ifdef PF_MPLS
                    463:        { PF_MPLS, "mpls" },
                    464: #endif
1.49      pooka     465:        { -1, NULL }
                    466: };
                    467:
                    468: static void
                    469: sockparser(char *buf)
                    470: {
                    471:        char *p, *l;
                    472:        bool value;
                    473:        int i;
                    474:
                    475:        /* if "all" is present, it must be specified first */
                    476:        if (strncmp(buf, "all", strlen("all")) == 0) {
1.50      pooka     477:                for (i = 0; i < (int)__arraycount(rumpsockets); i++) {
1.49      pooka     478:                        rumpsockets[i] = true;
                    479:                }
                    480:                buf += strlen("all");
                    481:                if (*buf == ':')
                    482:                        buf++;
                    483:        }
                    484:
                    485:        for (p = strtok_r(buf, ":", &l); p; p = strtok_r(NULL, ":", &l)) {
                    486:                value = true;
                    487:                if (strncmp(p, "no", strlen("no")) == 0) {
                    488:                        value = false;
                    489:                        p += strlen("no");
                    490:                }
1.45      pooka     491:
1.49      pooka     492:                for (i = 0; socketmap[i].name; i++) {
                    493:                        if (strcmp(p, socketmap[i].name) == 0) {
                    494:                                rumpsockets[socketmap[i].pf] = value;
                    495:                                break;
                    496:                        }
                    497:                }
                    498:                if (socketmap[i].name == NULL) {
1.78      pooka     499:                        errx(1, "invalid socket specifier %s", p);
1.49      pooka     500:                }
                    501:        }
                    502: }
                    503:
                    504: static void
                    505: pathparser(char *buf)
                    506: {
                    507:
1.57      pooka     508:        /* sanity-check */
1.49      pooka     509:        if (*buf != '/')
                    510:                errx(1, "hijack path specifier must begin with ``/''");
1.57      pooka     511:        rumpprefixlen = strlen(buf);
                    512:        if (rumpprefixlen < 2)
                    513:                errx(1, "invalid hijack prefix: %s", buf);
                    514:        if (buf[rumpprefixlen-1] == '/' && strspn(buf, "/") != rumpprefixlen)
                    515:                errx(1, "hijack prefix may end in slash only if pure "
                    516:                    "slash, gave %s", buf);
1.49      pooka     517:
                    518:        if ((rumpprefix = strdup(buf)) == NULL)
                    519:                err(1, "strdup");
                    520:        rumpprefixlen = strlen(rumpprefix);
                    521: }
                    522:
1.75      pooka     523: static struct blanket {
                    524:        const char *pfx;
                    525:        size_t len;
                    526: } *blanket;
                    527: static int nblanket;
                    528:
                    529: static void
                    530: blanketparser(char *buf)
                    531: {
                    532:        char *p, *l;
                    533:        int i;
                    534:
                    535:        for (nblanket = 0, p = buf; p; p = strchr(p+1, ':'), nblanket++)
                    536:                continue;
                    537:
                    538:        blanket = malloc(nblanket * sizeof(*blanket));
                    539:        if (blanket == NULL)
                    540:                err(1, "alloc blanket %d", nblanket);
                    541:
                    542:        for (p = strtok_r(buf, ":", &l), i = 0; p;
                    543:            p = strtok_r(NULL, ":", &l), i++) {
                    544:                blanket[i].pfx = strdup(p);
                    545:                if (blanket[i].pfx == NULL)
                    546:                        err(1, "strdup blanket");
                    547:                blanket[i].len = strlen(p);
                    548:
                    549:                if (blanket[i].len == 0 || *blanket[i].pfx != '/')
                    550:                        errx(1, "invalid blanket specifier %s", p);
                    551:                if (*(blanket[i].pfx + blanket[i].len-1) == '/')
                    552:                        errx(1, "invalid blanket specifier %s", p);
                    553:        }
                    554: }
                    555:
1.78      pooka     556: #define VFSBIT_NFSSVC          0x01
                    557: #define VFSBIT_GETVFSSTAT      0x02
                    558: #define VFSBIT_FHCALLS         0x04
                    559: static unsigned vfsbits;
                    560:
                    561: static struct {
                    562:        int bit;
                    563:        const char *name;
                    564: } vfscalls[] = {
                    565:        { VFSBIT_NFSSVC, "nfssvc" },
                    566:        { VFSBIT_GETVFSSTAT, "getvfsstat" },
                    567:        { VFSBIT_FHCALLS, "fhcalls" },
                    568:        { -1, NULL }
                    569: };
                    570:
                    571: static void
                    572: vfsparser(char *buf)
                    573: {
                    574:        char *p, *l;
                    575:        bool turnon;
                    576:        unsigned int fullmask;
                    577:        int i;
                    578:
                    579:        /* build the full mask and sanity-check while we're at it */
                    580:        fullmask = 0;
                    581:        for (i = 0; vfscalls[i].name != NULL; i++) {
                    582:                if (fullmask & vfscalls[i].bit)
                    583:                        errx(1, "problem exists between vi and chair");
                    584:                fullmask |= vfscalls[i].bit;
                    585:        }
                    586:
                    587:
                    588:        /* if "all" is present, it must be specified first */
                    589:        if (strncmp(buf, "all", strlen("all")) == 0) {
                    590:                vfsbits = fullmask;
                    591:                buf += strlen("all");
                    592:                if (*buf == ':')
                    593:                        buf++;
                    594:        }
                    595:
                    596:        for (p = strtok_r(buf, ":", &l); p; p = strtok_r(NULL, ":", &l)) {
                    597:                turnon = true;
                    598:                if (strncmp(p, "no", strlen("no")) == 0) {
                    599:                        turnon = false;
                    600:                        p += strlen("no");
                    601:                }
                    602:
                    603:                for (i = 0; vfscalls[i].name; i++) {
                    604:                        if (strcmp(p, vfscalls[i].name) == 0) {
                    605:                                if (turnon)
                    606:                                        vfsbits |= vfscalls[i].bit;
                    607:                                else
                    608:                                        vfsbits &= ~vfscalls[i].bit;
                    609:                                break;
                    610:                        }
                    611:                }
                    612:                if (vfscalls[i].name == NULL) {
                    613:                        errx(1, "invalid vfscall specifier %s", p);
                    614:                }
                    615:        }
                    616: }
                    617:
                    618: static bool rumpsysctl = false;
                    619:
                    620: static void
                    621: sysctlparser(char *buf)
                    622: {
                    623:
                    624:        if (buf == NULL) {
                    625:                rumpsysctl = true;
                    626:                return;
                    627:        }
                    628:
                    629:        if (strcasecmp(buf, "y") == 0 || strcasecmp(buf, "yes") == 0 ||
                    630:            strcasecmp(buf, "yep") == 0 || strcasecmp(buf, "tottakai") == 0) {
                    631:                rumpsysctl = true;
                    632:                return;
                    633:        }
                    634:        if (strcasecmp(buf, "n") == 0 || strcasecmp(buf, "no") == 0) {
                    635:                rumpsysctl = false;
                    636:                return;
                    637:        }
                    638:
                    639:        errx(1, "sysctl value should be y(es)/n(o), gave: %s", buf);
                    640: }
                    641:
1.49      pooka     642: static struct {
                    643:        void (*parsefn)(char *);
                    644:        const char *name;
1.78      pooka     645:        bool needvalues;
1.49      pooka     646: } hijackparse[] = {
1.78      pooka     647:        { sockparser, "socket", true },
                    648:        { pathparser, "path", true },
                    649:        { blanketparser, "blanket", true },
                    650:        { vfsparser, "vfs", true },
                    651:        { sysctlparser, "sysctl", false },
                    652:        { NULL, NULL, false },
1.49      pooka     653: };
                    654:
                    655: static void
                    656: parsehijack(char *hijack)
                    657: {
                    658:        char *p, *p2, *l;
                    659:        const char *hijackcopy;
1.78      pooka     660:        bool nop2;
1.49      pooka     661:        int i;
                    662:
                    663:        if ((hijackcopy = strdup(hijack)) == NULL)
                    664:                err(1, "strdup");
                    665:
                    666:        /* disable everything explicitly */
                    667:        for (i = 0; i < PF_MAX; i++)
                    668:                rumpsockets[i] = false;
                    669:
                    670:        for (p = strtok_r(hijack, ",", &l); p; p = strtok_r(NULL, ",", &l)) {
1.78      pooka     671:                nop2 = false;
1.49      pooka     672:                p2 = strchr(p, '=');
1.78      pooka     673:                if (!p2) {
                    674:                        nop2 = true;
                    675:                        p2 = p + strlen(p);
                    676:                }
1.49      pooka     677:
                    678:                for (i = 0; hijackparse[i].parsefn; i++) {
                    679:                        if (strncmp(hijackparse[i].name, p,
                    680:                            (size_t)(p2-p)) == 0) {
1.78      pooka     681:                                if (nop2 && hijackparse[i].needvalues)
                    682:                                        errx(1, "invalid hijack specifier: %s",
                    683:                                            hijackcopy);
                    684:                                hijackparse[i].parsefn(nop2 ? NULL : p2+1);
1.49      pooka     685:                                break;
                    686:                        }
                    687:                }
                    688:        }
                    689:
                    690: }
1.7       pooka     691:
1.1       pooka     692: static void __attribute__((constructor))
                    693: rcinit(void)
                    694: {
1.49      pooka     695:        char buf[1024];
1.19      pooka     696:        unsigned i, j;
1.1       pooka     697:
1.17      pooka     698:        host_fork = dlsym(RTLD_NEXT, "fork");
1.25      pooka     699:        host_daemon = dlsym(RTLD_NEXT, "daemon");
1.62      pooka     700:        host_mmap = dlsym(RTLD_NEXT, "mmap");
1.17      pooka     701:
                    702:        /*
                    703:         * In theory cannot print anything during lookups because
                    704:         * we might not have the call vector set up.  so, the errx()
                    705:         * is a bit of a strech, but it might work.
                    706:         */
1.1       pooka     707:
1.17      pooka     708:        for (i = 0; i < DUALCALL__NUM; i++) {
                    709:                /* build runtime O(1) access */
                    710:                for (j = 0; j < __arraycount(syscnames); j++) {
                    711:                        if (syscnames[j].scm_callnum == i)
                    712:                                break;
                    713:                }
                    714:
                    715:                if (j == __arraycount(syscnames))
                    716:                        errx(1, "rumphijack error: syscall pos %d missing", i);
                    717:
1.23      pooka     718:                syscalls[i].bs_host = dlsym(RTLD_NEXT,
                    719:                    syscnames[j].scm_hostname);
1.17      pooka     720:                if (syscalls[i].bs_host == NULL)
1.70      pooka     721:                        errx(1, "hostcall %s not found!",
1.17      pooka     722:                            syscnames[j].scm_hostname);
                    723:
1.23      pooka     724:                syscalls[i].bs_rump = dlsym(RTLD_NEXT,
                    725:                    syscnames[j].scm_rumpname);
1.17      pooka     726:                if (syscalls[i].bs_rump == NULL)
1.70      pooka     727:                        errx(1, "rumpcall %s not found!",
1.17      pooka     728:                            syscnames[j].scm_rumpname);
1.1       pooka     729:        }
                    730:
1.22      pooka     731:        if (rumpclient_init() == -1)
1.1       pooka     732:                err(1, "rumpclient init");
1.28      pooka     733:
1.49      pooka     734:        /* check which syscalls we're supposed to hijack */
                    735:        if (getenv_r("RUMPHIJACK", buf, sizeof(buf)) == -1) {
                    736:                strcpy(buf, RUMPHIJACK_DEFAULT);
                    737:        }
                    738:        parsehijack(buf);
                    739:
1.28      pooka     740:        /* set client persistence level */
1.44      pooka     741:        if (getenv_r("RUMPHIJACK_RETRYCONNECT", buf, sizeof(buf)) != -1) {
1.28      pooka     742:                if (strcmp(buf, "die") == 0)
                    743:                        rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_DIE);
                    744:                else if (strcmp(buf, "inftime") == 0)
                    745:                        rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_INFTIME);
                    746:                else if (strcmp(buf, "once") == 0)
                    747:                        rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_ONCE);
                    748:                else {
                    749:                        time_t timeout;
1.44      pooka     750:                        char *ep;
1.28      pooka     751:
1.44      pooka     752:                        timeout = (time_t)strtoll(buf, &ep, 10);
                    753:                        if (timeout <= 0 || ep != buf + strlen(buf))
                    754:                                errx(1, "RUMPHIJACK_RETRYCONNECT must be "
                    755:                                    "keyword or integer, got: %s", buf);
1.28      pooka     756:
                    757:                        rumpclient_setconnretry(timeout);
                    758:                }
                    759:        }
1.39      pooka     760:
1.71      pooka     761:        if (getenv_r("RUMPHIJACK__DUP2INFO", buf, sizeof(buf)) == 0) {
                    762:                if (sscanf(buf, "%u,%u,%u",
                    763:                    &dup2vec[0], &dup2vec[1], &dup2vec[2]) != 3) {
                    764:                        warnx("invalid dup2mask: %s", buf);
                    765:                        memset(dup2vec, 0, sizeof(dup2vec));
                    766:                }
                    767:                unsetenv("RUMPHIJACK__DUP2INFO");
1.45      pooka     768:        }
                    769:        if (getenv_r("RUMPHIJACK__PWDINRUMP", buf, sizeof(buf)) == 0) {
1.49      pooka     770:                pwdinrump = true;
1.45      pooka     771:                unsetenv("RUMPHIJACK__PWDINRUMP");
1.39      pooka     772:        }
1.1       pooka     773: }
                    774:
1.71      pooka     775: /* Need runtime selection.  low for now due to FD_SETSIZE */
1.2       pooka     776: #define HIJACK_FDOFF 128
1.71      pooka     777:
1.2       pooka     778: static int
                    779: fd_rump2host(int fd)
                    780: {
                    781:
                    782:        if (fd == -1)
                    783:                return fd;
1.71      pooka     784:        return fd + HIJACK_FDOFF;
                    785: }
1.2       pooka     786:
1.71      pooka     787: static int
                    788: fd_rump2host_withdup(int fd)
                    789: {
                    790:        int hfd;
1.2       pooka     791:
1.71      pooka     792:        _DIAGASSERT(fd != -1);
                    793:        hfd = unmapdup2(fd);
                    794:        if (hfd != -1) {
                    795:                _DIAGASSERT(hfd <= DUP2HIGH);
                    796:                return hfd;
                    797:        }
                    798:        return fd_rump2host(fd);
1.2       pooka     799: }
                    800:
                    801: static int
                    802: fd_host2rump(int fd)
                    803: {
                    804:
1.71      pooka     805:        if (!isdup2d(fd))
                    806:                return fd - HIJACK_FDOFF;
                    807:        else
                    808:                return mapdup2(fd);
1.2       pooka     809: }
                    810:
                    811: static bool
                    812: fd_isrump(int fd)
                    813: {
                    814:
1.71      pooka     815:        return isdup2d(fd) || fd >= HIJACK_FDOFF;
1.2       pooka     816: }
                    817:
1.40      pooka     818: #define assertfd(_fd_) assert(ISDUP2D(_fd_) || (_fd_) >= HIJACK_FDOFF)
                    819:
1.75      pooka     820: static enum pathtype
1.45      pooka     821: path_isrump(const char *path)
                    822: {
1.76      pooka     823:        size_t plen;
1.75      pooka     824:        int i;
1.45      pooka     825:
1.75      pooka     826:        if (rumpprefix == NULL && nblanket == 0)
                    827:                return PATH_HOST;
1.49      pooka     828:
1.45      pooka     829:        if (*path == '/') {
1.76      pooka     830:                plen = strlen(path);
                    831:                if (rumpprefix && plen >= rumpprefixlen) {
                    832:                        if (strncmp(path, rumpprefix, rumpprefixlen) == 0
                    833:                            && (plen == rumpprefixlen
                    834:                              || *(path + rumpprefixlen) == '/')) {
1.75      pooka     835:                                return PATH_RUMP;
                    836:                        }
                    837:                }
                    838:                for (i = 0; i < nblanket; i++) {
                    839:                        if (strncmp(path, blanket[i].pfx, blanket[i].len) == 0)
                    840:                                return PATH_RUMPBLANKET;
                    841:                }
                    842:
                    843:                return PATH_HOST;
1.45      pooka     844:        } else {
1.75      pooka     845:                return pwdinrump ? PATH_RUMP : PATH_HOST;
1.45      pooka     846:        }
                    847: }
                    848:
                    849: static const char *rootpath = "/";
                    850: static const char *
                    851: path_host2rump(const char *path)
                    852: {
                    853:        const char *rv;
                    854:
                    855:        if (*path == '/') {
1.49      pooka     856:                rv = path + rumpprefixlen;
1.45      pooka     857:                if (*rv == '\0')
                    858:                        rv = rootpath;
                    859:        } else {
                    860:                rv = path;
                    861:        }
                    862:
                    863:        return rv;
                    864: }
                    865:
1.40      pooka     866: static int
                    867: dodup(int oldd, int minfd)
                    868: {
                    869:        int (*op_fcntl)(int, int, ...);
                    870:        int newd;
                    871:        int isrump;
                    872:
                    873:        DPRINTF(("dup -> %d (minfd %d)\n", oldd, minfd));
                    874:        if (fd_isrump(oldd)) {
                    875:                op_fcntl = GETSYSCALL(rump, FCNTL);
                    876:                oldd = fd_host2rump(oldd);
1.63      pooka     877:                if (minfd >= HIJACK_FDOFF)
                    878:                        minfd -= HIJACK_FDOFF;
1.40      pooka     879:                isrump = 1;
                    880:        } else {
                    881:                op_fcntl = GETSYSCALL(host, FCNTL);
                    882:                isrump = 0;
                    883:        }
                    884:
                    885:        newd = op_fcntl(oldd, F_DUPFD, minfd);
                    886:
                    887:        if (isrump)
                    888:                newd = fd_rump2host(newd);
                    889:        DPRINTF(("dup <- %d\n", newd));
                    890:
                    891:        return newd;
                    892: }
1.2       pooka     893:
1.47      pooka     894: /*
                    895:  * dup a host file descriptor so that it doesn't collide with the dup2mask
                    896:  */
                    897: static int
                    898: fd_dupgood(int fd)
                    899: {
                    900:        int (*op_fcntl)(int, int, ...) = GETSYSCALL(host, FCNTL);
                    901:        int (*op_close)(int) = GETSYSCALL(host, CLOSE);
                    902:        int ofd, i;
                    903:
1.71      pooka     904:        for (i = 1; isdup2d(fd); i++) {
1.47      pooka     905:                ofd = fd;
                    906:                fd = op_fcntl(ofd, F_DUPFD, i);
                    907:                op_close(ofd);
                    908:        }
                    909:
                    910:        return fd;
                    911: }
                    912:
1.45      pooka     913: int
                    914: open(const char *path, int flags, ...)
                    915: {
                    916:        int (*op_open)(const char *, int, ...);
                    917:        bool isrump;
                    918:        va_list ap;
1.75      pooka     919:        enum pathtype pt;
1.45      pooka     920:        int fd;
                    921:
1.71      pooka     922:        DPRINTF(("open -> %s (%s)\n", path, whichpath(path)));
                    923:
1.75      pooka     924:        if ((pt = path_isrump(path)) != PATH_HOST) {
                    925:                if (pt == PATH_RUMP)
                    926:                        path = path_host2rump(path);
1.45      pooka     927:                op_open = GETSYSCALL(rump, OPEN);
                    928:                isrump = true;
                    929:        } else {
                    930:                op_open = GETSYSCALL(host, OPEN);
                    931:                isrump = false;
                    932:        }
                    933:
                    934:        va_start(ap, flags);
                    935:        fd = op_open(path, flags, va_arg(ap, mode_t));
                    936:        va_end(ap);
                    937:
                    938:        if (isrump)
                    939:                fd = fd_rump2host(fd);
1.47      pooka     940:        else
                    941:                fd = fd_dupgood(fd);
1.71      pooka     942:
                    943:        DPRINTF(("open <- %d (%s)\n", fd, whichfd(fd)));
1.45      pooka     944:        return fd;
                    945: }
                    946:
                    947: int
                    948: chdir(const char *path)
                    949: {
                    950:        int (*op_chdir)(const char *);
1.75      pooka     951:        enum pathtype pt;
1.45      pooka     952:        int rv;
                    953:
1.75      pooka     954:        if ((pt = path_isrump(path)) != PATH_HOST) {
1.45      pooka     955:                op_chdir = GETSYSCALL(rump, CHDIR);
1.75      pooka     956:                if (pt == PATH_RUMP)
                    957:                        path = path_host2rump(path);
1.45      pooka     958:        } else {
                    959:                op_chdir = GETSYSCALL(host, CHDIR);
                    960:        }
                    961:
                    962:        rv = op_chdir(path);
1.75      pooka     963:        if (rv == 0)
                    964:                pwdinrump = pt != PATH_HOST;
1.45      pooka     965:
                    966:        return rv;
                    967: }
                    968:
                    969: int
                    970: fchdir(int fd)
                    971: {
                    972:        int (*op_fchdir)(int);
                    973:        bool isrump;
                    974:        int rv;
                    975:
                    976:        if (fd_isrump(fd)) {
                    977:                op_fchdir = GETSYSCALL(rump, FCHDIR);
                    978:                isrump = true;
                    979:                fd = fd_host2rump(fd);
                    980:        } else {
                    981:                op_fchdir = GETSYSCALL(host, FCHDIR);
                    982:                isrump = false;
                    983:        }
                    984:
                    985:        rv = op_fchdir(fd);
                    986:        if (rv == 0) {
1.75      pooka     987:                pwdinrump = isrump;
1.45      pooka     988:        }
                    989:
                    990:        return rv;
                    991: }
                    992:
1.52      pooka     993: int
1.57      pooka     994: __getcwd(char *bufp, size_t len)
                    995: {
                    996:        int (*op___getcwd)(char *, size_t);
1.75      pooka     997:        size_t prefixgap;
                    998:        bool iamslash;
1.57      pooka     999:        int rv;
                   1000:
1.75      pooka    1001:        if (pwdinrump && rumpprefix) {
1.57      pooka    1002:                if (rumpprefix[rumpprefixlen-1] == '/')
                   1003:                        iamslash = true;
                   1004:                else
                   1005:                        iamslash = false;
                   1006:
                   1007:                if (iamslash)
                   1008:                        prefixgap = rumpprefixlen - 1; /* ``//+path'' */
                   1009:                else
                   1010:                        prefixgap = rumpprefixlen; /* ``/pfx+/path'' */
                   1011:                if (len <= prefixgap) {
1.66      pooka    1012:                        errno = ERANGE;
                   1013:                        return -1;
1.57      pooka    1014:                }
                   1015:
                   1016:                op___getcwd = GETSYSCALL(rump, __GETCWD);
                   1017:                rv = op___getcwd(bufp + prefixgap, len - prefixgap);
                   1018:                if (rv == -1)
                   1019:                        return rv;
                   1020:
                   1021:                /* augment the "/" part only for a non-root path */
                   1022:                memcpy(bufp, rumpprefix, rumpprefixlen);
                   1023:
                   1024:                /* append / only to non-root cwd */
                   1025:                if (rv != 2)
                   1026:                        bufp[prefixgap] = '/';
                   1027:
                   1028:                /* don't append extra slash in the purely-slash case */
                   1029:                if (rv == 2 && !iamslash)
                   1030:                        bufp[rumpprefixlen] = '\0';
1.75      pooka    1031:        } else if (pwdinrump) {
                   1032:                /* assume blanket.  we can't provide a prefix here */
                   1033:                op___getcwd = GETSYSCALL(rump, __GETCWD);
                   1034:                rv = op___getcwd(bufp, len);
1.57      pooka    1035:        } else {
                   1036:                op___getcwd = GETSYSCALL(host, __GETCWD);
1.75      pooka    1037:                rv = op___getcwd(bufp, len);
1.57      pooka    1038:        }
1.75      pooka    1039:
                   1040:        return rv;
1.57      pooka    1041: }
                   1042:
                   1043: int
1.52      pooka    1044: rename(const char *from, const char *to)
                   1045: {
                   1046:        int (*op_rename)(const char *, const char *);
1.75      pooka    1047:        enum pathtype ptf, ptt;
1.52      pooka    1048:
1.75      pooka    1049:        if ((ptf = path_isrump(from)) != PATH_HOST) {
                   1050:                if ((ptt = path_isrump(to)) == PATH_HOST) {
1.66      pooka    1051:                        errno = EXDEV;
                   1052:                        return -1;
                   1053:                }
1.52      pooka    1054:
1.75      pooka    1055:                if (ptf == PATH_RUMP)
                   1056:                        from = path_host2rump(from);
                   1057:                if (ptt == PATH_RUMP)
                   1058:                        to = path_host2rump(to);
1.52      pooka    1059:                op_rename = GETSYSCALL(rump, RENAME);
                   1060:        } else {
1.75      pooka    1061:                if (path_isrump(to) != PATH_HOST) {
1.66      pooka    1062:                        errno = EXDEV;
                   1063:                        return -1;
                   1064:                }
1.53      pooka    1065:
1.52      pooka    1066:                op_rename = GETSYSCALL(host, RENAME);
                   1067:        }
                   1068:
                   1069:        return op_rename(from, to);
                   1070: }
                   1071:
1.1       pooka    1072: int __socket30(int, int, int);
                   1073: int
                   1074: __socket30(int domain, int type, int protocol)
                   1075: {
1.17      pooka    1076:        int (*op_socket)(int, int, int);
1.1       pooka    1077:        int fd;
1.49      pooka    1078:        bool isrump;
1.7       pooka    1079:
1.49      pooka    1080:        isrump = domain < PF_MAX && rumpsockets[domain];
1.1       pooka    1081:
1.49      pooka    1082:        if (isrump)
                   1083:                op_socket = GETSYSCALL(rump, SOCKET);
                   1084:        else
1.17      pooka    1085:                op_socket = GETSYSCALL(host, SOCKET);
                   1086:        fd = op_socket(domain, type, protocol);
1.2       pooka    1087:
1.49      pooka    1088:        if (isrump)
1.7       pooka    1089:                fd = fd_rump2host(fd);
1.47      pooka    1090:        else
                   1091:                fd = fd_dupgood(fd);
1.7       pooka    1092:        DPRINTF(("socket <- %d\n", fd));
1.2       pooka    1093:
1.7       pooka    1094:        return fd;
1.1       pooka    1095: }
                   1096:
                   1097: int
                   1098: accept(int s, struct sockaddr *addr, socklen_t *addrlen)
                   1099: {
1.17      pooka    1100:        int (*op_accept)(int, struct sockaddr *, socklen_t *);
1.1       pooka    1101:        int fd;
1.7       pooka    1102:        bool isrump;
                   1103:
                   1104:        isrump = fd_isrump(s);
1.1       pooka    1105:
1.2       pooka    1106:        DPRINTF(("accept -> %d", s));
1.7       pooka    1107:        if (isrump) {
1.17      pooka    1108:                op_accept = GETSYSCALL(rump, ACCEPT);
1.7       pooka    1109:                s = fd_host2rump(s);
                   1110:        } else {
1.17      pooka    1111:                op_accept = GETSYSCALL(host, ACCEPT);
1.7       pooka    1112:        }
1.17      pooka    1113:        fd = op_accept(s, addr, addrlen);
1.7       pooka    1114:        if (fd != -1 && isrump)
                   1115:                fd = fd_rump2host(fd);
1.47      pooka    1116:        else
                   1117:                fd = fd_dupgood(fd);
1.7       pooka    1118:
                   1119:        DPRINTF((" <- %d\n", fd));
1.2       pooka    1120:
1.7       pooka    1121:        return fd;
1.1       pooka    1122: }
                   1123:
1.17      pooka    1124: /*
                   1125:  * ioctl and fcntl are varargs calls and need special treatment
                   1126:  */
1.1       pooka    1127: int
1.17      pooka    1128: ioctl(int fd, unsigned long cmd, ...)
1.1       pooka    1129: {
1.17      pooka    1130:        int (*op_ioctl)(int, unsigned long cmd, ...);
                   1131:        va_list ap;
                   1132:        int rv;
1.1       pooka    1133:
1.17      pooka    1134:        DPRINTF(("ioctl -> %d\n", fd));
                   1135:        if (fd_isrump(fd)) {
                   1136:                fd = fd_host2rump(fd);
                   1137:                op_ioctl = GETSYSCALL(rump, IOCTL);
1.7       pooka    1138:        } else {
1.17      pooka    1139:                op_ioctl = GETSYSCALL(host, IOCTL);
1.7       pooka    1140:        }
1.1       pooka    1141:
1.17      pooka    1142:        va_start(ap, cmd);
                   1143:        rv = op_ioctl(fd, cmd, va_arg(ap, void *));
                   1144:        va_end(ap);
                   1145:        return rv;
1.1       pooka    1146: }
                   1147:
                   1148: int
1.17      pooka    1149: fcntl(int fd, int cmd, ...)
1.1       pooka    1150: {
1.17      pooka    1151:        int (*op_fcntl)(int, int, ...);
                   1152:        va_list ap;
1.71      pooka    1153:        int rv, minfd, i, maxdup2;
1.40      pooka    1154:
                   1155:        DPRINTF(("fcntl -> %d (cmd %d)\n", fd, cmd));
                   1156:
                   1157:        switch (cmd) {
                   1158:        case F_DUPFD:
                   1159:                va_start(ap, cmd);
                   1160:                minfd = va_arg(ap, int);
                   1161:                va_end(ap);
                   1162:                return dodup(fd, minfd);
                   1163:
                   1164:        case F_CLOSEM:
                   1165:                /*
                   1166:                 * So, if fd < HIJACKOFF, we want to do a host closem.
                   1167:                 */
                   1168:
                   1169:                if (fd < HIJACK_FDOFF) {
                   1170:                        int closemfd = fd;
1.1       pooka    1171:
1.40      pooka    1172:                        if (rumpclient__closenotify(&closemfd,
1.39      pooka    1173:                            RUMPCLIENT_CLOSE_FCLOSEM) == -1)
                   1174:                                return -1;
1.40      pooka    1175:                        op_fcntl = GETSYSCALL(host, FCNTL);
                   1176:                        rv = op_fcntl(closemfd, cmd);
                   1177:                        if (rv)
                   1178:                                return rv;
                   1179:                }
                   1180:
                   1181:                /*
                   1182:                 * Additionally, we want to do a rump closem, but only
1.71      pooka    1183:                 * for the file descriptors not dup2'd.
1.40      pooka    1184:                 */
                   1185:
1.71      pooka    1186:                for (i = 0, maxdup2 = 0; i <= DUP2HIGH; i++) {
1.72      pooka    1187:                        if (dup2vec[i] & DUP2BIT) {
                   1188:                                int val;
                   1189:
                   1190:                                val = dup2vec[i] & DUP2FDMASK;
                   1191:                                maxdup2 = MAX(val, maxdup2);
                   1192:                        }
1.40      pooka    1193:                }
                   1194:
                   1195:                if (fd >= HIJACK_FDOFF)
                   1196:                        fd -= HIJACK_FDOFF;
                   1197:                else
                   1198:                        fd = 0;
1.71      pooka    1199:                fd = MAX(maxdup2+1, fd);
1.40      pooka    1200:
                   1201:                /* hmm, maybe we should close rump fd's not within dup2mask? */
                   1202:                return rump_sys_fcntl(fd, F_CLOSEM);
                   1203:
                   1204:        case F_MAXFD:
                   1205:                /*
                   1206:                 * For maxfd, if there's a rump kernel fd, return
                   1207:                 * it hostified.  Otherwise, return host's MAXFD
                   1208:                 * return value.
                   1209:                 */
                   1210:                if ((rv = rump_sys_fcntl(fd, F_MAXFD)) != -1) {
                   1211:                        /*
                   1212:                         * This might go a little wrong in case
                   1213:                         * of dup2 to [012], but I'm not sure if
                   1214:                         * there's a justification for tracking
                   1215:                         * that info.  Consider e.g.
                   1216:                         * dup2(rumpfd, 2) followed by rump_sys_open()
                   1217:                         * returning 1.  We should return 1+HIJACKOFF,
                   1218:                         * not 2+HIJACKOFF.  However, if [01] is not
                   1219:                         * open, the correct return value is 2.
                   1220:                         */
                   1221:                        return fd_rump2host(fd);
                   1222:                } else {
                   1223:                        op_fcntl = GETSYSCALL(host, FCNTL);
                   1224:                        return op_fcntl(fd, F_MAXFD);
                   1225:                }
                   1226:                /*NOTREACHED*/
                   1227:
                   1228:        default:
                   1229:                if (fd_isrump(fd)) {
                   1230:                        fd = fd_host2rump(fd);
                   1231:                        op_fcntl = GETSYSCALL(rump, FCNTL);
                   1232:                } else {
                   1233:                        op_fcntl = GETSYSCALL(host, FCNTL);
                   1234:                }
                   1235:
                   1236:                va_start(ap, cmd);
                   1237:                rv = op_fcntl(fd, cmd, va_arg(ap, void *));
                   1238:                va_end(ap);
                   1239:                return rv;
1.7       pooka    1240:        }
1.40      pooka    1241:        /*NOTREACHED*/
1.1       pooka    1242: }
                   1243:
1.39      pooka    1244: int
                   1245: close(int fd)
                   1246: {
                   1247:        int (*op_close)(int);
                   1248:        int rv;
                   1249:
                   1250:        DPRINTF(("close -> %d\n", fd));
                   1251:        if (fd_isrump(fd)) {
1.71      pooka    1252:                bool undup2 = false;
                   1253:                int ofd;
                   1254:
                   1255:                if (isdup2d(ofd = fd)) {
                   1256:                        undup2 = true;
                   1257:                }
1.39      pooka    1258:
1.47      pooka    1259:                fd = fd_host2rump(fd);
1.71      pooka    1260:                if (!undup2 && killdup2alias(fd)) {
1.47      pooka    1261:                        return 0;
                   1262:                }
                   1263:
1.39      pooka    1264:                op_close = GETSYSCALL(rump, CLOSE);
                   1265:                rv = op_close(fd);
1.71      pooka    1266:                if (rv == 0 && undup2) {
                   1267:                        clrdup2(ofd);
                   1268:                }
1.39      pooka    1269:        } else {
                   1270:                if (rumpclient__closenotify(&fd, RUMPCLIENT_CLOSE_CLOSE) == -1)
                   1271:                        return -1;
                   1272:                op_close = GETSYSCALL(host, CLOSE);
                   1273:                rv = op_close(fd);
                   1274:        }
                   1275:
                   1276:        return rv;
                   1277: }
                   1278:
1.17      pooka    1279: /*
                   1280:  * write cannot issue a standard debug printf due to recursion
                   1281:  */
1.1       pooka    1282: ssize_t
1.17      pooka    1283: write(int fd, const void *buf, size_t blen)
1.1       pooka    1284: {
1.17      pooka    1285:        ssize_t (*op_write)(int, const void *, size_t);
1.1       pooka    1286:
1.17      pooka    1287:        if (fd_isrump(fd)) {
                   1288:                fd = fd_host2rump(fd);
                   1289:                op_write = GETSYSCALL(rump, WRITE);
1.16      pooka    1290:        } else {
1.17      pooka    1291:                op_write = GETSYSCALL(host, WRITE);
1.16      pooka    1292:        }
1.1       pooka    1293:
1.17      pooka    1294:        return op_write(fd, buf, blen);
1.2       pooka    1295: }
                   1296:
                   1297: /*
                   1298:  * dup2 is special.  we allow dup2 of a rump kernel fd to 0-2 since
                   1299:  * many programs do that.  dup2 of a rump kernel fd to another value
                   1300:  * not >= fdoff is an error.
                   1301:  *
                   1302:  * Note: cannot rump2host newd, because it is often hardcoded.
                   1303:  */
                   1304: int
                   1305: dup2(int oldd, int newd)
                   1306: {
1.17      pooka    1307:        int (*host_dup2)(int, int);
1.2       pooka    1308:        int rv;
                   1309:
                   1310:        DPRINTF(("dup2 -> %d (o) -> %d (n)\n", oldd, newd));
                   1311:
                   1312:        if (fd_isrump(oldd)) {
1.71      pooka    1313:                int (*op_close)(int) = GETSYSCALL(host, CLOSE);
                   1314:
                   1315:                /* only allow fd 0-2 for cross-kernel dup */
                   1316:                if (!(newd >= 0 && newd <= 2 && !fd_isrump(newd))) {
1.66      pooka    1317:                        errno = EBADF;
                   1318:                        return -1;
                   1319:                }
1.71      pooka    1320:
                   1321:                /* regular dup2? */
                   1322:                if (fd_isrump(newd)) {
                   1323:                        newd = fd_host2rump(newd);
                   1324:                        rv = rump_sys_dup2(oldd, newd);
                   1325:                        return fd_rump2host(rv);
                   1326:                }
                   1327:
                   1328:                /*
                   1329:                 * dup2 rump => host?  just establish an
                   1330:                 * entry in the mapping table.
                   1331:                 */
                   1332:                op_close(newd);
                   1333:                setdup2(newd, fd_host2rump(oldd));
                   1334:                rv = 0;
1.2       pooka    1335:        } else {
1.17      pooka    1336:                host_dup2 = syscalls[DUALCALL_DUP2].bs_host;
1.39      pooka    1337:                if (rumpclient__closenotify(&newd, RUMPCLIENT_CLOSE_DUP2) == -1)
                   1338:                        return -1;
1.10      pooka    1339:                rv = host_dup2(oldd, newd);
1.2       pooka    1340:        }
1.10      pooka    1341:
                   1342:        return rv;
1.2       pooka    1343: }
                   1344:
1.34      pooka    1345: int
                   1346: dup(int oldd)
                   1347: {
                   1348:
1.40      pooka    1349:        return dodup(oldd, 0);
1.34      pooka    1350: }
                   1351:
1.2       pooka    1352: pid_t
                   1353: fork()
                   1354: {
                   1355:        pid_t rv;
                   1356:
                   1357:        DPRINTF(("fork\n"));
                   1358:
1.43      pooka    1359:        rv = rumpclient__dofork(host_fork);
1.2       pooka    1360:
                   1361:        DPRINTF(("fork returns %d\n", rv));
                   1362:        return rv;
1.1       pooka    1363: }
1.43      pooka    1364: /* we do not have the luxury of not requiring a stackframe */
                   1365: __strong_alias(__vfork14,fork);
1.1       pooka    1366:
1.25      pooka    1367: int
                   1368: daemon(int nochdir, int noclose)
                   1369: {
                   1370:        struct rumpclient_fork *rf;
                   1371:
                   1372:        if ((rf = rumpclient_prefork()) == NULL)
                   1373:                return -1;
                   1374:
                   1375:        if (host_daemon(nochdir, noclose) == -1)
                   1376:                return -1;
                   1377:
                   1378:        if (rumpclient_fork_init(rf) == -1)
                   1379:                return -1;
                   1380:
                   1381:        return 0;
                   1382: }
                   1383:
1.39      pooka    1384: int
1.42      pooka    1385: execve(const char *path, char *const argv[], char *const envp[])
1.39      pooka    1386: {
                   1387:        char buf[128];
                   1388:        char *dup2str;
1.49      pooka    1389:        const char *pwdinrumpstr;
1.42      pooka    1390:        char **newenv;
                   1391:        size_t nelem;
                   1392:        int rv, sverrno;
1.71      pooka    1393:        int bonus = 2, i = 0;
1.45      pooka    1394:
1.71      pooka    1395:        snprintf(buf, sizeof(buf), "RUMPHIJACK__DUP2INFO=%u,%u,%u",
                   1396:            dup2vec[0], dup2vec[1], dup2vec[2]);
                   1397:        dup2str = strdup(buf);
                   1398:        if (dup2str == NULL) {
                   1399:                errno = ENOMEM;
                   1400:                return -1;
1.45      pooka    1401:        }
1.39      pooka    1402:
1.45      pooka    1403:        if (pwdinrump) {
1.49      pooka    1404:                pwdinrumpstr = "RUMPHIJACK__PWDINRUMP=true";
1.45      pooka    1405:                bonus++;
                   1406:        } else {
                   1407:                pwdinrumpstr = NULL;
                   1408:        }
1.39      pooka    1409:
1.42      pooka    1410:        for (nelem = 0; envp && envp[nelem]; nelem++)
                   1411:                continue;
1.71      pooka    1412:        newenv = malloc(sizeof(*newenv) * (nelem+bonus));
1.42      pooka    1413:        if (newenv == NULL) {
1.39      pooka    1414:                free(dup2str);
1.66      pooka    1415:                errno = ENOMEM;
                   1416:                return -1;
1.39      pooka    1417:        }
1.42      pooka    1418:        memcpy(newenv, envp, nelem*sizeof(*newenv));
1.71      pooka    1419:        newenv[nelem+i] = dup2str;
                   1420:        i++;
                   1421:
1.45      pooka    1422:        if (pwdinrumpstr) {
1.49      pooka    1423:                newenv[nelem+i] = __UNCONST(pwdinrumpstr);
1.45      pooka    1424:                i++;
                   1425:        }
                   1426:        newenv[nelem+i] = NULL;
                   1427:        _DIAGASSERT(i < bonus);
1.42      pooka    1428:
                   1429:        rv = rumpclient_exec(path, argv, newenv);
                   1430:
                   1431:        _DIAGASSERT(rv != 0);
                   1432:        sverrno = errno;
                   1433:        free(newenv);
                   1434:        free(dup2str);
                   1435:        errno = sverrno;
1.39      pooka    1436:        return rv;
                   1437: }
                   1438:
1.1       pooka    1439: /*
1.17      pooka    1440:  * select is done by calling poll.
1.1       pooka    1441:  */
                   1442: int
1.29      pooka    1443: REALSELECT(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
1.4       pooka    1444:        struct timeval *timeout)
1.1       pooka    1445: {
1.4       pooka    1446:        struct pollfd *pfds;
                   1447:        struct timespec ts, *tsp = NULL;
1.19      pooka    1448:        nfds_t realnfds;
                   1449:        int i, j;
1.4       pooka    1450:        int rv, incr;
                   1451:
1.7       pooka    1452:        DPRINTF(("select\n"));
                   1453:
1.4       pooka    1454:        /*
                   1455:         * Well, first we must scan the fds to figure out how many
                   1456:         * fds there really are.  This is because up to and including
1.17      pooka    1457:         * nb5 poll() silently refuses nfds > process_maxopen_fds.
1.4       pooka    1458:         * Seems to be fixed in current, thank the maker.
                   1459:         * god damn cluster...bomb.
                   1460:         */
                   1461:
                   1462:        for (i = 0, realnfds = 0; i < nfds; i++) {
                   1463:                if (readfds && FD_ISSET(i, readfds)) {
                   1464:                        realnfds++;
                   1465:                        continue;
                   1466:                }
                   1467:                if (writefds && FD_ISSET(i, writefds)) {
                   1468:                        realnfds++;
                   1469:                        continue;
                   1470:                }
                   1471:                if (exceptfds && FD_ISSET(i, exceptfds)) {
                   1472:                        realnfds++;
                   1473:                        continue;
1.1       pooka    1474:                }
                   1475:        }
                   1476:
1.6       pooka    1477:        if (realnfds) {
1.38      pooka    1478:                pfds = calloc(realnfds, sizeof(*pfds));
1.6       pooka    1479:                if (!pfds)
                   1480:                        return -1;
                   1481:        } else {
                   1482:                pfds = NULL;
                   1483:        }
1.1       pooka    1484:
1.4       pooka    1485:        for (i = 0, j = 0; i < nfds; i++) {
                   1486:                incr = 0;
                   1487:                if (readfds && FD_ISSET(i, readfds)) {
                   1488:                        pfds[j].fd = i;
                   1489:                        pfds[j].events |= POLLIN;
                   1490:                        incr=1;
                   1491:                }
                   1492:                if (writefds && FD_ISSET(i, writefds)) {
                   1493:                        pfds[j].fd = i;
                   1494:                        pfds[j].events |= POLLOUT;
                   1495:                        incr=1;
                   1496:                }
                   1497:                if (exceptfds && FD_ISSET(i, exceptfds)) {
                   1498:                        pfds[j].fd = i;
                   1499:                        pfds[j].events |= POLLHUP|POLLERR;
                   1500:                        incr=1;
1.1       pooka    1501:                }
1.4       pooka    1502:                if (incr)
                   1503:                        j++;
1.1       pooka    1504:        }
1.37      pooka    1505:        assert(j == (int)realnfds);
1.1       pooka    1506:
1.4       pooka    1507:        if (timeout) {
                   1508:                TIMEVAL_TO_TIMESPEC(timeout, &ts);
                   1509:                tsp = &ts;
                   1510:        }
1.29      pooka    1511:        rv = REALPOLLTS(pfds, realnfds, tsp, NULL);
1.36      pooka    1512:        /*
                   1513:         * "If select() returns with an error the descriptor sets
                   1514:         * will be unmodified"
                   1515:         */
                   1516:        if (rv < 0)
1.4       pooka    1517:                goto out;
                   1518:
                   1519:        /*
1.36      pooka    1520:         * zero out results (can't use FD_ZERO for the
                   1521:         * obvious select-me-not reason).  whee.
                   1522:         *
                   1523:         * We do this here since some software ignores the return
                   1524:         * value of select, and hence if the timeout expires, it may
                   1525:         * assume all input descriptors have activity.
1.4       pooka    1526:         */
                   1527:        for (i = 0; i < nfds; i++) {
                   1528:                if (readfds)
                   1529:                        FD_CLR(i, readfds);
                   1530:                if (writefds)
                   1531:                        FD_CLR(i, writefds);
                   1532:                if (exceptfds)
                   1533:                        FD_CLR(i, exceptfds);
1.1       pooka    1534:        }
1.36      pooka    1535:        if (rv == 0)
                   1536:                goto out;
1.1       pooka    1537:
1.36      pooka    1538:        /*
                   1539:         * We have >0 fds with activity.  Harvest the results.
                   1540:         */
1.19      pooka    1541:        for (i = 0; i < (int)realnfds; i++) {
1.4       pooka    1542:                if (readfds) {
                   1543:                        if (pfds[i].revents & POLLIN) {
                   1544:                                FD_SET(pfds[i].fd, readfds);
                   1545:                        }
                   1546:                }
                   1547:                if (writefds) {
                   1548:                        if (pfds[i].revents & POLLOUT) {
                   1549:                                FD_SET(pfds[i].fd, writefds);
                   1550:                        }
                   1551:                }
                   1552:                if (exceptfds) {
                   1553:                        if (pfds[i].revents & (POLLHUP|POLLERR)) {
                   1554:                                FD_SET(pfds[i].fd, exceptfds);
                   1555:                        }
                   1556:                }
1.1       pooka    1557:        }
                   1558:
1.4       pooka    1559:  out:
                   1560:        free(pfds);
1.1       pooka    1561:        return rv;
                   1562: }
                   1563:
                   1564: static void
                   1565: checkpoll(struct pollfd *fds, nfds_t nfds, int *hostcall, int *rumpcall)
                   1566: {
                   1567:        nfds_t i;
                   1568:
                   1569:        for (i = 0; i < nfds; i++) {
1.12      pooka    1570:                if (fds[i].fd == -1)
                   1571:                        continue;
                   1572:
1.2       pooka    1573:                if (fd_isrump(fds[i].fd))
                   1574:                        (*rumpcall)++;
                   1575:                else
1.1       pooka    1576:                        (*hostcall)++;
                   1577:        }
                   1578: }
                   1579:
                   1580: static void
1.2       pooka    1581: adjustpoll(struct pollfd *fds, nfds_t nfds, int (*fdadj)(int))
1.1       pooka    1582: {
                   1583:        nfds_t i;
                   1584:
                   1585:        for (i = 0; i < nfds; i++) {
1.2       pooka    1586:                fds[i].fd = fdadj(fds[i].fd);
1.1       pooka    1587:        }
                   1588: }
                   1589:
                   1590: /*
                   1591:  * poll is easy as long as the call comes in the fds only in one
                   1592:  * kernel.  otherwise its quite tricky...
                   1593:  */
                   1594: struct pollarg {
                   1595:        struct pollfd *pfds;
                   1596:        nfds_t nfds;
1.3       pooka    1597:        const struct timespec *ts;
                   1598:        const sigset_t *sigmask;
1.1       pooka    1599:        int pipefd;
                   1600:        int errnum;
                   1601: };
                   1602:
                   1603: static void *
                   1604: hostpoll(void *arg)
                   1605: {
1.17      pooka    1606:        int (*op_pollts)(struct pollfd *, nfds_t, const struct timespec *,
                   1607:                         const sigset_t *);
1.1       pooka    1608:        struct pollarg *parg = arg;
                   1609:        intptr_t rv;
                   1610:
1.35      pooka    1611:        op_pollts = GETSYSCALL(host, POLLTS);
1.17      pooka    1612:        rv = op_pollts(parg->pfds, parg->nfds, parg->ts, parg->sigmask);
1.1       pooka    1613:        if (rv == -1)
                   1614:                parg->errnum = errno;
                   1615:        rump_sys_write(parg->pipefd, &rv, sizeof(rv));
                   1616:
                   1617:        return (void *)(intptr_t)rv;
                   1618: }
                   1619:
                   1620: int
1.29      pooka    1621: REALPOLLTS(struct pollfd *fds, nfds_t nfds, const struct timespec *ts,
1.3       pooka    1622:        const sigset_t *sigmask)
1.1       pooka    1623: {
1.3       pooka    1624:        int (*op_pollts)(struct pollfd *, nfds_t, const struct timespec *,
                   1625:                         const sigset_t *);
1.17      pooka    1626:        int (*host_close)(int);
1.1       pooka    1627:        int hostcall = 0, rumpcall = 0;
                   1628:        pthread_t pt;
                   1629:        nfds_t i;
                   1630:        int rv;
                   1631:
1.2       pooka    1632:        DPRINTF(("poll\n"));
1.1       pooka    1633:        checkpoll(fds, nfds, &hostcall, &rumpcall);
                   1634:
                   1635:        if (hostcall && rumpcall) {
                   1636:                struct pollfd *pfd_host = NULL, *pfd_rump = NULL;
                   1637:                int rpipe[2] = {-1,-1}, hpipe[2] = {-1,-1};
                   1638:                struct pollarg parg;
                   1639:                uintptr_t lrv;
                   1640:                int sverrno = 0, trv;
                   1641:
                   1642:                /*
                   1643:                 * ok, this is where it gets tricky.  We must support
                   1644:                 * this since it's a very common operation in certain
                   1645:                 * types of software (telnet, netcat, etc).  We allocate
                   1646:                 * two vectors and run two poll commands in separate
                   1647:                 * threads.  Whichever returns first "wins" and the
                   1648:                 * other kernel's fds won't show activity.
                   1649:                 */
                   1650:                rv = -1;
                   1651:
                   1652:                /* allocate full vector for O(n) joining after call */
                   1653:                pfd_host = malloc(sizeof(*pfd_host)*(nfds+1));
                   1654:                if (!pfd_host)
                   1655:                        goto out;
                   1656:                pfd_rump = malloc(sizeof(*pfd_rump)*(nfds+1));
                   1657:                if (!pfd_rump) {
                   1658:                        goto out;
                   1659:                }
                   1660:
1.59      pooka    1661:                /*
                   1662:                 * then, open two pipes, one for notifications
                   1663:                 * to each kernel.
1.73      pooka    1664:                 *
                   1665:                 * At least the rump pipe should probably be
                   1666:                 * cached, along with the helper threads.  This
                   1667:                 * should give a microbenchmark improvement (haven't
                   1668:                 * experienced a macro-level problem yet, though).
1.59      pooka    1669:                 */
                   1670:                if ((rv = rump_sys_pipe(rpipe)) == -1) {
                   1671:                        sverrno = errno;
                   1672:                }
                   1673:                if (rv == 0 && (rv = pipe(hpipe)) == -1) {
                   1674:                        sverrno = errno;
                   1675:                }
                   1676:
                   1677:                /* split vectors (or signal errors) */
1.1       pooka    1678:                for (i = 0; i < nfds; i++) {
1.59      pooka    1679:                        int fd;
                   1680:
                   1681:                        fds[i].revents = 0;
1.3       pooka    1682:                        if (fds[i].fd == -1) {
                   1683:                                pfd_host[i].fd = -1;
                   1684:                                pfd_rump[i].fd = -1;
                   1685:                        } else if (fd_isrump(fds[i].fd)) {
1.2       pooka    1686:                                pfd_host[i].fd = -1;
1.59      pooka    1687:                                fd = fd_host2rump(fds[i].fd);
                   1688:                                if (fd == rpipe[0] || fd == rpipe[1]) {
                   1689:                                        fds[i].revents = POLLNVAL;
                   1690:                                        if (rv != -1)
                   1691:                                                rv++;
                   1692:                                }
                   1693:                                pfd_rump[i].fd = fd;
1.2       pooka    1694:                                pfd_rump[i].events = fds[i].events;
                   1695:                        } else {
                   1696:                                pfd_rump[i].fd = -1;
1.59      pooka    1697:                                fd = fds[i].fd;
                   1698:                                if (fd == hpipe[0] || fd == hpipe[1]) {
                   1699:                                        fds[i].revents = POLLNVAL;
                   1700:                                        if (rv != -1)
                   1701:                                                rv++;
                   1702:                                }
                   1703:                                pfd_host[i].fd = fd;
1.1       pooka    1704:                                pfd_host[i].events = fds[i].events;
                   1705:                        }
1.39      pooka    1706:                        pfd_rump[i].revents = pfd_host[i].revents = 0;
1.1       pooka    1707:                }
1.59      pooka    1708:                if (rv) {
1.1       pooka    1709:                        goto out;
1.59      pooka    1710:                }
1.1       pooka    1711:
                   1712:                pfd_host[nfds].fd = hpipe[0];
                   1713:                pfd_host[nfds].events = POLLIN;
                   1714:                pfd_rump[nfds].fd = rpipe[0];
                   1715:                pfd_rump[nfds].events = POLLIN;
                   1716:
                   1717:                /*
                   1718:                 * then, create a thread to do host part and meanwhile
                   1719:                 * do rump kernel part right here
                   1720:                 */
                   1721:
                   1722:                parg.pfds = pfd_host;
                   1723:                parg.nfds = nfds+1;
1.3       pooka    1724:                parg.ts = ts;
                   1725:                parg.sigmask = sigmask;
1.1       pooka    1726:                parg.pipefd = rpipe[1];
                   1727:                pthread_create(&pt, NULL, hostpoll, &parg);
                   1728:
1.35      pooka    1729:                op_pollts = GETSYSCALL(rump, POLLTS);
1.3       pooka    1730:                lrv = op_pollts(pfd_rump, nfds+1, ts, NULL);
1.1       pooka    1731:                sverrno = errno;
                   1732:                write(hpipe[1], &rv, sizeof(rv));
                   1733:                pthread_join(pt, (void *)&trv);
                   1734:
                   1735:                /* check who "won" and merge results */
                   1736:                if (lrv != 0 && pfd_host[nfds].revents & POLLIN) {
                   1737:                        rv = trv;
                   1738:
                   1739:                        for (i = 0; i < nfds; i++) {
                   1740:                                if (pfd_rump[i].fd != -1)
                   1741:                                        fds[i].revents = pfd_rump[i].revents;
                   1742:                        }
                   1743:                        sverrno = parg.errnum;
                   1744:                } else if (trv != 0 && pfd_rump[nfds].revents & POLLIN) {
                   1745:                        rv = trv;
                   1746:
                   1747:                        for (i = 0; i < nfds; i++) {
                   1748:                                if (pfd_host[i].fd != -1)
                   1749:                                        fds[i].revents = pfd_host[i].revents;
                   1750:                        }
                   1751:                } else {
                   1752:                        rv = 0;
                   1753:                }
                   1754:
                   1755:  out:
1.35      pooka    1756:                host_close = GETSYSCALL(host, CLOSE);
1.1       pooka    1757:                if (rpipe[0] != -1)
                   1758:                        rump_sys_close(rpipe[0]);
                   1759:                if (rpipe[1] != -1)
                   1760:                        rump_sys_close(rpipe[1]);
                   1761:                if (hpipe[0] != -1)
1.9       pooka    1762:                        host_close(hpipe[0]);
1.1       pooka    1763:                if (hpipe[1] != -1)
1.9       pooka    1764:                        host_close(hpipe[1]);
1.1       pooka    1765:                free(pfd_host);
                   1766:                free(pfd_rump);
                   1767:                errno = sverrno;
                   1768:        } else {
                   1769:                if (hostcall) {
1.35      pooka    1770:                        op_pollts = GETSYSCALL(host, POLLTS);
1.1       pooka    1771:                } else {
1.35      pooka    1772:                        op_pollts = GETSYSCALL(rump, POLLTS);
1.2       pooka    1773:                        adjustpoll(fds, nfds, fd_host2rump);
1.1       pooka    1774:                }
                   1775:
1.3       pooka    1776:                rv = op_pollts(fds, nfds, ts, sigmask);
1.1       pooka    1777:                if (rumpcall)
1.71      pooka    1778:                        adjustpoll(fds, nfds, fd_rump2host_withdup);
1.1       pooka    1779:        }
                   1780:
                   1781:        return rv;
                   1782: }
                   1783:
                   1784: int
1.24      pooka    1785: poll(struct pollfd *fds, nfds_t nfds, int timeout)
1.1       pooka    1786: {
1.3       pooka    1787:        struct timespec ts;
                   1788:        struct timespec *tsp = NULL;
                   1789:
                   1790:        if (timeout != INFTIM) {
                   1791:                ts.tv_sec = timeout / 1000;
1.11      pooka    1792:                ts.tv_nsec = (timeout % 1000) * 1000*1000;
1.3       pooka    1793:
                   1794:                tsp = &ts;
                   1795:        }
1.1       pooka    1796:
1.29      pooka    1797:        return REALPOLLTS(fds, nfds, tsp, NULL);
1.1       pooka    1798: }
1.10      pooka    1799:
                   1800: int
1.34      pooka    1801: REALKEVENT(int kq, const struct kevent *changelist, size_t nchanges,
                   1802:        struct kevent *eventlist, size_t nevents,
                   1803:        const struct timespec *timeout)
1.10      pooka    1804: {
1.34      pooka    1805:        int (*op_kevent)(int, const struct kevent *, size_t,
                   1806:                struct kevent *, size_t, const struct timespec *);
                   1807:        const struct kevent *ev;
                   1808:        size_t i;
1.10      pooka    1809:
1.34      pooka    1810:        /*
                   1811:         * Check that we don't attempt to kevent rump kernel fd's.
                   1812:         * That needs similar treatment to select/poll, but is slightly
                   1813:         * trickier since we need to manage to different kq descriptors.
                   1814:         * (TODO, in case you're wondering).
                   1815:         */
                   1816:        for (i = 0; i < nchanges; i++) {
                   1817:                ev = &changelist[i];
                   1818:                if (ev->filter == EVFILT_READ || ev->filter == EVFILT_WRITE ||
                   1819:                    ev->filter == EVFILT_VNODE) {
1.66      pooka    1820:                        if (fd_isrump((int)ev->ident)) {
                   1821:                                errno = ENOTSUP;
                   1822:                                return -1;
                   1823:                        }
1.34      pooka    1824:                }
1.27      pooka    1825:        }
1.10      pooka    1826:
1.35      pooka    1827:        op_kevent = GETSYSCALL(host, KEVENT);
1.34      pooka    1828:        return op_kevent(kq, changelist, nchanges, eventlist, nevents, timeout);
1.10      pooka    1829: }
1.17      pooka    1830:
                   1831: /*
1.62      pooka    1832:  * mmapping from a rump kernel is not supported, so disallow it.
                   1833:  */
                   1834: void *
                   1835: mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
                   1836: {
                   1837:
                   1838:        if (flags & MAP_FILE && fd_isrump(fd)) {
                   1839:                errno = ENOSYS;
                   1840:                return MAP_FAILED;
                   1841:        }
                   1842:        return host_mmap(addr, len, prot, flags, fd, offset);
                   1843: }
                   1844:
                   1845: /*
1.78      pooka    1846:  * these go to one or the other on a per-process configuration
                   1847:  */
                   1848: int __sysctl(const int *, unsigned int, void *, size_t *, const void *, size_t);
                   1849: int
                   1850: __sysctl(const int *name, unsigned int namelen, void *old, size_t *oldlenp,
                   1851:        const void *new, size_t newlen)
                   1852: {
                   1853:        int (*op___sysctl)(const int *, unsigned int, void *, size_t *,
                   1854:            const void *, size_t);
                   1855:
                   1856:        if (rumpsysctl) {
                   1857:                op___sysctl = GETSYSCALL(rump, __SYSCTL);
                   1858:        } else {
                   1859:                op___sysctl = GETSYSCALL(host, __SYSCTL);
                   1860:                /* we haven't inited yet */
                   1861:                if (__predict_false(op___sysctl == NULL)) {
                   1862:                        op___sysctl = dlsym(RTLD_NEXT, "__sysctl");
                   1863:                }
                   1864:        }
                   1865:
                   1866:        return op___sysctl(name, namelen, old, oldlenp, new, newlen);
                   1867: }
                   1868:
                   1869: /*
1.17      pooka    1870:  * Rest are std type calls.
                   1871:  */
                   1872:
                   1873: FDCALL(int, bind, DUALCALL_BIND,                                       \
                   1874:        (int fd, const struct sockaddr *name, socklen_t namelen),       \
                   1875:        (int, const struct sockaddr *, socklen_t),                      \
                   1876:        (fd, name, namelen))
                   1877:
                   1878: FDCALL(int, connect, DUALCALL_CONNECT,                                 \
                   1879:        (int fd, const struct sockaddr *name, socklen_t namelen),       \
                   1880:        (int, const struct sockaddr *, socklen_t),                      \
                   1881:        (fd, name, namelen))
                   1882:
                   1883: FDCALL(int, getpeername, DUALCALL_GETPEERNAME,                         \
                   1884:        (int fd, struct sockaddr *name, socklen_t *namelen),            \
                   1885:        (int, struct sockaddr *, socklen_t *),                          \
                   1886:        (fd, name, namelen))
                   1887:
                   1888: FDCALL(int, getsockname, DUALCALL_GETSOCKNAME,                                 \
                   1889:        (int fd, struct sockaddr *name, socklen_t *namelen),            \
                   1890:        (int, struct sockaddr *, socklen_t *),                          \
                   1891:        (fd, name, namelen))
                   1892:
                   1893: FDCALL(int, listen, DUALCALL_LISTEN,                                   \
                   1894:        (int fd, int backlog),                                          \
                   1895:        (int, int),                                                     \
                   1896:        (fd, backlog))
                   1897:
                   1898: FDCALL(ssize_t, recvfrom, DUALCALL_RECVFROM,                           \
                   1899:        (int fd, void *buf, size_t len, int flags,                      \
                   1900:            struct sockaddr *from, socklen_t *fromlen),                 \
                   1901:        (int, void *, size_t, int, struct sockaddr *, socklen_t *),     \
                   1902:        (fd, buf, len, flags, from, fromlen))
                   1903:
                   1904: FDCALL(ssize_t, sendto, DUALCALL_SENDTO,                               \
                   1905:        (int fd, const void *buf, size_t len, int flags,                \
                   1906:            const struct sockaddr *to, socklen_t tolen),                \
                   1907:        (int, const void *, size_t, int,                                \
                   1908:            const struct sockaddr *, socklen_t),                        \
                   1909:        (fd, buf, len, flags, to, tolen))
                   1910:
                   1911: FDCALL(ssize_t, recvmsg, DUALCALL_RECVMSG,                             \
                   1912:        (int fd, struct msghdr *msg, int flags),                        \
                   1913:        (int, struct msghdr *, int),                                    \
                   1914:        (fd, msg, flags))
                   1915:
                   1916: FDCALL(ssize_t, sendmsg, DUALCALL_SENDMSG,                             \
                   1917:        (int fd, const struct msghdr *msg, int flags),                  \
                   1918:        (int, const struct msghdr *, int),                              \
                   1919:        (fd, msg, flags))
                   1920:
                   1921: FDCALL(int, getsockopt, DUALCALL_GETSOCKOPT,                           \
                   1922:        (int fd, int level, int optn, void *optval, socklen_t *optlen), \
                   1923:        (int, int, int, void *, socklen_t *),                           \
                   1924:        (fd, level, optn, optval, optlen))
                   1925:
                   1926: FDCALL(int, setsockopt, DUALCALL_SETSOCKOPT,                           \
                   1927:        (int fd, int level, int optn,                                   \
                   1928:            const void *optval, socklen_t optlen),                      \
                   1929:        (int, int, int, const void *, socklen_t),                       \
                   1930:        (fd, level, optn, optval, optlen))
                   1931:
                   1932: FDCALL(int, shutdown, DUALCALL_SHUTDOWN,                               \
                   1933:        (int fd, int how),                                              \
                   1934:        (int, int),                                                     \
                   1935:        (fd, how))
                   1936:
1.21      christos 1937: #if _FORTIFY_SOURCE > 0
                   1938: #define STUB(fun) __ssp_weak_name(fun)
                   1939: ssize_t _sys_readlink(const char * __restrict, char * __restrict, size_t);
                   1940: ssize_t
                   1941: STUB(readlink)(const char * __restrict path, char * __restrict buf,
                   1942:     size_t bufsiz)
                   1943: {
                   1944:        return _sys_readlink(path, buf, bufsiz);
                   1945: }
                   1946:
                   1947: char *_sys_getcwd(char *, size_t);
                   1948: char *
                   1949: STUB(getcwd)(char *buf, size_t size)
                   1950: {
                   1951:        return _sys_getcwd(buf, size);
                   1952: }
                   1953: #else
                   1954: #define STUB(fun) fun
                   1955: #endif
                   1956:
1.31      pooka    1957: FDCALL(ssize_t, REALREAD, DUALCALL_READ,                               \
1.17      pooka    1958:        (int fd, void *buf, size_t buflen),                             \
                   1959:        (int, void *, size_t),                                          \
                   1960:        (fd, buf, buflen))
                   1961:
1.18      pooka    1962: FDCALL(ssize_t, readv, DUALCALL_READV,                                         \
1.17      pooka    1963:        (int fd, const struct iovec *iov, int iovcnt),                  \
                   1964:        (int, const struct iovec *, int),                               \
                   1965:        (fd, iov, iovcnt))
                   1966:
1.60      pooka    1967: FDCALL(ssize_t, REALPREAD, DUALCALL_PREAD,                             \
                   1968:        (int fd, void *buf, size_t nbytes, off_t offset),               \
                   1969:        (int, void *, size_t, off_t),                                   \
                   1970:        (fd, buf, nbytes, offset))
                   1971:
                   1972: FDCALL(ssize_t, preadv, DUALCALL_PREADV,                               \
                   1973:        (int fd, const struct iovec *iov, int iovcnt, off_t offset),    \
                   1974:        (int, const struct iovec *, int, off_t),                        \
                   1975:        (fd, iov, iovcnt, offset))
                   1976:
1.17      pooka    1977: FDCALL(ssize_t, writev, DUALCALL_WRITEV,                               \
                   1978:        (int fd, const struct iovec *iov, int iovcnt),                  \
                   1979:        (int, const struct iovec *, int),                               \
                   1980:        (fd, iov, iovcnt))
1.45      pooka    1981:
1.60      pooka    1982: FDCALL(ssize_t, REALPWRITE, DUALCALL_PWRITE,                           \
                   1983:        (int fd, const void *buf, size_t nbytes, off_t offset),         \
                   1984:        (int, const void *, size_t, off_t),                             \
                   1985:        (fd, buf, nbytes, offset))
                   1986:
                   1987: FDCALL(ssize_t, pwritev, DUALCALL_PWRITEV,                             \
                   1988:        (int fd, const struct iovec *iov, int iovcnt, off_t offset),    \
                   1989:        (int, const struct iovec *, int, off_t),                        \
                   1990:        (fd, iov, iovcnt, offset))
                   1991:
1.45      pooka    1992: FDCALL(int, REALFSTAT, DUALCALL_FSTAT,                                 \
                   1993:        (int fd, struct stat *sb),                                      \
                   1994:        (int, struct stat *),                                           \
                   1995:        (fd, sb))
                   1996:
                   1997: FDCALL(int, fstatvfs1, DUALCALL_FSTATVFS1,                             \
                   1998:        (int fd, struct statvfs *buf, int flags),                       \
                   1999:        (int, struct statvfs *, int),                                   \
                   2000:        (fd, buf, flags))
                   2001:
1.61      pooka    2002: FDCALL(off_t, lseek, DUALCALL_LSEEK,                                   \
1.45      pooka    2003:        (int fd, off_t offset, int whence),                             \
                   2004:        (int, off_t, int),                                              \
                   2005:        (fd, offset, whence))
1.61      pooka    2006: __strong_alias(_lseek,lseek);
1.45      pooka    2007:
                   2008: FDCALL(int, REALGETDENTS, DUALCALL_GETDENTS,                           \
                   2009:        (int fd, char *buf, size_t nbytes),                             \
                   2010:        (int, char *, size_t),                                          \
                   2011:        (fd, buf, nbytes))
                   2012:
                   2013: FDCALL(int, fchown, DUALCALL_FCHOWN,                                   \
                   2014:        (int fd, uid_t owner, gid_t group),                             \
                   2015:        (int, uid_t, gid_t),                                            \
                   2016:        (fd, owner, group))
                   2017:
                   2018: FDCALL(int, fchmod, DUALCALL_FCHMOD,                                   \
                   2019:        (int fd, mode_t mode),                                          \
                   2020:        (int, mode_t),                                                  \
                   2021:        (fd, mode))
                   2022:
                   2023: FDCALL(int, ftruncate, DUALCALL_FTRUNCATE,                             \
                   2024:        (int fd, off_t length),                                         \
                   2025:        (int, off_t),                                                   \
                   2026:        (fd, length))
                   2027:
                   2028: FDCALL(int, fsync, DUALCALL_FSYNC,                                     \
                   2029:        (int fd),                                                       \
                   2030:        (int),                                                          \
                   2031:        (fd))
                   2032:
                   2033: FDCALL(int, fsync_range, DUALCALL_FSYNC_RANGE,                         \
                   2034:        (int fd, int how, off_t start, off_t length),                   \
                   2035:        (int, int, off_t, off_t),                                       \
                   2036:        (fd, how, start, length))
                   2037:
                   2038: FDCALL(int, futimes, DUALCALL_FUTIMES,                                 \
                   2039:        (int fd, const struct timeval *tv),                             \
                   2040:        (int, const struct timeval *),                                  \
                   2041:        (fd, tv))
                   2042:
1.60      pooka    2043: FDCALL(int, fchflags, DUALCALL_FCHFLAGS,                               \
                   2044:        (int fd, u_long flags),                                         \
                   2045:        (int, u_long),                                                  \
                   2046:        (fd, flags))
                   2047:
1.45      pooka    2048: /*
                   2049:  * path-based selectors
                   2050:  */
                   2051:
                   2052: PATHCALL(int, REALSTAT, DUALCALL_STAT,                                 \
                   2053:        (const char *path, struct stat *sb),                            \
                   2054:        (const char *, struct stat *),                                  \
                   2055:        (path, sb))
                   2056:
                   2057: PATHCALL(int, REALLSTAT, DUALCALL_LSTAT,                               \
                   2058:        (const char *path, struct stat *sb),                            \
                   2059:        (const char *, struct stat *),                                  \
                   2060:        (path, sb))
                   2061:
                   2062: PATHCALL(int, chown, DUALCALL_CHOWN,                                   \
                   2063:        (const char *path, uid_t owner, gid_t group),                   \
                   2064:        (const char *, uid_t, gid_t),                                   \
                   2065:        (path, owner, group))
                   2066:
                   2067: PATHCALL(int, lchown, DUALCALL_LCHOWN,                                 \
                   2068:        (const char *path, uid_t owner, gid_t group),                   \
                   2069:        (const char *, uid_t, gid_t),                                   \
                   2070:        (path, owner, group))
                   2071:
                   2072: PATHCALL(int, chmod, DUALCALL_CHMOD,                                   \
                   2073:        (const char *path, mode_t mode),                                \
                   2074:        (const char *, mode_t),                                         \
                   2075:        (path, mode))
                   2076:
                   2077: PATHCALL(int, lchmod, DUALCALL_LCHMOD,                                 \
                   2078:        (const char *path, mode_t mode),                                \
                   2079:        (const char *, mode_t),                                         \
                   2080:        (path, mode))
                   2081:
                   2082: PATHCALL(int, statvfs1, DUALCALL_STATVFS1,                             \
                   2083:        (const char *path, struct statvfs *buf, int flags),             \
                   2084:        (const char *, struct statvfs *, int),                          \
                   2085:        (path, buf, flags))
                   2086:
                   2087: PATHCALL(int, unlink, DUALCALL_UNLINK,                                 \
                   2088:        (const char *path),                                             \
                   2089:        (const char *),                                                 \
                   2090:        (path))
                   2091:
                   2092: PATHCALL(int, symlink, DUALCALL_SYMLINK,                               \
1.58      pooka    2093:        (const char *target, const char *path),                         \
1.45      pooka    2094:        (const char *, const char *),                                   \
1.58      pooka    2095:        (target, path))
1.45      pooka    2096:
1.46      pooka    2097: PATHCALL(ssize_t, readlink, DUALCALL_READLINK,                         \
1.45      pooka    2098:        (const char *path, char *buf, size_t bufsiz),                   \
                   2099:        (const char *, char *, size_t),                                 \
                   2100:        (path, buf, bufsiz))
                   2101:
                   2102: PATHCALL(int, mkdir, DUALCALL_MKDIR,                                   \
                   2103:        (const char *path, mode_t mode),                                \
                   2104:        (const char *, mode_t),                                         \
                   2105:        (path, mode))
                   2106:
                   2107: PATHCALL(int, rmdir, DUALCALL_RMDIR,                                   \
                   2108:        (const char *path),                                             \
                   2109:        (const char *),                                                 \
                   2110:        (path))
                   2111:
                   2112: PATHCALL(int, utimes, DUALCALL_UTIMES,                                 \
                   2113:        (const char *path, const struct timeval *tv),                   \
                   2114:        (const char *, const struct timeval *),                         \
                   2115:        (path, tv))
                   2116:
                   2117: PATHCALL(int, lutimes, DUALCALL_LUTIMES,                               \
                   2118:        (const char *path, const struct timeval *tv),                   \
                   2119:        (const char *, const struct timeval *),                         \
                   2120:        (path, tv))
                   2121:
1.60      pooka    2122: PATHCALL(int, chflags, DUALCALL_CHFLAGS,                               \
                   2123:        (const char *path, u_long flags),                               \
                   2124:        (const char *, u_long),                                         \
                   2125:        (path, flags))
                   2126:
                   2127: PATHCALL(int, lchflags, DUALCALL_LCHFLAGS,                             \
                   2128:        (const char *path, u_long flags),                               \
                   2129:        (const char *, u_long),                                         \
                   2130:        (path, flags))
                   2131:
1.45      pooka    2132: PATHCALL(int, truncate, DUALCALL_TRUNCATE,                             \
                   2133:        (const char *path, off_t length),                               \
                   2134:        (const char *, off_t),                                          \
                   2135:        (path, length))
1.48      pooka    2136:
1.65      pooka    2137: PATHCALL(int, access, DUALCALL_ACCESS,                                 \
                   2138:        (const char *path, int mode),                                   \
                   2139:        (const char *, int),                                            \
                   2140:        (path, mode))
                   2141:
1.68      pooka    2142: PATHCALL(int, REALMKNOD, DUALCALL_MKNOD,                               \
                   2143:        (const char *path, mode_t mode, dev_t dev),                     \
                   2144:        (const char *, mode_t, dev_t),                                  \
                   2145:        (path, mode, dev))
                   2146:
1.48      pooka    2147: /*
                   2148:  * Note: with mount the decisive parameter is the mount
                   2149:  * destination directory.  This is because we don't really know
                   2150:  * about the "source" directory in a generic call (and besides,
                   2151:  * it might not even exist, cf. nfs).
                   2152:  */
                   2153: PATHCALL(int, REALMOUNT, DUALCALL_MOUNT,                               \
                   2154:        (const char *type, const char *path, int flags,                 \
                   2155:            void *data, size_t dlen),                                   \
                   2156:        (const char *, const char *, int, void *, size_t),              \
                   2157:        (type, path, flags, data, dlen))
                   2158:
                   2159: PATHCALL(int, unmount, DUALCALL_UNMOUNT,                               \
                   2160:        (const char *path, int flags),                                  \
                   2161:        (const char *, int),                                            \
                   2162:        (path, flags))
1.78      pooka    2163:
                   2164: /*
                   2165:  * These act different on a per-process vfs configuration
                   2166:  */
                   2167:
                   2168: VFSCALL(VFSBIT_GETVFSSTAT, int, getvfsstat, DUALCALL_GETVFSSTAT,       \
                   2169:        (struct statvfs *buf, size_t buflen, int flags),                \
                   2170:        (struct statvfs *, size_t, int),                                \
                   2171:        (buf, buflen, flags))
                   2172:
                   2173: VFSCALL(VFSBIT_FHCALLS, int, REALGETFH, DUALCALL_GETFH,                        \
                   2174:        (const char *path, void *fhp, size_t *fh_size),                 \
                   2175:        (const char *, void *, size_t *),                               \
                   2176:        (path, fhp, fh_size))
                   2177:
                   2178: VFSCALL(VFSBIT_FHCALLS, int, REALFHOPEN, DUALCALL_FHOPEN,              \
                   2179:        (const void *fhp, size_t fh_size, int flags),                   \
                   2180:        (const char *, size_t, int),                                    \
                   2181:        (fhp, fh_size, flags))
                   2182:
                   2183: VFSCALL(VFSBIT_FHCALLS, int, REALFHSTAT, DUALCALL_FHSTAT,              \
                   2184:        (const void *fhp, size_t fh_size, struct stat *sb),             \
                   2185:        (const char *, size_t, struct stat *),                          \
                   2186:        (fhp, fh_size, sb))
                   2187:
                   2188: VFSCALL(VFSBIT_FHCALLS, int, REALFHSTATVFS1, DUALCALL_FHSTATVFS1,      \
                   2189:        (const void *fhp, size_t fh_size, struct statvfs *sb, int flgs),\
                   2190:        (const char *, size_t, struct statvfs *, int),                  \
                   2191:        (fhp, fh_size, sb, flgs))
                   2192:
                   2193: /* finally, put nfssvc here.  "keep the namespace clean" */
                   2194:
                   2195: #include <nfs/rpcv2.h>
                   2196: #include <nfs/nfs.h>
                   2197:
                   2198: int
                   2199: nfssvc(int flags, void *argstructp)
                   2200: {
                   2201:        int (*op_nfssvc)(int, void *);
                   2202:
                   2203:        if (vfsbits & VFSBIT_NFSSVC){
                   2204:                struct nfsd_args *nfsdargs;
                   2205:
                   2206:                /* massage the socket descriptor if necessary */
                   2207:                if (flags == NFSSVC_ADDSOCK) {
                   2208:                        nfsdargs = argstructp;
                   2209:                        nfsdargs->sock = fd_host2rump(nfsdargs->sock);
                   2210:                }
                   2211:                op_nfssvc = GETSYSCALL(rump, NFSSVC);
                   2212:        } else
                   2213:                op_nfssvc = GETSYSCALL(host, NFSSVC);
                   2214:
                   2215:        return op_nfssvc(flags, argstructp);
                   2216: }

CVSweb <webmaster@jp.NetBSD.org>