Deleted Added
full compact
linux_file.c (49788) linux_file.c (49845)
1/*-
2 * Copyright (c) 1994-1995 S�ren Schmidt
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer
10 * in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software withough specific prior written permission
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
1/*-
2 * Copyright (c) 1994-1995 S�ren Schmidt
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer
10 * in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software withough specific prior written permission
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $Id: linux_file.c,v 1.29 1999/08/13 09:27:54 marcel Exp $
28 * $Id: linux_file.c,v 1.30 1999/08/14 18:20:44 marcel Exp $
29 */
30
31#include "opt_compat.h"
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/sysproto.h>
36#include <sys/fcntl.h>
37#include <sys/file.h>
38#include <sys/filedesc.h>
39#include <sys/lock.h>
40#include <sys/proc.h>
41#include <sys/vnode.h>
42#include <sys/malloc.h>
43#include <sys/dirent.h>
44#include <sys/conf.h>
45#include <sys/tty.h>
46
47#include <i386/linux/linux.h>
48#include <i386/linux/linux_proto.h>
49#include <i386/linux/linux_util.h>
50
51int
52linux_creat(struct proc *p, struct linux_creat_args *args)
53{
54 struct open_args /* {
55 char *path;
56 int flags;
57 int mode;
58 } */ bsd_open_args;
59 caddr_t sg;
60
61 sg = stackgap_init();
62 CHECKALTCREAT(p, &sg, args->path);
63
64#ifdef DEBUG
65 printf("Linux-emul(%d): creat(%s, %d)\n",
66 p->p_pid, args->path, args->mode);
67#endif
68 bsd_open_args.path = args->path;
69 bsd_open_args.mode = args->mode;
70 bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC;
71 return open(p, &bsd_open_args);
72}
73
74int
75linux_open(struct proc *p, struct linux_open_args *args)
76{
77 struct open_args /* {
78 char *path;
79 int flags;
80 int mode;
81 } */ bsd_open_args;
82 int error;
83 caddr_t sg;
84
85 sg = stackgap_init();
86
87 if (args->flags & LINUX_O_CREAT)
88 CHECKALTCREAT(p, &sg, args->path);
89 else
90 CHECKALTEXIST(p, &sg, args->path);
91
92#ifdef DEBUG
93 printf("Linux-emul(%d): open(%s, 0x%x, 0x%x)\n",
94 p->p_pid, args->path, args->flags, args->mode);
95#endif
96 bsd_open_args.flags = 0;
97 if (args->flags & LINUX_O_RDONLY)
98 bsd_open_args.flags |= O_RDONLY;
99 if (args->flags & LINUX_O_WRONLY)
100 bsd_open_args.flags |= O_WRONLY;
101 if (args->flags & LINUX_O_RDWR)
102 bsd_open_args.flags |= O_RDWR;
103 if (args->flags & LINUX_O_NDELAY)
104 bsd_open_args.flags |= O_NONBLOCK;
105 if (args->flags & LINUX_O_APPEND)
106 bsd_open_args.flags |= O_APPEND;
107 if (args->flags & LINUX_O_SYNC)
108 bsd_open_args.flags |= O_FSYNC;
109 if (args->flags & LINUX_O_NONBLOCK)
110 bsd_open_args.flags |= O_NONBLOCK;
111 if (args->flags & LINUX_FASYNC)
112 bsd_open_args.flags |= O_ASYNC;
113 if (args->flags & LINUX_O_CREAT)
114 bsd_open_args.flags |= O_CREAT;
115 if (args->flags & LINUX_O_TRUNC)
116 bsd_open_args.flags |= O_TRUNC;
117 if (args->flags & LINUX_O_EXCL)
118 bsd_open_args.flags |= O_EXCL;
119 if (args->flags & LINUX_O_NOCTTY)
120 bsd_open_args.flags |= O_NOCTTY;
121 bsd_open_args.path = args->path;
122 bsd_open_args.mode = args->mode;
123
124 error = open(p, &bsd_open_args);
125 if (!error && !(bsd_open_args.flags & O_NOCTTY) &&
126 SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
127 struct filedesc *fdp = p->p_fd;
128 struct file *fp = fdp->fd_ofiles[p->p_retval[0]];
129
130 if (fp->f_type == DTYPE_VNODE)
131 (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p);
132 }
133#ifdef DEBUG
134 printf("Linux-emul(%d): open returns error %d\n",
135 p->p_pid, error);
136#endif
137 return error;
138}
139
140struct linux_flock {
141 short l_type;
142 short l_whence;
143 linux_off_t l_start;
144 linux_off_t l_len;
145 linux_pid_t l_pid;
146};
147
148static void
149linux_to_bsd_flock(struct linux_flock *linux_flock, struct flock *bsd_flock)
150{
151 switch (linux_flock->l_type) {
152 case LINUX_F_RDLCK:
153 bsd_flock->l_type = F_RDLCK;
154 break;
155 case LINUX_F_WRLCK:
156 bsd_flock->l_type = F_WRLCK;
157 break;
158 case LINUX_F_UNLCK:
159 bsd_flock->l_type = F_UNLCK;
160 break;
161 default:
162 bsd_flock->l_type = -1;
163 break;
164 }
165 bsd_flock->l_whence = linux_flock->l_whence;
166 bsd_flock->l_start = (off_t)linux_flock->l_start;
167 bsd_flock->l_len = (off_t)linux_flock->l_len;
168 bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
169}
170
171static void
172bsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock)
173{
174 switch (bsd_flock->l_type) {
175 case F_RDLCK:
176 linux_flock->l_type = LINUX_F_RDLCK;
177 break;
178 case F_WRLCK:
179 linux_flock->l_type = LINUX_F_WRLCK;
180 break;
181 case F_UNLCK:
182 linux_flock->l_type = LINUX_F_UNLCK;
183 break;
184 }
185 linux_flock->l_whence = bsd_flock->l_whence;
186 linux_flock->l_start = (linux_off_t)bsd_flock->l_start;
187 linux_flock->l_len = (linux_off_t)bsd_flock->l_len;
188 linux_flock->l_pid = (linux_pid_t)bsd_flock->l_pid;
189}
190
191int
192linux_fcntl(struct proc *p, struct linux_fcntl_args *args)
193{
194 int error, result;
195 struct fcntl_args /* {
196 int fd;
197 int cmd;
198 int arg;
199 } */ fcntl_args;
200 struct linux_flock linux_flock;
201 struct flock *bsd_flock;
202 struct filedesc *fdp;
203 struct file *fp;
204 struct vnode *vp;
205 long pgid;
206 struct pgrp *pgrp;
207 struct tty *tp, *(*d_tty) __P((dev_t));
208 caddr_t sg;
209 dev_t dev;
210
211 sg = stackgap_init();
212 bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(struct flock));
213 d_tty = NULL;
214
215#ifdef DEBUG
216 printf("Linux-emul(%d): fcntl(%d, %08x, *)\n",
217 p->p_pid, args->fd, args->cmd);
218#endif
219 fcntl_args.fd = args->fd;
29 */
30
31#include "opt_compat.h"
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/sysproto.h>
36#include <sys/fcntl.h>
37#include <sys/file.h>
38#include <sys/filedesc.h>
39#include <sys/lock.h>
40#include <sys/proc.h>
41#include <sys/vnode.h>
42#include <sys/malloc.h>
43#include <sys/dirent.h>
44#include <sys/conf.h>
45#include <sys/tty.h>
46
47#include <i386/linux/linux.h>
48#include <i386/linux/linux_proto.h>
49#include <i386/linux/linux_util.h>
50
51int
52linux_creat(struct proc *p, struct linux_creat_args *args)
53{
54 struct open_args /* {
55 char *path;
56 int flags;
57 int mode;
58 } */ bsd_open_args;
59 caddr_t sg;
60
61 sg = stackgap_init();
62 CHECKALTCREAT(p, &sg, args->path);
63
64#ifdef DEBUG
65 printf("Linux-emul(%d): creat(%s, %d)\n",
66 p->p_pid, args->path, args->mode);
67#endif
68 bsd_open_args.path = args->path;
69 bsd_open_args.mode = args->mode;
70 bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC;
71 return open(p, &bsd_open_args);
72}
73
74int
75linux_open(struct proc *p, struct linux_open_args *args)
76{
77 struct open_args /* {
78 char *path;
79 int flags;
80 int mode;
81 } */ bsd_open_args;
82 int error;
83 caddr_t sg;
84
85 sg = stackgap_init();
86
87 if (args->flags & LINUX_O_CREAT)
88 CHECKALTCREAT(p, &sg, args->path);
89 else
90 CHECKALTEXIST(p, &sg, args->path);
91
92#ifdef DEBUG
93 printf("Linux-emul(%d): open(%s, 0x%x, 0x%x)\n",
94 p->p_pid, args->path, args->flags, args->mode);
95#endif
96 bsd_open_args.flags = 0;
97 if (args->flags & LINUX_O_RDONLY)
98 bsd_open_args.flags |= O_RDONLY;
99 if (args->flags & LINUX_O_WRONLY)
100 bsd_open_args.flags |= O_WRONLY;
101 if (args->flags & LINUX_O_RDWR)
102 bsd_open_args.flags |= O_RDWR;
103 if (args->flags & LINUX_O_NDELAY)
104 bsd_open_args.flags |= O_NONBLOCK;
105 if (args->flags & LINUX_O_APPEND)
106 bsd_open_args.flags |= O_APPEND;
107 if (args->flags & LINUX_O_SYNC)
108 bsd_open_args.flags |= O_FSYNC;
109 if (args->flags & LINUX_O_NONBLOCK)
110 bsd_open_args.flags |= O_NONBLOCK;
111 if (args->flags & LINUX_FASYNC)
112 bsd_open_args.flags |= O_ASYNC;
113 if (args->flags & LINUX_O_CREAT)
114 bsd_open_args.flags |= O_CREAT;
115 if (args->flags & LINUX_O_TRUNC)
116 bsd_open_args.flags |= O_TRUNC;
117 if (args->flags & LINUX_O_EXCL)
118 bsd_open_args.flags |= O_EXCL;
119 if (args->flags & LINUX_O_NOCTTY)
120 bsd_open_args.flags |= O_NOCTTY;
121 bsd_open_args.path = args->path;
122 bsd_open_args.mode = args->mode;
123
124 error = open(p, &bsd_open_args);
125 if (!error && !(bsd_open_args.flags & O_NOCTTY) &&
126 SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
127 struct filedesc *fdp = p->p_fd;
128 struct file *fp = fdp->fd_ofiles[p->p_retval[0]];
129
130 if (fp->f_type == DTYPE_VNODE)
131 (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p);
132 }
133#ifdef DEBUG
134 printf("Linux-emul(%d): open returns error %d\n",
135 p->p_pid, error);
136#endif
137 return error;
138}
139
140struct linux_flock {
141 short l_type;
142 short l_whence;
143 linux_off_t l_start;
144 linux_off_t l_len;
145 linux_pid_t l_pid;
146};
147
148static void
149linux_to_bsd_flock(struct linux_flock *linux_flock, struct flock *bsd_flock)
150{
151 switch (linux_flock->l_type) {
152 case LINUX_F_RDLCK:
153 bsd_flock->l_type = F_RDLCK;
154 break;
155 case LINUX_F_WRLCK:
156 bsd_flock->l_type = F_WRLCK;
157 break;
158 case LINUX_F_UNLCK:
159 bsd_flock->l_type = F_UNLCK;
160 break;
161 default:
162 bsd_flock->l_type = -1;
163 break;
164 }
165 bsd_flock->l_whence = linux_flock->l_whence;
166 bsd_flock->l_start = (off_t)linux_flock->l_start;
167 bsd_flock->l_len = (off_t)linux_flock->l_len;
168 bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
169}
170
171static void
172bsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock)
173{
174 switch (bsd_flock->l_type) {
175 case F_RDLCK:
176 linux_flock->l_type = LINUX_F_RDLCK;
177 break;
178 case F_WRLCK:
179 linux_flock->l_type = LINUX_F_WRLCK;
180 break;
181 case F_UNLCK:
182 linux_flock->l_type = LINUX_F_UNLCK;
183 break;
184 }
185 linux_flock->l_whence = bsd_flock->l_whence;
186 linux_flock->l_start = (linux_off_t)bsd_flock->l_start;
187 linux_flock->l_len = (linux_off_t)bsd_flock->l_len;
188 linux_flock->l_pid = (linux_pid_t)bsd_flock->l_pid;
189}
190
191int
192linux_fcntl(struct proc *p, struct linux_fcntl_args *args)
193{
194 int error, result;
195 struct fcntl_args /* {
196 int fd;
197 int cmd;
198 int arg;
199 } */ fcntl_args;
200 struct linux_flock linux_flock;
201 struct flock *bsd_flock;
202 struct filedesc *fdp;
203 struct file *fp;
204 struct vnode *vp;
205 long pgid;
206 struct pgrp *pgrp;
207 struct tty *tp, *(*d_tty) __P((dev_t));
208 caddr_t sg;
209 dev_t dev;
210
211 sg = stackgap_init();
212 bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(struct flock));
213 d_tty = NULL;
214
215#ifdef DEBUG
216 printf("Linux-emul(%d): fcntl(%d, %08x, *)\n",
217 p->p_pid, args->fd, args->cmd);
218#endif
219 fcntl_args.fd = args->fd;
220 fcntl_args.arg = 0;
221
222 switch (args->cmd) {
223 case LINUX_F_DUPFD:
224 fcntl_args.cmd = F_DUPFD;
220
221 switch (args->cmd) {
222 case LINUX_F_DUPFD:
223 fcntl_args.cmd = F_DUPFD;
224 fcntl_args.arg = args->arg;
225 return fcntl(p, &fcntl_args);
226
227 case LINUX_F_GETFD:
228 fcntl_args.cmd = F_GETFD;
229 return fcntl(p, &fcntl_args);
230
231 case LINUX_F_SETFD:
232 fcntl_args.cmd = F_SETFD;
225 return fcntl(p, &fcntl_args);
226
227 case LINUX_F_GETFD:
228 fcntl_args.cmd = F_GETFD;
229 return fcntl(p, &fcntl_args);
230
231 case LINUX_F_SETFD:
232 fcntl_args.cmd = F_SETFD;
233 fcntl_args.arg = args->arg;
233 return fcntl(p, &fcntl_args);
234
235 case LINUX_F_GETFL:
236 fcntl_args.cmd = F_GETFL;
237 error = fcntl(p, &fcntl_args);
238 result = p->p_retval[0];
239 p->p_retval[0] = 0;
240 if (result & O_RDONLY) p->p_retval[0] |= LINUX_O_RDONLY;
241 if (result & O_WRONLY) p->p_retval[0] |= LINUX_O_WRONLY;
242 if (result & O_RDWR) p->p_retval[0] |= LINUX_O_RDWR;
243 if (result & O_NDELAY) p->p_retval[0] |= LINUX_O_NONBLOCK;
244 if (result & O_APPEND) p->p_retval[0] |= LINUX_O_APPEND;
245 if (result & O_FSYNC) p->p_retval[0] |= LINUX_O_SYNC;
246 if (result & O_ASYNC) p->p_retval[0] |= LINUX_FASYNC;
247 return error;
248
249 case LINUX_F_SETFL:
234 return fcntl(p, &fcntl_args);
235
236 case LINUX_F_GETFL:
237 fcntl_args.cmd = F_GETFL;
238 error = fcntl(p, &fcntl_args);
239 result = p->p_retval[0];
240 p->p_retval[0] = 0;
241 if (result & O_RDONLY) p->p_retval[0] |= LINUX_O_RDONLY;
242 if (result & O_WRONLY) p->p_retval[0] |= LINUX_O_WRONLY;
243 if (result & O_RDWR) p->p_retval[0] |= LINUX_O_RDWR;
244 if (result & O_NDELAY) p->p_retval[0] |= LINUX_O_NONBLOCK;
245 if (result & O_APPEND) p->p_retval[0] |= LINUX_O_APPEND;
246 if (result & O_FSYNC) p->p_retval[0] |= LINUX_O_SYNC;
247 if (result & O_ASYNC) p->p_retval[0] |= LINUX_FASYNC;
248 return error;
249
250 case LINUX_F_SETFL:
251 fcntl_args.arg = 0;
250 if (args->arg & LINUX_O_NDELAY) fcntl_args.arg |= O_NONBLOCK;
251 if (args->arg & LINUX_O_APPEND) fcntl_args.arg |= O_APPEND;
252 if (args->arg & LINUX_O_SYNC) fcntl_args.arg |= O_FSYNC;
253 if (args->arg & LINUX_FASYNC) fcntl_args.arg |= O_ASYNC;
254 fcntl_args.cmd = F_SETFL;
255 return fcntl(p, &fcntl_args);
256
257 case LINUX_F_GETLK:
258 if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
259 sizeof(struct linux_flock))))
260 return error;
261 linux_to_bsd_flock(&linux_flock, bsd_flock);
262 fcntl_args.cmd = F_GETLK;
263 fcntl_args.arg = (int)bsd_flock;
264 error = fcntl(p, &fcntl_args);
265 if (error)
266 return error;
267 bsd_to_linux_flock(bsd_flock, &linux_flock);
268 return copyout((caddr_t)&linux_flock, (caddr_t)args->arg,
269 sizeof(struct linux_flock));
270
271 case LINUX_F_SETLK:
272 if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
273 sizeof(struct linux_flock))))
274 return error;
275 linux_to_bsd_flock(&linux_flock, bsd_flock);
276 fcntl_args.cmd = F_SETLK;
277 fcntl_args.arg = (int)bsd_flock;
278 return fcntl(p, &fcntl_args);
279
280 case LINUX_F_SETLKW:
281 if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
282 sizeof(struct linux_flock))))
283 return error;
284 linux_to_bsd_flock(&linux_flock, bsd_flock);
285 fcntl_args.cmd = F_SETLKW;
286 fcntl_args.arg = (int)bsd_flock;
287 return fcntl(p, &fcntl_args);
288
289 case LINUX_F_SETOWN:
290 case LINUX_F_GETOWN:
291 /*
292 * We need to route around the normal fcntl() for these calls,
293 * since it uses TIOC{G,S}PGRP, which is too restrictive for
294 * Linux F_{G,S}ETOWN semantics. For sockets, this problem
295 * does not exist.
296 */
297 fdp = p->p_fd;
298 if ((u_int)args->fd >= fdp->fd_nfiles ||
299 (fp = fdp->fd_ofiles[args->fd]) == NULL)
300 return EBADF;
301 if (fp->f_type == DTYPE_SOCKET) {
302 fcntl_args.cmd = args->cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN;
303 fcntl_args.arg = args->arg;
304 return fcntl(p, &fcntl_args);
305 }
306 vp = (struct vnode *)fp->f_data;
307 dev = vn_todev(vp);
308 if (vp->v_type != VCHR || dev == NODEV)
309 return EINVAL;
310 d_tty = devsw(dev)->d_devtotty;
311 if (!d_tty || (!(tp = (*d_tty)(dev))))
312 return EINVAL;
313 if (args->cmd == LINUX_F_GETOWN) {
314 p->p_retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
315 return 0;
316 }
317 if ((long)args->arg <= 0) {
318 pgid = -(long)args->arg;
319 } else {
320 struct proc *p1 = pfind((long)args->arg);
321 if (p1 == 0)
322 return (ESRCH);
323 pgid = (long)p1->p_pgrp->pg_id;
324 }
325 pgrp = pgfind(pgid);
326 if (pgrp == NULL || pgrp->pg_session != p->p_session)
327 return EPERM;
328 tp->t_pgrp = pgrp;
329 return 0;
330 }
331 return EINVAL;
332}
333
334int
335linux_lseek(struct proc *p, struct linux_lseek_args *args)
336{
337
338 struct lseek_args /* {
339 int fd;
340 int pad;
341 off_t offset;
342 int whence;
343 } */ tmp_args;
344 int error;
345
346#ifdef DEBUG
347 printf("Linux-emul(%ld): lseek(%d, %ld, %d)\n",
348 (long)p->p_pid, args->fdes, args->off, args->whence);
349#endif
350 tmp_args.fd = args->fdes;
351 tmp_args.offset = (off_t)args->off;
352 tmp_args.whence = args->whence;
353 error = lseek(p, &tmp_args);
354 return error;
355}
356
357int
358linux_llseek(struct proc *p, struct linux_llseek_args *args)
359{
360 struct lseek_args bsd_args;
361 int error;
362 off_t off;
363
364#ifdef DEBUG
365 printf("Linux-emul(%d): llseek(%d, %d:%d, %d)\n",
366 p->p_pid, args->fd, args->ohigh, args->olow, args->whence);
367#endif
368 off = (args->olow) | (((off_t) args->ohigh) << 32);
369
370 bsd_args.fd = args->fd;
371 bsd_args.offset = off;
372 bsd_args.whence = args->whence;
373
374 if ((error = lseek(p, &bsd_args)))
375 return error;
376
377 if ((error = copyout(p->p_retval, (caddr_t)args->res, sizeof (off_t))))
378 return error;
379
380 p->p_retval[0] = 0;
381 return 0;
382}
383
384
385struct linux_dirent {
386 long dino;
387 linux_off_t doff;
388 unsigned short dreclen;
389 char dname[LINUX_NAME_MAX + 1];
390};
391
392#define LINUX_RECLEN(de,namlen) \
393 ALIGN((((char *)&(de)->dname - (char *)de) + (namlen) + 1))
394
395int
396linux_readdir(struct proc *p, struct linux_readdir_args *args)
397{
398 struct linux_getdents_args lda;
399
400 lda.fd = args->fd;
401 lda.dent = args->dent;
402 lda.count = 1;
403 return linux_getdents(p, &lda);
404}
405
406int
407linux_getdents(struct proc *p, struct linux_getdents_args *args)
408{
409 register struct dirent *bdp;
410 struct vnode *vp;
411 caddr_t inp, buf; /* BSD-format */
412 int len, reclen; /* BSD-format */
413 caddr_t outp; /* Linux-format */
414 int resid, linuxreclen=0; /* Linux-format */
415 struct file *fp;
416 struct uio auio;
417 struct iovec aiov;
418 struct vattr va;
419 off_t off;
420 struct linux_dirent linux_dirent;
421 int buflen, error, eofflag, nbytes, justone;
422 u_long *cookies = NULL, *cookiep;
423 int ncookies;
424
425#ifdef DEBUG
426 printf("Linux-emul(%d): getdents(%d, *, %d)\n",
427 p->p_pid, args->fd, args->count);
428#endif
429 if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0) {
430 return (error);
431 }
432
433 if ((fp->f_flag & FREAD) == 0)
434 return (EBADF);
435
436 vp = (struct vnode *) fp->f_data;
437
438 if (vp->v_type != VDIR)
439 return (EINVAL);
440
441 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) {
442 return error;
443 }
444
445 nbytes = args->count;
446 if (nbytes == 1) {
447 nbytes = sizeof (struct linux_dirent);
448 justone = 1;
449 }
450 else
451 justone = 0;
452
453 off = fp->f_offset;
454#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */
455 buflen = max(DIRBLKSIZ, nbytes);
456 buflen = min(buflen, MAXBSIZE);
457 buf = malloc(buflen, M_TEMP, M_WAITOK);
458 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
459again:
460 aiov.iov_base = buf;
461 aiov.iov_len = buflen;
462 auio.uio_iov = &aiov;
463 auio.uio_iovcnt = 1;
464 auio.uio_rw = UIO_READ;
465 auio.uio_segflg = UIO_SYSSPACE;
466 auio.uio_procp = p;
467 auio.uio_resid = buflen;
468 auio.uio_offset = off;
469
470 if (cookies) {
471 free(cookies, M_TEMP);
472 cookies = NULL;
473 }
474
475 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies);
476 if (error) {
477 goto out;
478 }
479
480 inp = buf;
481 outp = (caddr_t) args->dent;
482 resid = nbytes;
483 if ((len = buflen - auio.uio_resid) <= 0) {
484 goto eof;
485 }
486
487 cookiep = cookies;
488
489 if (cookies) {
490 /*
491 * When using cookies, the vfs has the option of reading from
492 * a different offset than that supplied (UFS truncates the
493 * offset to a block boundary to make sure that it never reads
494 * partway through a directory entry, even if the directory
495 * has been compacted).
496 */
497 while (len > 0 && ncookies > 0 && *cookiep <= off) {
498 bdp = (struct dirent *) inp;
499 len -= bdp->d_reclen;
500 inp += bdp->d_reclen;
501 cookiep++;
502 ncookies--;
503 }
504 }
505
506 while (len > 0) {
507 if (cookiep && ncookies == 0)
508 break;
509 bdp = (struct dirent *) inp;
510 reclen = bdp->d_reclen;
511 if (reclen & 3) {
512 printf("linux_readdir: reclen=%d\n", reclen);
513 error = EFAULT;
514 goto out;
515 }
516
517 if (bdp->d_fileno == 0) {
518 inp += reclen;
519 if (cookiep) {
520 off = *cookiep++;
521 ncookies--;
522 } else
523 off += reclen;
524 len -= reclen;
525 continue;
526 }
527 linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen);
528 if (reclen > len || resid < linuxreclen) {
529 outp++;
530 break;
531 }
532 linux_dirent.dino = (long) bdp->d_fileno;
533 if (justone) {
534 /*
535 * old linux-style readdir usage.
536 */
537 linux_dirent.doff = (linux_off_t) linuxreclen;
538 linux_dirent.dreclen = (u_short) bdp->d_namlen;
539 } else {
540 linux_dirent.doff = (linux_off_t) off;
541 linux_dirent.dreclen = (u_short) linuxreclen;
542 }
543 strcpy(linux_dirent.dname, bdp->d_name);
544 if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) {
545 goto out;
546 }
547 inp += reclen;
548 if (cookiep) {
549 off = *cookiep++;
550 ncookies--;
551 } else
552 off += reclen;
553 outp += linuxreclen;
554 resid -= linuxreclen;
555 len -= reclen;
556 if (justone)
557 break;
558 }
559
560 if (outp == (caddr_t) args->dent)
561 goto again;
562 fp->f_offset = off;
563
564 if (justone)
565 nbytes = resid + linuxreclen;
566
567eof:
568 p->p_retval[0] = nbytes - resid;
569out:
570 if (cookies)
571 free(cookies, M_TEMP);
572 VOP_UNLOCK(vp, 0, p);
573 free(buf, M_TEMP);
574 return error;
575}
576
577/*
578 * These exist mainly for hooks for doing /compat/linux translation.
579 */
580
581int
582linux_access(struct proc *p, struct linux_access_args *args)
583{
584 struct access_args bsd;
585 caddr_t sg;
586
587 sg = stackgap_init();
588 CHECKALTEXIST(p, &sg, args->path);
589
590#ifdef DEBUG
591 printf("Linux-emul(%d): access(%s, %d)\n",
592 p->p_pid, args->path, args->flags);
593#endif
594 bsd.path = args->path;
595 bsd.flags = args->flags;
596
597 return access(p, &bsd);
598}
599
600int
601linux_unlink(struct proc *p, struct linux_unlink_args *args)
602{
603 struct unlink_args bsd;
604 caddr_t sg;
605
606 sg = stackgap_init();
607 CHECKALTEXIST(p, &sg, args->path);
608
609#ifdef DEBUG
610 printf("Linux-emul(%d): unlink(%s)\n",
611 p->p_pid, args->path);
612#endif
613 bsd.path = args->path;
614
615 return unlink(p, &bsd);
616}
617
618int
619linux_chdir(struct proc *p, struct linux_chdir_args *args)
620{
621 struct chdir_args bsd;
622 caddr_t sg;
623
624 sg = stackgap_init();
625 CHECKALTEXIST(p, &sg, args->path);
626
627#ifdef DEBUG
628 printf("Linux-emul(%d): chdir(%s)\n",
629 p->p_pid, args->path);
630#endif
631 bsd.path = args->path;
632
633 return chdir(p, &bsd);
634}
635
636int
637linux_chmod(struct proc *p, struct linux_chmod_args *args)
638{
639 struct chmod_args bsd;
640 caddr_t sg;
641
642 sg = stackgap_init();
643 CHECKALTEXIST(p, &sg, args->path);
644
645#ifdef DEBUG
646 printf("Linux-emul(%d): chmod(%s, %d)\n",
647 p->p_pid, args->path, args->mode);
648#endif
649 bsd.path = args->path;
650 bsd.mode = args->mode;
651
652 return chmod(p, &bsd);
653}
654
655int
656linux_chown(struct proc *p, struct linux_chown_args *args)
657{
658 struct chown_args bsd;
659 caddr_t sg;
660
661 sg = stackgap_init();
662 CHECKALTEXIST(p, &sg, args->path);
663
664#ifdef DEBUG
665 printf("Linux-emul(%d): chown(%s, %d, %d)\n",
666 p->p_pid, args->path, args->uid, args->gid);
667#endif
668 bsd.path = args->path;
669 /* XXX size casts here */
670 bsd.uid = args->uid;
671 bsd.gid = args->gid;
672
673 return chown(p, &bsd);
674}
675
676int
677linux_lchown(struct proc *p, struct linux_lchown_args *args)
678{
679 struct lchown_args bsd;
680 caddr_t sg;
681
682 sg = stackgap_init();
683 CHECKALTEXIST(p, &sg, args->path);
684
685#ifdef DEBUG
686 printf("Linux-emul(%d): lchown(%s, %d, %d)\n",
687 p->p_pid, args->path, args->uid, args->gid);
688#endif
689 bsd.path = args->path;
690 /* XXX size casts here */
691 bsd.uid = args->uid;
692 bsd.gid = args->gid;
693
694 return lchown(p, &bsd);
695}
696
697int
698linux_mkdir(struct proc *p, struct linux_mkdir_args *args)
699{
700 struct mkdir_args bsd;
701 caddr_t sg;
702
703 sg = stackgap_init();
704 CHECKALTCREAT(p, &sg, args->path);
705
706#ifdef DEBUG
707 printf("Linux-emul(%d): mkdir(%s, %d)\n",
708 p->p_pid, args->path, args->mode);
709#endif
710 bsd.path = args->path;
711 bsd.mode = args->mode;
712
713 return mkdir(p, &bsd);
714}
715
716int
717linux_rmdir(struct proc *p, struct linux_rmdir_args *args)
718{
719 struct rmdir_args bsd;
720 caddr_t sg;
721
722 sg = stackgap_init();
723 CHECKALTEXIST(p, &sg, args->path);
724
725#ifdef DEBUG
726 printf("Linux-emul(%d): rmdir(%s)\n",
727 p->p_pid, args->path);
728#endif
729 bsd.path = args->path;
730
731 return rmdir(p, &bsd);
732}
733
734int
735linux_rename(struct proc *p, struct linux_rename_args *args)
736{
737 struct rename_args bsd;
738 caddr_t sg;
739
740 sg = stackgap_init();
741 CHECKALTEXIST(p, &sg, args->from);
742 CHECKALTCREAT(p, &sg, args->to);
743
744#ifdef DEBUG
745 printf("Linux-emul(%d): rename(%s, %s)\n",
746 p->p_pid, args->from, args->to);
747#endif
748 bsd.from = args->from;
749 bsd.to = args->to;
750
751 return rename(p, &bsd);
752}
753
754int
755linux_symlink(struct proc *p, struct linux_symlink_args *args)
756{
757 struct symlink_args bsd;
758 caddr_t sg;
759
760 sg = stackgap_init();
761 CHECKALTEXIST(p, &sg, args->path);
762 CHECKALTCREAT(p, &sg, args->to);
763
764#ifdef DEBUG
765 printf("Linux-emul(%d): symlink(%s, %s)\n",
766 p->p_pid, args->path, args->to);
767#endif
768 bsd.path = args->path;
769 bsd.link = args->to;
770
771 return symlink(p, &bsd);
772}
773
774int
775linux_execve(struct proc *p, struct linux_execve_args *args)
776{
777 struct execve_args bsd;
778 caddr_t sg;
779
780 sg = stackgap_init();
781 CHECKALTEXIST(p, &sg, args->path);
782
783#ifdef DEBUG
784 printf("Linux-emul(%d): execve(%s)\n",
785 p->p_pid, args->path);
786#endif
787 bsd.fname = args->path;
788 bsd.argv = args->argp;
789 bsd.envv = args->envp;
790
791 return execve(p, &bsd);
792}
793
794int
795linux_readlink(struct proc *p, struct linux_readlink_args *args)
796{
797 struct readlink_args bsd;
798 caddr_t sg;
799
800 sg = stackgap_init();
801 CHECKALTEXIST(p, &sg, args->name);
802
803#ifdef DEBUG
804 printf("Linux-emul(%ld): readlink(%s, %p, %d)\n",
805 (long)p->p_pid, args->name, (void *)args->buf, args->count);
806#endif
807 bsd.path = args->name;
808 bsd.buf = args->buf;
809 bsd.count = args->count;
810
811 return readlink(p, &bsd);
812}
813
814int
815linux_truncate(struct proc *p, struct linux_truncate_args *args)
816{
817 struct truncate_args bsd;
818 caddr_t sg;
819
820 sg = stackgap_init();
821 CHECKALTEXIST(p, &sg, args->path);
822
823#ifdef DEBUG
824 printf("Linux-emul(%d): truncate(%s, %ld)\n",
825 p->p_pid, args->path, args->length);
826#endif
827 bsd.path = args->path;
828 bsd.length = args->length;
829
830 return truncate(p, &bsd);
831}
832
833int
834linux_link(struct proc *p, struct linux_link_args *args)
835{
836 struct link_args bsd;
837 caddr_t sg;
838
839 sg = stackgap_init();
840 CHECKALTEXIST(p, &sg, args->path);
841 CHECKALTCREAT(p, &sg, args->to);
842
843#ifdef DEBUG
844 printf("Linux-emul(%d): link(%s, %s)\n", p->p_pid, args->path, args->to);
845#endif
846
847 bsd.path = args->path;
848 bsd.link = args->to;
849
850 return link(p, &bsd);
851}
852
853int
854linux_getcwd(struct proc *p, struct linux_getcwd_args *args)
855{
856 struct __getcwd_args bsd;
857
858#ifdef DEBUG
859 printf("Linux-emul(%d): getcwd(%p, %ld)\n",
860 p->p_pid, args->buf, args->bufsize);
861#endif
862
863 bsd.buf = args->buf;
864 bsd.buflen = args->bufsize;
865 return __getcwd(p, &bsd);
866}
252 if (args->arg & LINUX_O_NDELAY) fcntl_args.arg |= O_NONBLOCK;
253 if (args->arg & LINUX_O_APPEND) fcntl_args.arg |= O_APPEND;
254 if (args->arg & LINUX_O_SYNC) fcntl_args.arg |= O_FSYNC;
255 if (args->arg & LINUX_FASYNC) fcntl_args.arg |= O_ASYNC;
256 fcntl_args.cmd = F_SETFL;
257 return fcntl(p, &fcntl_args);
258
259 case LINUX_F_GETLK:
260 if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
261 sizeof(struct linux_flock))))
262 return error;
263 linux_to_bsd_flock(&linux_flock, bsd_flock);
264 fcntl_args.cmd = F_GETLK;
265 fcntl_args.arg = (int)bsd_flock;
266 error = fcntl(p, &fcntl_args);
267 if (error)
268 return error;
269 bsd_to_linux_flock(bsd_flock, &linux_flock);
270 return copyout((caddr_t)&linux_flock, (caddr_t)args->arg,
271 sizeof(struct linux_flock));
272
273 case LINUX_F_SETLK:
274 if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
275 sizeof(struct linux_flock))))
276 return error;
277 linux_to_bsd_flock(&linux_flock, bsd_flock);
278 fcntl_args.cmd = F_SETLK;
279 fcntl_args.arg = (int)bsd_flock;
280 return fcntl(p, &fcntl_args);
281
282 case LINUX_F_SETLKW:
283 if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
284 sizeof(struct linux_flock))))
285 return error;
286 linux_to_bsd_flock(&linux_flock, bsd_flock);
287 fcntl_args.cmd = F_SETLKW;
288 fcntl_args.arg = (int)bsd_flock;
289 return fcntl(p, &fcntl_args);
290
291 case LINUX_F_SETOWN:
292 case LINUX_F_GETOWN:
293 /*
294 * We need to route around the normal fcntl() for these calls,
295 * since it uses TIOC{G,S}PGRP, which is too restrictive for
296 * Linux F_{G,S}ETOWN semantics. For sockets, this problem
297 * does not exist.
298 */
299 fdp = p->p_fd;
300 if ((u_int)args->fd >= fdp->fd_nfiles ||
301 (fp = fdp->fd_ofiles[args->fd]) == NULL)
302 return EBADF;
303 if (fp->f_type == DTYPE_SOCKET) {
304 fcntl_args.cmd = args->cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN;
305 fcntl_args.arg = args->arg;
306 return fcntl(p, &fcntl_args);
307 }
308 vp = (struct vnode *)fp->f_data;
309 dev = vn_todev(vp);
310 if (vp->v_type != VCHR || dev == NODEV)
311 return EINVAL;
312 d_tty = devsw(dev)->d_devtotty;
313 if (!d_tty || (!(tp = (*d_tty)(dev))))
314 return EINVAL;
315 if (args->cmd == LINUX_F_GETOWN) {
316 p->p_retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
317 return 0;
318 }
319 if ((long)args->arg <= 0) {
320 pgid = -(long)args->arg;
321 } else {
322 struct proc *p1 = pfind((long)args->arg);
323 if (p1 == 0)
324 return (ESRCH);
325 pgid = (long)p1->p_pgrp->pg_id;
326 }
327 pgrp = pgfind(pgid);
328 if (pgrp == NULL || pgrp->pg_session != p->p_session)
329 return EPERM;
330 tp->t_pgrp = pgrp;
331 return 0;
332 }
333 return EINVAL;
334}
335
336int
337linux_lseek(struct proc *p, struct linux_lseek_args *args)
338{
339
340 struct lseek_args /* {
341 int fd;
342 int pad;
343 off_t offset;
344 int whence;
345 } */ tmp_args;
346 int error;
347
348#ifdef DEBUG
349 printf("Linux-emul(%ld): lseek(%d, %ld, %d)\n",
350 (long)p->p_pid, args->fdes, args->off, args->whence);
351#endif
352 tmp_args.fd = args->fdes;
353 tmp_args.offset = (off_t)args->off;
354 tmp_args.whence = args->whence;
355 error = lseek(p, &tmp_args);
356 return error;
357}
358
359int
360linux_llseek(struct proc *p, struct linux_llseek_args *args)
361{
362 struct lseek_args bsd_args;
363 int error;
364 off_t off;
365
366#ifdef DEBUG
367 printf("Linux-emul(%d): llseek(%d, %d:%d, %d)\n",
368 p->p_pid, args->fd, args->ohigh, args->olow, args->whence);
369#endif
370 off = (args->olow) | (((off_t) args->ohigh) << 32);
371
372 bsd_args.fd = args->fd;
373 bsd_args.offset = off;
374 bsd_args.whence = args->whence;
375
376 if ((error = lseek(p, &bsd_args)))
377 return error;
378
379 if ((error = copyout(p->p_retval, (caddr_t)args->res, sizeof (off_t))))
380 return error;
381
382 p->p_retval[0] = 0;
383 return 0;
384}
385
386
387struct linux_dirent {
388 long dino;
389 linux_off_t doff;
390 unsigned short dreclen;
391 char dname[LINUX_NAME_MAX + 1];
392};
393
394#define LINUX_RECLEN(de,namlen) \
395 ALIGN((((char *)&(de)->dname - (char *)de) + (namlen) + 1))
396
397int
398linux_readdir(struct proc *p, struct linux_readdir_args *args)
399{
400 struct linux_getdents_args lda;
401
402 lda.fd = args->fd;
403 lda.dent = args->dent;
404 lda.count = 1;
405 return linux_getdents(p, &lda);
406}
407
408int
409linux_getdents(struct proc *p, struct linux_getdents_args *args)
410{
411 register struct dirent *bdp;
412 struct vnode *vp;
413 caddr_t inp, buf; /* BSD-format */
414 int len, reclen; /* BSD-format */
415 caddr_t outp; /* Linux-format */
416 int resid, linuxreclen=0; /* Linux-format */
417 struct file *fp;
418 struct uio auio;
419 struct iovec aiov;
420 struct vattr va;
421 off_t off;
422 struct linux_dirent linux_dirent;
423 int buflen, error, eofflag, nbytes, justone;
424 u_long *cookies = NULL, *cookiep;
425 int ncookies;
426
427#ifdef DEBUG
428 printf("Linux-emul(%d): getdents(%d, *, %d)\n",
429 p->p_pid, args->fd, args->count);
430#endif
431 if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0) {
432 return (error);
433 }
434
435 if ((fp->f_flag & FREAD) == 0)
436 return (EBADF);
437
438 vp = (struct vnode *) fp->f_data;
439
440 if (vp->v_type != VDIR)
441 return (EINVAL);
442
443 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) {
444 return error;
445 }
446
447 nbytes = args->count;
448 if (nbytes == 1) {
449 nbytes = sizeof (struct linux_dirent);
450 justone = 1;
451 }
452 else
453 justone = 0;
454
455 off = fp->f_offset;
456#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */
457 buflen = max(DIRBLKSIZ, nbytes);
458 buflen = min(buflen, MAXBSIZE);
459 buf = malloc(buflen, M_TEMP, M_WAITOK);
460 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
461again:
462 aiov.iov_base = buf;
463 aiov.iov_len = buflen;
464 auio.uio_iov = &aiov;
465 auio.uio_iovcnt = 1;
466 auio.uio_rw = UIO_READ;
467 auio.uio_segflg = UIO_SYSSPACE;
468 auio.uio_procp = p;
469 auio.uio_resid = buflen;
470 auio.uio_offset = off;
471
472 if (cookies) {
473 free(cookies, M_TEMP);
474 cookies = NULL;
475 }
476
477 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies);
478 if (error) {
479 goto out;
480 }
481
482 inp = buf;
483 outp = (caddr_t) args->dent;
484 resid = nbytes;
485 if ((len = buflen - auio.uio_resid) <= 0) {
486 goto eof;
487 }
488
489 cookiep = cookies;
490
491 if (cookies) {
492 /*
493 * When using cookies, the vfs has the option of reading from
494 * a different offset than that supplied (UFS truncates the
495 * offset to a block boundary to make sure that it never reads
496 * partway through a directory entry, even if the directory
497 * has been compacted).
498 */
499 while (len > 0 && ncookies > 0 && *cookiep <= off) {
500 bdp = (struct dirent *) inp;
501 len -= bdp->d_reclen;
502 inp += bdp->d_reclen;
503 cookiep++;
504 ncookies--;
505 }
506 }
507
508 while (len > 0) {
509 if (cookiep && ncookies == 0)
510 break;
511 bdp = (struct dirent *) inp;
512 reclen = bdp->d_reclen;
513 if (reclen & 3) {
514 printf("linux_readdir: reclen=%d\n", reclen);
515 error = EFAULT;
516 goto out;
517 }
518
519 if (bdp->d_fileno == 0) {
520 inp += reclen;
521 if (cookiep) {
522 off = *cookiep++;
523 ncookies--;
524 } else
525 off += reclen;
526 len -= reclen;
527 continue;
528 }
529 linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen);
530 if (reclen > len || resid < linuxreclen) {
531 outp++;
532 break;
533 }
534 linux_dirent.dino = (long) bdp->d_fileno;
535 if (justone) {
536 /*
537 * old linux-style readdir usage.
538 */
539 linux_dirent.doff = (linux_off_t) linuxreclen;
540 linux_dirent.dreclen = (u_short) bdp->d_namlen;
541 } else {
542 linux_dirent.doff = (linux_off_t) off;
543 linux_dirent.dreclen = (u_short) linuxreclen;
544 }
545 strcpy(linux_dirent.dname, bdp->d_name);
546 if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) {
547 goto out;
548 }
549 inp += reclen;
550 if (cookiep) {
551 off = *cookiep++;
552 ncookies--;
553 } else
554 off += reclen;
555 outp += linuxreclen;
556 resid -= linuxreclen;
557 len -= reclen;
558 if (justone)
559 break;
560 }
561
562 if (outp == (caddr_t) args->dent)
563 goto again;
564 fp->f_offset = off;
565
566 if (justone)
567 nbytes = resid + linuxreclen;
568
569eof:
570 p->p_retval[0] = nbytes - resid;
571out:
572 if (cookies)
573 free(cookies, M_TEMP);
574 VOP_UNLOCK(vp, 0, p);
575 free(buf, M_TEMP);
576 return error;
577}
578
579/*
580 * These exist mainly for hooks for doing /compat/linux translation.
581 */
582
583int
584linux_access(struct proc *p, struct linux_access_args *args)
585{
586 struct access_args bsd;
587 caddr_t sg;
588
589 sg = stackgap_init();
590 CHECKALTEXIST(p, &sg, args->path);
591
592#ifdef DEBUG
593 printf("Linux-emul(%d): access(%s, %d)\n",
594 p->p_pid, args->path, args->flags);
595#endif
596 bsd.path = args->path;
597 bsd.flags = args->flags;
598
599 return access(p, &bsd);
600}
601
602int
603linux_unlink(struct proc *p, struct linux_unlink_args *args)
604{
605 struct unlink_args bsd;
606 caddr_t sg;
607
608 sg = stackgap_init();
609 CHECKALTEXIST(p, &sg, args->path);
610
611#ifdef DEBUG
612 printf("Linux-emul(%d): unlink(%s)\n",
613 p->p_pid, args->path);
614#endif
615 bsd.path = args->path;
616
617 return unlink(p, &bsd);
618}
619
620int
621linux_chdir(struct proc *p, struct linux_chdir_args *args)
622{
623 struct chdir_args bsd;
624 caddr_t sg;
625
626 sg = stackgap_init();
627 CHECKALTEXIST(p, &sg, args->path);
628
629#ifdef DEBUG
630 printf("Linux-emul(%d): chdir(%s)\n",
631 p->p_pid, args->path);
632#endif
633 bsd.path = args->path;
634
635 return chdir(p, &bsd);
636}
637
638int
639linux_chmod(struct proc *p, struct linux_chmod_args *args)
640{
641 struct chmod_args bsd;
642 caddr_t sg;
643
644 sg = stackgap_init();
645 CHECKALTEXIST(p, &sg, args->path);
646
647#ifdef DEBUG
648 printf("Linux-emul(%d): chmod(%s, %d)\n",
649 p->p_pid, args->path, args->mode);
650#endif
651 bsd.path = args->path;
652 bsd.mode = args->mode;
653
654 return chmod(p, &bsd);
655}
656
657int
658linux_chown(struct proc *p, struct linux_chown_args *args)
659{
660 struct chown_args bsd;
661 caddr_t sg;
662
663 sg = stackgap_init();
664 CHECKALTEXIST(p, &sg, args->path);
665
666#ifdef DEBUG
667 printf("Linux-emul(%d): chown(%s, %d, %d)\n",
668 p->p_pid, args->path, args->uid, args->gid);
669#endif
670 bsd.path = args->path;
671 /* XXX size casts here */
672 bsd.uid = args->uid;
673 bsd.gid = args->gid;
674
675 return chown(p, &bsd);
676}
677
678int
679linux_lchown(struct proc *p, struct linux_lchown_args *args)
680{
681 struct lchown_args bsd;
682 caddr_t sg;
683
684 sg = stackgap_init();
685 CHECKALTEXIST(p, &sg, args->path);
686
687#ifdef DEBUG
688 printf("Linux-emul(%d): lchown(%s, %d, %d)\n",
689 p->p_pid, args->path, args->uid, args->gid);
690#endif
691 bsd.path = args->path;
692 /* XXX size casts here */
693 bsd.uid = args->uid;
694 bsd.gid = args->gid;
695
696 return lchown(p, &bsd);
697}
698
699int
700linux_mkdir(struct proc *p, struct linux_mkdir_args *args)
701{
702 struct mkdir_args bsd;
703 caddr_t sg;
704
705 sg = stackgap_init();
706 CHECKALTCREAT(p, &sg, args->path);
707
708#ifdef DEBUG
709 printf("Linux-emul(%d): mkdir(%s, %d)\n",
710 p->p_pid, args->path, args->mode);
711#endif
712 bsd.path = args->path;
713 bsd.mode = args->mode;
714
715 return mkdir(p, &bsd);
716}
717
718int
719linux_rmdir(struct proc *p, struct linux_rmdir_args *args)
720{
721 struct rmdir_args bsd;
722 caddr_t sg;
723
724 sg = stackgap_init();
725 CHECKALTEXIST(p, &sg, args->path);
726
727#ifdef DEBUG
728 printf("Linux-emul(%d): rmdir(%s)\n",
729 p->p_pid, args->path);
730#endif
731 bsd.path = args->path;
732
733 return rmdir(p, &bsd);
734}
735
736int
737linux_rename(struct proc *p, struct linux_rename_args *args)
738{
739 struct rename_args bsd;
740 caddr_t sg;
741
742 sg = stackgap_init();
743 CHECKALTEXIST(p, &sg, args->from);
744 CHECKALTCREAT(p, &sg, args->to);
745
746#ifdef DEBUG
747 printf("Linux-emul(%d): rename(%s, %s)\n",
748 p->p_pid, args->from, args->to);
749#endif
750 bsd.from = args->from;
751 bsd.to = args->to;
752
753 return rename(p, &bsd);
754}
755
756int
757linux_symlink(struct proc *p, struct linux_symlink_args *args)
758{
759 struct symlink_args bsd;
760 caddr_t sg;
761
762 sg = stackgap_init();
763 CHECKALTEXIST(p, &sg, args->path);
764 CHECKALTCREAT(p, &sg, args->to);
765
766#ifdef DEBUG
767 printf("Linux-emul(%d): symlink(%s, %s)\n",
768 p->p_pid, args->path, args->to);
769#endif
770 bsd.path = args->path;
771 bsd.link = args->to;
772
773 return symlink(p, &bsd);
774}
775
776int
777linux_execve(struct proc *p, struct linux_execve_args *args)
778{
779 struct execve_args bsd;
780 caddr_t sg;
781
782 sg = stackgap_init();
783 CHECKALTEXIST(p, &sg, args->path);
784
785#ifdef DEBUG
786 printf("Linux-emul(%d): execve(%s)\n",
787 p->p_pid, args->path);
788#endif
789 bsd.fname = args->path;
790 bsd.argv = args->argp;
791 bsd.envv = args->envp;
792
793 return execve(p, &bsd);
794}
795
796int
797linux_readlink(struct proc *p, struct linux_readlink_args *args)
798{
799 struct readlink_args bsd;
800 caddr_t sg;
801
802 sg = stackgap_init();
803 CHECKALTEXIST(p, &sg, args->name);
804
805#ifdef DEBUG
806 printf("Linux-emul(%ld): readlink(%s, %p, %d)\n",
807 (long)p->p_pid, args->name, (void *)args->buf, args->count);
808#endif
809 bsd.path = args->name;
810 bsd.buf = args->buf;
811 bsd.count = args->count;
812
813 return readlink(p, &bsd);
814}
815
816int
817linux_truncate(struct proc *p, struct linux_truncate_args *args)
818{
819 struct truncate_args bsd;
820 caddr_t sg;
821
822 sg = stackgap_init();
823 CHECKALTEXIST(p, &sg, args->path);
824
825#ifdef DEBUG
826 printf("Linux-emul(%d): truncate(%s, %ld)\n",
827 p->p_pid, args->path, args->length);
828#endif
829 bsd.path = args->path;
830 bsd.length = args->length;
831
832 return truncate(p, &bsd);
833}
834
835int
836linux_link(struct proc *p, struct linux_link_args *args)
837{
838 struct link_args bsd;
839 caddr_t sg;
840
841 sg = stackgap_init();
842 CHECKALTEXIST(p, &sg, args->path);
843 CHECKALTCREAT(p, &sg, args->to);
844
845#ifdef DEBUG
846 printf("Linux-emul(%d): link(%s, %s)\n", p->p_pid, args->path, args->to);
847#endif
848
849 bsd.path = args->path;
850 bsd.link = args->to;
851
852 return link(p, &bsd);
853}
854
855int
856linux_getcwd(struct proc *p, struct linux_getcwd_args *args)
857{
858 struct __getcwd_args bsd;
859
860#ifdef DEBUG
861 printf("Linux-emul(%d): getcwd(%p, %ld)\n",
862 p->p_pid, args->buf, args->bufsize);
863#endif
864
865 bsd.buf = args->buf;
866 bsd.buflen = args->bufsize;
867 return __getcwd(p, &bsd);
868}