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