Sat Apr 11 12:54:41 2015 UTC ()
Define the expansion of the VFORK macro, not the symbol `VFORK'.

Fixes hijacking processes that vfork and exec.  Symptom was the child
would spin with read/EAGAIN <-> kevent/EBADF because the inheritance
mechanism relied on setting the holyfd to -1 on fork...which didn't
happen if we didn't hijack vfork.

ok pooka@


(riastradh)
diff -r1.116 -r1.117 src/lib/librumphijack/hijack.c

cvs diff -r1.116 -r1.117 src/lib/librumphijack/hijack.c (switch to unified diff)

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