linux_llseek.c revision 1.12 1 /* $NetBSD: linux_llseek.c,v 1.12 1995/10/07 06:27:05 mycroft Exp $ */
2
3 /*
4 * Copyright (c) 1995 Frank van der Linden
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed for the NetBSD Project
18 * by Frank van der Linden
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/namei.h>
37 #include <sys/proc.h>
38 #include <sys/file.h>
39 #include <sys/stat.h>
40 #include <sys/filedesc.h>
41 #include <sys/ioctl.h>
42 #include <sys/kernel.h>
43 #include <sys/mount.h>
44 #include <sys/malloc.h>
45
46 #include <sys/syscallargs.h>
47
48 #include <compat/linux/linux_types.h>
49 #include <compat/linux/linux_signal.h>
50 #include <compat/linux/linux_syscallargs.h>
51 #include <compat/linux/linux_fcntl.h>
52 #include <compat/linux/linux_util.h>
53
54 /*
55 * Some file-related calls are handled here. The usual flag conversion
56 * an structure conversion is done, and alternate emul path searching.
57 */
58
59 /*
60 * The next two functions convert between the Linux and NetBSD values
61 * of the flags used in open(2) and fcntl(2).
62 */
63 static int
64 linux_to_bsd_ioflags(int lflags)
65 {
66 int res = 0;
67
68 res |= cvtto_bsd_mask(lflags, LINUX_O_WRONLY, O_WRONLY);
69 res |= cvtto_bsd_mask(lflags, LINUX_O_RDONLY, O_RDONLY);
70 res |= cvtto_bsd_mask(lflags, LINUX_O_RDWR, O_RDWR);
71 res |= cvtto_bsd_mask(lflags, LINUX_O_CREAT, O_CREAT);
72 res |= cvtto_bsd_mask(lflags, LINUX_O_EXCL, O_EXCL);
73 res |= cvtto_bsd_mask(lflags, LINUX_O_NOCTTY, O_NOCTTY);
74 res |= cvtto_bsd_mask(lflags, LINUX_O_TRUNC, O_TRUNC);
75 res |= cvtto_bsd_mask(lflags, LINUX_O_NDELAY, O_NDELAY);
76 res |= cvtto_bsd_mask(lflags, LINUX_O_SYNC, O_FSYNC);
77 res |= cvtto_bsd_mask(lflags, LINUX_FASYNC, O_ASYNC);
78 res |= cvtto_bsd_mask(lflags, LINUX_O_APPEND, O_APPEND);
79
80 return res;
81 }
82
83 static int
84 bsd_to_linux_ioflags(int bflags)
85 {
86 int res = 0;
87
88 res |= cvtto_linux_mask(bflags, O_WRONLY, LINUX_O_WRONLY);
89 res |= cvtto_linux_mask(bflags, O_RDONLY, LINUX_O_RDONLY);
90 res |= cvtto_linux_mask(bflags, O_RDWR, LINUX_O_RDWR);
91 res |= cvtto_linux_mask(bflags, O_CREAT, LINUX_O_CREAT);
92 res |= cvtto_linux_mask(bflags, O_EXCL, LINUX_O_EXCL);
93 res |= cvtto_linux_mask(bflags, O_NOCTTY, LINUX_O_NOCTTY);
94 res |= cvtto_linux_mask(bflags, O_TRUNC, LINUX_O_TRUNC);
95 res |= cvtto_linux_mask(bflags, O_NDELAY, LINUX_O_NDELAY);
96 res |= cvtto_linux_mask(bflags, O_FSYNC, LINUX_O_SYNC);
97 res |= cvtto_linux_mask(bflags, O_ASYNC, LINUX_FASYNC);
98 res |= cvtto_linux_mask(bflags, O_APPEND, LINUX_O_APPEND);
99
100 return res;
101 }
102
103 /*
104 * creat(2) is an obsolete function, but it's present as a Linux
105 * system call, so let's deal with it.
106 *
107 * Just call open(2) with the TRUNC, CREAT and WRONLY flags.
108 */
109 int
110 linux_sys_creat(p, v, retval)
111 struct proc *p;
112 void *v;
113 register_t *retval;
114 {
115 struct linux_sys_creat_args /* {
116 syscallarg(char *) path;
117 syscallarg(int) mode;
118 } */ *uap = v;
119 struct sys_open_args oa;
120 caddr_t sg;
121
122 sg = stackgap_init(p->p_emul);
123 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
124
125 SCARG(&oa, path) = SCARG(uap, path);
126 SCARG(&oa, flags) = O_CREAT | O_TRUNC | O_WRONLY;
127 SCARG(&oa, mode) = SCARG(uap, mode);
128
129 return sys_open(p, &oa, retval);
130 }
131
132 /*
133 * open(2). Take care of the different flag values, and let the
134 * NetBSD syscall do the real work. See if this operation
135 * gives the current process a controlling terminal.
136 * (XXX is this necessary?)
137 */
138 int
139 linux_sys_open(p, v, retval)
140 struct proc *p;
141 void *v;
142 register_t *retval;
143 {
144 struct linux_sys_open_args /* {
145 syscallarg(char *) path;
146 syscallarg(int) flags;
147 syscallarg(int) mode;
148 } */ *uap = v;
149 int error, fl;
150 struct sys_open_args boa;
151 caddr_t sg;
152
153 sg = stackgap_init(p->p_emul);
154
155 fl = linux_to_bsd_ioflags(SCARG(uap, flags));
156
157 if (fl & O_CREAT)
158 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
159 else
160 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
161
162 SCARG(&boa, path) = SCARG(uap, path);
163 SCARG(&boa, flags) = fl;
164 SCARG(&boa, mode) = SCARG(uap, mode);
165
166 if ((error = sys_open(p, &boa, retval)))
167 return error;
168
169 /*
170 * this bit from sunos_misc.c (and svr4_fcntl.c).
171 * If we are a session leader, and we don't have a controlling
172 * terminal yet, and the O_NOCTTY flag is not set, try to make
173 * this the controlling terminal.
174 */
175 if (!(fl & O_NOCTTY) && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
176 struct filedesc *fdp = p->p_fd;
177 struct file *fp = fdp->fd_ofiles[*retval];
178
179 /* ignore any error, just give it a try */
180 if (fp->f_type == DTYPE_VNODE)
181 (fp->f_ops->fo_ioctl) (fp, TIOCSCTTY, (caddr_t) 0, p);
182 }
183 return 0;
184 }
185
186 /*
187 * This appears to be part of a Linux attempt to switch to 64 bits file sizes.
188 */
189 int
190 linux_sys_llseek(p, v, retval)
191 struct proc *p;
192 void *v;
193 register_t *retval;
194 {
195 struct linux_sys_llseek_args /* {
196 syscallarg(int) fd;
197 syscallarg(uint32_t) ohigh;
198 syscallarg(uint32_t) olow;
199 syscallarg(caddr_t) res;
200 syscallarg(int) whence;
201 } */ *uap = v;
202 struct sys_lseek_args bla;
203 int error;
204 off_t off;
205
206 off = SCARG(uap, olow) | (((off_t) SCARG(uap, ohigh)) << 32);
207
208 SCARG(&bla, fd) = SCARG(uap, fd);
209 SCARG(&bla, offset) = off;
210 SCARG(&bla, whence) = SCARG(uap, whence);
211
212 if ((error = sys_lseek(p, &bla, retval)))
213 return error;
214
215 if ((error = copyout(retval, SCARG(uap, res), sizeof (off_t))))
216 return error;
217
218 retval[0] = 0;
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(p, v, retval)
282 struct proc *p;
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 int fd, cmd, error, val;
292 caddr_t arg, sg;
293 struct linux_flock lfl;
294 struct flock *bfp, bfl;
295 struct sys_fcntl_args fca;
296
297 fd = SCARG(uap, fd);
298 cmd = SCARG(uap, cmd);
299 arg = (caddr_t) SCARG(uap, arg);
300
301 switch (cmd) {
302 case LINUX_F_DUPFD:
303 cmd = F_DUPFD;
304 break;
305 case LINUX_F_GETFD:
306 cmd = F_GETFD;
307 break;
308 case LINUX_F_SETFD:
309 cmd = F_SETFD;
310 break;
311 case LINUX_F_GETFL:
312 SCARG(&fca, fd) = fd;
313 SCARG(&fca, cmd) = F_GETFL;
314 SCARG(&fca, arg) = arg;
315 if ((error = sys_fcntl(p, &fca, retval)))
316 return error;
317 retval[0] = bsd_to_linux_ioflags(retval[0]);
318 return 0;
319 case LINUX_F_SETFL:
320 val = linux_to_bsd_ioflags((int)SCARG(uap, arg));
321 SCARG(&fca, fd) = fd;
322 SCARG(&fca, cmd) = F_SETFL;
323 SCARG(&fca, arg) = (caddr_t) val;
324 return sys_fcntl(p, &fca, retval);
325 case LINUX_F_GETLK:
326 sg = stackgap_init(p->p_emul);
327 bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
328 SCARG(&fca, fd) = fd;
329 SCARG(&fca, cmd) = F_GETLK;
330 SCARG(&fca, arg) = bfp;
331 if ((error = sys_fcntl(p, &fca, retval)))
332 return error;
333 if ((error = copyin(bfp, &bfl, sizeof bfl)))
334 return error;
335 bsd_to_linux_flock(&bfl, &lfl);
336 return copyout(&lfl, arg, sizeof lfl);
337 break;
338 case LINUX_F_SETLK:
339 case LINUX_F_SETLKW:
340 cmd = (cmd == LINUX_F_SETLK ? F_SETLK : F_SETLKW);
341 if ((error = copyin(arg, &lfl, sizeof lfl)))
342 return error;
343 linux_to_bsd_flock(&lfl, &bfl);
344 sg = stackgap_init(p->p_emul);
345 bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
346 if ((error = copyout(&bfl, bfp, sizeof bfl)))
347 return error;
348 SCARG(&fca, fd) = fd;
349 SCARG(&fca, cmd) = cmd;
350 SCARG(&fca, arg) = bfp;
351 return sys_fcntl(p, &fca, retval);
352 break;
353 case LINUX_F_SETOWN:
354 cmd = F_SETOWN;
355 break;
356 case LINUX_F_GETOWN:
357 cmd = F_GETOWN;
358 break;
359 default:
360 return EOPNOTSUPP;
361 }
362
363 SCARG(&fca, fd) = fd;
364 SCARG(&fca, cmd) = cmd;
365 SCARG(&fca, arg) = arg;
366
367 return sys_fcntl(p, &fca, retval);
368 }
369
370 /*
371 * Convert a NetBSD stat structure to a Linux stat structure.
372 * Only the order of the fields and the padding in the structure
373 * is different. linux_fakedev is a machine-dependent function
374 * which optionally converts device driver major/minor numbers
375 * (XXX horrible, but what can you do against code that compares
376 * things against constant major device numbers? sigh)
377 */
378 static void
379 bsd_to_linux_stat(bsp, lsp)
380 struct stat *bsp;
381 struct linux_stat *lsp;
382 {
383
384 lsp->lst_dev = bsp->st_dev;
385 lsp->lst_ino = bsp->st_ino;
386 lsp->lst_mode = bsp->st_mode;
387 lsp->lst_nlink = bsp->st_nlink;
388 lsp->lst_uid = bsp->st_uid;
389 lsp->lst_gid = bsp->st_gid;
390 lsp->lst_rdev = linux_fakedev(bsp->st_rdev);
391 lsp->lst_size = bsp->st_size;
392 lsp->lst_blksize = bsp->st_blksize;
393 lsp->lst_blocks = bsp->st_blocks;
394 lsp->lst_atime = bsp->st_atime;
395 lsp->lst_mtime = bsp->st_mtime;
396 lsp->lst_ctime = bsp->st_ctime;
397 }
398
399 /*
400 * The stat functions below are plain sailing. stat and lstat are handled
401 * by one function to avoid code duplication.
402 */
403 int
404 linux_sys_fstat(p, v, retval)
405 struct proc *p;
406 void *v;
407 register_t *retval;
408 {
409 struct linux_sys_fstat_args /* {
410 syscallarg(int) fd;
411 syscallarg(linux_stat *) sp;
412 } */ *uap = v;
413 struct sys_fstat_args fsa;
414 struct linux_stat tmplst;
415 struct stat *st,tmpst;
416 caddr_t sg;
417 int error;
418
419 sg = stackgap_init(p->p_emul);
420
421 st = stackgap_alloc(&sg, sizeof (struct stat));
422
423 SCARG(&fsa, fd) = SCARG(uap, fd);
424 SCARG(&fsa, sb) = st;
425
426 if ((error = sys_fstat(p, &fsa, retval)))
427 return error;
428
429 if ((error = copyin(st, &tmpst, sizeof tmpst)))
430 return error;
431
432 bsd_to_linux_stat(&tmpst, &tmplst);
433
434 if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
435 return error;
436
437 return 0;
438 }
439
440 static int
441 linux_stat1(p, uap, retval, dolstat)
442 struct proc *p;
443 struct linux_sys_stat_args *uap;
444 register_t *retval;
445 int dolstat;
446 {
447 struct sys_stat_args sa;
448 struct linux_stat tmplst;
449 struct stat *st, tmpst;
450 caddr_t sg;
451 int error;
452
453 sg = stackgap_init(p->p_emul);
454
455 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
456
457 st = stackgap_alloc(&sg, sizeof (struct stat));
458 SCARG(&sa, ub) = st;
459 SCARG(&sa, path) = SCARG(uap, path);
460
461 if ((error = (dolstat ? sys_lstat(p, &sa, retval) :
462 sys_stat(p, &sa, retval))))
463 return error;
464
465 if ((error = copyin(st, &tmpst, sizeof tmpst)))
466 return error;
467
468 bsd_to_linux_stat(&tmpst, &tmplst);
469
470 if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
471 return error;
472
473 return 0;
474 }
475
476 int
477 linux_sys_stat(p, v, retval)
478 struct proc *p;
479 void *v;
480 register_t *retval;
481 {
482 struct linux_sys_stat_args /* {
483 syscallarg(char *) path;
484 syscallarg(struct linux_stat *) sp;
485 } */ *uap = v;
486
487 return linux_stat1(p, uap, retval, 0);
488 }
489
490 int
491 linux_sys_lstat(p, v, retval)
492 struct proc *p;
493 void *v;
494 register_t *retval;
495 {
496 struct linux_sys_lstat_args /* {
497 syscallarg(char *) path;
498 syscallarg(struct linux_stat *) sp;
499 } */ *uap = v;
500
501 return linux_stat1(p, uap, retval, 1);
502 }
503
504 /*
505 * The following syscalls are mostly here because of the alternate path check.
506 */
507 int
508 linux_sys_access(p, v, retval)
509 struct proc *p;
510 void *v;
511 register_t *retval;
512 {
513 struct linux_sys_access_args /* {
514 syscallarg(char *) path;
515 syscallarg(int) flags;
516 } */ *uap = v;
517 caddr_t sg = stackgap_init(p->p_emul);
518
519 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
520
521 return sys_access(p, uap, retval);
522 }
523
524 int
525 linux_sys_unlink(p, v, retval)
526 struct proc *p;
527 void *v;
528 register_t *retval;
529
530 {
531 struct linux_sys_unlink_args /* {
532 syscallarg(char *) path;
533 } */ *uap = v;
534 caddr_t sg = stackgap_init(p->p_emul);
535
536 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
537
538 return sys_unlink(p, uap, retval);
539 }
540
541 int
542 linux_sys_chdir(p, v, retval)
543 struct proc *p;
544 void *v;
545 register_t *retval;
546 {
547 struct linux_sys_chdir_args /* {
548 syscallarg(char *) path;
549 } */ *uap = v;
550 caddr_t sg = stackgap_init(p->p_emul);
551
552 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
553
554 return sys_chdir(p, uap, retval);
555 }
556
557 int
558 linux_sys_mknod(p, v, retval)
559 struct proc *p;
560 void *v;
561 register_t *retval;
562 {
563 struct linux_sys_mknod_args /* {
564 syscallarg(char *) path;
565 syscallarg(int) mode;
566 syscallarg(int) dev;
567 } */ *uap = v;
568 caddr_t sg = stackgap_init(p->p_emul);
569 struct sys_mkfifo_args bma;
570
571 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
572
573 /*
574 * BSD handles FIFOs seperately
575 */
576 if (SCARG(uap, mode) & S_IFIFO) {
577 SCARG(&bma, path) = SCARG(uap, path);
578 SCARG(&bma, mode) = SCARG(uap, mode);
579 return sys_mkfifo(p, uap, retval);
580 } else
581 return sys_mknod(p, uap, retval);
582 }
583
584 int
585 linux_sys_chmod(p, v, retval)
586 struct proc *p;
587 void *v;
588 register_t *retval;
589 {
590 struct linux_sys_chmod_args /* {
591 syscallarg(char *) path;
592 syscallarg(int) mode;
593 } */ *uap = v;
594 caddr_t sg = stackgap_init(p->p_emul);
595
596 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
597
598 return sys_chmod(p, uap, retval);
599 }
600
601 int
602 linux_sys_chown(p, v, retval)
603 struct proc *p;
604 void *v;
605 register_t *retval;
606 {
607 struct linux_sys_chown_args /* {
608 syscallarg(char *) path;
609 syscallarg(int) uid;
610 syscallarg(int) gid;
611 } */ *uap = v;
612 struct sys_chown_args bca;
613 caddr_t sg = stackgap_init(p->p_emul);
614
615 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
616
617 SCARG(&bca, path) = SCARG(uap, path);
618 SCARG(&bca, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
619 (uid_t)-1 : SCARG(uap, uid);
620 SCARG(&bca, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
621 (gid_t)-1 : SCARG(uap, gid);
622
623 return sys_chown(p, &bca, retval);
624 }
625
626 int
627 linux_sys_fchown(p, v, retval)
628 struct proc *p;
629 void *v;
630 register_t *retval;
631 {
632 struct linux_sys_fchown_args /* {
633 syscallarg(int) fd;
634 syscallarg(int) uid;
635 syscallarg(int) gid;
636 } */ *uap = v;
637 struct sys_fchown_args bfa;
638
639 SCARG(&bfa, fd) = SCARG(uap, fd);
640 SCARG(&bfa, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
641 (uid_t)-1 : SCARG(uap, uid);
642 SCARG(&bfa, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
643 (gid_t)-1 : SCARG(uap, gid);
644
645 return sys_fchown(p, &bfa, retval);
646 }
647
648 int
649 linux_sys_rename(p, v, retval)
650 struct proc *p;
651 void *v;
652 register_t *retval;
653 {
654 struct linux_sys_rename_args /* {
655 syscallarg(char *) from;
656 syscallarg(char *) to;
657 } */ *uap = v;
658 caddr_t sg = stackgap_init(p->p_emul);
659
660 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, from));
661 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
662
663 return sys_rename(p, uap, retval);
664 }
665
666 int
667 linux_sys_mkdir(p, v, retval)
668 struct proc *p;
669 void *v;
670 register_t *retval;
671 {
672 struct linux_sys_mkdir_args /* {
673 syscallarg(char *) path;
674 syscallarg(int) mode;
675 } */ *uap = v;
676 caddr_t sg = stackgap_init(p->p_emul);
677
678 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
679
680 return sys_mkdir(p, uap, retval);
681 }
682
683 int
684 linux_sys_rmdir(p, v, retval)
685 struct proc *p;
686 void *v;
687 register_t *retval;
688 {
689 struct linux_sys_rmdir_args /* {
690 syscallarg(char *) path;
691 } */ *uap = v;
692 caddr_t sg = stackgap_init(p->p_emul);
693
694 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
695
696 return sys_rmdir(p, uap, retval);
697 }
698
699 int
700 linux_sys_symlink(p, v, retval)
701 struct proc *p;
702 void *v;
703 register_t *retval;
704 {
705 struct linux_sys_symlink_args /* {
706 syscallarg(char *) path;
707 syscallarg(char *) to;
708 } */ *uap = v;
709 caddr_t sg = stackgap_init(p->p_emul);
710
711 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
712 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
713
714 return sys_symlink(p, uap, retval);
715 }
716
717 int
718 linux_sys_readlink(p, v, retval)
719 struct proc *p;
720 void *v;
721 register_t *retval;
722 {
723 struct linux_sys_readlink_args /* {
724 syscallarg(char *) name;
725 syscallarg(char *) buf;
726 syscallarg(int) count;
727 } */ *uap = v;
728 caddr_t sg = stackgap_init(p->p_emul);
729
730 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, name));
731
732 return sys_readlink(p, uap, retval);
733 }
734
735 int
736 linux_sys_truncate(p, v, retval)
737 struct proc *p;
738 void *v;
739 register_t *retval;
740 {
741 struct linux_sys_truncate_args /* {
742 syscallarg(char *) path;
743 syscallarg(long) length;
744 } */ *uap = v;
745 caddr_t sg = stackgap_init(p->p_emul);
746
747 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
748
749 return compat_43_sys_truncate(p, uap, retval);
750 }
751