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