[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.121.2.1

1.121.2.1! bouyer      1: /*      $NetBSD: hijack.c,v 1.122 2017/02/16 08:08:01 ozaki-r 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:
1.111     pooka      28: /*
                     29:  * XXX: rumphijack sort of works on glibc Linux.  But it's not
                     30:  * the same quality working as on NetBSD.
                     31:  * autoconf HAVE_FOO vs. __NetBSD__ / __linux__ could be further
                     32:  * improved.
                     33:  */
1.106     pooka      34: #include <rump/rumpuser_port.h>
1.96      pooka      35:
1.101     pooka      36: #if !defined(lint)
1.121.2.1! bouyer     37: __RCSID("$NetBSD: hijack.c,v 1.122 2017/02/16 08:08:01 ozaki-r Exp $");
1.101     pooka      38: #endif
1.1       pooka      39:
                     40: #include <sys/param.h>
                     41: #include <sys/types.h>
                     42: #include <sys/ioctl.h>
1.62      pooka      43: #include <sys/mman.h>
1.48      pooka      44: #include <sys/mount.h>
1.1       pooka      45: #include <sys/socket.h>
1.96      pooka      46: #include <sys/stat.h>
                     47: #include <sys/time.h>
1.102     pooka      48: #include <sys/uio.h>
1.96      pooka      49:
1.111     pooka      50: #ifdef __NetBSD__
1.107     justin     51: #include <sys/statvfs.h>
                     52: #endif
                     53:
1.111     pooka      54: #ifdef HAVE_KQUEUE
1.96      pooka      55: #include <sys/event.h>
                     56: #endif
                     57:
1.111     pooka      58: #ifdef __NetBSD__
1.91      dholland   59: #include <sys/quotactl.h>
1.96      pooka      60: #endif
1.1       pooka      61:
                     62: #include <assert.h>
                     63: #include <dlfcn.h>
                     64: #include <err.h>
                     65: #include <errno.h>
                     66: #include <fcntl.h>
                     67: #include <poll.h>
                     68: #include <pthread.h>
1.3       pooka      69: #include <signal.h>
1.1       pooka      70: #include <stdarg.h>
1.8       pooka      71: #include <stdbool.h>
1.96      pooka      72: #include <stdint.h>
1.1       pooka      73: #include <stdio.h>
                     74: #include <stdlib.h>
1.28      pooka      75: #include <string.h>
1.3       pooka      76: #include <time.h>
1.1       pooka      77: #include <unistd.h>
                     78:
1.96      pooka      79: #include <rump/rumpclient.h>
                     80: #include <rump/rump_syscalls.h>
                     81:
1.64      pooka      82: #include "hijack.h"
                     83:
1.96      pooka      84: /*
                     85:  * XXX: Consider autogenerating this, syscnames[] and syscalls[] with
                     86:  * a DSL where the tool also checks the symbols exported by this library
                     87:  * to make sure all relevant calls are accounted for.
                     88:  */
1.17      pooka      89: enum dualcall {
1.60      pooka      90:        DUALCALL_WRITE, DUALCALL_WRITEV, DUALCALL_PWRITE, DUALCALL_PWRITEV,
1.17      pooka      91:        DUALCALL_IOCTL, DUALCALL_FCNTL,
1.121.2.1! bouyer     92:        DUALCALL_SOCKET, DUALCALL_ACCEPT, DUALCALL_PACCEPT,
        !            93:        DUALCALL_BIND, DUALCALL_CONNECT,
1.17      pooka      94:        DUALCALL_GETPEERNAME, DUALCALL_GETSOCKNAME, DUALCALL_LISTEN,
                     95:        DUALCALL_RECVFROM, DUALCALL_RECVMSG,
                     96:        DUALCALL_SENDTO, DUALCALL_SENDMSG,
                     97:        DUALCALL_GETSOCKOPT, DUALCALL_SETSOCKOPT,
                     98:        DUALCALL_SHUTDOWN,
1.60      pooka      99:        DUALCALL_READ, DUALCALL_READV, DUALCALL_PREAD, DUALCALL_PREADV,
1.41      pooka     100:        DUALCALL_DUP2,
1.34      pooka     101:        DUALCALL_CLOSE,
1.17      pooka     102:        DUALCALL_POLLTS,
1.97      pooka     103:
                    104: #ifndef __linux__
1.45      pooka     105:        DUALCALL_STAT, DUALCALL_LSTAT, DUALCALL_FSTAT,
1.97      pooka     106: #endif
                    107:
1.45      pooka     108:        DUALCALL_CHMOD, DUALCALL_LCHMOD, DUALCALL_FCHMOD,
                    109:        DUALCALL_CHOWN, DUALCALL_LCHOWN, DUALCALL_FCHOWN,
                    110:        DUALCALL_OPEN,
                    111:        DUALCALL_CHDIR, DUALCALL_FCHDIR,
                    112:        DUALCALL_LSEEK,
                    113:        DUALCALL_UNLINK, DUALCALL_SYMLINK, DUALCALL_READLINK,
1.95      riastrad  114:        DUALCALL_LINK, DUALCALL_RENAME,
1.45      pooka     115:        DUALCALL_MKDIR, DUALCALL_RMDIR,
                    116:        DUALCALL_UTIMES, DUALCALL_LUTIMES, DUALCALL_FUTIMES,
1.113     enami     117:        DUALCALL_UTIMENSAT, DUALCALL_FUTIMENS,
1.45      pooka     118:        DUALCALL_TRUNCATE, DUALCALL_FTRUNCATE,
1.96      pooka     119:        DUALCALL_FSYNC,
1.97      pooka     120:        DUALCALL_ACCESS,
                    121:
                    122: #ifndef __linux__
1.57      pooka     123:        DUALCALL___GETCWD,
1.98      pooka     124:        DUALCALL_GETDENTS,
1.97      pooka     125: #endif
                    126:
                    127: #ifndef __linux__
1.68      pooka     128:        DUALCALL_MKNOD,
1.97      pooka     129: #endif
                    130:
1.111     pooka     131: #ifdef __NetBSD__
1.96      pooka     132:        DUALCALL_GETFH, DUALCALL_FHOPEN, DUALCALL_FHSTAT, DUALCALL_FHSTATVFS1,
1.97      pooka     133: #endif
                    134:
1.111     pooka     135: #ifdef HAVE_KQUEUE
1.97      pooka     136:        DUALCALL_KEVENT,
                    137: #endif
1.96      pooka     138:
1.111     pooka     139: #ifdef __NetBSD__
1.78      pooka     140:        DUALCALL___SYSCTL,
1.96      pooka     141: #endif
                    142:
1.111     pooka     143: #ifdef __NetBSD__
1.96      pooka     144:        DUALCALL_NFSSVC,
                    145: #endif
                    146:
1.111     pooka     147: #ifdef __NetBSD__
1.96      pooka     148:        DUALCALL_STATVFS1, DUALCALL_FSTATVFS1, DUALCALL_GETVFSSTAT,
                    149: #endif
                    150:
1.111     pooka     151: #ifdef __NetBSD__
1.96      pooka     152:        DUALCALL_MOUNT, DUALCALL_UNMOUNT,
                    153: #endif
                    154:
1.111     pooka     155: #ifdef HAVE_FSYNC_RANGE
1.96      pooka     156:        DUALCALL_FSYNC_RANGE,
                    157: #endif
                    158:
1.111     pooka     159: #ifdef HAVE_CHFLAGS
1.96      pooka     160:        DUALCALL_CHFLAGS, DUALCALL_LCHFLAGS, DUALCALL_FCHFLAGS,
                    161: #endif
                    162:
1.111     pooka     163: #ifdef HAVE___QUOTACTL
1.80      bouyer    164:        DUALCALL_QUOTACTL,
1.83      pooka     165: #endif
1.17      pooka     166:        DUALCALL__NUM
1.1       pooka     167: };
                    168:
1.8       pooka     169: #define RSYS_STRING(a) __STRING(a)
                    170: #define RSYS_NAME(a) RSYS_STRING(__CONCAT(RUMP_SYS_RENAME_,a))
                    171:
1.1       pooka     172: /*
1.14      pooka     173:  * Would be nice to get this automatically in sync with libc.
1.97      pooka     174:  * Also, this does not work for compat-using binaries (we should
                    175:  * provide all previous interfaces, not just the current ones)
1.14      pooka     176:  */
1.97      pooka     177: #if defined(__NetBSD__)
                    178:
1.14      pooka     179: #if !__NetBSD_Prereq__(5,99,7)
1.29      pooka     180: #define REALSELECT select
                    181: #define REALPOLLTS pollts
1.34      pooka     182: #define REALKEVENT kevent
1.45      pooka     183: #define REALSTAT __stat30
                    184: #define REALLSTAT __lstat30
                    185: #define REALFSTAT __fstat30
                    186: #define REALUTIMES utimes
                    187: #define REALLUTIMES lutimes
                    188: #define REALFUTIMES futimes
1.68      pooka     189: #define REALMKNOD mknod
1.78      pooka     190: #define REALFHSTAT __fhstat40
1.96      pooka     191: #else /* >= 5.99.7 */
1.29      pooka     192: #define REALSELECT _sys___select50
                    193: #define REALPOLLTS _sys___pollts50
1.34      pooka     194: #define REALKEVENT _sys___kevent50
1.45      pooka     195: #define REALSTAT __stat50
                    196: #define REALLSTAT __lstat50
                    197: #define REALFSTAT __fstat50
                    198: #define REALUTIMES __utimes50
                    199: #define REALLUTIMES __lutimes50
1.69      pooka     200: #define REALFUTIMES __futimes50
1.68      pooka     201: #define REALMKNOD __mknod50
1.78      pooka     202: #define REALFHSTAT __fhstat50
1.96      pooka     203: #endif /* < 5.99.7 */
1.97      pooka     204:
1.31      pooka     205: #define REALREAD _sys_read
1.60      pooka     206: #define REALPREAD _sys_pread
                    207: #define REALPWRITE _sys_pwrite
1.45      pooka     208: #define REALGETDENTS __getdents30
1.48      pooka     209: #define REALMOUNT __mount50
1.78      pooka     210: #define REALGETFH __getfh30
                    211: #define REALFHOPEN __fhopen40
                    212: #define REALFHSTATVFS1 __fhstatvfs140
1.96      pooka     213: #define REALSOCKET __socket30
                    214:
                    215: #define LSEEK_ALIAS _lseek
                    216: #define VFORK __vfork14
                    217:
1.97      pooka     218: int REALSTAT(const char *, struct stat *);
                    219: int REALLSTAT(const char *, struct stat *);
                    220: int REALFSTAT(int, struct stat *);
                    221: int REALMKNOD(const char *, mode_t, dev_t);
1.98      pooka     222: int REALGETDENTS(int, char *, size_t);
1.97      pooka     223:
                    224: int __getcwd(char *, size_t);
                    225:
                    226: #elif defined(__linux__) /* glibc, really */
1.96      pooka     227:
                    228: #define REALREAD read
                    229: #define REALPREAD pread
                    230: #define REALPWRITE pwrite
                    231: #define REALSELECT select
                    232: #define REALPOLLTS ppoll
                    233: #define REALUTIMES utimes
                    234: #define REALLUTIMES lutimes
                    235: #define REALFUTIMES futimes
                    236: #define REALFHSTAT fhstat
                    237: #define REALSOCKET socket
                    238:
1.97      pooka     239: #else /* !NetBSD && !linux */
                    240:
                    241: #error platform not supported
                    242:
                    243: #endif /* platform */
1.14      pooka     244:
1.29      pooka     245: int REALSELECT(int, fd_set *, fd_set *, fd_set *, struct timeval *);
                    246: int REALPOLLTS(struct pollfd *, nfds_t,
1.20      pooka     247:               const struct timespec *, const sigset_t *);
1.34      pooka     248: int REALKEVENT(int, const struct kevent *, size_t, struct kevent *, size_t,
                    249:               const struct timespec *);
1.31      pooka     250: ssize_t REALREAD(int, void *, size_t);
1.60      pooka     251: ssize_t REALPREAD(int, void *, size_t, off_t);
                    252: ssize_t REALPWRITE(int, const void *, size_t, off_t);
1.45      pooka     253: int REALUTIMES(const char *, const struct timeval [2]);
                    254: int REALLUTIMES(const char *, const struct timeval [2]);
                    255: int REALFUTIMES(int, const struct timeval [2]);
1.48      pooka     256: int REALMOUNT(const char *, const char *, int, void *, size_t);
1.78      pooka     257: int REALGETFH(const char *, void *, size_t *);
                    258: int REALFHOPEN(const void *, size_t, int);
                    259: int REALFHSTAT(const void *, size_t, struct stat *);
                    260: int REALFHSTATVFS1(const void *, size_t, struct statvfs *, int);
1.96      pooka     261: int REALSOCKET(int, int, int);
                    262:
1.17      pooka     263: #define S(a) __STRING(a)
                    264: struct sysnames {
                    265:        enum dualcall scm_callnum;
                    266:        const char *scm_hostname;
                    267:        const char *scm_rumpname;
1.83      pooka     268: } syscnames[] = {
1.96      pooka     269:        { DUALCALL_SOCKET,      S(REALSOCKET),  RSYS_NAME(SOCKET)       },
1.17      pooka     270:        { DUALCALL_ACCEPT,      "accept",       RSYS_NAME(ACCEPT)       },
1.121.2.1! bouyer    271:        { DUALCALL_PACCEPT,     "paccept",      RSYS_NAME(PACCEPT)      },
1.17      pooka     272:        { DUALCALL_BIND,        "bind",         RSYS_NAME(BIND)         },
                    273:        { DUALCALL_CONNECT,     "connect",      RSYS_NAME(CONNECT)      },
                    274:        { DUALCALL_GETPEERNAME, "getpeername",  RSYS_NAME(GETPEERNAME)  },
                    275:        { DUALCALL_GETSOCKNAME, "getsockname",  RSYS_NAME(GETSOCKNAME)  },
                    276:        { DUALCALL_LISTEN,      "listen",       RSYS_NAME(LISTEN)       },
                    277:        { DUALCALL_RECVFROM,    "recvfrom",     RSYS_NAME(RECVFROM)     },
                    278:        { DUALCALL_RECVMSG,     "recvmsg",      RSYS_NAME(RECVMSG)      },
                    279:        { DUALCALL_SENDTO,      "sendto",       RSYS_NAME(SENDTO)       },
                    280:        { DUALCALL_SENDMSG,     "sendmsg",      RSYS_NAME(SENDMSG)      },
                    281:        { DUALCALL_GETSOCKOPT,  "getsockopt",   RSYS_NAME(GETSOCKOPT)   },
                    282:        { DUALCALL_SETSOCKOPT,  "setsockopt",   RSYS_NAME(SETSOCKOPT)   },
                    283:        { DUALCALL_SHUTDOWN,    "shutdown",     RSYS_NAME(SHUTDOWN)     },
1.31      pooka     284:        { DUALCALL_READ,        S(REALREAD),    RSYS_NAME(READ)         },
1.17      pooka     285:        { DUALCALL_READV,       "readv",        RSYS_NAME(READV)        },
1.60      pooka     286:        { DUALCALL_PREAD,       S(REALPREAD),   RSYS_NAME(PREAD)        },
                    287:        { DUALCALL_PREADV,      "preadv",       RSYS_NAME(PREADV)       },
1.17      pooka     288:        { DUALCALL_WRITE,       "write",        RSYS_NAME(WRITE)        },
                    289:        { DUALCALL_WRITEV,      "writev",       RSYS_NAME(WRITEV)       },
1.60      pooka     290:        { DUALCALL_PWRITE,      S(REALPWRITE),  RSYS_NAME(PWRITE)       },
                    291:        { DUALCALL_PWRITEV,     "pwritev",      RSYS_NAME(PWRITEV)      },
1.17      pooka     292:        { DUALCALL_IOCTL,       "ioctl",        RSYS_NAME(IOCTL)        },
                    293:        { DUALCALL_FCNTL,       "fcntl",        RSYS_NAME(FCNTL)        },
                    294:        { DUALCALL_DUP2,        "dup2",         RSYS_NAME(DUP2)         },
                    295:        { DUALCALL_CLOSE,       "close",        RSYS_NAME(CLOSE)        },
1.29      pooka     296:        { DUALCALL_POLLTS,      S(REALPOLLTS),  RSYS_NAME(POLLTS)       },
1.97      pooka     297: #ifndef __linux__
1.45      pooka     298:        { DUALCALL_STAT,        S(REALSTAT),    RSYS_NAME(STAT)         },
                    299:        { DUALCALL_LSTAT,       S(REALLSTAT),   RSYS_NAME(LSTAT)        },
                    300:        { DUALCALL_FSTAT,       S(REALFSTAT),   RSYS_NAME(FSTAT)        },
1.97      pooka     301: #endif
1.45      pooka     302:        { DUALCALL_CHOWN,       "chown",        RSYS_NAME(CHOWN)        },
                    303:        { DUALCALL_LCHOWN,      "lchown",       RSYS_NAME(LCHOWN)       },
                    304:        { DUALCALL_FCHOWN,      "fchown",       RSYS_NAME(FCHOWN)       },
                    305:        { DUALCALL_CHMOD,       "chmod",        RSYS_NAME(CHMOD)        },
                    306:        { DUALCALL_LCHMOD,      "lchmod",       RSYS_NAME(LCHMOD)       },
                    307:        { DUALCALL_FCHMOD,      "fchmod",       RSYS_NAME(FCHMOD)       },
                    308:        { DUALCALL_UTIMES,      S(REALUTIMES),  RSYS_NAME(UTIMES)       },
                    309:        { DUALCALL_LUTIMES,     S(REALLUTIMES), RSYS_NAME(LUTIMES)      },
                    310:        { DUALCALL_FUTIMES,     S(REALFUTIMES), RSYS_NAME(FUTIMES)      },
1.112     enami     311:        { DUALCALL_UTIMENSAT,   "utimensat",    RSYS_NAME(UTIMENSAT)    },
1.113     enami     312:        { DUALCALL_FUTIMENS,    "futimens",     RSYS_NAME(FUTIMENS)     },
1.45      pooka     313:        { DUALCALL_OPEN,        "open",         RSYS_NAME(OPEN)         },
                    314:        { DUALCALL_CHDIR,       "chdir",        RSYS_NAME(CHDIR)        },
                    315:        { DUALCALL_FCHDIR,      "fchdir",       RSYS_NAME(FCHDIR)       },
1.61      pooka     316:        { DUALCALL_LSEEK,       "lseek",        RSYS_NAME(LSEEK)        },
1.45      pooka     317:        { DUALCALL_UNLINK,      "unlink",       RSYS_NAME(UNLINK)       },
                    318:        { DUALCALL_SYMLINK,     "symlink",      RSYS_NAME(SYMLINK)      },
                    319:        { DUALCALL_READLINK,    "readlink",     RSYS_NAME(READLINK)     },
1.95      riastrad  320:        { DUALCALL_LINK,        "link",         RSYS_NAME(LINK)         },
1.45      pooka     321:        { DUALCALL_RENAME,      "rename",       RSYS_NAME(RENAME)       },
                    322:        { DUALCALL_MKDIR,       "mkdir",        RSYS_NAME(MKDIR)        },
                    323:        { DUALCALL_RMDIR,       "rmdir",        RSYS_NAME(RMDIR)        },
                    324:        { DUALCALL_TRUNCATE,    "truncate",     RSYS_NAME(TRUNCATE)     },
                    325:        { DUALCALL_FTRUNCATE,   "ftruncate",    RSYS_NAME(FTRUNCATE)    },
                    326:        { DUALCALL_FSYNC,       "fsync",        RSYS_NAME(FSYNC)        },
1.97      pooka     327:        { DUALCALL_ACCESS,      "access",       RSYS_NAME(ACCESS)       },
                    328:
                    329: #ifndef __linux__
1.57      pooka     330:        { DUALCALL___GETCWD,    "__getcwd",     RSYS_NAME(__GETCWD)     },
1.98      pooka     331:        { DUALCALL_GETDENTS,    S(REALGETDENTS),RSYS_NAME(GETDENTS)     },
1.97      pooka     332: #endif
                    333:
                    334: #ifndef __linux__
1.68      pooka     335:        { DUALCALL_MKNOD,       S(REALMKNOD),   RSYS_NAME(MKNOD)        },
1.97      pooka     336: #endif
                    337:
1.111     pooka     338: #ifdef __NetBSD__
1.79      bouyer    339:        { DUALCALL_GETFH,       S(REALGETFH),   RSYS_NAME(GETFH)        },
1.97      pooka     340:        { DUALCALL_FHOPEN,      S(REALFHOPEN),  RSYS_NAME(FHOPEN)       },
                    341:        { DUALCALL_FHSTAT,      S(REALFHSTAT),  RSYS_NAME(FHSTAT)       },
1.79      bouyer    342:        { DUALCALL_FHSTATVFS1,  S(REALFHSTATVFS1),RSYS_NAME(FHSTATVFS1) },
1.97      pooka     343: #endif
                    344:
1.111     pooka     345: #ifdef HAVE_KQUEUE
1.97      pooka     346:        { DUALCALL_KEVENT,      S(REALKEVENT),  RSYS_NAME(KEVENT)       },
                    347: #endif
1.96      pooka     348:
1.111     pooka     349: #ifdef __NetBSD__
1.96      pooka     350:        { DUALCALL___SYSCTL,    "__sysctl",     RSYS_NAME(__SYSCTL)     },
                    351: #endif
                    352:
1.111     pooka     353: #ifdef __NetBSD__
1.96      pooka     354:        { DUALCALL_NFSSVC,      "nfssvc",       RSYS_NAME(NFSSVC)       },
                    355: #endif
                    356:
1.111     pooka     357: #ifdef __NetBSD__
1.96      pooka     358:        { DUALCALL_STATVFS1,    "statvfs1",     RSYS_NAME(STATVFS1)     },
                    359:        { DUALCALL_FSTATVFS1,   "fstatvfs1",    RSYS_NAME(FSTATVFS1)    },
                    360:        { DUALCALL_GETVFSSTAT,  "getvfsstat",   RSYS_NAME(GETVFSSTAT)   },
                    361: #endif
                    362:
1.111     pooka     363: #ifdef __NetBSD__
1.96      pooka     364:        { DUALCALL_MOUNT,       S(REALMOUNT),   RSYS_NAME(MOUNT)        },
                    365:        { DUALCALL_UNMOUNT,     "unmount",      RSYS_NAME(UNMOUNT)      },
                    366: #endif
                    367:
1.111     pooka     368: #ifdef HAVE_FSYNC_RANGE
1.96      pooka     369:        { DUALCALL_FSYNC_RANGE, "fsync_range",  RSYS_NAME(FSYNC_RANGE)  },
                    370: #endif
                    371:
1.111     pooka     372: #ifdef HAVE_CHFLAGS
1.96      pooka     373:        { DUALCALL_CHFLAGS,     "chflags",      RSYS_NAME(CHFLAGS)      },
                    374:        { DUALCALL_LCHFLAGS,    "lchflags",     RSYS_NAME(LCHFLAGS)     },
                    375:        { DUALCALL_FCHFLAGS,    "fchflags",     RSYS_NAME(FCHFLAGS)     },
1.111     pooka     376: #endif /* HAVE_CHFLAGS */
1.96      pooka     377:
1.111     pooka     378: #ifdef HAVE___QUOTACTL
1.91      dholland  379:        { DUALCALL_QUOTACTL,    "__quotactl",   RSYS_NAME(__QUOTACTL)   },
1.111     pooka     380: #endif /* HAVE___QUOTACTL */
1.96      pooka     381:
1.17      pooka     382: };
                    383: #undef S
                    384:
                    385: struct bothsys {
                    386:        void *bs_host;
                    387:        void *bs_rump;
                    388: } syscalls[DUALCALL__NUM];
                    389: #define GETSYSCALL(which, name) syscalls[DUALCALL_##name].bs_##which
                    390:
1.71      pooka     391: static pid_t   (*host_fork)(void);
                    392: static int     (*host_daemon)(int, int);
                    393: static void *  (*host_mmap)(void *, size_t, int, int, int, off_t);
                    394:
1.75      pooka     395: /*
                    396:  * This tracks if our process is in a subdirectory of /rump.
                    397:  * It's preserved over exec.
                    398:  */
                    399: static bool pwdinrump;
                    400:
                    401: enum pathtype { PATH_HOST, PATH_RUMP, PATH_RUMPBLANKET };
                    402:
                    403: static bool            fd_isrump(int);
                    404: static enum pathtype   path_isrump(const char *);
1.71      pooka     405:
1.85      pooka     406: /* default FD_SETSIZE is 256 ==> default fdoff is 128 */
                    407: static int hijack_fdoff = FD_SETSIZE/2;
                    408:
1.71      pooka     409: /*
                    410:  * Maintain a mapping table for the usual dup2 suspects.
1.74      pooka     411:  * Could use atomic ops to operate on dup2vec, but an application
                    412:  * racing there is not well-defined, so don't bother.
1.71      pooka     413:  */
                    414: /* note: you cannot change this without editing the env-passing code */
                    415: #define DUP2HIGH 2
                    416: static uint32_t dup2vec[DUP2HIGH+1];
                    417: #define DUP2BIT (1<<31)
                    418: #define DUP2ALIAS (1<<30)
                    419: #define DUP2FDMASK ((1<<30)-1)
                    420:
                    421: static bool
                    422: isdup2d(int fd)
                    423: {
                    424:
                    425:        return fd <= DUP2HIGH && fd >= 0 && dup2vec[fd] & DUP2BIT;
                    426: }
                    427:
                    428: static int
                    429: mapdup2(int hostfd)
                    430: {
                    431:
                    432:        _DIAGASSERT(isdup2d(hostfd));
                    433:        return dup2vec[hostfd] & DUP2FDMASK;
                    434: }
                    435:
                    436: static int
                    437: unmapdup2(int rumpfd)
                    438: {
                    439:        int i;
                    440:
                    441:        for (i = 0; i <= DUP2HIGH; i++) {
1.72      pooka     442:                if (dup2vec[i] & DUP2BIT &&
                    443:                    (dup2vec[i] & DUP2FDMASK) == (unsigned)rumpfd)
1.71      pooka     444:                        return i;
                    445:        }
                    446:        return -1;
                    447: }
                    448:
                    449: static void
                    450: setdup2(int hostfd, int rumpfd)
                    451: {
                    452:
                    453:        if (hostfd > DUP2HIGH) {
                    454:                _DIAGASSERT(0);
                    455:                return;
                    456:        }
                    457:
                    458:        dup2vec[hostfd] = DUP2BIT | DUP2ALIAS | rumpfd;
                    459: }
                    460:
                    461: static void
                    462: clrdup2(int hostfd)
                    463: {
                    464:
                    465:        if (hostfd > DUP2HIGH) {
                    466:                _DIAGASSERT(0);
                    467:                return;
                    468:        }
                    469:
                    470:        dup2vec[hostfd] = 0;
                    471: }
                    472:
                    473: static bool
                    474: killdup2alias(int rumpfd)
                    475: {
                    476:        int hostfd;
                    477:
                    478:        if ((hostfd = unmapdup2(rumpfd)) == -1)
                    479:                return false;
                    480:
                    481:        if (dup2vec[hostfd] & DUP2ALIAS) {
                    482:                dup2vec[hostfd] &= ~DUP2ALIAS;
                    483:                return true;
                    484:        }
                    485:        return false;
                    486: }
1.17      pooka     487:
                    488: //#define DEBUGJACK
                    489: #ifdef DEBUGJACK
                    490: #define DPRINTF(x) mydprintf x
                    491: static void
                    492: mydprintf(const char *fmt, ...)
                    493: {
                    494:        va_list ap;
                    495:
1.71      pooka     496:        if (isdup2d(STDERR_FILENO))
1.17      pooka     497:                return;
                    498:
                    499:        va_start(ap, fmt);
                    500:        vfprintf(stderr, fmt, ap);
                    501:        va_end(ap);
                    502: }
                    503:
1.71      pooka     504: static const char *
                    505: whichfd(int fd)
                    506: {
                    507:
                    508:        if (fd == -1)
                    509:                return "-1";
                    510:        else if (fd_isrump(fd))
                    511:                return "rump";
                    512:        else
                    513:                return "host";
                    514: }
                    515:
                    516: static const char *
                    517: whichpath(const char *path)
                    518: {
                    519:
                    520:        if (path_isrump(path))
                    521:                return "rump";
                    522:        else
                    523:                return "host";
                    524: }
                    525:
1.17      pooka     526: #else
                    527: #define DPRINTF(x)
1.14      pooka     528: #endif
                    529:
1.114     pooka     530: #define ATCALL(type, name, rcname, args, proto, vars)                  \
                    531: type name args                                                         \
                    532: {                                                                      \
                    533:        type (*fun) proto;                                              \
                    534:        int isrump = -1;                                                \
                    535:                                                                        \
1.115     pooka     536:        if (fd == AT_FDCWD || *path == '/') {                           \
1.114     pooka     537:                isrump = path_isrump(path);                             \
                    538:        } else {                                                        \
                    539:                isrump = fd_isrump(fd);                                 \
                    540:        }                                                               \
                    541:                                                                        \
                    542:        DPRINTF(("%s -> %d:%s (%s)\n", __STRING(name),                  \
                    543:            fd, path, isrump ? "rump" : "host"));                       \
                    544:                                                                        \
                    545:        assert(isrump != -1);                                           \
                    546:        if (isrump) {                                                   \
                    547:                fun = syscalls[rcname].bs_rump;                         \
                    548:                if (fd != AT_FDCWD)                                     \
                    549:                        fd = fd_host2rump(fd);                          \
                    550:                path = path_host2rump(path);                            \
                    551:        } else {                                                        \
                    552:                fun = syscalls[rcname].bs_host;                         \
                    553:        }                                                               \
                    554:        return fun vars;                                                \
                    555: }
                    556:
1.17      pooka     557: #define FDCALL(type, name, rcname, args, proto, vars)                  \
                    558: type name args                                                         \
                    559: {                                                                      \
                    560:        type (*fun) proto;                                              \
                    561:                                                                        \
1.71      pooka     562:        DPRINTF(("%s -> %d (%s)\n", __STRING(name), fd, whichfd(fd)));  \
1.17      pooka     563:        if (fd_isrump(fd)) {                                            \
                    564:                fun = syscalls[rcname].bs_rump;                         \
                    565:                fd = fd_host2rump(fd);                                  \
                    566:        } else {                                                        \
                    567:                fun = syscalls[rcname].bs_host;                         \
                    568:        }                                                               \
                    569:                                                                        \
                    570:        return fun vars;                                                \
                    571: }
                    572:
1.45      pooka     573: #define PATHCALL(type, name, rcname, args, proto, vars)                        \
                    574: type name args                                                         \
                    575: {                                                                      \
                    576:        type (*fun) proto;                                              \
1.75      pooka     577:        enum pathtype pt;                                               \
1.45      pooka     578:                                                                        \
1.71      pooka     579:        DPRINTF(("%s -> %s (%s)\n", __STRING(name), path,               \
                    580:            whichpath(path)));                                          \
1.75      pooka     581:        if ((pt = path_isrump(path)) != PATH_HOST) {                    \
1.45      pooka     582:                fun = syscalls[rcname].bs_rump;                         \
1.75      pooka     583:                if (pt == PATH_RUMP)                                    \
                    584:                        path = path_host2rump(path);                    \
1.45      pooka     585:        } else {                                                        \
                    586:                fun = syscalls[rcname].bs_host;                         \
                    587:        }                                                               \
                    588:                                                                        \
                    589:        return fun vars;                                                \
                    590: }
                    591:
1.78      pooka     592: #define VFSCALL(bit, type, name, rcname, args, proto, vars)            \
                    593: type name args                                                         \
                    594: {                                                                      \
                    595:        type (*fun) proto;                                              \
                    596:                                                                        \
                    597:        DPRINTF(("%s (0x%x, 0x%x)\n", __STRING(name), bit, vfsbits));   \
                    598:        if (vfsbits & bit) {                                            \
                    599:                fun = syscalls[rcname].bs_rump;                         \
                    600:        } else {                                                        \
                    601:                fun = syscalls[rcname].bs_host;                         \
                    602:        }                                                               \
                    603:                                                                        \
                    604:        return fun vars;                                                \
                    605: }
                    606:
1.14      pooka     607: /*
1.49      pooka     608:  * These variables are set from the RUMPHIJACK string and control
                    609:  * which operations can product rump kernel file descriptors.
                    610:  * This should be easily extendable for future needs.
                    611:  */
                    612: #define RUMPHIJACK_DEFAULT "path=/rump,socket=all:nolocal"
                    613: static bool rumpsockets[PF_MAX];
                    614: static const char *rumpprefix;
                    615: static size_t rumpprefixlen;
                    616:
                    617: static struct {
                    618:        int pf;
                    619:        const char *name;
                    620: } socketmap[] = {
1.51      pooka     621:        { PF_LOCAL, "local" },
1.49      pooka     622:        { PF_INET, "inet" },
1.96      pooka     623: #ifdef PF_LINK
1.49      pooka     624:        { PF_LINK, "link" },
1.96      pooka     625: #endif
1.55      pooka     626: #ifdef PF_OROUTE
1.56      pooka     627:        { PF_OROUTE, "oroute" },
                    628: #endif
1.49      pooka     629:        { PF_ROUTE, "route" },
                    630:        { PF_INET6, "inet6" },
1.55      pooka     631: #ifdef PF_MPLS
                    632:        { PF_MPLS, "mpls" },
                    633: #endif
1.49      pooka     634:        { -1, NULL }
                    635: };
                    636:
                    637: static void
                    638: sockparser(char *buf)
                    639: {
1.96      pooka     640:        char *p, *l = NULL;
1.49      pooka     641:        bool value;
                    642:        int i;
                    643:
                    644:        /* if "all" is present, it must be specified first */
                    645:        if (strncmp(buf, "all", strlen("all")) == 0) {
1.50      pooka     646:                for (i = 0; i < (int)__arraycount(rumpsockets); i++) {
1.49      pooka     647:                        rumpsockets[i] = true;
                    648:                }
                    649:                buf += strlen("all");
                    650:                if (*buf == ':')
                    651:                        buf++;
                    652:        }
                    653:
                    654:        for (p = strtok_r(buf, ":", &l); p; p = strtok_r(NULL, ":", &l)) {
                    655:                value = true;
                    656:                if (strncmp(p, "no", strlen("no")) == 0) {
                    657:                        value = false;
                    658:                        p += strlen("no");
                    659:                }
1.45      pooka     660:
1.49      pooka     661:                for (i = 0; socketmap[i].name; i++) {
                    662:                        if (strcmp(p, socketmap[i].name) == 0) {
                    663:                                rumpsockets[socketmap[i].pf] = value;
                    664:                                break;
                    665:                        }
                    666:                }
                    667:                if (socketmap[i].name == NULL) {
1.78      pooka     668:                        errx(1, "invalid socket specifier %s", p);
1.49      pooka     669:                }
                    670:        }
                    671: }
                    672:
                    673: static void
                    674: pathparser(char *buf)
                    675: {
                    676:
1.57      pooka     677:        /* sanity-check */
1.49      pooka     678:        if (*buf != '/')
                    679:                errx(1, "hijack path specifier must begin with ``/''");
1.57      pooka     680:        rumpprefixlen = strlen(buf);
                    681:        if (rumpprefixlen < 2)
                    682:                errx(1, "invalid hijack prefix: %s", buf);
                    683:        if (buf[rumpprefixlen-1] == '/' && strspn(buf, "/") != rumpprefixlen)
                    684:                errx(1, "hijack prefix may end in slash only if pure "
                    685:                    "slash, gave %s", buf);
1.49      pooka     686:
                    687:        if ((rumpprefix = strdup(buf)) == NULL)
                    688:                err(1, "strdup");
                    689:        rumpprefixlen = strlen(rumpprefix);
                    690: }
                    691:
1.75      pooka     692: static struct blanket {
                    693:        const char *pfx;
                    694:        size_t len;
                    695: } *blanket;
                    696: static int nblanket;
                    697:
                    698: static void
                    699: blanketparser(char *buf)
                    700: {
1.96      pooka     701:        char *p, *l = NULL;
1.75      pooka     702:        int i;
                    703:
                    704:        for (nblanket = 0, p = buf; p; p = strchr(p+1, ':'), nblanket++)
                    705:                continue;
                    706:
                    707:        blanket = malloc(nblanket * sizeof(*blanket));
                    708:        if (blanket == NULL)
                    709:                err(1, "alloc blanket %d", nblanket);
                    710:
                    711:        for (p = strtok_r(buf, ":", &l), i = 0; p;
                    712:            p = strtok_r(NULL, ":", &l), i++) {
                    713:                blanket[i].pfx = strdup(p);
                    714:                if (blanket[i].pfx == NULL)
                    715:                        err(1, "strdup blanket");
                    716:                blanket[i].len = strlen(p);
                    717:
                    718:                if (blanket[i].len == 0 || *blanket[i].pfx != '/')
                    719:                        errx(1, "invalid blanket specifier %s", p);
                    720:                if (*(blanket[i].pfx + blanket[i].len-1) == '/')
                    721:                        errx(1, "invalid blanket specifier %s", p);
                    722:        }
                    723: }
                    724:
1.78      pooka     725: #define VFSBIT_NFSSVC          0x01
                    726: #define VFSBIT_GETVFSSTAT      0x02
                    727: #define VFSBIT_FHCALLS         0x04
                    728: static unsigned vfsbits;
                    729:
                    730: static struct {
                    731:        int bit;
                    732:        const char *name;
                    733: } vfscalls[] = {
                    734:        { VFSBIT_NFSSVC, "nfssvc" },
                    735:        { VFSBIT_GETVFSSTAT, "getvfsstat" },
                    736:        { VFSBIT_FHCALLS, "fhcalls" },
                    737:        { -1, NULL }
                    738: };
                    739:
                    740: static void
                    741: vfsparser(char *buf)
                    742: {
1.96      pooka     743:        char *p, *l = NULL;
1.78      pooka     744:        bool turnon;
                    745:        unsigned int fullmask;
                    746:        int i;
                    747:
                    748:        /* build the full mask and sanity-check while we're at it */
                    749:        fullmask = 0;
                    750:        for (i = 0; vfscalls[i].name != NULL; i++) {
                    751:                if (fullmask & vfscalls[i].bit)
                    752:                        errx(1, "problem exists between vi and chair");
                    753:                fullmask |= vfscalls[i].bit;
                    754:        }
                    755:
                    756:
                    757:        /* if "all" is present, it must be specified first */
                    758:        if (strncmp(buf, "all", strlen("all")) == 0) {
                    759:                vfsbits = fullmask;
                    760:                buf += strlen("all");
                    761:                if (*buf == ':')
                    762:                        buf++;
                    763:        }
                    764:
                    765:        for (p = strtok_r(buf, ":", &l); p; p = strtok_r(NULL, ":", &l)) {
                    766:                turnon = true;
                    767:                if (strncmp(p, "no", strlen("no")) == 0) {
                    768:                        turnon = false;
                    769:                        p += strlen("no");
                    770:                }
                    771:
                    772:                for (i = 0; vfscalls[i].name; i++) {
                    773:                        if (strcmp(p, vfscalls[i].name) == 0) {
                    774:                                if (turnon)
                    775:                                        vfsbits |= vfscalls[i].bit;
                    776:                                else
                    777:                                        vfsbits &= ~vfscalls[i].bit;
                    778:                                break;
                    779:                        }
                    780:                }
                    781:                if (vfscalls[i].name == NULL) {
                    782:                        errx(1, "invalid vfscall specifier %s", p);
                    783:                }
                    784:        }
                    785: }
                    786:
                    787: static bool rumpsysctl = false;
                    788:
                    789: static void
                    790: sysctlparser(char *buf)
                    791: {
                    792:
                    793:        if (buf == NULL) {
                    794:                rumpsysctl = true;
                    795:                return;
                    796:        }
                    797:
                    798:        if (strcasecmp(buf, "y") == 0 || strcasecmp(buf, "yes") == 0 ||
                    799:            strcasecmp(buf, "yep") == 0 || strcasecmp(buf, "tottakai") == 0) {
                    800:                rumpsysctl = true;
                    801:                return;
                    802:        }
                    803:        if (strcasecmp(buf, "n") == 0 || strcasecmp(buf, "no") == 0) {
                    804:                rumpsysctl = false;
                    805:                return;
                    806:        }
                    807:
                    808:        errx(1, "sysctl value should be y(es)/n(o), gave: %s", buf);
                    809: }
                    810:
1.85      pooka     811: static void
                    812: fdoffparser(char *buf)
                    813: {
                    814:        unsigned long fdoff;
                    815:        char *ep;
                    816:
                    817:        if (*buf == '-') {
                    818:                errx(1, "fdoff must not be negative");
                    819:        }
                    820:        fdoff = strtoul(buf, &ep, 10);
                    821:        if (*ep != '\0')
                    822:                errx(1, "invalid fdoff specifier \"%s\"", buf);
                    823:        if (fdoff >= INT_MAX/2 || fdoff < 3)
                    824:                errx(1, "fdoff out of range");
                    825:        hijack_fdoff = fdoff;
                    826: }
                    827:
1.49      pooka     828: static struct {
                    829:        void (*parsefn)(char *);
                    830:        const char *name;
1.78      pooka     831:        bool needvalues;
1.49      pooka     832: } hijackparse[] = {
1.78      pooka     833:        { sockparser, "socket", true },
                    834:        { pathparser, "path", true },
                    835:        { blanketparser, "blanket", true },
                    836:        { vfsparser, "vfs", true },
                    837:        { sysctlparser, "sysctl", false },
1.86      pooka     838:        { fdoffparser, "fdoff", true },
1.78      pooka     839:        { NULL, NULL, false },
1.49      pooka     840: };
                    841:
                    842: static void
                    843: parsehijack(char *hijack)
                    844: {
                    845:        char *p, *p2, *l;
                    846:        const char *hijackcopy;
1.78      pooka     847:        bool nop2;
1.49      pooka     848:        int i;
                    849:
                    850:        if ((hijackcopy = strdup(hijack)) == NULL)
                    851:                err(1, "strdup");
                    852:
                    853:        /* disable everything explicitly */
                    854:        for (i = 0; i < PF_MAX; i++)
                    855:                rumpsockets[i] = false;
                    856:
                    857:        for (p = strtok_r(hijack, ",", &l); p; p = strtok_r(NULL, ",", &l)) {
1.78      pooka     858:                nop2 = false;
1.49      pooka     859:                p2 = strchr(p, '=');
1.78      pooka     860:                if (!p2) {
                    861:                        nop2 = true;
                    862:                        p2 = p + strlen(p);
                    863:                }
1.49      pooka     864:
                    865:                for (i = 0; hijackparse[i].parsefn; i++) {
                    866:                        if (strncmp(hijackparse[i].name, p,
                    867:                            (size_t)(p2-p)) == 0) {
1.78      pooka     868:                                if (nop2 && hijackparse[i].needvalues)
                    869:                                        errx(1, "invalid hijack specifier: %s",
                    870:                                            hijackcopy);
                    871:                                hijackparse[i].parsefn(nop2 ? NULL : p2+1);
1.49      pooka     872:                                break;
                    873:                        }
                    874:                }
1.81      pooka     875:
                    876:                if (hijackparse[i].parsefn == NULL)
                    877:                        errx(1, "invalid hijack specifier name in %s", p);
1.49      pooka     878:        }
                    879:
                    880: }
1.7       pooka     881:
1.1       pooka     882: static void __attribute__((constructor))
                    883: rcinit(void)
                    884: {
1.49      pooka     885:        char buf[1024];
1.19      pooka     886:        unsigned i, j;
1.1       pooka     887:
1.17      pooka     888:        host_fork = dlsym(RTLD_NEXT, "fork");
1.25      pooka     889:        host_daemon = dlsym(RTLD_NEXT, "daemon");
1.118     pooka     890:        if (host_mmap == NULL)
                    891:                host_mmap = dlsym(RTLD_NEXT, "mmap");
1.17      pooka     892:
                    893:        /*
                    894:         * In theory cannot print anything during lookups because
                    895:         * we might not have the call vector set up.  so, the errx()
                    896:         * is a bit of a strech, but it might work.
                    897:         */
1.1       pooka     898:
1.17      pooka     899:        for (i = 0; i < DUALCALL__NUM; i++) {
                    900:                /* build runtime O(1) access */
1.83      pooka     901:                for (j = 0; j < __arraycount(syscnames); j++) {
                    902:                        if (syscnames[j].scm_callnum == i)
                    903:                                break;
                    904:                }
1.81      pooka     905:
1.83      pooka     906:                if (j == __arraycount(syscnames))
                    907:                        errx(1, "rumphijack error: syscall pos %d missing", i);
1.17      pooka     908:
1.23      pooka     909:                syscalls[i].bs_host = dlsym(RTLD_NEXT,
1.83      pooka     910:                    syscnames[j].scm_hostname);
                    911:                if (syscalls[i].bs_host == NULL)
                    912:                        errx(1, "hostcall %s not found!",
                    913:                            syscnames[j].scm_hostname);
1.17      pooka     914:
1.23      pooka     915:                syscalls[i].bs_rump = dlsym(RTLD_NEXT,
1.83      pooka     916:                    syscnames[j].scm_rumpname);
1.17      pooka     917:                if (syscalls[i].bs_rump == NULL)
1.70      pooka     918:                        errx(1, "rumpcall %s not found!",
1.83      pooka     919:                            syscnames[j].scm_rumpname);
1.1       pooka     920:        }
                    921:
1.22      pooka     922:        if (rumpclient_init() == -1)
1.1       pooka     923:                err(1, "rumpclient init");
1.28      pooka     924:
1.49      pooka     925:        /* check which syscalls we're supposed to hijack */
                    926:        if (getenv_r("RUMPHIJACK", buf, sizeof(buf)) == -1) {
                    927:                strcpy(buf, RUMPHIJACK_DEFAULT);
                    928:        }
                    929:        parsehijack(buf);
                    930:
1.28      pooka     931:        /* set client persistence level */
1.44      pooka     932:        if (getenv_r("RUMPHIJACK_RETRYCONNECT", buf, sizeof(buf)) != -1) {
1.28      pooka     933:                if (strcmp(buf, "die") == 0)
                    934:                        rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_DIE);
                    935:                else if (strcmp(buf, "inftime") == 0)
                    936:                        rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_INFTIME);
                    937:                else if (strcmp(buf, "once") == 0)
                    938:                        rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_ONCE);
                    939:                else {
                    940:                        time_t timeout;
1.44      pooka     941:                        char *ep;
1.28      pooka     942:
1.44      pooka     943:                        timeout = (time_t)strtoll(buf, &ep, 10);
                    944:                        if (timeout <= 0 || ep != buf + strlen(buf))
                    945:                                errx(1, "RUMPHIJACK_RETRYCONNECT must be "
                    946:                                    "keyword or integer, got: %s", buf);
1.28      pooka     947:
                    948:                        rumpclient_setconnretry(timeout);
                    949:                }
                    950:        }
1.39      pooka     951:
1.71      pooka     952:        if (getenv_r("RUMPHIJACK__DUP2INFO", buf, sizeof(buf)) == 0) {
                    953:                if (sscanf(buf, "%u,%u,%u",
                    954:                    &dup2vec[0], &dup2vec[1], &dup2vec[2]) != 3) {
                    955:                        warnx("invalid dup2mask: %s", buf);
                    956:                        memset(dup2vec, 0, sizeof(dup2vec));
                    957:                }
                    958:                unsetenv("RUMPHIJACK__DUP2INFO");
1.45      pooka     959:        }
                    960:        if (getenv_r("RUMPHIJACK__PWDINRUMP", buf, sizeof(buf)) == 0) {
1.49      pooka     961:                pwdinrump = true;
1.45      pooka     962:                unsetenv("RUMPHIJACK__PWDINRUMP");
1.39      pooka     963:        }
1.1       pooka     964: }
                    965:
1.2       pooka     966: static int
                    967: fd_rump2host(int fd)
                    968: {
                    969:
                    970:        if (fd == -1)
                    971:                return fd;
1.85      pooka     972:        return fd + hijack_fdoff;
1.71      pooka     973: }
1.2       pooka     974:
1.71      pooka     975: static int
                    976: fd_rump2host_withdup(int fd)
                    977: {
                    978:        int hfd;
1.2       pooka     979:
1.71      pooka     980:        _DIAGASSERT(fd != -1);
                    981:        hfd = unmapdup2(fd);
                    982:        if (hfd != -1) {
                    983:                _DIAGASSERT(hfd <= DUP2HIGH);
                    984:                return hfd;
                    985:        }
                    986:        return fd_rump2host(fd);
1.2       pooka     987: }
                    988:
                    989: static int
                    990: fd_host2rump(int fd)
                    991: {
1.71      pooka     992:        if (!isdup2d(fd))
1.85      pooka     993:                return fd - hijack_fdoff;
1.71      pooka     994:        else
                    995:                return mapdup2(fd);
1.2       pooka     996: }
                    997:
                    998: static bool
                    999: fd_isrump(int fd)
                   1000: {
                   1001:
1.85      pooka    1002:        return isdup2d(fd) || fd >= hijack_fdoff;
1.2       pooka    1003: }
                   1004:
1.85      pooka    1005: #define assertfd(_fd_) assert(ISDUP2D(_fd_) || (_fd_) >= hijack_fdoff)
1.40      pooka    1006:
1.75      pooka    1007: static enum pathtype
1.45      pooka    1008: path_isrump(const char *path)
                   1009: {
1.76      pooka    1010:        size_t plen;
1.75      pooka    1011:        int i;
1.45      pooka    1012:
1.75      pooka    1013:        if (rumpprefix == NULL && nblanket == 0)
                   1014:                return PATH_HOST;
1.49      pooka    1015:
1.45      pooka    1016:        if (*path == '/') {
1.76      pooka    1017:                plen = strlen(path);
                   1018:                if (rumpprefix && plen >= rumpprefixlen) {
                   1019:                        if (strncmp(path, rumpprefix, rumpprefixlen) == 0
                   1020:                            && (plen == rumpprefixlen
                   1021:                              || *(path + rumpprefixlen) == '/')) {
1.75      pooka    1022:                                return PATH_RUMP;
                   1023:                        }
                   1024:                }
                   1025:                for (i = 0; i < nblanket; i++) {
                   1026:                        if (strncmp(path, blanket[i].pfx, blanket[i].len) == 0)
                   1027:                                return PATH_RUMPBLANKET;
                   1028:                }
                   1029:
                   1030:                return PATH_HOST;
1.45      pooka    1031:        } else {
1.75      pooka    1032:                return pwdinrump ? PATH_RUMP : PATH_HOST;
1.45      pooka    1033:        }
                   1034: }
                   1035:
                   1036: static const char *rootpath = "/";
                   1037: static const char *
                   1038: path_host2rump(const char *path)
                   1039: {
                   1040:        const char *rv;
                   1041:
                   1042:        if (*path == '/') {
1.49      pooka    1043:                rv = path + rumpprefixlen;
1.45      pooka    1044:                if (*rv == '\0')
                   1045:                        rv = rootpath;
                   1046:        } else {
                   1047:                rv = path;
                   1048:        }
                   1049:
                   1050:        return rv;
                   1051: }
                   1052:
1.40      pooka    1053: static int
                   1054: dodup(int oldd, int minfd)
                   1055: {
                   1056:        int (*op_fcntl)(int, int, ...);
                   1057:        int newd;
                   1058:        int isrump;
                   1059:
                   1060:        DPRINTF(("dup -> %d (minfd %d)\n", oldd, minfd));
                   1061:        if (fd_isrump(oldd)) {
                   1062:                op_fcntl = GETSYSCALL(rump, FCNTL);
                   1063:                oldd = fd_host2rump(oldd);
1.85      pooka    1064:                if (minfd >= hijack_fdoff)
                   1065:                        minfd -= hijack_fdoff;
1.40      pooka    1066:                isrump = 1;
                   1067:        } else {
1.120     kre      1068:                if (minfd >= hijack_fdoff) {
                   1069:                        errno = EINVAL;
                   1070:                        return -1;
                   1071:                }
1.40      pooka    1072:                op_fcntl = GETSYSCALL(host, FCNTL);
                   1073:                isrump = 0;
                   1074:        }
                   1075:
                   1076:        newd = op_fcntl(oldd, F_DUPFD, minfd);
                   1077:
                   1078:        if (isrump)
                   1079:                newd = fd_rump2host(newd);
                   1080:        DPRINTF(("dup <- %d\n", newd));
                   1081:
                   1082:        return newd;
                   1083: }
1.2       pooka    1084:
1.47      pooka    1085: /*
1.85      pooka    1086:  * Check that host fd value does not exceed fdoffset and if necessary
                   1087:  * dup the file descriptor so that it doesn't collide with the dup2mask.
1.47      pooka    1088:  */
                   1089: static int
1.85      pooka    1090: fd_host2host(int fd)
1.47      pooka    1091: {
                   1092:        int (*op_fcntl)(int, int, ...) = GETSYSCALL(host, FCNTL);
                   1093:        int (*op_close)(int) = GETSYSCALL(host, CLOSE);
                   1094:        int ofd, i;
                   1095:
1.85      pooka    1096:        if (fd >= hijack_fdoff) {
                   1097:                op_close(fd);
                   1098:                errno = ENFILE;
                   1099:                return -1;
                   1100:        }
                   1101:
1.71      pooka    1102:        for (i = 1; isdup2d(fd); i++) {
1.47      pooka    1103:                ofd = fd;
                   1104:                fd = op_fcntl(ofd, F_DUPFD, i);
                   1105:                op_close(ofd);
                   1106:        }
                   1107:
                   1108:        return fd;
                   1109: }
                   1110:
1.45      pooka    1111: int
                   1112: open(const char *path, int flags, ...)
                   1113: {
                   1114:        int (*op_open)(const char *, int, ...);
                   1115:        bool isrump;
                   1116:        va_list ap;
1.75      pooka    1117:        enum pathtype pt;
1.45      pooka    1118:        int fd;
                   1119:
1.71      pooka    1120:        DPRINTF(("open -> %s (%s)\n", path, whichpath(path)));
                   1121:
1.75      pooka    1122:        if ((pt = path_isrump(path)) != PATH_HOST) {
                   1123:                if (pt == PATH_RUMP)
                   1124:                        path = path_host2rump(path);
1.45      pooka    1125:                op_open = GETSYSCALL(rump, OPEN);
                   1126:                isrump = true;
                   1127:        } else {
                   1128:                op_open = GETSYSCALL(host, OPEN);
                   1129:                isrump = false;
                   1130:        }
                   1131:
                   1132:        va_start(ap, flags);
                   1133:        fd = op_open(path, flags, va_arg(ap, mode_t));
                   1134:        va_end(ap);
                   1135:
                   1136:        if (isrump)
                   1137:                fd = fd_rump2host(fd);
1.47      pooka    1138:        else
1.85      pooka    1139:                fd = fd_host2host(fd);
1.71      pooka    1140:
                   1141:        DPRINTF(("open <- %d (%s)\n", fd, whichfd(fd)));
1.45      pooka    1142:        return fd;
                   1143: }
                   1144:
                   1145: int
                   1146: chdir(const char *path)
                   1147: {
                   1148:        int (*op_chdir)(const char *);
1.75      pooka    1149:        enum pathtype pt;
1.45      pooka    1150:        int rv;
                   1151:
1.75      pooka    1152:        if ((pt = path_isrump(path)) != PATH_HOST) {
1.45      pooka    1153:                op_chdir = GETSYSCALL(rump, CHDIR);
1.75      pooka    1154:                if (pt == PATH_RUMP)
                   1155:                        path = path_host2rump(path);
1.45      pooka    1156:        } else {
                   1157:                op_chdir = GETSYSCALL(host, CHDIR);
                   1158:        }
                   1159:
                   1160:        rv = op_chdir(path);
1.75      pooka    1161:        if (rv == 0)
                   1162:                pwdinrump = pt != PATH_HOST;
1.45      pooka    1163:
                   1164:        return rv;
                   1165: }
                   1166:
                   1167: int
                   1168: fchdir(int fd)
                   1169: {
                   1170:        int (*op_fchdir)(int);
                   1171:        bool isrump;
                   1172:        int rv;
                   1173:
                   1174:        if (fd_isrump(fd)) {
                   1175:                op_fchdir = GETSYSCALL(rump, FCHDIR);
                   1176:                isrump = true;
                   1177:                fd = fd_host2rump(fd);
                   1178:        } else {
                   1179:                op_fchdir = GETSYSCALL(host, FCHDIR);
                   1180:                isrump = false;
                   1181:        }
                   1182:
                   1183:        rv = op_fchdir(fd);
                   1184:        if (rv == 0) {
1.75      pooka    1185:                pwdinrump = isrump;
1.45      pooka    1186:        }
                   1187:
                   1188:        return rv;
                   1189: }
                   1190:
1.97      pooka    1191: #ifndef __linux__
1.52      pooka    1192: int
1.57      pooka    1193: __getcwd(char *bufp, size_t len)
                   1194: {
                   1195:        int (*op___getcwd)(char *, size_t);
1.75      pooka    1196:        size_t prefixgap;
                   1197:        bool iamslash;
1.57      pooka    1198:        int rv;
                   1199:
1.75      pooka    1200:        if (pwdinrump && rumpprefix) {
1.57      pooka    1201:                if (rumpprefix[rumpprefixlen-1] == '/')
                   1202:                        iamslash = true;
                   1203:                else
                   1204:                        iamslash = false;
                   1205:
                   1206:                if (iamslash)
                   1207:                        prefixgap = rumpprefixlen - 1; /* ``//+path'' */
                   1208:                else
                   1209:                        prefixgap = rumpprefixlen; /* ``/pfx+/path'' */
                   1210:                if (len <= prefixgap) {
1.66      pooka    1211:                        errno = ERANGE;
                   1212:                        return -1;
1.57      pooka    1213:                }
                   1214:
                   1215:                op___getcwd = GETSYSCALL(rump, __GETCWD);
                   1216:                rv = op___getcwd(bufp + prefixgap, len - prefixgap);
                   1217:                if (rv == -1)
                   1218:                        return rv;
                   1219:
                   1220:                /* augment the "/" part only for a non-root path */
                   1221:                memcpy(bufp, rumpprefix, rumpprefixlen);
                   1222:
                   1223:                /* append / only to non-root cwd */
                   1224:                if (rv != 2)
                   1225:                        bufp[prefixgap] = '/';
                   1226:
                   1227:                /* don't append extra slash in the purely-slash case */
                   1228:                if (rv == 2 && !iamslash)
                   1229:                        bufp[rumpprefixlen] = '\0';
1.75      pooka    1230:        } else if (pwdinrump) {
                   1231:                /* assume blanket.  we can't provide a prefix here */
                   1232:                op___getcwd = GETSYSCALL(rump, __GETCWD);
                   1233:                rv = op___getcwd(bufp, len);
1.57      pooka    1234:        } else {
                   1235:                op___getcwd = GETSYSCALL(host, __GETCWD);
1.75      pooka    1236:                rv = op___getcwd(bufp, len);
1.57      pooka    1237:        }
1.75      pooka    1238:
                   1239:        return rv;
1.57      pooka    1240: }
1.97      pooka    1241: #endif
1.57      pooka    1242:
1.95      riastrad 1243: static int
                   1244: moveish(const char *from, const char *to,
                   1245:     int (*rump_op)(const char *, const char *),
                   1246:     int (*host_op)(const char *, const char *))
1.52      pooka    1247: {
1.95      riastrad 1248:        int (*op)(const char *, const char *);
1.75      pooka    1249:        enum pathtype ptf, ptt;
1.52      pooka    1250:
1.75      pooka    1251:        if ((ptf = path_isrump(from)) != PATH_HOST) {
                   1252:                if ((ptt = path_isrump(to)) == PATH_HOST) {
1.66      pooka    1253:                        errno = EXDEV;
                   1254:                        return -1;
                   1255:                }
1.52      pooka    1256:
1.75      pooka    1257:                if (ptf == PATH_RUMP)
                   1258:                        from = path_host2rump(from);
                   1259:                if (ptt == PATH_RUMP)
                   1260:                        to = path_host2rump(to);
1.95      riastrad 1261:                op = rump_op;
1.52      pooka    1262:        } else {
1.75      pooka    1263:                if (path_isrump(to) != PATH_HOST) {
1.66      pooka    1264:                        errno = EXDEV;
                   1265:                        return -1;
                   1266:                }
1.53      pooka    1267:
1.95      riastrad 1268:                op = host_op;
1.52      pooka    1269:        }
                   1270:
1.95      riastrad 1271:        return op(from, to);
                   1272: }
                   1273:
                   1274: int
                   1275: link(const char *from, const char *to)
                   1276: {
                   1277:        return moveish(from, to,
                   1278:            GETSYSCALL(rump, LINK), GETSYSCALL(host, LINK));
                   1279: }
                   1280:
                   1281: int
                   1282: rename(const char *from, const char *to)
                   1283: {
                   1284:        return moveish(from, to,
                   1285:            GETSYSCALL(rump, RENAME), GETSYSCALL(host, RENAME));
1.52      pooka    1286: }
                   1287:
1.1       pooka    1288: int
1.96      pooka    1289: REALSOCKET(int domain, int type, int protocol)
1.1       pooka    1290: {
1.17      pooka    1291:        int (*op_socket)(int, int, int);
1.1       pooka    1292:        int fd;
1.49      pooka    1293:        bool isrump;
1.7       pooka    1294:
1.49      pooka    1295:        isrump = domain < PF_MAX && rumpsockets[domain];
1.1       pooka    1296:
1.49      pooka    1297:        if (isrump)
                   1298:                op_socket = GETSYSCALL(rump, SOCKET);
                   1299:        else
1.17      pooka    1300:                op_socket = GETSYSCALL(host, SOCKET);
                   1301:        fd = op_socket(domain, type, protocol);
1.2       pooka    1302:
1.49      pooka    1303:        if (isrump)
1.7       pooka    1304:                fd = fd_rump2host(fd);
1.47      pooka    1305:        else
1.85      pooka    1306:                fd = fd_host2host(fd);
1.7       pooka    1307:        DPRINTF(("socket <- %d\n", fd));
1.2       pooka    1308:
1.7       pooka    1309:        return fd;
1.1       pooka    1310: }
                   1311:
                   1312: int
                   1313: accept(int s, struct sockaddr *addr, socklen_t *addrlen)
                   1314: {
1.17      pooka    1315:        int (*op_accept)(int, struct sockaddr *, socklen_t *);
1.1       pooka    1316:        int fd;
1.7       pooka    1317:        bool isrump;
                   1318:
                   1319:        isrump = fd_isrump(s);
1.1       pooka    1320:
1.2       pooka    1321:        DPRINTF(("accept -> %d", s));
1.7       pooka    1322:        if (isrump) {
1.17      pooka    1323:                op_accept = GETSYSCALL(rump, ACCEPT);
1.7       pooka    1324:                s = fd_host2rump(s);
                   1325:        } else {
1.17      pooka    1326:                op_accept = GETSYSCALL(host, ACCEPT);
1.7       pooka    1327:        }
1.17      pooka    1328:        fd = op_accept(s, addr, addrlen);
1.7       pooka    1329:        if (fd != -1 && isrump)
                   1330:                fd = fd_rump2host(fd);
1.47      pooka    1331:        else
1.85      pooka    1332:                fd = fd_host2host(fd);
1.7       pooka    1333:
                   1334:        DPRINTF((" <- %d\n", fd));
1.2       pooka    1335:
1.7       pooka    1336:        return fd;
1.1       pooka    1337: }
                   1338:
1.121.2.1! bouyer   1339: int
        !          1340: paccept(int s, struct sockaddr *addr, socklen_t *addrlen,
        !          1341:     const sigset_t * restrict sigmask, int flags)
        !          1342: {
        !          1343:        int (*op_paccept)(int, struct sockaddr *, socklen_t *,
        !          1344:            const sigset_t * restrict, int);
        !          1345:        int fd;
        !          1346:        bool isrump;
        !          1347:
        !          1348:        isrump = fd_isrump(s);
        !          1349:
        !          1350:        DPRINTF(("paccept -> %d", s));
        !          1351:        if (isrump) {
        !          1352:                op_paccept = GETSYSCALL(rump, PACCEPT);
        !          1353:                s = fd_host2rump(s);
        !          1354:        } else {
        !          1355:                op_paccept = GETSYSCALL(host, PACCEPT);
        !          1356:        }
        !          1357:        fd = op_paccept(s, addr, addrlen, sigmask, flags);
        !          1358:        if (fd != -1 && isrump)
        !          1359:                fd = fd_rump2host(fd);
        !          1360:        else
        !          1361:                fd = fd_host2host(fd);
        !          1362:
        !          1363:        DPRINTF((" <- %d\n", fd));
        !          1364:
        !          1365:        return fd;
        !          1366: }
        !          1367:
1.17      pooka    1368: /*
1.103     pooka    1369:  * ioctl() and fcntl() are varargs calls and need special treatment.
                   1370:  */
                   1371:
                   1372: /*
                   1373:  * Various [Linux] libc's have various signatures for ioctl so we
                   1374:  * need to handle the discrepancies.  On NetBSD, we use the
                   1375:  * one with unsigned long cmd.
1.17      pooka    1376:  */
1.1       pooka    1377: int
1.103     pooka    1378: #ifdef HAVE_IOCTL_CMD_INT
                   1379: ioctl(int fd, int cmd, ...)
                   1380: {
                   1381:        int (*op_ioctl)(int, int cmd, ...);
                   1382: #else
1.17      pooka    1383: ioctl(int fd, unsigned long cmd, ...)
1.1       pooka    1384: {
1.17      pooka    1385:        int (*op_ioctl)(int, unsigned long cmd, ...);
1.103     pooka    1386: #endif
1.17      pooka    1387:        va_list ap;
                   1388:        int rv;
1.1       pooka    1389:
1.17      pooka    1390:        DPRINTF(("ioctl -> %d\n", fd));
                   1391:        if (fd_isrump(fd)) {
                   1392:                fd = fd_host2rump(fd);
                   1393:                op_ioctl = GETSYSCALL(rump, IOCTL);
1.7       pooka    1394:        } else {
1.17      pooka    1395:                op_ioctl = GETSYSCALL(host, IOCTL);
1.7       pooka    1396:        }
1.1       pooka    1397:
1.17      pooka    1398:        va_start(ap, cmd);
                   1399:        rv = op_ioctl(fd, cmd, va_arg(ap, void *));
                   1400:        va_end(ap);
                   1401:        return rv;
1.1       pooka    1402: }
                   1403:
                   1404: int
1.17      pooka    1405: fcntl(int fd, int cmd, ...)
1.1       pooka    1406: {
1.17      pooka    1407:        int (*op_fcntl)(int, int, ...);
                   1408:        va_list ap;
1.96      pooka    1409:        int rv, minfd;
1.40      pooka    1410:
                   1411:        DPRINTF(("fcntl -> %d (cmd %d)\n", fd, cmd));
                   1412:
                   1413:        switch (cmd) {
1.121     christos 1414:        case F_DUPFD_CLOEXEC:   /* Ignore CLOEXEC bit for now */
1.40      pooka    1415:        case F_DUPFD:
                   1416:                va_start(ap, cmd);
                   1417:                minfd = va_arg(ap, int);
                   1418:                va_end(ap);
                   1419:                return dodup(fd, minfd);
                   1420:
1.96      pooka    1421: #ifdef F_CLOSEM
                   1422:        case F_CLOSEM: {
                   1423:                int maxdup2, i;
                   1424:
1.40      pooka    1425:                /*
                   1426:                 * So, if fd < HIJACKOFF, we want to do a host closem.
                   1427:                 */
                   1428:
1.85      pooka    1429:                if (fd < hijack_fdoff) {
1.40      pooka    1430:                        int closemfd = fd;
1.1       pooka    1431:
1.40      pooka    1432:                        if (rumpclient__closenotify(&closemfd,
1.39      pooka    1433:                            RUMPCLIENT_CLOSE_FCLOSEM) == -1)
                   1434:                                return -1;
1.40      pooka    1435:                        op_fcntl = GETSYSCALL(host, FCNTL);
                   1436:                        rv = op_fcntl(closemfd, cmd);
                   1437:                        if (rv)
                   1438:                                return rv;
                   1439:                }
                   1440:
                   1441:                /*
                   1442:                 * Additionally, we want to do a rump closem, but only
1.71      pooka    1443:                 * for the file descriptors not dup2'd.
1.40      pooka    1444:                 */
                   1445:
1.110     pooka    1446:                for (i = 0, maxdup2 = -1; i <= DUP2HIGH; i++) {
1.72      pooka    1447:                        if (dup2vec[i] & DUP2BIT) {
                   1448:                                int val;
                   1449:
                   1450:                                val = dup2vec[i] & DUP2FDMASK;
                   1451:                                maxdup2 = MAX(val, maxdup2);
                   1452:                        }
1.40      pooka    1453:                }
                   1454:
1.85      pooka    1455:                if (fd >= hijack_fdoff)
                   1456:                        fd -= hijack_fdoff;
1.40      pooka    1457:                else
                   1458:                        fd = 0;
1.71      pooka    1459:                fd = MAX(maxdup2+1, fd);
1.40      pooka    1460:
                   1461:                /* hmm, maybe we should close rump fd's not within dup2mask? */
                   1462:                return rump_sys_fcntl(fd, F_CLOSEM);
1.96      pooka    1463:        }
                   1464: #endif /* F_CLOSEM */
1.40      pooka    1465:
1.96      pooka    1466: #ifdef F_MAXFD
1.40      pooka    1467:        case F_MAXFD:
                   1468:                /*
                   1469:                 * For maxfd, if there's a rump kernel fd, return
                   1470:                 * it hostified.  Otherwise, return host's MAXFD
                   1471:                 * return value.
                   1472:                 */
                   1473:                if ((rv = rump_sys_fcntl(fd, F_MAXFD)) != -1) {
                   1474:                        /*
                   1475:                         * This might go a little wrong in case
                   1476:                         * of dup2 to [012], but I'm not sure if
                   1477:                         * there's a justification for tracking
                   1478:                         * that info.  Consider e.g.
                   1479:                         * dup2(rumpfd, 2) followed by rump_sys_open()
                   1480:                         * returning 1.  We should return 1+HIJACKOFF,
                   1481:                         * not 2+HIJACKOFF.  However, if [01] is not
                   1482:                         * open, the correct return value is 2.
                   1483:                         */
                   1484:                        return fd_rump2host(fd);
                   1485:                } else {
                   1486:                        op_fcntl = GETSYSCALL(host, FCNTL);
                   1487:                        return op_fcntl(fd, F_MAXFD);
                   1488:                }
                   1489:                /*NOTREACHED*/
1.96      pooka    1490: #endif /* F_MAXFD */
1.40      pooka    1491:
                   1492:        default:
                   1493:                if (fd_isrump(fd)) {
                   1494:                        fd = fd_host2rump(fd);
                   1495:                        op_fcntl = GETSYSCALL(rump, FCNTL);
                   1496:                } else {
                   1497:                        op_fcntl = GETSYSCALL(host, FCNTL);
                   1498:                }
                   1499:
                   1500:                va_start(ap, cmd);
                   1501:                rv = op_fcntl(fd, cmd, va_arg(ap, void *));
                   1502:                va_end(ap);
                   1503:                return rv;
1.7       pooka    1504:        }
1.40      pooka    1505:        /*NOTREACHED*/
1.1       pooka    1506: }
                   1507:
1.39      pooka    1508: int
                   1509: close(int fd)
                   1510: {
                   1511:        int (*op_close)(int);
                   1512:        int rv;
                   1513:
                   1514:        DPRINTF(("close -> %d\n", fd));
                   1515:        if (fd_isrump(fd)) {
1.71      pooka    1516:                bool undup2 = false;
                   1517:                int ofd;
                   1518:
                   1519:                if (isdup2d(ofd = fd)) {
                   1520:                        undup2 = true;
                   1521:                }
1.39      pooka    1522:
1.47      pooka    1523:                fd = fd_host2rump(fd);
1.71      pooka    1524:                if (!undup2 && killdup2alias(fd)) {
1.47      pooka    1525:                        return 0;
                   1526:                }
                   1527:
1.39      pooka    1528:                op_close = GETSYSCALL(rump, CLOSE);
                   1529:                rv = op_close(fd);
1.71      pooka    1530:                if (rv == 0 && undup2) {
                   1531:                        clrdup2(ofd);
                   1532:                }
1.39      pooka    1533:        } else {
                   1534:                if (rumpclient__closenotify(&fd, RUMPCLIENT_CLOSE_CLOSE) == -1)
                   1535:                        return -1;
                   1536:                op_close = GETSYSCALL(host, CLOSE);
                   1537:                rv = op_close(fd);
                   1538:        }
                   1539:
                   1540:        return rv;
                   1541: }
                   1542:
1.17      pooka    1543: /*
                   1544:  * write cannot issue a standard debug printf due to recursion
                   1545:  */
1.1       pooka    1546: ssize_t
1.17      pooka    1547: write(int fd, const void *buf, size_t blen)
1.1       pooka    1548: {
1.17      pooka    1549:        ssize_t (*op_write)(int, const void *, size_t);
1.1       pooka    1550:
1.17      pooka    1551:        if (fd_isrump(fd)) {
                   1552:                fd = fd_host2rump(fd);
                   1553:                op_write = GETSYSCALL(rump, WRITE);
1.16      pooka    1554:        } else {
1.17      pooka    1555:                op_write = GETSYSCALL(host, WRITE);
1.16      pooka    1556:        }
1.1       pooka    1557:
1.17      pooka    1558:        return op_write(fd, buf, blen);
1.2       pooka    1559: }
                   1560:
                   1561: /*
1.94      yamt     1562:  * file descriptor passing
                   1563:  *
                   1564:  * we intercept sendmsg and recvmsg to convert file descriptors in
                   1565:  * control messages.  an attempt to send a descriptor from a different kernel
                   1566:  * is rejected.  (ENOTSUP)
                   1567:  */
                   1568:
                   1569: static int
                   1570: msg_convert(struct msghdr *msg, int (*func)(int))
                   1571: {
                   1572:        struct cmsghdr *cmsg;
                   1573:
                   1574:        for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
                   1575:            cmsg = CMSG_NXTHDR(msg, cmsg)) {
                   1576:                if (cmsg->cmsg_level == SOL_SOCKET &&
                   1577:                    cmsg->cmsg_type == SCM_RIGHTS) {
                   1578:                        int *fdp = (void *)CMSG_DATA(cmsg);
                   1579:                        const size_t size =
                   1580:                            cmsg->cmsg_len - __CMSG_ALIGN(sizeof(*cmsg));
1.99      martin   1581:                        const int nfds = (int)(size / sizeof(int));
1.94      yamt     1582:                        const int * const efdp = fdp + nfds;
                   1583:
                   1584:                        while (fdp < efdp) {
                   1585:                                const int newval = func(*fdp);
                   1586:
                   1587:                                if (newval < 0) {
                   1588:                                        return ENOTSUP;
                   1589:                                }
                   1590:                                *fdp = newval;
                   1591:                                fdp++;
                   1592:                        }
                   1593:                }
                   1594:        }
                   1595:        return 0;
                   1596: }
                   1597:
                   1598: ssize_t
                   1599: recvmsg(int fd, struct msghdr *msg, int flags)
                   1600: {
                   1601:        ssize_t (*op_recvmsg)(int, struct msghdr *, int);
                   1602:        ssize_t ret;
                   1603:        const bool isrump = fd_isrump(fd);
                   1604:
                   1605:        if (isrump) {
                   1606:                fd = fd_host2rump(fd);
                   1607:                op_recvmsg = GETSYSCALL(rump, RECVMSG);
                   1608:        } else {
                   1609:                op_recvmsg = GETSYSCALL(host, RECVMSG);
                   1610:        }
                   1611:        ret = op_recvmsg(fd, msg, flags);
                   1612:        if (ret == -1) {
                   1613:                return ret;
                   1614:        }
                   1615:        /*
                   1616:         * convert descriptors in the message.
                   1617:         */
                   1618:        if (isrump) {
                   1619:                msg_convert(msg, fd_rump2host);
                   1620:        } else {
                   1621:                msg_convert(msg, fd_host2host);
                   1622:        }
                   1623:        return ret;
                   1624: }
                   1625:
1.97      pooka    1626: ssize_t
                   1627: recv(int fd, void *buf, size_t len, int flags)
                   1628: {
                   1629:
                   1630:        return recvfrom(fd, buf, len, flags, NULL, NULL);
                   1631: }
                   1632:
                   1633: ssize_t
                   1634: send(int fd, const void *buf, size_t len, int flags)
                   1635: {
                   1636:
                   1637:        return sendto(fd, buf, len, flags, NULL, 0);
                   1638: }
                   1639:
1.94      yamt     1640: static int
                   1641: fd_check_rump(int fd)
                   1642: {
                   1643:
                   1644:        return fd_isrump(fd) ? 0 : -1;
                   1645: }
                   1646:
                   1647: static int
                   1648: fd_check_host(int fd)
                   1649: {
                   1650:
                   1651:        return !fd_isrump(fd) ? 0 : -1;
                   1652: }
                   1653:
                   1654: ssize_t
                   1655: sendmsg(int fd, const struct msghdr *msg, int flags)
                   1656: {
                   1657:        ssize_t (*op_sendmsg)(int, const struct msghdr *, int);
                   1658:        const bool isrump = fd_isrump(fd);
                   1659:        int error;
                   1660:
                   1661:        /*
                   1662:         * reject descriptors from a different kernel.
                   1663:         */
                   1664:        error = msg_convert(__UNCONST(msg),
                   1665:            isrump ? fd_check_rump: fd_check_host);
                   1666:        if (error != 0) {
                   1667:                errno = error;
                   1668:                return -1;
                   1669:        }
                   1670:        /*
                   1671:         * convert descriptors in the message to raw values.
                   1672:         */
                   1673:        if (isrump) {
                   1674:                fd = fd_host2rump(fd);
                   1675:                /*
                   1676:                 * XXX we directly modify the given message assuming:
                   1677:                 * - cmsg is writable (typically on caller's stack)
                   1678:                 * - caller don't care cmsg's contents after calling sendmsg.
                   1679:                 *   (thus no need to restore values)
                   1680:                 *
                   1681:                 * it's safer to copy and modify instead.
                   1682:                 */
                   1683:                msg_convert(__UNCONST(msg), fd_host2rump);
                   1684:                op_sendmsg = GETSYSCALL(rump, SENDMSG);
                   1685:        } else {
                   1686:                op_sendmsg = GETSYSCALL(host, SENDMSG);
                   1687:        }
                   1688:        return op_sendmsg(fd, msg, flags);
                   1689: }
                   1690:
                   1691: /*
1.2       pooka    1692:  * dup2 is special.  we allow dup2 of a rump kernel fd to 0-2 since
                   1693:  * many programs do that.  dup2 of a rump kernel fd to another value
                   1694:  * not >= fdoff is an error.
                   1695:  *
                   1696:  * Note: cannot rump2host newd, because it is often hardcoded.
                   1697:  */
                   1698: int
                   1699: dup2(int oldd, int newd)
                   1700: {
1.17      pooka    1701:        int (*host_dup2)(int, int);
1.2       pooka    1702:        int rv;
                   1703:
                   1704:        DPRINTF(("dup2 -> %d (o) -> %d (n)\n", oldd, newd));
                   1705:
                   1706:        if (fd_isrump(oldd)) {
1.71      pooka    1707:                int (*op_close)(int) = GETSYSCALL(host, CLOSE);
                   1708:
                   1709:                /* only allow fd 0-2 for cross-kernel dup */
                   1710:                if (!(newd >= 0 && newd <= 2 && !fd_isrump(newd))) {
1.66      pooka    1711:                        errno = EBADF;
                   1712:                        return -1;
                   1713:                }
1.71      pooka    1714:
                   1715:                /* regular dup2? */
                   1716:                if (fd_isrump(newd)) {
                   1717:                        newd = fd_host2rump(newd);
                   1718:                        rv = rump_sys_dup2(oldd, newd);
                   1719:                        return fd_rump2host(rv);
                   1720:                }
                   1721:
                   1722:                /*
                   1723:                 * dup2 rump => host?  just establish an
                   1724:                 * entry in the mapping table.
                   1725:                 */
                   1726:                op_close(newd);
                   1727:                setdup2(newd, fd_host2rump(oldd));
                   1728:                rv = 0;
1.2       pooka    1729:        } else {
1.17      pooka    1730:                host_dup2 = syscalls[DUALCALL_DUP2].bs_host;
1.39      pooka    1731:                if (rumpclient__closenotify(&newd, RUMPCLIENT_CLOSE_DUP2) == -1)
                   1732:                        return -1;
1.10      pooka    1733:                rv = host_dup2(oldd, newd);
1.2       pooka    1734:        }
1.10      pooka    1735:
                   1736:        return rv;
1.2       pooka    1737: }
                   1738:
1.34      pooka    1739: int
                   1740: dup(int oldd)
                   1741: {
                   1742:
1.40      pooka    1743:        return dodup(oldd, 0);
1.34      pooka    1744: }
                   1745:
1.2       pooka    1746: pid_t
1.93      abs      1747: fork(void)
1.2       pooka    1748: {
                   1749:        pid_t rv;
                   1750:
                   1751:        DPRINTF(("fork\n"));
                   1752:
1.43      pooka    1753:        rv = rumpclient__dofork(host_fork);
1.2       pooka    1754:
                   1755:        DPRINTF(("fork returns %d\n", rv));
                   1756:        return rv;
1.1       pooka    1757: }
1.96      pooka    1758: #ifdef VFORK
1.43      pooka    1759: /* we do not have the luxury of not requiring a stackframe */
1.117     riastrad 1760: #define        __strong_alias_macro(m, f)      __strong_alias(m, f)
                   1761: __strong_alias_macro(VFORK,fork);
1.96      pooka    1762: #endif
1.1       pooka    1763:
1.25      pooka    1764: int
                   1765: daemon(int nochdir, int noclose)
                   1766: {
                   1767:        struct rumpclient_fork *rf;
                   1768:
                   1769:        if ((rf = rumpclient_prefork()) == NULL)
                   1770:                return -1;
                   1771:
                   1772:        if (host_daemon(nochdir, noclose) == -1)
                   1773:                return -1;
                   1774:
                   1775:        if (rumpclient_fork_init(rf) == -1)
                   1776:                return -1;
                   1777:
                   1778:        return 0;
                   1779: }
                   1780:
1.39      pooka    1781: int
1.42      pooka    1782: execve(const char *path, char *const argv[], char *const envp[])
1.39      pooka    1783: {
                   1784:        char buf[128];
                   1785:        char *dup2str;
1.49      pooka    1786:        const char *pwdinrumpstr;
1.42      pooka    1787:        char **newenv;
                   1788:        size_t nelem;
                   1789:        int rv, sverrno;
1.71      pooka    1790:        int bonus = 2, i = 0;
1.45      pooka    1791:
1.71      pooka    1792:        snprintf(buf, sizeof(buf), "RUMPHIJACK__DUP2INFO=%u,%u,%u",
                   1793:            dup2vec[0], dup2vec[1], dup2vec[2]);
                   1794:        dup2str = strdup(buf);
                   1795:        if (dup2str == NULL) {
                   1796:                errno = ENOMEM;
                   1797:                return -1;
1.45      pooka    1798:        }
1.39      pooka    1799:
1.45      pooka    1800:        if (pwdinrump) {
1.49      pooka    1801:                pwdinrumpstr = "RUMPHIJACK__PWDINRUMP=true";
1.45      pooka    1802:                bonus++;
                   1803:        } else {
                   1804:                pwdinrumpstr = NULL;
                   1805:        }
1.39      pooka    1806:
1.42      pooka    1807:        for (nelem = 0; envp && envp[nelem]; nelem++)
                   1808:                continue;
1.71      pooka    1809:        newenv = malloc(sizeof(*newenv) * (nelem+bonus));
1.42      pooka    1810:        if (newenv == NULL) {
1.39      pooka    1811:                free(dup2str);
1.66      pooka    1812:                errno = ENOMEM;
                   1813:                return -1;
1.39      pooka    1814:        }
1.42      pooka    1815:        memcpy(newenv, envp, nelem*sizeof(*newenv));
1.71      pooka    1816:        newenv[nelem+i] = dup2str;
                   1817:        i++;
                   1818:
1.45      pooka    1819:        if (pwdinrumpstr) {
1.49      pooka    1820:                newenv[nelem+i] = __UNCONST(pwdinrumpstr);
1.45      pooka    1821:                i++;
                   1822:        }
                   1823:        newenv[nelem+i] = NULL;
                   1824:        _DIAGASSERT(i < bonus);
1.42      pooka    1825:
                   1826:        rv = rumpclient_exec(path, argv, newenv);
                   1827:
                   1828:        _DIAGASSERT(rv != 0);
                   1829:        sverrno = errno;
                   1830:        free(newenv);
                   1831:        free(dup2str);
                   1832:        errno = sverrno;
1.39      pooka    1833:        return rv;
                   1834: }
                   1835:
1.1       pooka    1836: /*
1.17      pooka    1837:  * select is done by calling poll.
1.1       pooka    1838:  */
                   1839: int
1.29      pooka    1840: REALSELECT(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
1.4       pooka    1841:        struct timeval *timeout)
1.1       pooka    1842: {
1.4       pooka    1843:        struct pollfd *pfds;
                   1844:        struct timespec ts, *tsp = NULL;
1.19      pooka    1845:        nfds_t realnfds;
                   1846:        int i, j;
1.4       pooka    1847:        int rv, incr;
                   1848:
1.100     pooka    1849:        DPRINTF(("select %d %p %p %p %p\n", nfds,
                   1850:            readfds, writefds, exceptfds, timeout));
1.7       pooka    1851:
1.4       pooka    1852:        /*
                   1853:         * Well, first we must scan the fds to figure out how many
                   1854:         * fds there really are.  This is because up to and including
1.17      pooka    1855:         * nb5 poll() silently refuses nfds > process_maxopen_fds.
1.4       pooka    1856:         * Seems to be fixed in current, thank the maker.
                   1857:         * god damn cluster...bomb.
                   1858:         */
                   1859:
                   1860:        for (i = 0, realnfds = 0; i < nfds; i++) {
                   1861:                if (readfds && FD_ISSET(i, readfds)) {
                   1862:                        realnfds++;
                   1863:                        continue;
                   1864:                }
                   1865:                if (writefds && FD_ISSET(i, writefds)) {
                   1866:                        realnfds++;
                   1867:                        continue;
                   1868:                }
                   1869:                if (exceptfds && FD_ISSET(i, exceptfds)) {
                   1870:                        realnfds++;
                   1871:                        continue;
1.1       pooka    1872:                }
                   1873:        }
                   1874:
1.6       pooka    1875:        if (realnfds) {
1.38      pooka    1876:                pfds = calloc(realnfds, sizeof(*pfds));
1.6       pooka    1877:                if (!pfds)
                   1878:                        return -1;
                   1879:        } else {
                   1880:                pfds = NULL;
                   1881:        }
1.1       pooka    1882:
1.4       pooka    1883:        for (i = 0, j = 0; i < nfds; i++) {
                   1884:                incr = 0;
                   1885:                if (readfds && FD_ISSET(i, readfds)) {
                   1886:                        pfds[j].fd = i;
                   1887:                        pfds[j].events |= POLLIN;
                   1888:                        incr=1;
                   1889:                }
                   1890:                if (writefds && FD_ISSET(i, writefds)) {
                   1891:                        pfds[j].fd = i;
                   1892:                        pfds[j].events |= POLLOUT;
                   1893:                        incr=1;
                   1894:                }
                   1895:                if (exceptfds && FD_ISSET(i, exceptfds)) {
                   1896:                        pfds[j].fd = i;
                   1897:                        pfds[j].events |= POLLHUP|POLLERR;
                   1898:                        incr=1;
1.1       pooka    1899:                }
1.4       pooka    1900:                if (incr)
                   1901:                        j++;
1.1       pooka    1902:        }
1.37      pooka    1903:        assert(j == (int)realnfds);
1.1       pooka    1904:
1.4       pooka    1905:        if (timeout) {
                   1906:                TIMEVAL_TO_TIMESPEC(timeout, &ts);
                   1907:                tsp = &ts;
                   1908:        }
1.29      pooka    1909:        rv = REALPOLLTS(pfds, realnfds, tsp, NULL);
1.36      pooka    1910:        /*
                   1911:         * "If select() returns with an error the descriptor sets
                   1912:         * will be unmodified"
                   1913:         */
                   1914:        if (rv < 0)
1.4       pooka    1915:                goto out;
                   1916:
                   1917:        /*
1.36      pooka    1918:         * zero out results (can't use FD_ZERO for the
                   1919:         * obvious select-me-not reason).  whee.
                   1920:         *
                   1921:         * We do this here since some software ignores the return
                   1922:         * value of select, and hence if the timeout expires, it may
                   1923:         * assume all input descriptors have activity.
1.4       pooka    1924:         */
                   1925:        for (i = 0; i < nfds; i++) {
                   1926:                if (readfds)
                   1927:                        FD_CLR(i, readfds);
                   1928:                if (writefds)
                   1929:                        FD_CLR(i, writefds);
                   1930:                if (exceptfds)
                   1931:                        FD_CLR(i, exceptfds);
1.1       pooka    1932:        }
1.36      pooka    1933:        if (rv == 0)
                   1934:                goto out;
1.1       pooka    1935:
1.36      pooka    1936:        /*
                   1937:         * We have >0 fds with activity.  Harvest the results.
                   1938:         */
1.19      pooka    1939:        for (i = 0; i < (int)realnfds; i++) {
1.4       pooka    1940:                if (readfds) {
                   1941:                        if (pfds[i].revents & POLLIN) {
                   1942:                                FD_SET(pfds[i].fd, readfds);
                   1943:                        }
                   1944:                }
                   1945:                if (writefds) {
                   1946:                        if (pfds[i].revents & POLLOUT) {
                   1947:                                FD_SET(pfds[i].fd, writefds);
                   1948:                        }
                   1949:                }
                   1950:                if (exceptfds) {
                   1951:                        if (pfds[i].revents & (POLLHUP|POLLERR)) {
                   1952:                                FD_SET(pfds[i].fd, exceptfds);
                   1953:                        }
                   1954:                }
1.1       pooka    1955:        }
                   1956:
1.4       pooka    1957:  out:
                   1958:        free(pfds);
1.1       pooka    1959:        return rv;
                   1960: }
                   1961:
                   1962: static void
                   1963: checkpoll(struct pollfd *fds, nfds_t nfds, int *hostcall, int *rumpcall)
                   1964: {
                   1965:        nfds_t i;
                   1966:
                   1967:        for (i = 0; i < nfds; i++) {
1.12      pooka    1968:                if (fds[i].fd == -1)
                   1969:                        continue;
                   1970:
1.2       pooka    1971:                if (fd_isrump(fds[i].fd))
                   1972:                        (*rumpcall)++;
                   1973:                else
1.1       pooka    1974:                        (*hostcall)++;
                   1975:        }
                   1976: }
                   1977:
                   1978: static void
1.2       pooka    1979: adjustpoll(struct pollfd *fds, nfds_t nfds, int (*fdadj)(int))
1.1       pooka    1980: {
                   1981:        nfds_t i;
                   1982:
                   1983:        for (i = 0; i < nfds; i++) {
1.2       pooka    1984:                fds[i].fd = fdadj(fds[i].fd);
1.1       pooka    1985:        }
                   1986: }
                   1987:
                   1988: /*
                   1989:  * poll is easy as long as the call comes in the fds only in one
                   1990:  * kernel.  otherwise its quite tricky...
                   1991:  */
                   1992: struct pollarg {
                   1993:        struct pollfd *pfds;
                   1994:        nfds_t nfds;
1.3       pooka    1995:        const struct timespec *ts;
                   1996:        const sigset_t *sigmask;
1.1       pooka    1997:        int pipefd;
                   1998:        int errnum;
                   1999: };
                   2000:
                   2001: static void *
                   2002: hostpoll(void *arg)
                   2003: {
1.17      pooka    2004:        int (*op_pollts)(struct pollfd *, nfds_t, const struct timespec *,
                   2005:                         const sigset_t *);
1.1       pooka    2006:        struct pollarg *parg = arg;
                   2007:        intptr_t rv;
                   2008:
1.35      pooka    2009:        op_pollts = GETSYSCALL(host, POLLTS);
1.17      pooka    2010:        rv = op_pollts(parg->pfds, parg->nfds, parg->ts, parg->sigmask);
1.1       pooka    2011:        if (rv == -1)
                   2012:                parg->errnum = errno;
                   2013:        rump_sys_write(parg->pipefd, &rv, sizeof(rv));
                   2014:
1.92      martin   2015:        return (void *)rv;
1.1       pooka    2016: }
                   2017:
                   2018: int
1.29      pooka    2019: REALPOLLTS(struct pollfd *fds, nfds_t nfds, const struct timespec *ts,
1.3       pooka    2020:        const sigset_t *sigmask)
1.1       pooka    2021: {
1.3       pooka    2022:        int (*op_pollts)(struct pollfd *, nfds_t, const struct timespec *,
                   2023:                         const sigset_t *);
1.17      pooka    2024:        int (*host_close)(int);
1.1       pooka    2025:        int hostcall = 0, rumpcall = 0;
                   2026:        pthread_t pt;
                   2027:        nfds_t i;
                   2028:        int rv;
                   2029:
1.100     pooka    2030:        DPRINTF(("poll %p %d %p %p\n", fds, (int)nfds, ts, sigmask));
1.1       pooka    2031:        checkpoll(fds, nfds, &hostcall, &rumpcall);
                   2032:
                   2033:        if (hostcall && rumpcall) {
                   2034:                struct pollfd *pfd_host = NULL, *pfd_rump = NULL;
                   2035:                int rpipe[2] = {-1,-1}, hpipe[2] = {-1,-1};
                   2036:                struct pollarg parg;
1.92      martin   2037:                void *trv_val;
1.99      martin   2038:                int sverrno = 0, rv_rump, rv_host, errno_rump, errno_host;
1.1       pooka    2039:
                   2040:                /*
                   2041:                 * ok, this is where it gets tricky.  We must support
                   2042:                 * this since it's a very common operation in certain
                   2043:                 * types of software (telnet, netcat, etc).  We allocate
                   2044:                 * two vectors and run two poll commands in separate
                   2045:                 * threads.  Whichever returns first "wins" and the
                   2046:                 * other kernel's fds won't show activity.
                   2047:                 */
                   2048:                rv = -1;
                   2049:
                   2050:                /* allocate full vector for O(n) joining after call */
                   2051:                pfd_host = malloc(sizeof(*pfd_host)*(nfds+1));
                   2052:                if (!pfd_host)
                   2053:                        goto out;
                   2054:                pfd_rump = malloc(sizeof(*pfd_rump)*(nfds+1));
                   2055:                if (!pfd_rump) {
                   2056:                        goto out;
                   2057:                }
                   2058:
1.59      pooka    2059:                /*
                   2060:                 * then, open two pipes, one for notifications
                   2061:                 * to each kernel.
1.73      pooka    2062:                 *
                   2063:                 * At least the rump pipe should probably be
                   2064:                 * cached, along with the helper threads.  This
                   2065:                 * should give a microbenchmark improvement (haven't
                   2066:                 * experienced a macro-level problem yet, though).
1.59      pooka    2067:                 */
                   2068:                if ((rv = rump_sys_pipe(rpipe)) == -1) {
                   2069:                        sverrno = errno;
                   2070:                }
                   2071:                if (rv == 0 && (rv = pipe(hpipe)) == -1) {
                   2072:                        sverrno = errno;
                   2073:                }
                   2074:
                   2075:                /* split vectors (or signal errors) */
1.1       pooka    2076:                for (i = 0; i < nfds; i++) {
1.59      pooka    2077:                        int fd;
                   2078:
                   2079:                        fds[i].revents = 0;
1.3       pooka    2080:                        if (fds[i].fd == -1) {
                   2081:                                pfd_host[i].fd = -1;
                   2082:                                pfd_rump[i].fd = -1;
                   2083:                        } else if (fd_isrump(fds[i].fd)) {
1.2       pooka    2084:                                pfd_host[i].fd = -1;
1.59      pooka    2085:                                fd = fd_host2rump(fds[i].fd);
                   2086:                                if (fd == rpipe[0] || fd == rpipe[1]) {
                   2087:                                        fds[i].revents = POLLNVAL;
                   2088:                                        if (rv != -1)
                   2089:                                                rv++;
                   2090:                                }
                   2091:                                pfd_rump[i].fd = fd;
1.2       pooka    2092:                                pfd_rump[i].events = fds[i].events;
                   2093:                        } else {
                   2094:                                pfd_rump[i].fd = -1;
1.59      pooka    2095:                                fd = fds[i].fd;
                   2096:                                if (fd == hpipe[0] || fd == hpipe[1]) {
                   2097:                                        fds[i].revents = POLLNVAL;
                   2098:                                        if (rv != -1)
                   2099:                                                rv++;
                   2100:                                }
                   2101:                                pfd_host[i].fd = fd;
1.1       pooka    2102:                                pfd_host[i].events = fds[i].events;
                   2103:                        }
1.39      pooka    2104:                        pfd_rump[i].revents = pfd_host[i].revents = 0;
1.1       pooka    2105:                }
1.59      pooka    2106:                if (rv) {
1.1       pooka    2107:                        goto out;
1.59      pooka    2108:                }
1.1       pooka    2109:
                   2110:                pfd_host[nfds].fd = hpipe[0];
                   2111:                pfd_host[nfds].events = POLLIN;
                   2112:                pfd_rump[nfds].fd = rpipe[0];
                   2113:                pfd_rump[nfds].events = POLLIN;
                   2114:
                   2115:                /*
                   2116:                 * then, create a thread to do host part and meanwhile
                   2117:                 * do rump kernel part right here
                   2118:                 */
                   2119:
                   2120:                parg.pfds = pfd_host;
                   2121:                parg.nfds = nfds+1;
1.3       pooka    2122:                parg.ts = ts;
                   2123:                parg.sigmask = sigmask;
1.1       pooka    2124:                parg.pipefd = rpipe[1];
                   2125:                pthread_create(&pt, NULL, hostpoll, &parg);
                   2126:
1.35      pooka    2127:                op_pollts = GETSYSCALL(rump, POLLTS);
1.99      martin   2128:                rv_rump = op_pollts(pfd_rump, nfds+1, ts, NULL);
                   2129:                errno_rump = errno;
1.1       pooka    2130:                write(hpipe[1], &rv, sizeof(rv));
1.92      martin   2131:                pthread_join(pt, &trv_val);
1.99      martin   2132:                rv_host = (int)(intptr_t)trv_val;
                   2133:                errno_host = parg.errnum;
1.1       pooka    2134:
1.99      martin   2135:                /* strip cross-thread notification from real results */
1.109     gson     2136:                if (rv_host > 0 && pfd_host[nfds].revents & POLLIN) {
1.99      martin   2137:                        rv_host--;
                   2138:                }
1.109     gson     2139:                if (rv_rump > 0 && pfd_rump[nfds].revents & POLLIN) {
1.99      martin   2140:                        rv_rump--;
                   2141:                }
                   2142:
                   2143:                /* then merge the results into what's reported to the caller */
                   2144:                if (rv_rump > 0 || rv_host > 0) {
                   2145:                        /* SUCCESS */
                   2146:
                   2147:                        rv = 0;
                   2148:                        if (rv_rump > 0) {
                   2149:                                for (i = 0; i < nfds; i++) {
                   2150:                                        if (pfd_rump[i].fd != -1)
                   2151:                                                fds[i].revents
                   2152:                                                    = pfd_rump[i].revents;
                   2153:                                }
                   2154:                                rv += rv_rump;
1.1       pooka    2155:                        }
1.99      martin   2156:                        if (rv_host > 0) {
                   2157:                                for (i = 0; i < nfds; i++) {
                   2158:                                        if (pfd_host[i].fd != -1)
                   2159:                                                fds[i].revents
                   2160:                                                    = pfd_host[i].revents;
                   2161:                                }
                   2162:                                rv += rv_host;
                   2163:                        }
                   2164:                        assert(rv > 0);
                   2165:                        sverrno = 0;
                   2166:                } else if (rv_rump == -1 || rv_host == -1) {
                   2167:                        /* ERROR */
                   2168:
                   2169:                        /* just pick one kernel at "random" */
                   2170:                        rv = -1;
                   2171:                        if (rv_host == -1) {
                   2172:                                sverrno = errno_host;
                   2173:                        } else if (rv_rump == -1) {
                   2174:                                sverrno = errno_rump;
1.1       pooka    2175:                        }
                   2176:                } else {
1.99      martin   2177:                        /* TIMEOUT */
                   2178:
1.1       pooka    2179:                        rv = 0;
1.99      martin   2180:                        assert(rv_rump == 0 && rv_host == 0);
1.1       pooka    2181:                }
                   2182:
                   2183:  out:
1.35      pooka    2184:                host_close = GETSYSCALL(host, CLOSE);
1.1       pooka    2185:                if (rpipe[0] != -1)
                   2186:                        rump_sys_close(rpipe[0]);
                   2187:                if (rpipe[1] != -1)
                   2188:                        rump_sys_close(rpipe[1]);
                   2189:                if (hpipe[0] != -1)
1.9       pooka    2190:                        host_close(hpipe[0]);
1.1       pooka    2191:                if (hpipe[1] != -1)
1.9       pooka    2192:                        host_close(hpipe[1]);
1.1       pooka    2193:                free(pfd_host);
                   2194:                free(pfd_rump);
                   2195:                errno = sverrno;
                   2196:        } else {
                   2197:                if (hostcall) {
1.35      pooka    2198:                        op_pollts = GETSYSCALL(host, POLLTS);
1.1       pooka    2199:                } else {
1.35      pooka    2200:                        op_pollts = GETSYSCALL(rump, POLLTS);
1.2       pooka    2201:                        adjustpoll(fds, nfds, fd_host2rump);
1.1       pooka    2202:                }
                   2203:
1.3       pooka    2204:                rv = op_pollts(fds, nfds, ts, sigmask);
1.1       pooka    2205:                if (rumpcall)
1.71      pooka    2206:                        adjustpoll(fds, nfds, fd_rump2host_withdup);
1.1       pooka    2207:        }
                   2208:
                   2209:        return rv;
                   2210: }
                   2211:
                   2212: int
1.24      pooka    2213: poll(struct pollfd *fds, nfds_t nfds, int timeout)
1.1       pooka    2214: {
1.3       pooka    2215:        struct timespec ts;
                   2216:        struct timespec *tsp = NULL;
                   2217:
                   2218:        if (timeout != INFTIM) {
                   2219:                ts.tv_sec = timeout / 1000;
1.11      pooka    2220:                ts.tv_nsec = (timeout % 1000) * 1000*1000;
1.3       pooka    2221:
                   2222:                tsp = &ts;
                   2223:        }
1.1       pooka    2224:
1.29      pooka    2225:        return REALPOLLTS(fds, nfds, tsp, NULL);
1.1       pooka    2226: }
1.10      pooka    2227:
1.111     pooka    2228: #ifdef HAVE_KQUEUE
1.10      pooka    2229: int
1.34      pooka    2230: REALKEVENT(int kq, const struct kevent *changelist, size_t nchanges,
                   2231:        struct kevent *eventlist, size_t nevents,
                   2232:        const struct timespec *timeout)
1.10      pooka    2233: {
1.34      pooka    2234:        int (*op_kevent)(int, const struct kevent *, size_t,
                   2235:                struct kevent *, size_t, const struct timespec *);
                   2236:        const struct kevent *ev;
                   2237:        size_t i;
1.10      pooka    2238:
1.34      pooka    2239:        /*
                   2240:         * Check that we don't attempt to kevent rump kernel fd's.
                   2241:         * That needs similar treatment to select/poll, but is slightly
                   2242:         * trickier since we need to manage to different kq descriptors.
                   2243:         * (TODO, in case you're wondering).
                   2244:         */
                   2245:        for (i = 0; i < nchanges; i++) {
                   2246:                ev = &changelist[i];
                   2247:                if (ev->filter == EVFILT_READ || ev->filter == EVFILT_WRITE ||
                   2248:                    ev->filter == EVFILT_VNODE) {
1.66      pooka    2249:                        if (fd_isrump((int)ev->ident)) {
                   2250:                                errno = ENOTSUP;
                   2251:                                return -1;
                   2252:                        }
1.34      pooka    2253:                }
1.27      pooka    2254:        }
1.10      pooka    2255:
1.35      pooka    2256:        op_kevent = GETSYSCALL(host, KEVENT);
1.34      pooka    2257:        return op_kevent(kq, changelist, nchanges, eventlist, nevents, timeout);
1.10      pooka    2258: }
1.111     pooka    2259: #endif /* HAVE_KQUEUE */
1.17      pooka    2260:
                   2261: /*
1.62      pooka    2262:  * mmapping from a rump kernel is not supported, so disallow it.
                   2263:  */
                   2264: void *
                   2265: mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
                   2266: {
                   2267:
                   2268:        if (flags & MAP_FILE && fd_isrump(fd)) {
                   2269:                errno = ENOSYS;
                   2270:                return MAP_FAILED;
                   2271:        }
1.118     pooka    2272:        if (__predict_false(host_mmap == NULL)) {
1.119     pooka    2273:                host_mmap = rumphijack_dlsym(RTLD_NEXT, "mmap");
1.118     pooka    2274:        }
1.62      pooka    2275:        return host_mmap(addr, len, prot, flags, fd, offset);
                   2276: }
                   2277:
1.111     pooka    2278: #ifdef __NetBSD__
1.62      pooka    2279: /*
1.78      pooka    2280:  * these go to one or the other on a per-process configuration
                   2281:  */
                   2282: int __sysctl(const int *, unsigned int, void *, size_t *, const void *, size_t);
                   2283: int
                   2284: __sysctl(const int *name, unsigned int namelen, void *old, size_t *oldlenp,
                   2285:        const void *new, size_t newlen)
                   2286: {
                   2287:        int (*op___sysctl)(const int *, unsigned int, void *, size_t *,
                   2288:            const void *, size_t);
                   2289:
                   2290:        if (rumpsysctl) {
                   2291:                op___sysctl = GETSYSCALL(rump, __SYSCTL);
                   2292:        } else {
                   2293:                op___sysctl = GETSYSCALL(host, __SYSCTL);
                   2294:                /* we haven't inited yet */
                   2295:                if (__predict_false(op___sysctl == NULL)) {
1.84      pooka    2296:                        op___sysctl = rumphijack_dlsym(RTLD_NEXT, "__sysctl");
1.78      pooka    2297:                }
                   2298:        }
                   2299:
                   2300:        return op___sysctl(name, namelen, old, oldlenp, new, newlen);
                   2301: }
1.96      pooka    2302: #endif
1.78      pooka    2303:
                   2304: /*
1.17      pooka    2305:  * Rest are std type calls.
                   2306:  */
                   2307:
1.116     pooka    2308: #ifdef HAVE_UTIMENSAT
1.114     pooka    2309: ATCALL(int, utimensat, DUALCALL_UTIMENSAT,                             \
                   2310:        (int fd, const char *path, const struct timespec t[2], int f),  \
                   2311:        (int, const char *, const struct timespec [2], int),
                   2312:        (fd, path, t, f))
1.116     pooka    2313: #endif
1.114     pooka    2314:
1.17      pooka    2315: FDCALL(int, bind, DUALCALL_BIND,                                       \
                   2316:        (int fd, const struct sockaddr *name, socklen_t namelen),       \
                   2317:        (int, const struct sockaddr *, socklen_t),                      \
                   2318:        (fd, name, namelen))
                   2319:
                   2320: FDCALL(int, connect, DUALCALL_CONNECT,                                 \
                   2321:        (int fd, const struct sockaddr *name, socklen_t namelen),       \
                   2322:        (int, const struct sockaddr *, socklen_t),                      \
                   2323:        (fd, name, namelen))
                   2324:
                   2325: FDCALL(int, getpeername, DUALCALL_GETPEERNAME,                         \
                   2326:        (int fd, struct sockaddr *name, socklen_t *namelen),            \
                   2327:        (int, struct sockaddr *, socklen_t *),                          \
                   2328:        (fd, name, namelen))
                   2329:
                   2330: FDCALL(int, getsockname, DUALCALL_GETSOCKNAME,                                 \
                   2331:        (int fd, struct sockaddr *name, socklen_t *namelen),            \
                   2332:        (int, struct sockaddr *, socklen_t *),                          \
                   2333:        (fd, name, namelen))
                   2334:
                   2335: FDCALL(int, listen, DUALCALL_LISTEN,                                   \
                   2336:        (int fd, int backlog),                                          \
                   2337:        (int, int),                                                     \
                   2338:        (fd, backlog))
                   2339:
                   2340: FDCALL(ssize_t, recvfrom, DUALCALL_RECVFROM,                           \
                   2341:        (int fd, void *buf, size_t len, int flags,                      \
                   2342:            struct sockaddr *from, socklen_t *fromlen),                 \
                   2343:        (int, void *, size_t, int, struct sockaddr *, socklen_t *),     \
                   2344:        (fd, buf, len, flags, from, fromlen))
                   2345:
                   2346: FDCALL(ssize_t, sendto, DUALCALL_SENDTO,                               \
                   2347:        (int fd, const void *buf, size_t len, int flags,                \
                   2348:            const struct sockaddr *to, socklen_t tolen),                \
                   2349:        (int, const void *, size_t, int,                                \
                   2350:            const struct sockaddr *, socklen_t),                        \
                   2351:        (fd, buf, len, flags, to, tolen))
                   2352:
                   2353: FDCALL(int, getsockopt, DUALCALL_GETSOCKOPT,                           \
                   2354:        (int fd, int level, int optn, void *optval, socklen_t *optlen), \
                   2355:        (int, int, int, void *, socklen_t *),                           \
                   2356:        (fd, level, optn, optval, optlen))
                   2357:
                   2358: FDCALL(int, setsockopt, DUALCALL_SETSOCKOPT,                           \
                   2359:        (int fd, int level, int optn,                                   \
                   2360:            const void *optval, socklen_t optlen),                      \
                   2361:        (int, int, int, const void *, socklen_t),                       \
                   2362:        (fd, level, optn, optval, optlen))
                   2363:
                   2364: FDCALL(int, shutdown, DUALCALL_SHUTDOWN,                               \
                   2365:        (int fd, int how),                                              \
                   2366:        (int, int),                                                     \
                   2367:        (fd, how))
                   2368:
1.31      pooka    2369: FDCALL(ssize_t, REALREAD, DUALCALL_READ,                               \
1.17      pooka    2370:        (int fd, void *buf, size_t buflen),                             \
                   2371:        (int, void *, size_t),                                          \
                   2372:        (fd, buf, buflen))
                   2373:
1.100     pooka    2374: #ifdef __linux__
                   2375: ssize_t __read_chk(int, void *, size_t)
                   2376:     __attribute__((alias("read")));
                   2377: #endif
                   2378:
1.18      pooka    2379: FDCALL(ssize_t, readv, DUALCALL_READV,                                         \
1.17      pooka    2380:        (int fd, const struct iovec *iov, int iovcnt),                  \
                   2381:        (int, const struct iovec *, int),                               \
                   2382:        (fd, iov, iovcnt))
                   2383:
1.60      pooka    2384: FDCALL(ssize_t, REALPREAD, DUALCALL_PREAD,                             \
                   2385:        (int fd, void *buf, size_t nbytes, off_t offset),               \
                   2386:        (int, void *, size_t, off_t),                                   \
                   2387:        (fd, buf, nbytes, offset))
                   2388:
                   2389: FDCALL(ssize_t, preadv, DUALCALL_PREADV,                               \
                   2390:        (int fd, const struct iovec *iov, int iovcnt, off_t offset),    \
                   2391:        (int, const struct iovec *, int, off_t),                        \
                   2392:        (fd, iov, iovcnt, offset))
                   2393:
1.17      pooka    2394: FDCALL(ssize_t, writev, DUALCALL_WRITEV,                               \
                   2395:        (int fd, const struct iovec *iov, int iovcnt),                  \
                   2396:        (int, const struct iovec *, int),                               \
                   2397:        (fd, iov, iovcnt))
1.45      pooka    2398:
1.60      pooka    2399: FDCALL(ssize_t, REALPWRITE, DUALCALL_PWRITE,                           \
                   2400:        (int fd, const void *buf, size_t nbytes, off_t offset),         \
                   2401:        (int, const void *, size_t, off_t),                             \
                   2402:        (fd, buf, nbytes, offset))
                   2403:
                   2404: FDCALL(ssize_t, pwritev, DUALCALL_PWRITEV,                             \
                   2405:        (int fd, const struct iovec *iov, int iovcnt, off_t offset),    \
                   2406:        (int, const struct iovec *, int, off_t),                        \
                   2407:        (fd, iov, iovcnt, offset))
                   2408:
1.97      pooka    2409: #ifndef __linux__
1.45      pooka    2410: FDCALL(int, REALFSTAT, DUALCALL_FSTAT,                                 \
                   2411:        (int fd, struct stat *sb),                                      \
                   2412:        (int, struct stat *),                                           \
                   2413:        (fd, sb))
1.97      pooka    2414: #endif
1.45      pooka    2415:
1.111     pooka    2416: #ifdef __NetBSD__
1.45      pooka    2417: FDCALL(int, fstatvfs1, DUALCALL_FSTATVFS1,                             \
                   2418:        (int fd, struct statvfs *buf, int flags),                       \
                   2419:        (int, struct statvfs *, int),                                   \
                   2420:        (fd, buf, flags))
1.96      pooka    2421: #endif
1.45      pooka    2422:
1.61      pooka    2423: FDCALL(off_t, lseek, DUALCALL_LSEEK,                                   \
1.45      pooka    2424:        (int fd, off_t offset, int whence),                             \
                   2425:        (int, off_t, int),                                              \
                   2426:        (fd, offset, whence))
1.96      pooka    2427: #ifdef LSEEK_ALIAS
                   2428: __strong_alias(LSEEK_ALIAS,lseek);
                   2429: #endif
1.45      pooka    2430:
1.98      pooka    2431: #ifndef __linux__
1.45      pooka    2432: FDCALL(int, REALGETDENTS, DUALCALL_GETDENTS,                           \
                   2433:        (int fd, char *buf, size_t nbytes),                             \
                   2434:        (int, char *, size_t),                                          \
                   2435:        (fd, buf, nbytes))
1.98      pooka    2436: #endif
1.45      pooka    2437:
                   2438: FDCALL(int, fchown, DUALCALL_FCHOWN,                                   \
                   2439:        (int fd, uid_t owner, gid_t group),                             \
                   2440:        (int, uid_t, gid_t),                                            \
                   2441:        (fd, owner, group))
                   2442:
                   2443: FDCALL(int, fchmod, DUALCALL_FCHMOD,                                   \
                   2444:        (int fd, mode_t mode),                                          \
                   2445:        (int, mode_t),                                                  \
                   2446:        (fd, mode))
                   2447:
                   2448: FDCALL(int, ftruncate, DUALCALL_FTRUNCATE,                             \
                   2449:        (int fd, off_t length),                                         \
                   2450:        (int, off_t),                                                   \
                   2451:        (fd, length))
                   2452:
                   2453: FDCALL(int, fsync, DUALCALL_FSYNC,                                     \
                   2454:        (int fd),                                                       \
                   2455:        (int),                                                          \
                   2456:        (fd))
                   2457:
1.111     pooka    2458: #ifdef HAVE_FSYNC_RANGE
1.45      pooka    2459: FDCALL(int, fsync_range, DUALCALL_FSYNC_RANGE,                         \
                   2460:        (int fd, int how, off_t start, off_t length),                   \
                   2461:        (int, int, off_t, off_t),                                       \
                   2462:        (fd, how, start, length))
1.96      pooka    2463: #endif
1.45      pooka    2464:
                   2465: FDCALL(int, futimes, DUALCALL_FUTIMES,                                 \
                   2466:        (int fd, const struct timeval *tv),                             \
                   2467:        (int, const struct timeval *),                                  \
                   2468:        (fd, tv))
                   2469:
1.113     enami    2470: FDCALL(int, futimens, DUALCALL_FUTIMENS,                               \
                   2471:        (int fd, const struct timespec *ts),                            \
                   2472:        (int, const struct timespec *),                                 \
                   2473:        (fd, ts))
                   2474:
1.111     pooka    2475: #ifdef HAVE_CHFLAGS
1.60      pooka    2476: FDCALL(int, fchflags, DUALCALL_FCHFLAGS,                               \
                   2477:        (int fd, u_long flags),                                         \
                   2478:        (int, u_long),                                                  \
                   2479:        (fd, flags))
1.96      pooka    2480: #endif
1.60      pooka    2481:
1.45      pooka    2482: /*
                   2483:  * path-based selectors
                   2484:  */
                   2485:
1.97      pooka    2486: #ifndef __linux__
1.45      pooka    2487: PATHCALL(int, REALSTAT, DUALCALL_STAT,                                 \
                   2488:        (const char *path, struct stat *sb),                            \
                   2489:        (const char *, struct stat *),                                  \
                   2490:        (path, sb))
                   2491:
                   2492: PATHCALL(int, REALLSTAT, DUALCALL_LSTAT,                               \
                   2493:        (const char *path, struct stat *sb),                            \
                   2494:        (const char *, struct stat *),                                  \
                   2495:        (path, sb))
1.97      pooka    2496: #endif
1.45      pooka    2497:
                   2498: PATHCALL(int, chown, DUALCALL_CHOWN,                                   \
                   2499:        (const char *path, uid_t owner, gid_t group),                   \
                   2500:        (const char *, uid_t, gid_t),                                   \
                   2501:        (path, owner, group))
                   2502:
                   2503: PATHCALL(int, lchown, DUALCALL_LCHOWN,                                 \
                   2504:        (const char *path, uid_t owner, gid_t group),                   \
                   2505:        (const char *, uid_t, gid_t),                                   \
                   2506:        (path, owner, group))
                   2507:
                   2508: PATHCALL(int, chmod, DUALCALL_CHMOD,                                   \
                   2509:        (const char *path, mode_t mode),                                \
                   2510:        (const char *, mode_t),                                         \
                   2511:        (path, mode))
                   2512:
                   2513: PATHCALL(int, lchmod, DUALCALL_LCHMOD,                                 \
                   2514:        (const char *path, mode_t mode),                                \
                   2515:        (const char *, mode_t),                                         \
                   2516:        (path, mode))
                   2517:
1.111     pooka    2518: #ifdef __NetBSD__
1.45      pooka    2519: PATHCALL(int, statvfs1, DUALCALL_STATVFS1,                             \
                   2520:        (const char *path, struct statvfs *buf, int flags),             \
                   2521:        (const char *, struct statvfs *, int),                          \
                   2522:        (path, buf, flags))
1.96      pooka    2523: #endif
1.45      pooka    2524:
                   2525: PATHCALL(int, unlink, DUALCALL_UNLINK,                                 \
                   2526:        (const char *path),                                             \
                   2527:        (const char *),                                                 \
                   2528:        (path))
                   2529:
                   2530: PATHCALL(int, symlink, DUALCALL_SYMLINK,                               \
1.58      pooka    2531:        (const char *target, const char *path),                         \
1.45      pooka    2532:        (const char *, const char *),                                   \
1.58      pooka    2533:        (target, path))
1.45      pooka    2534:
1.100     pooka    2535: /*
                   2536:  * readlink() can be called from malloc which can be called
                   2537:  * from dlsym() during init
                   2538:  */
                   2539: ssize_t
                   2540: readlink(const char *path, char *buf, size_t bufsiz)
                   2541: {
                   2542:        int (*op_readlink)(const char *, char *, size_t);
                   2543:        enum pathtype pt;
                   2544:
                   2545:        if ((pt = path_isrump(path)) != PATH_HOST) {
                   2546:                op_readlink = GETSYSCALL(rump, READLINK);
                   2547:                if (pt == PATH_RUMP)
                   2548:                        path = path_host2rump(path);
                   2549:        } else {
                   2550:                op_readlink = GETSYSCALL(host, READLINK);
                   2551:        }
                   2552:
                   2553:        if (__predict_false(op_readlink == NULL)) {
                   2554:                errno = ENOENT;
                   2555:                return -1;
                   2556:        }
                   2557:
                   2558:        return op_readlink(path, buf, bufsiz);
                   2559: }
1.45      pooka    2560:
                   2561: PATHCALL(int, mkdir, DUALCALL_MKDIR,                                   \
                   2562:        (const char *path, mode_t mode),                                \
                   2563:        (const char *, mode_t),                                         \
                   2564:        (path, mode))
                   2565:
                   2566: PATHCALL(int, rmdir, DUALCALL_RMDIR,                                   \
                   2567:        (const char *path),                                             \
                   2568:        (const char *),                                                 \
                   2569:        (path))
                   2570:
                   2571: PATHCALL(int, utimes, DUALCALL_UTIMES,                                 \
                   2572:        (const char *path, const struct timeval *tv),                   \
                   2573:        (const char *, const struct timeval *),                         \
                   2574:        (path, tv))
                   2575:
                   2576: PATHCALL(int, lutimes, DUALCALL_LUTIMES,                               \
                   2577:        (const char *path, const struct timeval *tv),                   \
                   2578:        (const char *, const struct timeval *),                         \
                   2579:        (path, tv))
                   2580:
1.111     pooka    2581: #ifdef HAVE_CHFLAGS
1.60      pooka    2582: PATHCALL(int, chflags, DUALCALL_CHFLAGS,                               \
                   2583:        (const char *path, u_long flags),                               \
                   2584:        (const char *, u_long),                                         \
                   2585:        (path, flags))
                   2586:
                   2587: PATHCALL(int, lchflags, DUALCALL_LCHFLAGS,                             \
                   2588:        (const char *path, u_long flags),                               \
                   2589:        (const char *, u_long),                                         \
                   2590:        (path, flags))
1.111     pooka    2591: #endif /* HAVE_CHFLAGS */
1.60      pooka    2592:
1.45      pooka    2593: PATHCALL(int, truncate, DUALCALL_TRUNCATE,                             \
                   2594:        (const char *path, off_t length),                               \
                   2595:        (const char *, off_t),                                          \
                   2596:        (path, length))
1.48      pooka    2597:
1.65      pooka    2598: PATHCALL(int, access, DUALCALL_ACCESS,                                 \
                   2599:        (const char *path, int mode),                                   \
                   2600:        (const char *, int),                                            \
                   2601:        (path, mode))
                   2602:
1.97      pooka    2603: #ifndef __linux__
1.68      pooka    2604: PATHCALL(int, REALMKNOD, DUALCALL_MKNOD,                               \
                   2605:        (const char *path, mode_t mode, dev_t dev),                     \
                   2606:        (const char *, mode_t, dev_t),                                  \
                   2607:        (path, mode, dev))
1.97      pooka    2608: #endif
1.68      pooka    2609:
1.48      pooka    2610: /*
                   2611:  * Note: with mount the decisive parameter is the mount
                   2612:  * destination directory.  This is because we don't really know
                   2613:  * about the "source" directory in a generic call (and besides,
                   2614:  * it might not even exist, cf. nfs).
                   2615:  */
1.111     pooka    2616: #ifdef __NetBSD__
1.48      pooka    2617: PATHCALL(int, REALMOUNT, DUALCALL_MOUNT,                               \
                   2618:        (const char *type, const char *path, int flags,                 \
                   2619:            void *data, size_t dlen),                                   \
                   2620:        (const char *, const char *, int, void *, size_t),              \
                   2621:        (type, path, flags, data, dlen))
                   2622:
                   2623: PATHCALL(int, unmount, DUALCALL_UNMOUNT,                               \
                   2624:        (const char *path, int flags),                                  \
                   2625:        (const char *, int),                                            \
                   2626:        (path, flags))
1.111     pooka    2627: #endif /* __NetBSD__ */
1.78      pooka    2628:
1.111     pooka    2629: #ifdef HAVE___QUOTACTL
1.91      dholland 2630: PATHCALL(int, __quotactl, DUALCALL_QUOTACTL,                           \
                   2631:        (const char *path, struct quotactl_args *args),                 \
                   2632:        (const char *, struct quotactl_args *),                         \
                   2633:        (path, args))
1.111     pooka    2634: #endif /* HAVE___QUOTACTL */
1.80      bouyer   2635:
1.111     pooka    2636: #ifdef __NetBSD__
1.82      pooka    2637: PATHCALL(int, REALGETFH, DUALCALL_GETFH,                               \
                   2638:        (const char *path, void *fhp, size_t *fh_size),                 \
                   2639:        (const char *, void *, size_t *),                               \
                   2640:        (path, fhp, fh_size))
1.97      pooka    2641: #endif
1.82      pooka    2642:
1.78      pooka    2643: /*
                   2644:  * These act different on a per-process vfs configuration
                   2645:  */
                   2646:
1.111     pooka    2647: #ifdef __NetBSD__
1.78      pooka    2648: VFSCALL(VFSBIT_GETVFSSTAT, int, getvfsstat, DUALCALL_GETVFSSTAT,       \
                   2649:        (struct statvfs *buf, size_t buflen, int flags),                \
                   2650:        (struct statvfs *, size_t, int),                                \
                   2651:        (buf, buflen, flags))
1.96      pooka    2652: #endif
1.78      pooka    2653:
1.111     pooka    2654: #ifdef __NetBSD__
1.78      pooka    2655: VFSCALL(VFSBIT_FHCALLS, int, REALFHOPEN, DUALCALL_FHOPEN,              \
                   2656:        (const void *fhp, size_t fh_size, int flags),                   \
                   2657:        (const char *, size_t, int),                                    \
                   2658:        (fhp, fh_size, flags))
                   2659:
                   2660: VFSCALL(VFSBIT_FHCALLS, int, REALFHSTAT, DUALCALL_FHSTAT,              \
                   2661:        (const void *fhp, size_t fh_size, struct stat *sb),             \
                   2662:        (const char *, size_t, struct stat *),                          \
                   2663:        (fhp, fh_size, sb))
                   2664:
                   2665: VFSCALL(VFSBIT_FHCALLS, int, REALFHSTATVFS1, DUALCALL_FHSTATVFS1,      \
                   2666:        (const void *fhp, size_t fh_size, struct statvfs *sb, int flgs),\
                   2667:        (const char *, size_t, struct statvfs *, int),                  \
                   2668:        (fhp, fh_size, sb, flgs))
1.97      pooka    2669: #endif
1.78      pooka    2670:
1.96      pooka    2671:
1.111     pooka    2672: #ifdef __NetBSD__
1.96      pooka    2673:
1.78      pooka    2674: /* finally, put nfssvc here.  "keep the namespace clean" */
                   2675: #include <nfs/rpcv2.h>
                   2676: #include <nfs/nfs.h>
                   2677:
                   2678: int
                   2679: nfssvc(int flags, void *argstructp)
                   2680: {
                   2681:        int (*op_nfssvc)(int, void *);
                   2682:
                   2683:        if (vfsbits & VFSBIT_NFSSVC){
                   2684:                struct nfsd_args *nfsdargs;
                   2685:
                   2686:                /* massage the socket descriptor if necessary */
                   2687:                if (flags == NFSSVC_ADDSOCK) {
                   2688:                        nfsdargs = argstructp;
                   2689:                        nfsdargs->sock = fd_host2rump(nfsdargs->sock);
                   2690:                }
                   2691:                op_nfssvc = GETSYSCALL(rump, NFSSVC);
                   2692:        } else
                   2693:                op_nfssvc = GETSYSCALL(host, NFSSVC);
                   2694:
                   2695:        return op_nfssvc(flags, argstructp);
                   2696: }
1.111     pooka    2697: #endif /* __NetBSD__ */

CVSweb <webmaster@jp.NetBSD.org>