vfs_syscalls.c revision 1.39 1 /* $NetBSD: vfs_syscalls.c,v 1.39 1994/11/18 02:48:58 christos Exp $ */
2
3 /*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * @(#)vfs_syscalls.c 8.15 (Berkeley) 6/4/94
41 */
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/namei.h>
46 #include <sys/filedesc.h>
47 #include <sys/kernel.h>
48 #include <sys/file.h>
49 #include <sys/stat.h>
50 #include <sys/vnode.h>
51 #include <sys/mount.h>
52 #include <sys/proc.h>
53 #include <sys/uio.h>
54 #include <sys/malloc.h>
55 #include <sys/dirent.h>
56
57 #include <sys/syscallargs.h>
58
59 #include <vm/vm.h>
60 #include <sys/sysctl.h>
61
62 static int change_dir __P((struct nameidata *ndp, struct proc *p));
63
64 /*
65 * Virtual File System System Calls
66 */
67
68 /*
69 * Mount a file system.
70 */
71 /* ARGSUSED */
72 mount(p, uap, retval)
73 struct proc *p;
74 register struct mount_args /* {
75 syscallarg(char *) type;
76 syscallarg(char *) path;
77 syscallarg(int) flags;
78 syscallarg(caddr_t) data;
79 } */ *uap;
80 register_t *retval;
81 {
82 register struct vnode *vp;
83 register struct mount *mp;
84 int error, flag;
85 u_long fsindex;
86 char fstypename[MFSNAMELEN];
87 struct nameidata nd;
88
89 /*
90 * Must be super user
91 */
92 if (error = suser(p->p_ucred, &p->p_acflag))
93 return (error);
94 /*
95 * Get vnode to be covered
96 */
97 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
98 SCARG(uap, path), p);
99 if (error = namei(&nd))
100 return (error);
101 vp = nd.ni_vp;
102 if (SCARG(uap, flags) & MNT_UPDATE) {
103 if ((vp->v_flag & VROOT) == 0) {
104 vput(vp);
105 return (EINVAL);
106 }
107 mp = vp->v_mount;
108 flag = mp->mnt_flag;
109 /*
110 * We only allow the filesystem to be reloaded if it
111 * is currently mounted read-only.
112 */
113 if ((SCARG(uap, flags) & MNT_RELOAD) &&
114 ((mp->mnt_flag & MNT_RDONLY) == 0)) {
115 vput(vp);
116 return (EOPNOTSUPP); /* Needs translation */
117 }
118 mp->mnt_flag |=
119 SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
120 VOP_UNLOCK(vp);
121 goto update;
122 }
123 if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0))
124 return (error);
125 if (vp->v_type != VDIR) {
126 vput(vp);
127 return (ENOTDIR);
128 }
129 if (error = copyin(SCARG(uap, type), fstypename, MFSNAMELEN)) {
130 #ifdef COMPAT_09
131 goto check_num;
132 #else
133 vput(vp);
134 return (error);
135 #endif
136 }
137 fstypename[MFSNAMELEN] = '\0';
138 for (fsindex = 0; fsindex < nvfssw; fsindex++)
139 if (vfssw[fsindex] != NULL &&
140 !strncmp(vfssw[fsindex]->vfs_name, fstypename, MFSNAMELEN))
141 break;
142 if (fsindex >= nvfssw) {
143 #ifdef COMPAT_09
144 check_num:
145 fsindex = (unsigned long)SCARG(uap, type);
146 if (fsindex >= nvfssw || vfssw[fsindex] == NULL) {
147 vput(vp);
148 return (ENODEV);
149 }
150 #else
151 vput(vp);
152 return (ENODEV);
153 #endif
154 }
155
156 /*
157 * Allocate and initialize the file system.
158 */
159 mp = (struct mount *)malloc((u_long)sizeof(struct mount),
160 M_MOUNT, M_WAITOK);
161 bzero((char *)mp, (u_long)sizeof(struct mount));
162 mp->mnt_op = vfssw[fsindex];
163 if (error = vfs_lock(mp)) {
164 free((caddr_t)mp, M_MOUNT);
165 vput(vp);
166 return (error);
167 }
168 if (vp->v_mountedhere != NULL) {
169 vfs_unlock(mp);
170 free((caddr_t)mp, M_MOUNT);
171 vput(vp);
172 return (EBUSY);
173 }
174 /* Do this early in case we block later. */
175 vfssw[fsindex]->vfs_refcount++;
176 vp->v_mountedhere = mp;
177 mp->mnt_vnodecovered = vp;
178 update:
179 /*
180 * Set the mount level flags.
181 */
182 if (SCARG(uap, flags) & MNT_RDONLY)
183 mp->mnt_flag |= MNT_RDONLY;
184 else if (mp->mnt_flag & MNT_RDONLY)
185 mp->mnt_flag |= MNT_WANTRDWR;
186 mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
187 MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
188 mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
189 MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
190 /*
191 * Mount the filesystem.
192 */
193 error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
194 if (mp->mnt_flag & MNT_UPDATE) {
195 vrele(vp);
196 if (mp->mnt_flag & MNT_WANTRDWR)
197 mp->mnt_flag &= ~MNT_RDONLY;
198 mp->mnt_flag &=~
199 (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
200 if (error)
201 mp->mnt_flag = flag;
202 return (error);
203 }
204 /*
205 * Put the new filesystem on the mount list after root.
206 */
207 cache_purge(vp);
208 if (!error) {
209 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
210 VOP_UNLOCK(vp);
211 vfs_unlock(mp);
212 error = VFS_START(mp, 0, p);
213 } else {
214 mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
215 vfssw[fsindex]->vfs_refcount--;
216 vfs_unlock(mp);
217 free((caddr_t)mp, M_MOUNT);
218 vput(vp);
219 }
220 return (error);
221 }
222
223 /*
224 * Unmount a file system.
225 *
226 * Note: unmount takes a path to the vnode mounted on as argument,
227 * not special file (as before).
228 */
229 /* ARGSUSED */
230 unmount(p, uap, retval)
231 struct proc *p;
232 register struct unmount_args /* {
233 syscallarg(char *) path;
234 syscallarg(int) flags;
235 } */ *uap;
236 register_t *retval;
237 {
238 register struct vnode *vp;
239 struct mount *mp;
240 int error;
241 struct nameidata nd;
242
243 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
244 SCARG(uap, path), p);
245 if (error = namei(&nd))
246 return (error);
247 vp = nd.ni_vp;
248
249 /*
250 * Unless this is a user mount, then must
251 * have suser privilege.
252 */
253 if (((vp->v_mount->mnt_flag & MNT_USER) == 0) &&
254 (error = suser(p->p_ucred, &p->p_acflag))) {
255 vput(vp);
256 return (error);
257 }
258
259 /*
260 * Must be the root of the filesystem
261 */
262 if ((vp->v_flag & VROOT) == 0) {
263 vput(vp);
264 return (EINVAL);
265 }
266 mp = vp->v_mount;
267 vput(vp);
268 return (dounmount(mp, SCARG(uap, flags), p));
269 }
270
271 /*
272 * Do the actual file system unmount.
273 */
274 dounmount(mp, flags, p)
275 register struct mount *mp;
276 int flags;
277 struct proc *p;
278 {
279 struct vnode *coveredvp;
280 int error;
281
282 coveredvp = mp->mnt_vnodecovered;
283 if (vfs_busy(mp))
284 return (EBUSY);
285 mp->mnt_flag |= MNT_UNMOUNT;
286 if (error = vfs_lock(mp))
287 return (error);
288
289 mp->mnt_flag &=~ MNT_ASYNC;
290 vnode_pager_umount(mp); /* release cached vnodes */
291 cache_purgevfs(mp); /* remove cache entries for this file sys */
292 if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 ||
293 (flags & MNT_FORCE))
294 error = VFS_UNMOUNT(mp, flags, p);
295 mp->mnt_flag &= ~MNT_UNMOUNT;
296 vfs_unbusy(mp);
297 if (error) {
298 vfs_unlock(mp);
299 } else {
300 vrele(coveredvp);
301 TAILQ_REMOVE(&mountlist, mp, mnt_list);
302 mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
303 mp->mnt_op->vfs_refcount--;
304 vfs_unlock(mp);
305 if (mp->mnt_vnodelist.lh_first != NULL)
306 panic("unmount: dangling vnode");
307 free((caddr_t)mp, M_MOUNT);
308 }
309 return (error);
310 }
311
312 /*
313 * Sync each mounted filesystem.
314 */
315 #ifdef DEBUG
316 int syncprt = 0;
317 struct ctldebug debug0 = { "syncprt", &syncprt };
318 #endif
319
320 /* ARGSUSED */
321 sync(p, uap, retval)
322 struct proc *p;
323 void *uap;
324 register_t *retval;
325 {
326 register struct mount *mp, *nmp;
327 int asyncflag;
328
329 for (mp = mountlist.tqh_first; mp != NULL; mp = nmp) {
330 nmp = mp->mnt_list.tqe_next;
331 /*
332 * The lock check below is to avoid races with mount
333 * and unmount.
334 */
335 if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 &&
336 !vfs_busy(mp)) {
337 asyncflag = mp->mnt_flag & MNT_ASYNC;
338 mp->mnt_flag &= ~MNT_ASYNC;
339 VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
340 if (asyncflag)
341 mp->mnt_flag |= MNT_ASYNC;
342 vfs_unbusy(mp);
343 nmp = mp->mnt_list.tqe_next;
344 }
345 }
346 #ifdef DEBUG
347 if (syncprt)
348 vfs_bufstats();
349 #endif /* DEBUG */
350 return (0);
351 }
352
353 /*
354 * Change filesystem quotas.
355 */
356 /* ARGSUSED */
357 quotactl(p, uap, retval)
358 struct proc *p;
359 register struct quotactl_args /* {
360 syscallarg(char *) path;
361 syscallarg(int) cmd;
362 syscallarg(int) uid;
363 syscallarg(caddr_t) arg;
364 } */ *uap;
365 register_t *retval;
366 {
367 register struct mount *mp;
368 int error;
369 struct nameidata nd;
370
371 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
372 if (error = namei(&nd))
373 return (error);
374 mp = nd.ni_vp->v_mount;
375 vrele(nd.ni_vp);
376 return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
377 SCARG(uap, arg), p));
378 }
379
380 /*
381 * Get filesystem statistics.
382 */
383 /* ARGSUSED */
384 statfs(p, uap, retval)
385 struct proc *p;
386 register struct statfs_args /* {
387 syscallarg(char *) path;
388 syscallarg(struct statfs *) buf;
389 } */ *uap;
390 register_t *retval;
391 {
392 register struct mount *mp;
393 register struct statfs *sp;
394 int error;
395 struct nameidata nd;
396
397 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
398 if (error = namei(&nd))
399 return (error);
400 mp = nd.ni_vp->v_mount;
401 sp = &mp->mnt_stat;
402 vrele(nd.ni_vp);
403 if (error = VFS_STATFS(mp, sp, p))
404 return (error);
405 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
406 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
407 }
408
409 /*
410 * Get filesystem statistics.
411 */
412 /* ARGSUSED */
413 fstatfs(p, uap, retval)
414 struct proc *p;
415 register struct fstatfs_args /* {
416 syscallarg(int) fd;
417 syscallarg(struct statfs *) buf;
418 } */ *uap;
419 register_t *retval;
420 {
421 struct file *fp;
422 struct mount *mp;
423 register struct statfs *sp;
424 int error;
425
426 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
427 return (error);
428 mp = ((struct vnode *)fp->f_data)->v_mount;
429 sp = &mp->mnt_stat;
430 if (error = VFS_STATFS(mp, sp, p))
431 return (error);
432 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
433 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
434 }
435
436 /*
437 * Get statistics on all filesystems.
438 */
439 getfsstat(p, uap, retval)
440 struct proc *p;
441 register struct getfsstat_args /* {
442 syscallarg(struct statfs *) buf;
443 syscallarg(long) bufsize;
444 syscallarg(int) flags;
445 } */ *uap;
446 register_t *retval;
447 {
448 register struct mount *mp, *nmp;
449 register struct statfs *sp;
450 caddr_t sfsp;
451 long count, maxcount, error;
452
453 maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
454 sfsp = (caddr_t)SCARG(uap, buf);
455 for (count = 0, mp = mountlist.tqh_first; mp != NULL; mp = nmp) {
456 nmp = mp->mnt_list.tqe_next;
457 if (sfsp && count < maxcount &&
458 ((mp->mnt_flag & MNT_MLOCK) == 0)) {
459 sp = &mp->mnt_stat;
460 /*
461 * If MNT_NOWAIT is specified, do not refresh the
462 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
463 */
464 if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 ||
465 (SCARG(uap, flags) & MNT_WAIT)) &&
466 (error = VFS_STATFS(mp, sp, p)))
467 continue;
468 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
469 if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp)))
470 return (error);
471 sfsp += sizeof(*sp);
472 }
473 count++;
474 }
475 if (sfsp && count > maxcount)
476 *retval = maxcount;
477 else
478 *retval = count;
479 return (0);
480 }
481
482 /*
483 * Change current working directory to a given file descriptor.
484 */
485 /* ARGSUSED */
486 fchdir(p, uap, retval)
487 struct proc *p;
488 struct fchdir_args /* {
489 syscallarg(int) fd;
490 } */ *uap;
491 register_t *retval;
492 {
493 register struct filedesc *fdp = p->p_fd;
494 register struct vnode *vp;
495 struct file *fp;
496 int error;
497
498 if (error = getvnode(fdp, SCARG(uap, fd), &fp))
499 return (error);
500 vp = (struct vnode *)fp->f_data;
501 VOP_LOCK(vp);
502 if (vp->v_type != VDIR)
503 error = ENOTDIR;
504 else
505 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
506 VOP_UNLOCK(vp);
507 if (error)
508 return (error);
509 VREF(vp);
510 vrele(fdp->fd_cdir);
511 fdp->fd_cdir = vp;
512 return (0);
513 }
514
515 /*
516 * Change current working directory (``.'').
517 */
518 /* ARGSUSED */
519 chdir(p, uap, retval)
520 struct proc *p;
521 struct chdir_args /* {
522 syscallarg(char *) path;
523 } */ *uap;
524 register_t *retval;
525 {
526 register struct filedesc *fdp = p->p_fd;
527 int error;
528 struct nameidata nd;
529
530 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
531 SCARG(uap, path), p);
532 if (error = change_dir(&nd, p))
533 return (error);
534 vrele(fdp->fd_cdir);
535 fdp->fd_cdir = nd.ni_vp;
536 return (0);
537 }
538
539 /*
540 * Change notion of root (``/'') directory.
541 */
542 /* ARGSUSED */
543 chroot(p, uap, retval)
544 struct proc *p;
545 struct chroot_args /* {
546 syscallarg(char *) path;
547 } */ *uap;
548 register_t *retval;
549 {
550 register struct filedesc *fdp = p->p_fd;
551 int error;
552 struct nameidata nd;
553
554 if (error = suser(p->p_ucred, &p->p_acflag))
555 return (error);
556 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
557 SCARG(uap, path), p);
558 if (error = change_dir(&nd, p))
559 return (error);
560 if (fdp->fd_rdir != NULL)
561 vrele(fdp->fd_rdir);
562 fdp->fd_rdir = nd.ni_vp;
563 return (0);
564 }
565
566 /*
567 * Common routine for chroot and chdir.
568 */
569 static int
570 change_dir(ndp, p)
571 register struct nameidata *ndp;
572 struct proc *p;
573 {
574 struct vnode *vp;
575 int error;
576
577 if (error = namei(ndp))
578 return (error);
579 vp = ndp->ni_vp;
580 if (vp->v_type != VDIR)
581 error = ENOTDIR;
582 else
583 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
584 VOP_UNLOCK(vp);
585 if (error)
586 vrele(vp);
587 return (error);
588 }
589
590 /*
591 * Check permissions, allocate an open file structure,
592 * and call the device open routine if any.
593 */
594 open(p, uap, retval)
595 struct proc *p;
596 register struct open_args /* {
597 syscallarg(char *) path;
598 syscallarg(int) flags;
599 syscallarg(int) mode;
600 } */ *uap;
601 register_t *retval;
602 {
603 register struct filedesc *fdp = p->p_fd;
604 register struct file *fp;
605 register struct vnode *vp;
606 int flags, cmode;
607 struct file *nfp;
608 int type, indx, error;
609 struct flock lf;
610 struct nameidata nd;
611 extern struct fileops vnops;
612
613 if (error = falloc(p, &nfp, &indx))
614 return (error);
615 fp = nfp;
616 flags = FFLAGS(SCARG(uap, flags));
617 cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
618 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
619 p->p_dupfd = -indx - 1; /* XXX check for fdopen */
620 fp->f_data = (caddr_t) NULL;
621 if (error = vn_open(&nd, flags, cmode, fp)) {
622 ffree(fp);
623 if ((error == ENODEV || error == ENXIO) &&
624 p->p_dupfd >= 0 && /* XXX from fdopen */
625 (error =
626 dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
627 *retval = indx;
628 return (0);
629 }
630 if (error == ERESTART)
631 error = EINTR;
632 fdp->fd_ofiles[indx] = NULL;
633 return (error);
634 }
635
636 p->p_dupfd = 0;
637 vp = nd.ni_vp;
638
639 if (fp->f_data != (caddr_t) NULL) {
640 /*
641 * The fp data was changed, so it is a cloning operation
642 * Cleanup and return
643 */
644 if (flags & FWRITE)
645 vp->v_writecount--;
646 vput(vp);
647 *retval = indx;
648 return (0);
649 }
650
651 fp->f_flag = flags & FMASK;
652 fp->f_type = DTYPE_VNODE;
653 fp->f_ops = &vnops;
654 fp->f_data = (caddr_t)vp;
655 if (flags & (O_EXLOCK | O_SHLOCK)) {
656 lf.l_whence = SEEK_SET;
657 lf.l_start = 0;
658 lf.l_len = 0;
659 if (flags & O_EXLOCK)
660 lf.l_type = F_WRLCK;
661 else
662 lf.l_type = F_RDLCK;
663 type = F_FLOCK;
664 if ((flags & FNONBLOCK) == 0)
665 type |= F_WAIT;
666 VOP_UNLOCK(vp);
667 if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
668 (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
669 ffree(fp);
670 fdp->fd_ofiles[indx] = NULL;
671 return (error);
672 }
673 VOP_LOCK(vp);
674 fp->f_flag |= FHASLOCK;
675 }
676 VOP_UNLOCK(vp);
677 *retval = indx;
678 return (0);
679 }
680
681 #ifdef COMPAT_43
682 /*
683 * Create a file.
684 */
685 compat_43_creat(p, uap, retval)
686 struct proc *p;
687 register struct compat_43_creat_args /* {
688 syscallarg(char *) path;
689 syscallarg(int) mode;
690 } */ *uap;
691 register_t *retval;
692 {
693 struct open_args /* {
694 syscallarg(char *) path;
695 syscallarg(int) flags;
696 syscallarg(int) mode;
697 } */ openuap;
698
699 SCARG(&openuap, path) = SCARG(uap, path);
700 SCARG(&openuap, mode) = SCARG(uap, mode);
701 SCARG(&openuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
702 return (open(p, &openuap, retval));
703 }
704 #endif /* COMPAT_43 */
705
706 /*
707 * Create a special file.
708 */
709 /* ARGSUSED */
710 mknod(p, uap, retval)
711 struct proc *p;
712 register struct mknod_args /* {
713 syscallarg(char *) path;
714 syscallarg(int) mode;
715 syscallarg(int) dev;
716 } */ *uap;
717 register_t *retval;
718 {
719 register struct vnode *vp;
720 struct vattr vattr;
721 int error;
722 struct nameidata nd;
723
724 if (error = suser(p->p_ucred, &p->p_acflag))
725 return (error);
726 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
727 if (error = namei(&nd))
728 return (error);
729 vp = nd.ni_vp;
730 if (vp != NULL) {
731 error = EEXIST;
732 goto bad;
733 }
734 VATTR_NULL(&vattr);
735 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
736 vattr.va_rdev = SCARG(uap, dev);
737
738 switch (SCARG(uap, mode) & S_IFMT) {
739 case S_IFMT: /* used by badsect to flag bad sectors */
740 vattr.va_type = VBAD;
741 break;
742 case S_IFCHR:
743 vattr.va_type = VCHR;
744 break;
745 case S_IFBLK:
746 vattr.va_type = VBLK;
747 break;
748 default:
749 error = EINVAL;
750 goto bad;
751 }
752 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
753 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
754 bad:
755 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
756 if (nd.ni_dvp == vp)
757 vrele(nd.ni_dvp);
758 else
759 vput(nd.ni_dvp);
760 if (vp)
761 vrele(vp);
762 return (error);
763 }
764
765 /*
766 * Create a named pipe.
767 */
768 /* ARGSUSED */
769 mkfifo(p, uap, retval)
770 struct proc *p;
771 register struct mkfifo_args /* {
772 syscallarg(char *) path;
773 syscallarg(int) mode;
774 } */ *uap;
775 register_t *retval;
776 {
777 struct vattr vattr;
778 int error;
779 struct nameidata nd;
780
781 #ifndef FIFO
782 return (EOPNOTSUPP);
783 #else
784 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
785 if (error = namei(&nd))
786 return (error);
787 if (nd.ni_vp != NULL) {
788 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
789 if (nd.ni_dvp == nd.ni_vp)
790 vrele(nd.ni_dvp);
791 else
792 vput(nd.ni_dvp);
793 vrele(nd.ni_vp);
794 return (EEXIST);
795 }
796 VATTR_NULL(&vattr);
797 vattr.va_type = VFIFO;
798 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
799 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
800 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
801 #endif /* FIFO */
802 }
803
804 /*
805 * Make a hard file link.
806 */
807 /* ARGSUSED */
808 link(p, uap, retval)
809 struct proc *p;
810 register struct link_args /* {
811 syscallarg(char *) path;
812 syscallarg(char *) link;
813 } */ *uap;
814 register_t *retval;
815 {
816 register struct vnode *vp;
817 struct nameidata nd;
818 int error;
819
820 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
821 if (error = namei(&nd))
822 return (error);
823 vp = nd.ni_vp;
824 if (vp->v_type == VDIR &&
825 (error = suser(p->p_ucred, &p->p_acflag)))
826 goto bad1;
827 nd.ni_cnd.cn_nameiop = CREATE;
828 nd.ni_cnd.cn_flags = LOCKPARENT;
829 nd.ni_dirp = SCARG(uap, link);
830 if (error = namei(&nd))
831 goto bad1;
832 if (nd.ni_vp != NULL) {
833 error = EEXIST;
834 goto bad2;
835 }
836 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
837 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
838 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
839 vrele(vp);
840 return (error);
841 bad2:
842 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
843 if (nd.ni_dvp == nd.ni_vp)
844 vrele(nd.ni_dvp);
845 else
846 vput(nd.ni_dvp);
847 if (nd.ni_vp)
848 vrele(nd.ni_vp);
849 bad1:
850 vrele(vp);
851 return (error);
852 }
853
854 /*
855 * Make a symbolic link.
856 */
857 /* ARGSUSED */
858 symlink(p, uap, retval)
859 struct proc *p;
860 register struct symlink_args /* {
861 syscallarg(char *) path;
862 syscallarg(char *) link;
863 } */ *uap;
864 register_t *retval;
865 {
866 struct vattr vattr;
867 char *path;
868 int error;
869 struct nameidata nd;
870
871 MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
872 if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, (u_int*)0))
873 goto bad;
874 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
875 if (error = namei(&nd))
876 goto bad;
877 if (nd.ni_vp) {
878 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
879 if (nd.ni_dvp == nd.ni_vp)
880 vrele(nd.ni_dvp);
881 else
882 vput(nd.ni_dvp);
883 vrele(nd.ni_vp);
884 error = EEXIST;
885 goto bad;
886 }
887 VATTR_NULL(&vattr);
888 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
889 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
890 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
891 bad:
892 FREE(path, M_NAMEI);
893 return (error);
894 }
895
896 /*
897 * Delete a name from the filesystem.
898 */
899 /* ARGSUSED */
900 unlink(p, uap, retval)
901 struct proc *p;
902 struct unlink_args /* {
903 syscallarg(char *) path;
904 } */ *uap;
905 register_t *retval;
906 {
907 register struct vnode *vp;
908 int error;
909 struct nameidata nd;
910
911 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
912 if (error = namei(&nd))
913 return (error);
914 vp = nd.ni_vp;
915 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
916 VOP_LOCK(vp);
917
918 if (vp->v_type == VDIR &&
919 (error = suser(p->p_ucred, &p->p_acflag)))
920 goto bad;
921 /*
922 * The root of a mounted filesystem cannot be deleted.
923 */
924 if (vp->v_flag & VROOT) {
925 error = EBUSY;
926 goto bad;
927 }
928 (void)vnode_pager_uncache(vp);
929 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
930 return (VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd));
931 bad:
932 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
933 if (nd.ni_dvp == vp)
934 vrele(nd.ni_dvp);
935 else
936 vput(nd.ni_dvp);
937 vput(vp);
938 return (error);
939 }
940
941 /*
942 * Reposition read/write file offset.
943 */
944 lseek(p, uap, retval)
945 struct proc *p;
946 register struct lseek_args /* {
947 syscallarg(int) fd;
948 syscallarg(int) pad;
949 syscallarg(off_t) offset;
950 syscallarg(int) whence;
951 } */ *uap;
952 register_t *retval;
953 {
954 struct ucred *cred = p->p_ucred;
955 register struct filedesc *fdp = p->p_fd;
956 register struct file *fp;
957 struct vattr vattr;
958 int error;
959
960 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
961 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
962 return (EBADF);
963 if (fp->f_type != DTYPE_VNODE)
964 return (ESPIPE);
965 switch (SCARG(uap, whence)) {
966 case L_INCR:
967 fp->f_offset += SCARG(uap, offset);
968 break;
969 case L_XTND:
970 if (error =
971 VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p))
972 return (error);
973 fp->f_offset = SCARG(uap, offset) + vattr.va_size;
974 break;
975 case L_SET:
976 fp->f_offset = SCARG(uap, offset);
977 break;
978 default:
979 return (EINVAL);
980 }
981 *(off_t *)retval = fp->f_offset;
982 return (0);
983 }
984
985 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) || defined(COMPAT_SVR4)
986 /*
987 * Reposition read/write file offset.
988 */
989 compat_43_lseek(p, uap, retval)
990 struct proc *p;
991 register struct compat_43_lseek_args /* {
992 syscallarg(int) fd;
993 syscallarg(long) offset;
994 syscallarg(int) whence;
995 } */ *uap;
996 register_t *retval;
997 {
998 struct lseek_args /* {
999 syscallarg(int) fd;
1000 syscallarg(int) pad;
1001 syscallarg(off_t) offset;
1002 syscallarg(int) whence;
1003 } */ nuap;
1004 off_t qret;
1005 int error;
1006
1007 SCARG(&nuap, fd) = SCARG(uap, fd);
1008 SCARG(&nuap, offset) = SCARG(uap, offset);
1009 SCARG(&nuap, whence) = SCARG(uap, whence);
1010 error = lseek(p, &nuap, &qret);
1011 *(long *)retval = qret;
1012 return (error);
1013 }
1014 #endif /* COMPAT_43 || COMPAT_SUNOS */
1015
1016 /*
1017 * Check access permissions.
1018 */
1019 access(p, uap, retval)
1020 struct proc *p;
1021 register struct access_args /* {
1022 syscallarg(char *) path;
1023 syscallarg(int) flags;
1024 } */ *uap;
1025 register_t *retval;
1026 {
1027 register struct ucred *cred = p->p_ucred;
1028 register struct vnode *vp;
1029 int error, flags, t_gid, t_uid;
1030 struct nameidata nd;
1031
1032 t_uid = cred->cr_uid;
1033 t_gid = cred->cr_groups[0];
1034 cred->cr_uid = p->p_cred->p_ruid;
1035 cred->cr_groups[0] = p->p_cred->p_rgid;
1036 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1037 SCARG(uap, path), p);
1038 if (error = namei(&nd))
1039 goto out1;
1040 vp = nd.ni_vp;
1041
1042 /* Flags == 0 means only check for existence. */
1043 if (SCARG(uap, flags)) {
1044 flags = 0;
1045 if (SCARG(uap, flags) & R_OK)
1046 flags |= VREAD;
1047 if (SCARG(uap, flags) & W_OK)
1048 flags |= VWRITE;
1049 if (SCARG(uap, flags) & X_OK)
1050 flags |= VEXEC;
1051 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1052 error = VOP_ACCESS(vp, flags, cred, p);
1053 }
1054 vput(vp);
1055 out1:
1056 cred->cr_uid = t_uid;
1057 cred->cr_groups[0] = t_gid;
1058 return (error);
1059 }
1060
1061 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) || defined(COMPAT_IBCS2)
1062 /*
1063 * Get file status; this version follows links.
1064 */
1065 /* ARGSUSED */
1066 compat_43_stat(p, uap, retval)
1067 struct proc *p;
1068 register struct compat_43_stat_args /* {
1069 syscallarg(char *) path;
1070 syscallarg(struct ostat *) ub;
1071 } */ *uap;
1072 register_t *retval;
1073 {
1074 struct stat sb;
1075 struct ostat osb;
1076 int error;
1077 struct nameidata nd;
1078
1079 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1080 SCARG(uap, path), p);
1081 if (error = namei(&nd))
1082 return (error);
1083 error = vn_stat(nd.ni_vp, &sb, p);
1084 vput(nd.ni_vp);
1085 if (error)
1086 return (error);
1087 cvtstat(&sb, &osb);
1088 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1089 return (error);
1090 }
1091
1092 /*
1093 * Get file status; this version does not follow links.
1094 */
1095 /* ARGSUSED */
1096 compat_43_lstat(p, uap, retval)
1097 struct proc *p;
1098 register struct compat_43_lstat_args /* {
1099 syscallarg(char *) path;
1100 syscallarg(struct ostat *) ub;
1101 } */ *uap;
1102 register_t *retval;
1103 {
1104 struct stat sb;
1105 struct ostat osb;
1106 int error;
1107 struct nameidata nd;
1108
1109 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
1110 SCARG(uap, path), p);
1111 if (error = namei(&nd))
1112 return (error);
1113 error = vn_stat(nd.ni_vp, &sb, p);
1114 vput(nd.ni_vp);
1115 if (error)
1116 return (error);
1117 cvtstat(&sb, &osb);
1118 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1119 return (error);
1120 }
1121
1122 /*
1123 * Convert from an old to a new stat structure.
1124 */
1125 cvtstat(st, ost)
1126 struct stat *st;
1127 struct ostat *ost;
1128 {
1129
1130 ost->st_dev = st->st_dev;
1131 ost->st_ino = st->st_ino;
1132 ost->st_mode = st->st_mode;
1133 ost->st_nlink = st->st_nlink;
1134 ost->st_uid = st->st_uid;
1135 ost->st_gid = st->st_gid;
1136 ost->st_rdev = st->st_rdev;
1137 if (st->st_size < (quad_t)1 << 32)
1138 ost->st_size = st->st_size;
1139 else
1140 ost->st_size = -2;
1141 ost->st_atime = st->st_atime;
1142 ost->st_mtime = st->st_mtime;
1143 ost->st_ctime = st->st_ctime;
1144 ost->st_blksize = st->st_blksize;
1145 ost->st_blocks = st->st_blocks;
1146 ost->st_flags = st->st_flags;
1147 ost->st_gen = st->st_gen;
1148 }
1149 #endif /* COMPAT_43 || COMPAT_SUNOS || COMPAT_IBCS2 */
1150
1151 /*
1152 * Get file status; this version follows links.
1153 */
1154 /* ARGSUSED */
1155 stat(p, uap, retval)
1156 struct proc *p;
1157 register struct stat_args /* {
1158 syscallarg(char *) path;
1159 syscallarg(struct stat *) ub;
1160 } */ *uap;
1161 register_t *retval;
1162 {
1163 struct stat sb;
1164 int error;
1165 struct nameidata nd;
1166
1167 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1168 SCARG(uap, path), p);
1169 if (error = namei(&nd))
1170 return (error);
1171 error = vn_stat(nd.ni_vp, &sb, p);
1172 vput(nd.ni_vp);
1173 if (error)
1174 return (error);
1175 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1176 return (error);
1177 }
1178
1179 /*
1180 * Get file status; this version does not follow links.
1181 */
1182 /* ARGSUSED */
1183 lstat(p, uap, retval)
1184 struct proc *p;
1185 register struct lstat_args /* {
1186 syscallarg(char *) path;
1187 syscallarg(struct stat *) ub;
1188 } */ *uap;
1189 register_t *retval;
1190 {
1191 int error;
1192 struct vnode *vp, *dvp;
1193 struct stat sb, sb1;
1194 struct nameidata nd;
1195
1196 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
1197 SCARG(uap, path), p);
1198 if (error = namei(&nd))
1199 return (error);
1200 /*
1201 * For symbolic links, always return the attributes of its
1202 * containing directory, except for mode, size, and links.
1203 */
1204 vp = nd.ni_vp;
1205 dvp = nd.ni_dvp;
1206 if (vp->v_type != VLNK) {
1207 if (dvp == vp)
1208 vrele(dvp);
1209 else
1210 vput(dvp);
1211 error = vn_stat(vp, &sb, p);
1212 vput(vp);
1213 if (error)
1214 return (error);
1215 } else {
1216 error = vn_stat(dvp, &sb, p);
1217 vput(dvp);
1218 if (error) {
1219 vput(vp);
1220 return (error);
1221 }
1222 error = vn_stat(vp, &sb1, p);
1223 vput(vp);
1224 if (error)
1225 return (error);
1226 sb.st_mode &= ~S_IFDIR;
1227 sb.st_mode |= S_IFLNK;
1228 sb.st_nlink = sb1.st_nlink;
1229 sb.st_size = sb1.st_size;
1230 sb.st_blocks = sb1.st_blocks;
1231 }
1232 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1233 return (error);
1234 }
1235
1236 /*
1237 * Get configurable pathname variables.
1238 */
1239 /* ARGSUSED */
1240 pathconf(p, uap, retval)
1241 struct proc *p;
1242 register struct pathconf_args /* {
1243 syscallarg(char *) path;
1244 syscallarg(int) name;
1245 } */ *uap;
1246 register_t *retval;
1247 {
1248 int error;
1249 struct nameidata nd;
1250
1251 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1252 SCARG(uap, path), p);
1253 if (error = namei(&nd))
1254 return (error);
1255 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
1256 vput(nd.ni_vp);
1257 return (error);
1258 }
1259
1260 /*
1261 * Return target name of a symbolic link.
1262 */
1263 /* ARGSUSED */
1264 readlink(p, uap, retval)
1265 struct proc *p;
1266 register struct readlink_args /* {
1267 syscallarg(char *) path;
1268 syscallarg(char *) buf;
1269 syscallarg(int) count;
1270 } */ *uap;
1271 register_t *retval;
1272 {
1273 register struct vnode *vp;
1274 struct iovec aiov;
1275 struct uio auio;
1276 int error;
1277 struct nameidata nd;
1278
1279 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
1280 SCARG(uap, path), p);
1281 if (error = namei(&nd))
1282 return (error);
1283 vp = nd.ni_vp;
1284 if (vp->v_type != VLNK)
1285 error = EINVAL;
1286 else {
1287 aiov.iov_base = SCARG(uap, buf);
1288 aiov.iov_len = SCARG(uap, count);
1289 auio.uio_iov = &aiov;
1290 auio.uio_iovcnt = 1;
1291 auio.uio_offset = 0;
1292 auio.uio_rw = UIO_READ;
1293 auio.uio_segflg = UIO_USERSPACE;
1294 auio.uio_procp = p;
1295 auio.uio_resid = SCARG(uap, count);
1296 error = VOP_READLINK(vp, &auio, p->p_ucred);
1297 }
1298 vput(vp);
1299 *retval = SCARG(uap, count) - auio.uio_resid;
1300 return (error);
1301 }
1302
1303 /*
1304 * Change flags of a file given a path name.
1305 */
1306 /* ARGSUSED */
1307 chflags(p, uap, retval)
1308 struct proc *p;
1309 register struct chflags_args /* {
1310 syscallarg(char *) path;
1311 syscallarg(int) flags;
1312 } */ *uap;
1313 register_t *retval;
1314 {
1315 register struct vnode *vp;
1316 struct vattr vattr;
1317 int error;
1318 struct nameidata nd;
1319
1320 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1321 if (error = namei(&nd))
1322 return (error);
1323 vp = nd.ni_vp;
1324 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1325 VOP_LOCK(vp);
1326 if (vp->v_mount->mnt_flag & MNT_RDONLY)
1327 error = EROFS;
1328 else {
1329 VATTR_NULL(&vattr);
1330 vattr.va_flags = SCARG(uap, flags);
1331 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1332 }
1333 vput(vp);
1334 return (error);
1335 }
1336
1337 /*
1338 * Change flags of a file given a file descriptor.
1339 */
1340 /* ARGSUSED */
1341 fchflags(p, uap, retval)
1342 struct proc *p;
1343 register struct fchflags_args /* {
1344 syscallarg(int) fd;
1345 syscallarg(int) flags;
1346 } */ *uap;
1347 register_t *retval;
1348 {
1349 struct vattr vattr;
1350 struct vnode *vp;
1351 struct file *fp;
1352 int error;
1353
1354 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1355 return (error);
1356 vp = (struct vnode *)fp->f_data;
1357 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1358 VOP_LOCK(vp);
1359 if (vp->v_mount->mnt_flag & MNT_RDONLY)
1360 error = EROFS;
1361 else {
1362 VATTR_NULL(&vattr);
1363 vattr.va_flags = SCARG(uap, flags);
1364 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1365 }
1366 VOP_UNLOCK(vp);
1367 return (error);
1368 }
1369
1370 /*
1371 * Change mode of a file given path name.
1372 */
1373 /* ARGSUSED */
1374 chmod(p, uap, retval)
1375 struct proc *p;
1376 register struct chmod_args /* {
1377 syscallarg(char *) path;
1378 syscallarg(int) mode;
1379 } */ *uap;
1380 register_t *retval;
1381 {
1382 register struct vnode *vp;
1383 struct vattr vattr;
1384 int error;
1385 struct nameidata nd;
1386
1387 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1388 if (error = namei(&nd))
1389 return (error);
1390 vp = nd.ni_vp;
1391 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1392 VOP_LOCK(vp);
1393 if (vp->v_mount->mnt_flag & MNT_RDONLY)
1394 error = EROFS;
1395 else {
1396 VATTR_NULL(&vattr);
1397 vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
1398 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1399 }
1400 vput(vp);
1401 return (error);
1402 }
1403
1404 /*
1405 * Change mode of a file given a file descriptor.
1406 */
1407 /* ARGSUSED */
1408 fchmod(p, uap, retval)
1409 struct proc *p;
1410 register struct fchmod_args /* {
1411 syscallarg(int) fd;
1412 syscallarg(int) mode;
1413 } */ *uap;
1414 register_t *retval;
1415 {
1416 struct vattr vattr;
1417 struct vnode *vp;
1418 struct file *fp;
1419 int error;
1420
1421 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1422 return (error);
1423 vp = (struct vnode *)fp->f_data;
1424 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1425 VOP_LOCK(vp);
1426 if (vp->v_mount->mnt_flag & MNT_RDONLY)
1427 error = EROFS;
1428 else {
1429 VATTR_NULL(&vattr);
1430 vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
1431 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1432 }
1433 VOP_UNLOCK(vp);
1434 return (error);
1435 }
1436
1437 /*
1438 * Set ownership given a path name.
1439 */
1440 /* ARGSUSED */
1441 chown(p, uap, retval)
1442 struct proc *p;
1443 register struct chown_args /* {
1444 syscallarg(char *) path;
1445 syscallarg(int) uid;
1446 syscallarg(int) gid;
1447 } */ *uap;
1448 register_t *retval;
1449 {
1450 register struct vnode *vp;
1451 struct vattr vattr;
1452 int error;
1453 struct nameidata nd;
1454
1455 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1456 if (error = namei(&nd))
1457 return (error);
1458 vp = nd.ni_vp;
1459 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1460 VOP_LOCK(vp);
1461 if (vp->v_mount->mnt_flag & MNT_RDONLY)
1462 error = EROFS;
1463 else {
1464 VATTR_NULL(&vattr);
1465 vattr.va_uid = SCARG(uap, uid);
1466 vattr.va_gid = SCARG(uap, gid);
1467 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1468 }
1469 vput(vp);
1470 return (error);
1471 }
1472
1473 /*
1474 * Set ownership given a file descriptor.
1475 */
1476 /* ARGSUSED */
1477 fchown(p, uap, retval)
1478 struct proc *p;
1479 register struct fchown_args /* {
1480 syscallarg(int) fd;
1481 syscallarg(int) uid;
1482 syscallarg(int) gid;
1483 } */ *uap;
1484 register_t *retval;
1485 {
1486 struct vattr vattr;
1487 struct vnode *vp;
1488 struct file *fp;
1489 int error;
1490
1491 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1492 return (error);
1493 vp = (struct vnode *)fp->f_data;
1494 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1495 VOP_LOCK(vp);
1496 if (vp->v_mount->mnt_flag & MNT_RDONLY)
1497 error = EROFS;
1498 else {
1499 VATTR_NULL(&vattr);
1500 vattr.va_uid = SCARG(uap, uid);
1501 vattr.va_gid = SCARG(uap, gid);
1502 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1503 }
1504 VOP_UNLOCK(vp);
1505 return (error);
1506 }
1507
1508 /*
1509 * Set the access and modification times of a file.
1510 */
1511 /* ARGSUSED */
1512 utimes(p, uap, retval)
1513 struct proc *p;
1514 register struct utimes_args /* {
1515 syscallarg(char *) path;
1516 syscallarg(struct timeval *) tptr;
1517 } */ *uap;
1518 register_t *retval;
1519 {
1520 register struct vnode *vp;
1521 struct timeval tv[2];
1522 struct vattr vattr;
1523 int error;
1524 struct nameidata nd;
1525
1526 VATTR_NULL(&vattr);
1527 if (SCARG(uap, tptr) == NULL) {
1528 microtime(&tv[0]);
1529 tv[1] = tv[0];
1530 vattr.va_vaflags |= VA_UTIMES_NULL;
1531 } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
1532 sizeof (tv)))
1533 return (error);
1534 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1535 if (error = namei(&nd))
1536 return (error);
1537 vp = nd.ni_vp;
1538 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1539 VOP_LOCK(vp);
1540 if (vp->v_mount->mnt_flag & MNT_RDONLY)
1541 error = EROFS;
1542 else {
1543 vattr.va_atime.ts_sec = tv[0].tv_sec;
1544 vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;
1545 vattr.va_mtime.ts_sec = tv[1].tv_sec;
1546 vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;
1547 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1548 }
1549 vput(vp);
1550 return (error);
1551 }
1552
1553 /*
1554 * Truncate a file given its path name.
1555 */
1556 /* ARGSUSED */
1557 truncate(p, uap, retval)
1558 struct proc *p;
1559 register struct truncate_args /* {
1560 syscallarg(char *) path;
1561 syscallarg(int) pad;
1562 syscallarg(off_t) length;
1563 } */ *uap;
1564 register_t *retval;
1565 {
1566 register struct vnode *vp;
1567 struct vattr vattr;
1568 int error;
1569 struct nameidata nd;
1570
1571 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1572 if (error = namei(&nd))
1573 return (error);
1574 vp = nd.ni_vp;
1575 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1576 VOP_LOCK(vp);
1577 if (vp->v_type == VDIR)
1578 error = EISDIR;
1579 else if ((error = vn_writechk(vp)) == 0 &&
1580 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
1581 VATTR_NULL(&vattr);
1582 vattr.va_size = SCARG(uap, length);
1583 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1584 }
1585 vput(vp);
1586 return (error);
1587 }
1588
1589 /*
1590 * Truncate a file given a file descriptor.
1591 */
1592 /* ARGSUSED */
1593 ftruncate(p, uap, retval)
1594 struct proc *p;
1595 register struct ftruncate_args /* {
1596 syscallarg(int) fd;
1597 syscallarg(int) pad;
1598 syscallarg(off_t) length;
1599 } */ *uap;
1600 register_t *retval;
1601 {
1602 struct vattr vattr;
1603 struct vnode *vp;
1604 struct file *fp;
1605 int error;
1606
1607 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1608 return (error);
1609 if ((fp->f_flag & FWRITE) == 0)
1610 return (EINVAL);
1611 vp = (struct vnode *)fp->f_data;
1612 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1613 VOP_LOCK(vp);
1614 if (vp->v_type == VDIR)
1615 error = EISDIR;
1616 else if ((error = vn_writechk(vp)) == 0) {
1617 VATTR_NULL(&vattr);
1618 vattr.va_size = SCARG(uap, length);
1619 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
1620 }
1621 VOP_UNLOCK(vp);
1622 return (error);
1623 }
1624
1625 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1626 /*
1627 * Truncate a file given its path name.
1628 */
1629 /* ARGSUSED */
1630 compat_43_truncate(p, uap, retval)
1631 struct proc *p;
1632 register struct compat_43_truncate_args /* {
1633 syscallarg(char *) path;
1634 syscallarg(long) length;
1635 } */ *uap;
1636 register_t *retval;
1637 {
1638 struct truncate_args nuap;
1639
1640 SCARG(&nuap, path) = SCARG(uap, path);
1641 SCARG(&nuap, length) = SCARG(uap, length);
1642 return (truncate(p, &nuap, retval));
1643 }
1644
1645 /*
1646 * Truncate a file given a file descriptor.
1647 */
1648 /* ARGSUSED */
1649 compat_43_ftruncate(p, uap, retval)
1650 struct proc *p;
1651 register struct compat_43_ftruncate_args /* {
1652 syscallarg(int) fd;
1653 syscallarg(long) length;
1654 } */ *uap;
1655 register_t *retval;
1656 {
1657 struct ftruncate_args nuap;
1658
1659 SCARG(&nuap, fd) = SCARG(uap, fd);
1660 SCARG(&nuap, length) = SCARG(uap, length);
1661 return (ftruncate(p, &nuap, retval));
1662 }
1663 #endif /* COMPAT_43 || COMPAT_SUNOS */
1664
1665 /*
1666 * Sync an open file.
1667 */
1668 /* ARGSUSED */
1669 fsync(p, uap, retval)
1670 struct proc *p;
1671 struct fsync_args /* {
1672 syscallarg(int) fd;
1673 } */ *uap;
1674 register_t *retval;
1675 {
1676 register struct vnode *vp;
1677 struct file *fp;
1678 int error;
1679
1680 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1681 return (error);
1682 vp = (struct vnode *)fp->f_data;
1683 VOP_LOCK(vp);
1684 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
1685 VOP_UNLOCK(vp);
1686 return (error);
1687 }
1688
1689 /*
1690 * Rename files. Source and destination must either both be directories,
1691 * or both not be directories. If target is a directory, it must be empty.
1692 */
1693 /* ARGSUSED */
1694 rename(p, uap, retval)
1695 struct proc *p;
1696 register struct rename_args /* {
1697 syscallarg(char *) from;
1698 syscallarg(char *) to;
1699 } */ *uap;
1700 register_t *retval;
1701 {
1702 register struct vnode *tvp, *fvp, *tdvp;
1703 struct nameidata fromnd, tond;
1704 int error;
1705
1706 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
1707 SCARG(uap, from), p);
1708 if (error = namei(&fromnd))
1709 return (error);
1710 fvp = fromnd.ni_vp;
1711 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
1712 UIO_USERSPACE, SCARG(uap, to), p);
1713 if (error = namei(&tond)) {
1714 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1715 vrele(fromnd.ni_dvp);
1716 vrele(fvp);
1717 goto out1;
1718 }
1719 tdvp = tond.ni_dvp;
1720 tvp = tond.ni_vp;
1721 if (tvp != NULL) {
1722 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1723 error = ENOTDIR;
1724 goto out;
1725 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1726 error = EISDIR;
1727 goto out;
1728 }
1729 }
1730 if (fvp == tdvp)
1731 error = EINVAL;
1732 /*
1733 * If source is the same as the destination (that is the
1734 * same inode number with the same name in the same directory),
1735 * then there is nothing to do.
1736 */
1737 if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1738 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1739 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1740 fromnd.ni_cnd.cn_namelen))
1741 error = -1;
1742 out:
1743 if (!error) {
1744 LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE);
1745 if (fromnd.ni_dvp != tdvp)
1746 LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1747 if (tvp)
1748 LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE);
1749 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1750 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1751 } else {
1752 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
1753 if (tdvp == tvp)
1754 vrele(tdvp);
1755 else
1756 vput(tdvp);
1757 if (tvp)
1758 vput(tvp);
1759 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1760 vrele(fromnd.ni_dvp);
1761 vrele(fvp);
1762 }
1763 vrele(tond.ni_startdir);
1764 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
1765 out1:
1766 if (fromnd.ni_startdir)
1767 vrele(fromnd.ni_startdir);
1768 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
1769 if (error == -1)
1770 return (0);
1771 return (error);
1772 }
1773
1774 /*
1775 * Make a directory file.
1776 */
1777 /* ARGSUSED */
1778 mkdir(p, uap, retval)
1779 struct proc *p;
1780 register struct mkdir_args /* {
1781 syscallarg(char *) path;
1782 syscallarg(int) mode;
1783 } */ *uap;
1784 register_t *retval;
1785 {
1786 register struct vnode *vp;
1787 struct vattr vattr;
1788 int error;
1789 struct nameidata nd;
1790
1791 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1792 if (error = namei(&nd))
1793 return (error);
1794 vp = nd.ni_vp;
1795 if (vp != NULL) {
1796 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1797 if (nd.ni_dvp == vp)
1798 vrele(nd.ni_dvp);
1799 else
1800 vput(nd.ni_dvp);
1801 vrele(vp);
1802 return (EEXIST);
1803 }
1804 VATTR_NULL(&vattr);
1805 vattr.va_type = VDIR;
1806 vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
1807 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1808 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1809 if (!error)
1810 vput(nd.ni_vp);
1811 return (error);
1812 }
1813
1814 /*
1815 * Remove a directory file.
1816 */
1817 /* ARGSUSED */
1818 rmdir(p, uap, retval)
1819 struct proc *p;
1820 struct rmdir_args /* {
1821 syscallarg(char *) path;
1822 } */ *uap;
1823 register_t *retval;
1824 {
1825 register struct vnode *vp;
1826 int error;
1827 struct nameidata nd;
1828
1829 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
1830 SCARG(uap, path), p);
1831 if (error = namei(&nd))
1832 return (error);
1833 vp = nd.ni_vp;
1834 if (vp->v_type != VDIR) {
1835 error = ENOTDIR;
1836 goto out;
1837 }
1838 /*
1839 * No rmdir "." please.
1840 */
1841 if (nd.ni_dvp == vp) {
1842 error = EINVAL;
1843 goto out;
1844 }
1845 /*
1846 * The root of a mounted filesystem cannot be deleted.
1847 */
1848 if (vp->v_flag & VROOT)
1849 error = EBUSY;
1850 out:
1851 if (!error) {
1852 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1853 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1854 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1855 } else {
1856 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1857 if (nd.ni_dvp == vp)
1858 vrele(nd.ni_dvp);
1859 else
1860 vput(nd.ni_dvp);
1861 vput(vp);
1862 }
1863 return (error);
1864 }
1865
1866 #if defined(COMPAT_43) || defined(COMPAT_HPUX)
1867 /*
1868 * Read a block of directory entries in a file system independent format.
1869 */
1870 compat_43_getdirentries(p, uap, retval)
1871 struct proc *p;
1872 register struct compat_43_getdirentries_args /* {
1873 syscallarg(int) fd;
1874 syscallarg(char *) buf;
1875 syscallarg(u_int) count;
1876 syscallarg(long *) basep;
1877 } */ *uap;
1878 register_t *retval;
1879 {
1880 register struct vnode *vp;
1881 struct file *fp;
1882 struct uio auio, kuio;
1883 struct iovec aiov, kiov;
1884 struct dirent *dp, *edp;
1885 caddr_t dirbuf;
1886 int error, eofflag, readcnt;
1887 long loff;
1888
1889 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1890 return (error);
1891 if ((fp->f_flag & FREAD) == 0)
1892 return (EBADF);
1893 vp = (struct vnode *)fp->f_data;
1894 unionread:
1895 if (vp->v_type != VDIR)
1896 return (EINVAL);
1897 aiov.iov_base = SCARG(uap, buf);
1898 aiov.iov_len = SCARG(uap, count);
1899 auio.uio_iov = &aiov;
1900 auio.uio_iovcnt = 1;
1901 auio.uio_rw = UIO_READ;
1902 auio.uio_segflg = UIO_USERSPACE;
1903 auio.uio_procp = p;
1904 auio.uio_resid = SCARG(uap, count);
1905 VOP_LOCK(vp);
1906 loff = auio.uio_offset = fp->f_offset;
1907 # if (BYTE_ORDER != LITTLE_ENDIAN)
1908 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
1909 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
1910 (u_long *)0, 0);
1911 fp->f_offset = auio.uio_offset;
1912 } else
1913 # endif
1914 {
1915 kuio = auio;
1916 kuio.uio_iov = &kiov;
1917 kuio.uio_segflg = UIO_SYSSPACE;
1918 kiov.iov_len = SCARG(uap, count);
1919 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
1920 kiov.iov_base = dirbuf;
1921 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
1922 (u_long *)0, 0);
1923 fp->f_offset = kuio.uio_offset;
1924 if (error == 0) {
1925 readcnt = SCARG(uap, count) - kuio.uio_resid;
1926 edp = (struct dirent *)&dirbuf[readcnt];
1927 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
1928 # if (BYTE_ORDER == LITTLE_ENDIAN)
1929 /*
1930 * The expected low byte of
1931 * dp->d_namlen is our dp->d_type.
1932 * The high MBZ byte of dp->d_namlen
1933 * is our dp->d_namlen.
1934 */
1935 dp->d_type = dp->d_namlen;
1936 dp->d_namlen = 0;
1937 # else
1938 /*
1939 * The dp->d_type is the high byte
1940 * of the expected dp->d_namlen,
1941 * so must be zero'ed.
1942 */
1943 dp->d_type = 0;
1944 # endif
1945 if (dp->d_reclen > 0) {
1946 dp = (struct dirent *)
1947 ((char *)dp + dp->d_reclen);
1948 } else {
1949 error = EIO;
1950 break;
1951 }
1952 }
1953 if (dp >= edp)
1954 error = uiomove(dirbuf, readcnt, &auio);
1955 }
1956 FREE(dirbuf, M_TEMP);
1957 }
1958 VOP_UNLOCK(vp);
1959 if (error)
1960 return (error);
1961
1962 #ifdef UNION
1963 {
1964 extern int (**union_vnodeop_p)();
1965 extern struct vnode *union_lowervp __P((struct vnode *));
1966
1967 if ((SCARG(uap, count) == auio.uio_resid) &&
1968 (vp->v_op == union_vnodeop_p)) {
1969 struct vnode *lvp;
1970
1971 lvp = union_lowervp(vp);
1972 if (lvp != NULLVP) {
1973 VOP_LOCK(lvp);
1974 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
1975 VOP_UNLOCK(lvp);
1976
1977 if (error) {
1978 vrele(lvp);
1979 return (error);
1980 }
1981 fp->f_data = (caddr_t) lvp;
1982 fp->f_offset = 0;
1983 error = vn_close(vp, FREAD, fp->f_cred, p);
1984 if (error)
1985 return (error);
1986 vp = lvp;
1987 goto unionread;
1988 }
1989 }
1990 }
1991 #endif /* UNION */
1992
1993 if ((SCARG(uap, count) == auio.uio_resid) &&
1994 (vp->v_flag & VROOT) && (vp->v_mount->mnt_flag & MNT_UNION)) {
1995 struct vnode *tvp = vp;
1996 vp = vp->v_mount->mnt_vnodecovered;
1997 VREF(vp);
1998 fp->f_data = (caddr_t) vp;
1999 fp->f_offset = 0;
2000 vrele(tvp);
2001 goto unionread;
2002 }
2003 error =
2004 copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), sizeof(long));
2005 *retval = SCARG(uap, count) - auio.uio_resid;
2006 return (error);
2007 }
2008 #endif /* COMPAT_43 */
2009
2010 /*
2011 * Read a block of directory entries in a file system independent format.
2012 */
2013 getdirentries(p, uap, retval)
2014 struct proc *p;
2015 register struct getdirentries_args /* {
2016 syscallarg(int) fd;
2017 syscallarg(char *) buf;
2018 syscallarg(u_int) count;
2019 syscallarg(long *) basep;
2020 } */ *uap;
2021 register_t *retval;
2022 {
2023 register struct vnode *vp;
2024 struct file *fp;
2025 struct uio auio;
2026 struct iovec aiov;
2027 long loff;
2028 int error, eofflag;
2029
2030 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
2031 return (error);
2032 if ((fp->f_flag & FREAD) == 0)
2033 return (EBADF);
2034 vp = (struct vnode *)fp->f_data;
2035 unionread:
2036 if (vp->v_type != VDIR)
2037 return (EINVAL);
2038 aiov.iov_base = SCARG(uap, buf);
2039 aiov.iov_len = SCARG(uap, count);
2040 auio.uio_iov = &aiov;
2041 auio.uio_iovcnt = 1;
2042 auio.uio_rw = UIO_READ;
2043 auio.uio_segflg = UIO_USERSPACE;
2044 auio.uio_procp = p;
2045 auio.uio_resid = SCARG(uap, count);
2046 VOP_LOCK(vp);
2047 loff = auio.uio_offset = fp->f_offset;
2048 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (u_long *)0, 0);
2049 fp->f_offset = auio.uio_offset;
2050 VOP_UNLOCK(vp);
2051 if (error)
2052 return (error);
2053
2054 #ifdef UNION
2055 {
2056 extern int (**union_vnodeop_p)();
2057 extern struct vnode *union_lowervp __P((struct vnode *));
2058
2059 if ((SCARG(uap, count) == auio.uio_resid) &&
2060 (vp->v_op == union_vnodeop_p)) {
2061 struct vnode *lvp;
2062
2063 lvp = union_lowervp(vp);
2064 if (lvp != NULLVP) {
2065 VOP_LOCK(lvp);
2066 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
2067 VOP_UNLOCK(lvp);
2068
2069 if (error) {
2070 vrele(lvp);
2071 return (error);
2072 }
2073 fp->f_data = (caddr_t) lvp;
2074 fp->f_offset = 0;
2075 error = vn_close(vp, FREAD, fp->f_cred, p);
2076 if (error)
2077 return (error);
2078 vp = lvp;
2079 goto unionread;
2080 }
2081 }
2082 }
2083 #endif /* UNION */
2084
2085 if ((SCARG(uap, count) == auio.uio_resid) &&
2086 (vp->v_flag & VROOT) && (vp->v_mount->mnt_flag & MNT_UNION)) {
2087 struct vnode *tvp = vp;
2088 vp = vp->v_mount->mnt_vnodecovered;
2089 VREF(vp);
2090 fp->f_data = (caddr_t) vp;
2091 fp->f_offset = 0;
2092 vrele(tvp);
2093 goto unionread;
2094 }
2095 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2096 sizeof(long));
2097 *retval = SCARG(uap, count) - auio.uio_resid;
2098 return (error);
2099 }
2100
2101 /*
2102 * Set the mode mask for creation of filesystem nodes.
2103 */
2104 mode_t /* XXX */
2105 umask(p, uap, retval)
2106 struct proc *p;
2107 struct umask_args /* {
2108 syscallarg(int) newmask;
2109 } */ *uap;
2110 register_t *retval;
2111 {
2112 register struct filedesc *fdp;
2113
2114 fdp = p->p_fd;
2115 *retval = fdp->fd_cmask;
2116 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
2117 return (0);
2118 }
2119
2120 /*
2121 * Void all references to file by ripping underlying filesystem
2122 * away from vnode.
2123 */
2124 /* ARGSUSED */
2125 revoke(p, uap, retval)
2126 struct proc *p;
2127 register struct revoke_args /* {
2128 syscallarg(char *) path;
2129 } */ *uap;
2130 register_t *retval;
2131 {
2132 register struct vnode *vp;
2133 struct vattr vattr;
2134 int error;
2135 struct nameidata nd;
2136
2137 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2138 if (error = namei(&nd))
2139 return (error);
2140 vp = nd.ni_vp;
2141 if (vp->v_type != VCHR && vp->v_type != VBLK) {
2142 error = EINVAL;
2143 goto out;
2144 }
2145 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
2146 goto out;
2147 if (p->p_ucred->cr_uid != vattr.va_uid &&
2148 (error = suser(p->p_ucred, &p->p_acflag)))
2149 goto out;
2150 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
2151 vgoneall(vp);
2152 out:
2153 vrele(vp);
2154 return (error);
2155 }
2156
2157 /*
2158 * Convert a user file descriptor to a kernel file entry.
2159 */
2160 getvnode(fdp, fd, fpp)
2161 struct filedesc *fdp;
2162 struct file **fpp;
2163 int fd;
2164 {
2165 struct file *fp;
2166
2167 if ((u_int)fd >= fdp->fd_nfiles ||
2168 (fp = fdp->fd_ofiles[fd]) == NULL)
2169 return (EBADF);
2170 if (fp->f_type != DTYPE_VNODE)
2171 return (EINVAL);
2172 *fpp = fp;
2173 return (0);
2174 }
2175