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