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