linux_file.c revision 1.38 1 /* $NetBSD: linux_file.c,v 1.38 2001/06/14 20:32:43 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Frank van der Linden and Eric Haszlakiewicz.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Functions in multiarch:
41 * linux_sys_llseek : linux_llseek.c
42 */
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/namei.h>
47 #include <sys/proc.h>
48 #include <sys/file.h>
49 #include <sys/stat.h>
50 #include <sys/filedesc.h>
51 #include <sys/ioctl.h>
52 #include <sys/kernel.h>
53 #include <sys/mount.h>
54 #include <sys/malloc.h>
55 #include <sys/vnode.h>
56 #include <sys/tty.h>
57 #include <sys/conf.h>
58
59 #include <sys/syscallargs.h>
60
61 #include <compat/linux/common/linux_types.h>
62 #include <compat/linux/common/linux_signal.h>
63 #include <compat/linux/common/linux_fcntl.h>
64 #include <compat/linux/common/linux_util.h>
65 #include <compat/linux/common/linux_machdep.h>
66
67 #include <compat/linux/linux_syscallargs.h>
68
69 static int linux_to_bsd_ioflags __P((int));
70 static int bsd_to_linux_ioflags __P((int));
71 static void bsd_to_linux_flock __P((struct flock *, struct linux_flock *));
72 static void linux_to_bsd_flock __P((struct linux_flock *, struct flock *));
73 static void bsd_to_linux_stat __P((struct stat *, struct linux_stat *));
74 static int linux_stat1 __P((struct proc *, void *, register_t *, int));
75
76 /*
77 * Some file-related calls are handled here. The usual flag conversion
78 * an structure conversion is done, and alternate emul path searching.
79 */
80
81 /*
82 * The next two functions convert between the Linux and NetBSD values
83 * of the flags used in open(2) and fcntl(2).
84 */
85 static int
86 linux_to_bsd_ioflags(lflags)
87 int lflags;
88 {
89 int res = 0;
90
91 res |= cvtto_bsd_mask(lflags, LINUX_O_WRONLY, O_WRONLY);
92 res |= cvtto_bsd_mask(lflags, LINUX_O_RDONLY, O_RDONLY);
93 res |= cvtto_bsd_mask(lflags, LINUX_O_RDWR, O_RDWR);
94 res |= cvtto_bsd_mask(lflags, LINUX_O_CREAT, O_CREAT);
95 res |= cvtto_bsd_mask(lflags, LINUX_O_EXCL, O_EXCL);
96 res |= cvtto_bsd_mask(lflags, LINUX_O_NOCTTY, O_NOCTTY);
97 res |= cvtto_bsd_mask(lflags, LINUX_O_TRUNC, O_TRUNC);
98 res |= cvtto_bsd_mask(lflags, LINUX_O_NDELAY, O_NDELAY);
99 res |= cvtto_bsd_mask(lflags, LINUX_O_SYNC, O_FSYNC);
100 res |= cvtto_bsd_mask(lflags, LINUX_FASYNC, O_ASYNC);
101 res |= cvtto_bsd_mask(lflags, LINUX_O_APPEND, O_APPEND);
102
103 return res;
104 }
105
106 static int
107 bsd_to_linux_ioflags(bflags)
108 int bflags;
109 {
110 int res = 0;
111
112 res |= cvtto_linux_mask(bflags, O_WRONLY, LINUX_O_WRONLY);
113 res |= cvtto_linux_mask(bflags, O_RDONLY, LINUX_O_RDONLY);
114 res |= cvtto_linux_mask(bflags, O_RDWR, LINUX_O_RDWR);
115 res |= cvtto_linux_mask(bflags, O_CREAT, LINUX_O_CREAT);
116 res |= cvtto_linux_mask(bflags, O_EXCL, LINUX_O_EXCL);
117 res |= cvtto_linux_mask(bflags, O_NOCTTY, LINUX_O_NOCTTY);
118 res |= cvtto_linux_mask(bflags, O_TRUNC, LINUX_O_TRUNC);
119 res |= cvtto_linux_mask(bflags, O_NDELAY, LINUX_O_NDELAY);
120 res |= cvtto_linux_mask(bflags, O_FSYNC, LINUX_O_SYNC);
121 res |= cvtto_linux_mask(bflags, O_ASYNC, LINUX_FASYNC);
122 res |= cvtto_linux_mask(bflags, O_APPEND, LINUX_O_APPEND);
123
124 return res;
125 }
126
127 /*
128 * creat(2) is an obsolete function, but it's present as a Linux
129 * system call, so let's deal with it.
130 *
131 * Note: On the Alpha this doesn't really exist in Linux, but it's defined
132 * in syscalls.master anyway so this doesn't have to be special cased.
133 *
134 * Just call open(2) with the TRUNC, CREAT and WRONLY flags.
135 */
136 int
137 linux_sys_creat(p, v, retval)
138 struct proc *p;
139 void *v;
140 register_t *retval;
141 {
142 struct linux_sys_creat_args /* {
143 syscallarg(const char *) path;
144 syscallarg(int) mode;
145 } */ *uap = v;
146 struct sys_open_args oa;
147 caddr_t sg;
148
149 sg = stackgap_init(p->p_emul);
150 CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
151
152 SCARG(&oa, path) = SCARG(uap, path);
153 SCARG(&oa, flags) = O_CREAT | O_TRUNC | O_WRONLY;
154 SCARG(&oa, mode) = SCARG(uap, mode);
155
156 return sys_open(p, &oa, retval);
157 }
158
159 /*
160 * open(2). Take care of the different flag values, and let the
161 * NetBSD syscall do the real work. See if this operation
162 * gives the current process a controlling terminal.
163 * (XXX is this necessary?)
164 */
165 int
166 linux_sys_open(p, v, retval)
167 struct proc *p;
168 void *v;
169 register_t *retval;
170 {
171 struct linux_sys_open_args /* {
172 syscallarg(const char *) path;
173 syscallarg(int) flags;
174 syscallarg(int) mode;
175 } */ *uap = v;
176 int error, fl;
177 struct sys_open_args boa;
178 caddr_t sg;
179
180 sg = stackgap_init(p->p_emul);
181
182 fl = linux_to_bsd_ioflags(SCARG(uap, flags));
183
184 if (fl & O_CREAT)
185 CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
186 else
187 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
188
189 SCARG(&boa, path) = SCARG(uap, path);
190 SCARG(&boa, flags) = fl;
191 SCARG(&boa, mode) = SCARG(uap, mode);
192
193 if ((error = sys_open(p, &boa, retval)))
194 return error;
195
196 /*
197 * this bit from sunos_misc.c (and svr4_fcntl.c).
198 * If we are a session leader, and we don't have a controlling
199 * terminal yet, and the O_NOCTTY flag is not set, try to make
200 * this the controlling terminal.
201 */
202 if (!(fl & O_NOCTTY) && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
203 struct filedesc *fdp = p->p_fd;
204 struct file *fp;
205
206 fp = fd_getfile(fdp, *retval);
207
208 /* ignore any error, just give it a try */
209 if (fp != NULL && fp->f_type == DTYPE_VNODE)
210 (fp->f_ops->fo_ioctl) (fp, TIOCSCTTY, (caddr_t) 0, p);
211 }
212 return 0;
213 }
214
215 /*
216 * The next two functions take care of converting the flock
217 * structure back and forth between Linux and NetBSD format.
218 * The only difference in the structures is the order of
219 * the fields, and the 'whence' value.
220 */
221 static void
222 bsd_to_linux_flock(bfp, lfp)
223 struct flock *bfp;
224 struct linux_flock *lfp;
225 {
226
227 lfp->l_start = bfp->l_start;
228 lfp->l_len = bfp->l_len;
229 lfp->l_pid = bfp->l_pid;
230 lfp->l_whence = bfp->l_whence;
231 switch (bfp->l_type) {
232 case F_RDLCK:
233 lfp->l_type = LINUX_F_RDLCK;
234 break;
235 case F_UNLCK:
236 lfp->l_type = LINUX_F_UNLCK;
237 break;
238 case F_WRLCK:
239 lfp->l_type = LINUX_F_WRLCK;
240 break;
241 }
242 }
243
244 static void
245 linux_to_bsd_flock(lfp, bfp)
246 struct linux_flock *lfp;
247 struct flock *bfp;
248 {
249
250 bfp->l_start = lfp->l_start;
251 bfp->l_len = lfp->l_len;
252 bfp->l_pid = lfp->l_pid;
253 bfp->l_whence = lfp->l_whence;
254 switch (lfp->l_type) {
255 case LINUX_F_RDLCK:
256 bfp->l_type = F_RDLCK;
257 break;
258 case LINUX_F_UNLCK:
259 bfp->l_type = F_UNLCK;
260 break;
261 case LINUX_F_WRLCK:
262 bfp->l_type = F_WRLCK;
263 break;
264 }
265 }
266
267 /*
268 * Most actions in the fcntl() call are straightforward; simply
269 * pass control to the NetBSD system call. A few commands need
270 * conversions after the actual system call has done its work,
271 * because the flag values and lock structure are different.
272 */
273 int
274 linux_sys_fcntl(p, v, retval)
275 struct proc *p;
276 void *v;
277 register_t *retval;
278 {
279 struct linux_sys_fcntl_args /* {
280 syscallarg(int) fd;
281 syscallarg(int) cmd;
282 syscallarg(void *) arg;
283 } */ *uap = v;
284 int fd, cmd, error;
285 u_long val;
286 caddr_t arg, sg;
287 struct linux_flock lfl;
288 struct flock *bfp, bfl;
289 struct sys_fcntl_args fca;
290 struct filedesc *fdp;
291 struct file *fp;
292 struct vnode *vp;
293 struct vattr va;
294 long pgid;
295 struct pgrp *pgrp;
296 struct tty *tp, *(*d_tty) __P((dev_t));
297
298 fd = SCARG(uap, fd);
299 cmd = SCARG(uap, cmd);
300 arg = (caddr_t) SCARG(uap, arg);
301
302 switch (cmd) {
303 case LINUX_F_DUPFD:
304 cmd = F_DUPFD;
305 break;
306 case LINUX_F_GETFD:
307 cmd = F_GETFD;
308 break;
309 case LINUX_F_SETFD:
310 cmd = F_SETFD;
311 break;
312 case LINUX_F_GETFL:
313 SCARG(&fca, fd) = fd;
314 SCARG(&fca, cmd) = F_GETFL;
315 SCARG(&fca, arg) = arg;
316 if ((error = sys_fcntl(p, &fca, retval)))
317 return error;
318 retval[0] = bsd_to_linux_ioflags(retval[0]);
319 return 0;
320 case LINUX_F_SETFL:
321 val = linux_to_bsd_ioflags((unsigned long)SCARG(uap, arg));
322 SCARG(&fca, fd) = fd;
323 SCARG(&fca, cmd) = F_SETFL;
324 SCARG(&fca, arg) = (caddr_t) val;
325 return sys_fcntl(p, &fca, retval);
326 case LINUX_F_GETLK:
327 sg = stackgap_init(p->p_emul);
328 bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
329 if ((error = copyin(arg, &lfl, sizeof lfl)))
330 return error;
331 linux_to_bsd_flock(&lfl, &bfl);
332 if ((error = copyout(&bfl, bfp, sizeof bfl)))
333 return error;
334 SCARG(&fca, fd) = fd;
335 SCARG(&fca, cmd) = F_GETLK;
336 SCARG(&fca, arg) = bfp;
337 if ((error = sys_fcntl(p, &fca, retval)))
338 return error;
339 if ((error = copyin(bfp, &bfl, sizeof bfl)))
340 return error;
341 bsd_to_linux_flock(&bfl, &lfl);
342 return copyout(&lfl, arg, sizeof lfl);
343 break;
344 case LINUX_F_SETLK:
345 case LINUX_F_SETLKW:
346 cmd = (cmd == LINUX_F_SETLK ? F_SETLK : F_SETLKW);
347 if ((error = copyin(arg, &lfl, sizeof lfl)))
348 return error;
349 linux_to_bsd_flock(&lfl, &bfl);
350 sg = stackgap_init(p->p_emul);
351 bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
352 if ((error = copyout(&bfl, bfp, sizeof bfl)))
353 return error;
354 SCARG(&fca, fd) = fd;
355 SCARG(&fca, cmd) = cmd;
356 SCARG(&fca, arg) = bfp;
357 return sys_fcntl(p, &fca, retval);
358 break;
359 case LINUX_F_SETOWN:
360 case LINUX_F_GETOWN:
361 /*
362 * We need to route around the normal fcntl() for these calls,
363 * since it uses TIOC{G,S}PGRP, which is too restrictive for
364 * Linux F_{G,S}ETOWN semantics. For sockets, this problem
365 * does not exist.
366 */
367 fdp = p->p_fd;
368 if ((fp = fd_getfile(fdp, fd)) == NULL)
369 return EBADF;
370 if (fp->f_type == DTYPE_SOCKET) {
371 cmd = cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN;
372 break;
373 }
374 vp = (struct vnode *)fp->f_data;
375 if (vp->v_type != VCHR)
376 return EINVAL;
377 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
378 return error;
379 d_tty = cdevsw[major(va.va_rdev)].d_tty;
380 if (!d_tty || (!(tp = (*d_tty)(va.va_rdev))))
381 return EINVAL;
382 if (cmd == LINUX_F_GETOWN) {
383 retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
384 return 0;
385 }
386 if ((long)arg <= 0) {
387 pgid = -(long)arg;
388 } else {
389 struct proc *p1 = pfind((long)arg);
390 if (p1 == 0)
391 return (ESRCH);
392 pgid = (long)p1->p_pgrp->pg_id;
393 }
394 pgrp = pgfind(pgid);
395 if (pgrp == NULL || pgrp->pg_session != p->p_session)
396 return EPERM;
397 tp->t_pgrp = pgrp;
398 return 0;
399 default:
400 return EOPNOTSUPP;
401 }
402
403 SCARG(&fca, fd) = fd;
404 SCARG(&fca, cmd) = cmd;
405 SCARG(&fca, arg) = arg;
406
407 return sys_fcntl(p, &fca, retval);
408 }
409
410 /*
411 * Convert a NetBSD stat structure to a Linux stat structure.
412 * Only the order of the fields and the padding in the structure
413 * is different. linux_fakedev is a machine-dependent function
414 * which optionally converts device driver major/minor numbers
415 * (XXX horrible, but what can you do against code that compares
416 * things against constant major device numbers? sigh)
417 */
418 static void
419 bsd_to_linux_stat(bsp, lsp)
420 struct stat *bsp;
421 struct linux_stat *lsp;
422 {
423
424 lsp->lst_dev = bsp->st_dev;
425 lsp->lst_ino = bsp->st_ino;
426 lsp->lst_mode = (linux_mode_t)bsp->st_mode;
427 if (bsp->st_nlink >= (1 << 15))
428 lsp->lst_nlink = (1 << 15) - 1;
429 else
430 lsp->lst_nlink = (linux_nlink_t)bsp->st_nlink;
431 lsp->lst_uid = bsp->st_uid;
432 lsp->lst_gid = bsp->st_gid;
433 lsp->lst_rdev = linux_fakedev(bsp->st_rdev);
434 lsp->lst_size = bsp->st_size;
435 lsp->lst_blksize = bsp->st_blksize;
436 lsp->lst_blocks = bsp->st_blocks;
437 lsp->lst_atime = bsp->st_atime;
438 lsp->lst_mtime = bsp->st_mtime;
439 lsp->lst_ctime = bsp->st_ctime;
440 }
441
442 /*
443 * The stat functions below are plain sailing. stat and lstat are handled
444 * by one function to avoid code duplication.
445 */
446 int
447 linux_sys_fstat(p, v, retval)
448 struct proc *p;
449 void *v;
450 register_t *retval;
451 {
452 struct linux_sys_fstat_args /* {
453 syscallarg(int) fd;
454 syscallarg(linux_stat *) sp;
455 } */ *uap = v;
456 struct sys___fstat13_args fsa;
457 struct linux_stat tmplst;
458 struct stat *st,tmpst;
459 caddr_t sg;
460 int error;
461
462 sg = stackgap_init(p->p_emul);
463
464 st = stackgap_alloc(&sg, sizeof (struct stat));
465
466 SCARG(&fsa, fd) = SCARG(uap, fd);
467 SCARG(&fsa, sb) = st;
468
469 if ((error = sys___fstat13(p, &fsa, retval)))
470 return error;
471
472 if ((error = copyin(st, &tmpst, sizeof tmpst)))
473 return error;
474
475 bsd_to_linux_stat(&tmpst, &tmplst);
476
477 if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
478 return error;
479
480 return 0;
481 }
482
483 static int
484 linux_stat1(p, v, retval, dolstat)
485 struct proc *p;
486 void *v;
487 register_t *retval;
488 int dolstat;
489 {
490 struct sys___stat13_args sa;
491 struct linux_stat tmplst;
492 struct stat *st, tmpst;
493 caddr_t sg;
494 int error;
495 struct linux_sys_stat_args *uap = v;
496
497 sg = stackgap_init(p->p_emul);
498 st = stackgap_alloc(&sg, sizeof (struct stat));
499 if (dolstat)
500 CHECK_ALT_SYMLINK(p, &sg, SCARG(uap, path));
501 else
502 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
503
504 SCARG(&sa, ub) = st;
505 SCARG(&sa, path) = SCARG(uap, path);
506
507 if ((error = (dolstat ? sys___lstat13(p, &sa, retval) :
508 sys___stat13(p, &sa, retval))))
509 return error;
510
511 if ((error = copyin(st, &tmpst, sizeof tmpst)))
512 return error;
513
514 bsd_to_linux_stat(&tmpst, &tmplst);
515
516 if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
517 return error;
518
519 return 0;
520 }
521
522 int
523 linux_sys_stat(p, v, retval)
524 struct proc *p;
525 void *v;
526 register_t *retval;
527 {
528 struct linux_sys_stat_args /* {
529 syscallarg(const char *) path;
530 syscallarg(struct linux_stat *) sp;
531 } */ *uap = v;
532
533 return linux_stat1(p, uap, retval, 0);
534 }
535
536 /* Note: this is "newlstat" in the Linux sources */
537 /* (we don't bother with the old lstat currently) */
538 int
539 linux_sys_lstat(p, v, retval)
540 struct proc *p;
541 void *v;
542 register_t *retval;
543 {
544 struct linux_sys_lstat_args /* {
545 syscallarg(const char *) path;
546 syscallarg(struct linux_stat *) sp;
547 } */ *uap = v;
548
549 return linux_stat1(p, uap, retval, 1);
550 }
551
552 /*
553 * The following syscalls are mostly here because of the alternate path check.
554 */
555 int
556 linux_sys_access(p, v, retval)
557 struct proc *p;
558 void *v;
559 register_t *retval;
560 {
561 struct linux_sys_access_args /* {
562 syscallarg(const char *) path;
563 syscallarg(int) flags;
564 } */ *uap = v;
565 caddr_t sg = stackgap_init(p->p_emul);
566
567 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
568
569 return sys_access(p, uap, retval);
570 }
571
572 int
573 linux_sys_unlink(p, v, retval)
574 struct proc *p;
575 void *v;
576 register_t *retval;
577
578 {
579 struct linux_sys_unlink_args /* {
580 syscallarg(const char *) path;
581 } */ *uap = v;
582 caddr_t sg = stackgap_init(p->p_emul);
583
584 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
585
586 return sys_unlink(p, uap, retval);
587 }
588
589 int
590 linux_sys_chdir(p, v, retval)
591 struct proc *p;
592 void *v;
593 register_t *retval;
594 {
595 struct linux_sys_chdir_args /* {
596 syscallarg(const char *) path;
597 } */ *uap = v;
598 caddr_t sg = stackgap_init(p->p_emul);
599
600 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
601
602 return sys_chdir(p, uap, retval);
603 }
604
605 int
606 linux_sys_mknod(p, v, retval)
607 struct proc *p;
608 void *v;
609 register_t *retval;
610 {
611 struct linux_sys_mknod_args /* {
612 syscallarg(const char *) path;
613 syscallarg(int) mode;
614 syscallarg(int) dev;
615 } */ *uap = v;
616 caddr_t sg = stackgap_init(p->p_emul);
617 struct sys_mkfifo_args bma;
618
619 CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
620
621 /*
622 * BSD handles FIFOs seperately
623 */
624 if (SCARG(uap, mode) & S_IFIFO) {
625 SCARG(&bma, path) = SCARG(uap, path);
626 SCARG(&bma, mode) = SCARG(uap, mode);
627 return sys_mkfifo(p, uap, retval);
628 } else
629 return sys_mknod(p, uap, retval);
630 }
631
632 int
633 linux_sys_chmod(p, v, retval)
634 struct proc *p;
635 void *v;
636 register_t *retval;
637 {
638 struct linux_sys_chmod_args /* {
639 syscallarg(const char *) path;
640 syscallarg(int) mode;
641 } */ *uap = v;
642 caddr_t sg = stackgap_init(p->p_emul);
643
644 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
645
646 return sys_chmod(p, uap, retval);
647 }
648
649 #if defined(__i386__) || defined(__m68k__)
650 int
651 linux_sys_chown16(p, v, retval)
652 struct proc *p;
653 void *v;
654 register_t *retval;
655 {
656 struct linux_sys_chown16_args /* {
657 syscallarg(const char *) path;
658 syscallarg(int) uid;
659 syscallarg(int) gid;
660 } */ *uap = v;
661 struct sys___posix_chown_args bca;
662 caddr_t sg = stackgap_init(p->p_emul);
663
664 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
665
666 SCARG(&bca, path) = SCARG(uap, path);
667 SCARG(&bca, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
668 (uid_t)-1 : SCARG(uap, uid);
669 SCARG(&bca, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
670 (gid_t)-1 : SCARG(uap, gid);
671
672 return sys___posix_chown(p, &bca, retval);
673 }
674
675 int
676 linux_sys_fchown16(p, v, retval)
677 struct proc *p;
678 void *v;
679 register_t *retval;
680 {
681 struct linux_sys_fchown16_args /* {
682 syscallarg(int) fd;
683 syscallarg(int) uid;
684 syscallarg(int) gid;
685 } */ *uap = v;
686 struct sys___posix_fchown_args bfa;
687
688 SCARG(&bfa, fd) = SCARG(uap, fd);
689 SCARG(&bfa, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
690 (uid_t)-1 : SCARG(uap, uid);
691 SCARG(&bfa, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
692 (gid_t)-1 : SCARG(uap, gid);
693
694 return sys___posix_fchown(p, &bfa, retval);
695 }
696
697 int
698 linux_sys_lchown16(p, v, retval)
699 struct proc *p;
700 void *v;
701 register_t *retval;
702 {
703 struct linux_sys_lchown16_args /* {
704 syscallarg(char *) path;
705 syscallarg(int) uid;
706 syscallarg(int) gid;
707 } */ *uap = v;
708 struct sys___posix_lchown_args bla;
709 caddr_t sg = stackgap_init(p->p_emul);
710
711 CHECK_ALT_SYMLINK(p, &sg, SCARG(uap, path));
712
713 SCARG(&bla, path) = SCARG(uap, path);
714 SCARG(&bla, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
715 (uid_t)-1 : SCARG(uap, uid);
716 SCARG(&bla, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
717 (gid_t)-1 : SCARG(uap, gid);
718
719 return sys___posix_lchown(p, &bla, retval);
720 }
721 #endif /* __i386__ || __m68k__ */
722 #if defined (__i386__) || defined (__m68k__) || defined (__powerpc__)
723 int
724 linux_sys_chown(p, v, retval)
725 struct proc *p;
726 void *v;
727 register_t *retval;
728 {
729 struct linux_sys_chown_args /* {
730 syscallarg(char *) path;
731 syscallarg(int) uid;
732 syscallarg(int) gid;
733 } */ *uap = v;
734 caddr_t sg = stackgap_init(p->p_emul);
735
736 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
737
738 return sys___posix_chown(p, uap, retval);
739 }
740
741 int
742 linux_sys_lchown(p, v, retval)
743 struct proc *p;
744 void *v;
745 register_t *retval;
746 {
747 struct linux_sys_lchown_args /* {
748 syscallarg(char *) path;
749 syscallarg(int) uid;
750 syscallarg(int) gid;
751 } */ *uap = v;
752 caddr_t sg = stackgap_init(p->p_emul);
753
754 CHECK_ALT_SYMLINK(p, &sg, SCARG(uap, path));
755
756 return sys___posix_lchown(p, uap, retval);
757 }
758 #endif /* __i386__ || __m68k__ || __powerpc__ */
759
760 int
761 linux_sys_rename(p, v, retval)
762 struct proc *p;
763 void *v;
764 register_t *retval;
765 {
766 struct linux_sys_rename_args /* {
767 syscallarg(const char *) from;
768 syscallarg(const char *) to;
769 } */ *uap = v;
770 caddr_t sg = stackgap_init(p->p_emul);
771
772 CHECK_ALT_EXIST(p, &sg, SCARG(uap, from));
773 CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
774
775 return sys___posix_rename(p, uap, retval);
776 }
777
778 int
779 linux_sys_mkdir(p, v, retval)
780 struct proc *p;
781 void *v;
782 register_t *retval;
783 {
784 struct linux_sys_mkdir_args /* {
785 syscallarg(const char *) path;
786 syscallarg(int) mode;
787 } */ *uap = v;
788 caddr_t sg = stackgap_init(p->p_emul);
789
790 CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
791
792 return sys_mkdir(p, uap, retval);
793 }
794
795 int
796 linux_sys_rmdir(p, v, retval)
797 struct proc *p;
798 void *v;
799 register_t *retval;
800 {
801 struct linux_sys_rmdir_args /* {
802 syscallarg(const char *) path;
803 } */ *uap = v;
804 caddr_t sg = stackgap_init(p->p_emul);
805
806 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
807
808 return sys_rmdir(p, uap, retval);
809 }
810
811 int
812 linux_sys_symlink(p, v, retval)
813 struct proc *p;
814 void *v;
815 register_t *retval;
816 {
817 struct linux_sys_symlink_args /* {
818 syscallarg(const char *) path;
819 syscallarg(const char *) to;
820 } */ *uap = v;
821 caddr_t sg = stackgap_init(p->p_emul);
822
823 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
824 CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
825
826 return sys_symlink(p, uap, retval);
827 }
828
829 int
830 linux_sys_link(p, v, retval)
831 struct proc *p;
832 void *v;
833 register_t *retval;
834 {
835 struct linux_sys_link_args /* {
836 syscallarg(const char *) path;
837 syscallarg(const char *) link;
838 } */ *uap = v;
839 caddr_t sg = stackgap_init(p->p_emul);
840
841 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
842 CHECK_ALT_CREAT(p, &sg, SCARG(uap, link));
843
844 return sys_link(p, uap, retval);
845 }
846
847 int
848 linux_sys_readlink(p, v, retval)
849 struct proc *p;
850 void *v;
851 register_t *retval;
852 {
853 struct linux_sys_readlink_args /* {
854 syscallarg(const char *) name;
855 syscallarg(char *) buf;
856 syscallarg(int) count;
857 } */ *uap = v;
858 caddr_t sg = stackgap_init(p->p_emul);
859
860 CHECK_ALT_SYMLINK(p, &sg, SCARG(uap, name));
861
862 return sys_readlink(p, uap, retval);
863 }
864
865 int
866 linux_sys_truncate(p, v, retval)
867 struct proc *p;
868 void *v;
869 register_t *retval;
870 {
871 struct linux_sys_truncate_args /* {
872 syscallarg(const char *) path;
873 syscallarg(long) length;
874 } */ *uap = v;
875 caddr_t sg = stackgap_init(p->p_emul);
876
877 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
878
879 return compat_43_sys_truncate(p, uap, retval);
880 }
881
882 /*
883 * This is just fsync() for now (just as it is in the Linux kernel)
884 * Note: this is not implemented under Linux on Alpha and Arm
885 * but should still be defined in our syscalls.master.
886 * (syscall #148 on the arm)
887 */
888 int
889 linux_sys_fdatasync(p, v, retval)
890 struct proc *p;
891 void *v;
892 register_t *retval;
893 {
894 #ifdef notdef
895 struct linux_sys_fdatasync_args /* {
896 syscallarg(int) fd;
897 } */ *uap = v;
898 #endif
899 return sys_fsync(p, v, retval);
900 }
901
902 /*
903 * pread(2).
904 */
905 int
906 linux_sys_pread(p, v, retval)
907 struct proc *p;
908 void *v;
909 register_t *retval;
910 {
911 struct linux_sys_pread_args /* {
912 syscallarg(int) fd;
913 syscallarg(void *) buf;
914 syscallarg(size_t) nbyte;
915 syscallarg(linux_off_t) offset;
916 } */ *uap = v;
917 struct sys_pread_args pra;
918
919 SCARG(&pra, fd) = SCARG(uap, fd);
920 SCARG(&pra, buf) = SCARG(uap, buf);
921 SCARG(&pra, nbyte) = SCARG(uap, nbyte);
922 SCARG(&pra, offset) = SCARG(uap, offset);
923
924 return sys_read(p, &pra, retval);
925 }
926
927 /*
928 * pwrite(2).
929 */
930 int
931 linux_sys_pwrite(p, v, retval)
932 struct proc *p;
933 void *v;
934 register_t *retval;
935 {
936 struct linux_sys_pwrite_args /* {
937 syscallarg(int) fd;
938 syscallarg(void *) buf;
939 syscallarg(size_t) nbyte;
940 syscallarg(linux_off_t) offset;
941 } */ *uap = v;
942 struct sys_pwrite_args pra;
943
944 SCARG(&pra, fd) = SCARG(uap, fd);
945 SCARG(&pra, buf) = SCARG(uap, buf);
946 SCARG(&pra, nbyte) = SCARG(uap, nbyte);
947 SCARG(&pra, offset) = SCARG(uap, offset);
948
949 return sys_write(p, &pra, retval);
950 }
951