xref: /freebsd/sys/compat/linux/linux_file.c (revision 3e0f6b97b257a96f7275e4442204263e44b16686)
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  *  $FreeBSD$
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     vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
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, NULL, NULL);
466     if (error) {
467 	goto out;
468     }
469 
470     inp = buf;
471     inp += blockoff;
472     outp = (caddr_t) args->dent;
473     resid = nbytes;
474     if ((len = buflen - auio.uio_resid - blockoff) == 0) {
475 	goto eof;
476     }
477 
478     while (len > 0) {
479 	bdp = (struct dirent *) inp;
480 	reclen = bdp->d_reclen;
481 	if (reclen & 3) {
482 	    printf("linux_readdir: reclen=%d\n", reclen);
483 	    error = EFAULT;
484 	    goto out;
485 	}
486 
487 	if (bdp->d_fileno == 0) {
488 	    inp += reclen;
489 	    off += reclen;
490 	    len -= reclen;
491 	    continue;
492 	}
493 	linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen);
494 	if (reclen > len || resid < linuxreclen) {
495 	    outp++;
496 	    break;
497 	}
498 	linux_dirent.dino = (long) bdp->d_fileno;
499 	if (justone) {
500 	    /*
501 	     * old linux-style readdir usage.
502 	     */
503 	    linux_dirent.doff = (linux_off_t) linuxreclen;
504 	    linux_dirent.dreclen = (u_short) bdp->d_namlen;
505 	} else {
506 	    linux_dirent.doff = (linux_off_t) off;
507 	    linux_dirent.dreclen = (u_short) linuxreclen;
508 	}
509 	strcpy(linux_dirent.dname, bdp->d_name);
510 	if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) {
511 	    goto out;
512 	}
513 	inp += reclen;
514 	off += reclen;
515 	outp += linuxreclen;
516 	resid -= linuxreclen;
517 	len -= reclen;
518 	if (justone)
519 	    break;
520     }
521 
522     if (outp == (caddr_t) args->dent)
523 	goto again;
524     fp->f_offset = off;
525 
526     if (justone)
527 	nbytes = resid + linuxreclen;
528 
529 eof:
530     *retval = nbytes - resid;
531 out:
532     VOP_UNLOCK(vp, 0, p);
533     free(buf, M_TEMP);
534     return error;
535 }
536 
537 /*
538  * These exist mainly for hooks for doing /compat/linux translation.
539  */
540 
541 int
542 linux_access(struct proc *p, struct linux_access_args *args, int *retval)
543 {
544 	struct access_args bsd;
545 	caddr_t sg;
546 
547 	sg = stackgap_init();
548 	CHECKALTEXIST(p, &sg, args->path);
549 
550 #ifdef DEBUG
551         printf("Linux-emul(%d): access(%s, %d)\n",
552 	    p->p_pid, args->path, args->flags);
553 #endif
554 	bsd.path = args->path;
555 	bsd.flags = args->flags;
556 
557 	return access(p, &bsd, retval);
558 }
559 
560 int
561 linux_unlink(struct proc *p, struct linux_unlink_args *args, int *retval)
562 {
563 	struct unlink_args bsd;
564 	caddr_t sg;
565 
566 	sg = stackgap_init();
567 	CHECKALTEXIST(p, &sg, args->path);
568 
569 #ifdef DEBUG
570 	printf("Linux-emul(%d): unlink(%s)\n",
571 	   p->p_pid, args->path);
572 #endif
573 	bsd.path = args->path;
574 
575 	return unlink(p, &bsd, retval);
576 }
577 
578 int
579 linux_chdir(struct proc *p, struct linux_chdir_args *args, int *retval)
580 {
581 	struct chdir_args bsd;
582 	caddr_t sg;
583 
584 	sg = stackgap_init();
585 	CHECKALTEXIST(p, &sg, args->path);
586 
587 #ifdef DEBUG
588 	printf("Linux-emul(%d): chdir(%s)\n",
589 	   p->p_pid, args->path);
590 #endif
591 	bsd.path = args->path;
592 
593 	return chdir(p, &bsd, retval);
594 }
595 
596 int
597 linux_chmod(struct proc *p, struct linux_chmod_args *args, int *retval)
598 {
599 	struct chmod_args bsd;
600 	caddr_t sg;
601 
602 	sg = stackgap_init();
603 	CHECKALTEXIST(p, &sg, args->path);
604 
605 #ifdef DEBUG
606         printf("Linux-emul(%d): chmod(%s, %d)\n",
607 	    p->p_pid, args->path, args->mode);
608 #endif
609 	bsd.path = args->path;
610 	bsd.mode = args->mode;
611 
612 	return chmod(p, &bsd, retval);
613 }
614 
615 int
616 linux_chown(struct proc *p, struct linux_chown_args *args, int *retval)
617 {
618 	struct chown_args bsd;
619 	caddr_t sg;
620 
621 	sg = stackgap_init();
622 	CHECKALTEXIST(p, &sg, args->path);
623 
624 #ifdef DEBUG
625         printf("Linux-emul(%d): chown(%s, %d, %d)\n",
626 	    p->p_pid, args->path, args->uid, args->gid);
627 #endif
628 	bsd.path = args->path;
629 	/* XXX size casts here */
630 	bsd.uid = args->uid;
631 	bsd.gid = args->gid;
632 
633 	return chown(p, &bsd, retval);
634 }
635 
636 int
637 linux_mkdir(struct proc *p, struct linux_mkdir_args *args, int *retval)
638 {
639 	struct mkdir_args bsd;
640 	caddr_t sg;
641 
642 	sg = stackgap_init();
643 	CHECKALTCREAT(p, &sg, args->path);
644 
645 #ifdef DEBUG
646         printf("Linux-emul(%d): mkdir(%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 mkdir(p, &bsd, retval);
653 }
654 
655 int
656 linux_rmdir(struct proc *p, struct linux_rmdir_args *args, int *retval)
657 {
658 	struct rmdir_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): rmdir(%s)\n",
666 	    p->p_pid, args->path);
667 #endif
668 	bsd.path = args->path;
669 
670 	return rmdir(p, &bsd, retval);
671 }
672 
673 int
674 linux_rename(struct proc *p, struct linux_rename_args *args, int *retval)
675 {
676 	struct rename_args bsd;
677 	caddr_t sg;
678 
679 	sg = stackgap_init();
680 	CHECKALTEXIST(p, &sg, args->from);
681 	CHECKALTCREAT(p, &sg, args->to);
682 
683 #ifdef DEBUG
684         printf("Linux-emul(%d): rename(%s, %s)\n",
685 	    p->p_pid, args->from, args->to);
686 #endif
687 	bsd.from = args->from;
688 	bsd.to = args->to;
689 
690 	return rename(p, &bsd, retval);
691 }
692 
693 int
694 linux_symlink(struct proc *p, struct linux_symlink_args *args, int *retval)
695 {
696 	struct symlink_args bsd;
697 	caddr_t sg;
698 
699 	sg = stackgap_init();
700 	CHECKALTEXIST(p, &sg, args->path);
701 	CHECKALTCREAT(p, &sg, args->to);
702 
703 #ifdef DEBUG
704         printf("Linux-emul(%d): symlink(%s, %s)\n",
705 	    p->p_pid, args->path, args->to);
706 #endif
707 	bsd.path = args->path;
708 	bsd.link = args->to;
709 
710 	return symlink(p, &bsd, retval);
711 }
712 
713 int
714 linux_execve(struct proc *p, struct linux_execve_args *args, int *retval)
715 {
716 	struct execve_args bsd;
717 	caddr_t sg;
718 
719 	sg = stackgap_init();
720 	CHECKALTEXIST(p, &sg, args->path);
721 
722 #ifdef DEBUG
723         printf("Linux-emul(%d): execve(%s)\n",
724 	    p->p_pid, args->path);
725 #endif
726 	bsd.fname = args->path;
727 	bsd.argv = args->argp;
728 	bsd.envv = args->envp;
729 
730 	return execve(p, &bsd, retval);
731 }
732 
733 int
734 linux_readlink(struct proc *p, struct linux_readlink_args *args, int *retval)
735 {
736 	struct readlink_args bsd;
737 	caddr_t sg;
738 
739 	sg = stackgap_init();
740 	CHECKALTEXIST(p, &sg, args->name);
741 
742 #ifdef DEBUG
743         printf("Linux-emul(%d): readlink(%s, 0x%x, %d)\n",
744 	    p->p_pid, args->name, args->buf, args->count);
745 #endif
746 	bsd.path = args->name;
747 	bsd.buf = args->buf;
748 	bsd.count = args->count;
749 
750 	return readlink(p, &bsd, retval);
751 }
752 
753 int
754 linux_truncate(struct proc *p, struct linux_truncate_args *args, int *retval)
755 {
756 	struct otruncate_args bsd;
757 	caddr_t sg;
758 
759 	sg = stackgap_init();
760 	CHECKALTEXIST(p, &sg, args->path);
761 
762 #ifdef DEBUG
763         printf("Linux-emul(%d): truncate(%s)\n",
764 	    p->p_pid, args->path);
765 #endif
766 	bsd.path = args->path;
767 
768 	return otruncate(p, &bsd, retval);
769 }
770 
771