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