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