vfs_syscalls.c revision 1.37 1 /* $NetBSD: vfs_syscalls.c,v 1.37 1994/11/14 06:01:22 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 VOP_UNLOCK(vp);
645 if (flags & FWRITE)
646 vp->v_writecount--;
647 vput(vp);
648 *retval = indx;
649 return (0);
650 }
651
652 fp->f_flag = flags & FMASK;
653 fp->f_type = DTYPE_VNODE;
654 fp->f_ops = &vnops;
655 fp->f_data = (caddr_t)vp;
656 if (flags & (O_EXLOCK | O_SHLOCK)) {
657 lf.l_whence = SEEK_SET;
658 lf.l_start = 0;
659 lf.l_len = 0;
660 if (flags & O_EXLOCK)
661 lf.l_type = F_WRLCK;
662 else
663 lf.l_type = F_RDLCK;
664 type = F_FLOCK;
665 if ((flags & FNONBLOCK) == 0)
666 type |= F_WAIT;
667 VOP_UNLOCK(vp);
668 if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
669 (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
670 ffree(fp);
671 fdp->fd_ofiles[indx] = NULL;
672 return (error);
673 }
674 VOP_LOCK(vp);
675 fp->f_flag |= FHASLOCK;
676 }
677 VOP_UNLOCK(vp);
678 *retval = indx;
679 return (0);
680 }
681
682 #ifdef COMPAT_43
683 /*
684 * Create a file.
685 */
686 compat_43_creat(p, uap, retval)
687 struct proc *p;
688 register struct compat_43_creat_args /* {
689 syscallarg(char *) path;
690 syscallarg(int) mode;
691 } */ *uap;
692 register_t *retval;
693 {
694 struct open_args /* {
695 syscallarg(char *) path;
696 syscallarg(int) flags;
697 syscallarg(int) mode;
698 } */ openuap;
699
700 SCARG(&openuap, path) = SCARG(uap, path);
701 SCARG(&openuap, mode) = SCARG(uap, mode);
702 SCARG(&openuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
703 return (open(p, &openuap, retval));
704 }
705 #endif /* COMPAT_43 */
706
707 /*
708 * Create a special file.
709 */
710 /* ARGSUSED */
711 mknod(p, uap, retval)
712 struct proc *p;
713 register struct mknod_args /* {
714 syscallarg(char *) path;
715 syscallarg(int) mode;
716 syscallarg(int) dev;
717 } */ *uap;
718 register_t *retval;
719 {
720 register struct vnode *vp;
721 struct vattr vattr;
722 int error;
723 struct nameidata nd;
724
725 if (error = suser(p->p_ucred, &p->p_acflag))
726 return (error);
727 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
728 if (error = namei(&nd))
729 return (error);
730 vp = nd.ni_vp;
731 if (vp != NULL) {
732 error = EEXIST;
733 goto bad;
734 }
735 VATTR_NULL(&vattr);
736 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
737 vattr.va_rdev = SCARG(uap, dev);
738
739 switch (SCARG(uap, mode) & S_IFMT) {
740 case S_IFMT: /* used by badsect to flag bad sectors */
741 vattr.va_type = VBAD;
742 break;
743 case S_IFCHR:
744 vattr.va_type = VCHR;
745 break;
746 case S_IFBLK:
747 vattr.va_type = VBLK;
748 break;
749 default:
750 error = EINVAL;
751 goto bad;
752 }
753 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
754 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
755 bad:
756 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
757 if (nd.ni_dvp == vp)
758 vrele(nd.ni_dvp);
759 else
760 vput(nd.ni_dvp);
761 if (vp)
762 vrele(vp);
763 return (error);
764 }
765
766 /*
767 * Create a named pipe.
768 */
769 /* ARGSUSED */
770 mkfifo(p, uap, retval)
771 struct proc *p;
772 register struct mkfifo_args /* {
773 syscallarg(char *) path;
774 syscallarg(int) mode;
775 } */ *uap;
776 register_t *retval;
777 {
778 struct vattr vattr;
779 int error;
780 struct nameidata nd;
781
782 #ifndef FIFO
783 return (EOPNOTSUPP);
784 #else
785 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
786 if (error = namei(&nd))
787 return (error);
788 if (nd.ni_vp != NULL) {
789 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
790 if (nd.ni_dvp == nd.ni_vp)
791 vrele(nd.ni_dvp);
792 else
793 vput(nd.ni_dvp);
794 vrele(nd.ni_vp);
795 return (EEXIST);
796 }
797 VATTR_NULL(&vattr);
798 vattr.va_type = VFIFO;
799 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
800 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
801 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
802 #endif /* FIFO */
803 }
804
805 /*
806 * Make a hard file link.
807 */
808 /* ARGSUSED */
809 link(p, uap, retval)
810 struct proc *p;
811 register struct link_args /* {
812 syscallarg(char *) path;
813 syscallarg(char *) link;
814 } */ *uap;
815 register_t *retval;
816 {
817 register struct vnode *vp;
818 struct nameidata nd;
819 int error;
820
821 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
822 if (error = namei(&nd))
823 return (error);
824 vp = nd.ni_vp;
825 if (vp->v_type == VDIR &&
826 (error = suser(p->p_ucred, &p->p_acflag)))
827 goto bad1;
828 nd.ni_cnd.cn_nameiop = CREATE;
829 nd.ni_cnd.cn_flags = LOCKPARENT;
830 nd.ni_dirp = SCARG(uap, link);
831 if (error = namei(&nd))
832 goto bad1;
833 if (nd.ni_vp != NULL) {
834 error = EEXIST;
835 goto bad2;
836 }
837 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
838 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
839 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
840 vrele(vp);
841 return (error);
842 bad2:
843 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
844 if (nd.ni_dvp == nd.ni_vp)
845 vrele(nd.ni_dvp);
846 else
847 vput(nd.ni_dvp);
848 if (nd.ni_vp)
849 vrele(nd.ni_vp);
850 bad1:
851 vrele(vp);
852 return (error);
853 }
854
855 /*
856 * Make a symbolic link.
857 */
858 /* ARGSUSED */
859 symlink(p, uap, retval)
860 struct proc *p;
861 register struct symlink_args /* {
862 syscallarg(char *) path;
863 syscallarg(char *) link;
864 } */ *uap;
865 register_t *retval;
866 {
867 struct vattr vattr;
868 char *path;
869 int error;
870 struct nameidata nd;
871
872 MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
873 if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, (u_int*)0))
874 goto bad;
875 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
876 if (error = namei(&nd))
877 goto bad;
878 if (nd.ni_vp) {
879 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
880 if (nd.ni_dvp == nd.ni_vp)
881 vrele(nd.ni_dvp);
882 else
883 vput(nd.ni_dvp);
884 vrele(nd.ni_vp);
885 error = EEXIST;
886 goto bad;
887 }
888 VATTR_NULL(&vattr);
889 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
890 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
891 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
892 bad:
893 FREE(path, M_NAMEI);
894 return (error);
895 }
896
897 /*
898 * Delete a name from the filesystem.
899 */
900 /* ARGSUSED */
901 unlink(p, uap, retval)
902 struct proc *p;
903 struct unlink_args /* {
904 syscallarg(char *) path;
905 } */ *uap;
906 register_t *retval;
907 {
908 register struct vnode *vp;
909 int error;
910 struct nameidata nd;
911
912 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
913 if (error = namei(&nd))
914 return (error);
915 vp = nd.ni_vp;
916 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
917 VOP_LOCK(vp);
918
919 if (vp->v_type == VDIR &&
920 (error = suser(p->p_ucred, &p->p_acflag)))
921 goto bad;
922 /*
923 * The root of a mounted filesystem cannot be deleted.
924 */
925 if (vp->v_flag & VROOT) {
926 error = EBUSY;
927 goto bad;
928 }
929 (void)vnode_pager_uncache(vp);
930 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
931 return (VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd));
932 bad:
933 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
934 if (nd.ni_dvp == vp)
935 vrele(nd.ni_dvp);
936 else
937 vput(nd.ni_dvp);
938 vput(vp);
939 return (error);
940 }
941
942 /*
943 * Reposition read/write file offset.
944 */
945 lseek(p, uap, retval)
946 struct proc *p;
947 register struct lseek_args /* {
948 syscallarg(int) fd;
949 syscallarg(int) pad;
950 syscallarg(off_t) offset;
951 syscallarg(int) whence;
952 } */ *uap;
953 register_t *retval;
954 {
955 struct ucred *cred = p->p_ucred;
956 register struct filedesc *fdp = p->p_fd;
957 register struct file *fp;
958 struct vattr vattr;
959 int error;
960
961 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
962 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
963 return (EBADF);
964 if (fp->f_type != DTYPE_VNODE)
965 return (ESPIPE);
966 switch (SCARG(uap, whence)) {
967 case L_INCR:
968 fp->f_offset += SCARG(uap, offset);
969 break;
970 case L_XTND:
971 if (error =
972 VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p))
973 return (error);
974 fp->f_offset = SCARG(uap, offset) + vattr.va_size;
975 break;
976 case L_SET:
977 fp->f_offset = SCARG(uap, offset);
978 break;
979 default:
980 return (EINVAL);
981 }
982 *(off_t *)retval = fp->f_offset;
983 return (0);
984 }
985
986 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
987 /*
988 * Reposition read/write file offset.
989 */
990 compat_43_lseek(p, uap, retval)
991 struct proc *p;
992 register struct compat_43_lseek_args /* {
993 syscallarg(int) fd;
994 syscallarg(long) offset;
995 syscallarg(int) whence;
996 } */ *uap;
997 register_t *retval;
998 {
999 struct lseek_args /* {
1000 syscallarg(int) fd;
1001 syscallarg(int) pad;
1002 syscallarg(off_t) offset;
1003 syscallarg(int) whence;
1004 } */ nuap;
1005 off_t qret;
1006 int error;
1007
1008 SCARG(&nuap, fd) = SCARG(uap, fd);
1009 SCARG(&nuap, offset) = SCARG(uap, offset);
1010 SCARG(&nuap, whence) = SCARG(uap, whence);
1011 error = lseek(p, &nuap, &qret);
1012 *(long *)retval = qret;
1013 return (error);
1014 }
1015 #endif /* COMPAT_43 || COMPAT_SUNOS */
1016
1017 /*
1018 * Check access permissions.
1019 */
1020 access(p, uap, retval)
1021 struct proc *p;
1022 register struct access_args /* {
1023 syscallarg(char *) path;
1024 syscallarg(int) flags;
1025 } */ *uap;
1026 register_t *retval;
1027 {
1028 register struct ucred *cred = p->p_ucred;
1029 register struct vnode *vp;
1030 int error, flags, t_gid, t_uid;
1031 struct nameidata nd;
1032
1033 t_uid = cred->cr_uid;
1034 t_gid = cred->cr_groups[0];
1035 cred->cr_uid = p->p_cred->p_ruid;
1036 cred->cr_groups[0] = p->p_cred->p_rgid;
1037 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1038 SCARG(uap, path), p);
1039 if (error = namei(&nd))
1040 goto out1;
1041 vp = nd.ni_vp;
1042
1043 /* Flags == 0 means only check for existence. */
1044 if (SCARG(uap, flags)) {
1045 flags = 0;
1046 if (SCARG(uap, flags) & R_OK)
1047 flags |= VREAD;
1048 if (SCARG(uap, flags) & W_OK)
1049 flags |= VWRITE;
1050 if (SCARG(uap, flags) & X_OK)
1051 flags |= VEXEC;
1052 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1053 error = VOP_ACCESS(vp, flags, cred, p);
1054 }
1055 vput(vp);
1056 out1:
1057 cred->cr_uid = t_uid;
1058 cred->cr_groups[0] = t_gid;
1059 return (error);
1060 }
1061
1062 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) || defined(COMPAT_IBCS2)
1063 /*
1064 * Get file status; this version follows links.
1065 */
1066 /* ARGSUSED */
1067 compat_43_stat(p, uap, retval)
1068 struct proc *p;
1069 register struct compat_43_stat_args /* {
1070 syscallarg(char *) path;
1071 syscallarg(struct ostat *) ub;
1072 } */ *uap;
1073 register_t *retval;
1074 {
1075 struct stat sb;
1076 struct ostat osb;
1077 int error;
1078 struct nameidata nd;
1079
1080 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1081 SCARG(uap, path), p);
1082 if (error = namei(&nd))
1083 return (error);
1084 error = vn_stat(nd.ni_vp, &sb, p);
1085 vput(nd.ni_vp);
1086 if (error)
1087 return (error);
1088 cvtstat(&sb, &osb);
1089 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1090 return (error);
1091 }
1092
1093 /*
1094 * Get file status; this version does not follow links.
1095 */
1096 /* ARGSUSED */
1097 compat_43_lstat(p, uap, retval)
1098 struct proc *p;
1099 register struct compat_43_lstat_args /* {
1100 syscallarg(char *) path;
1101 syscallarg(struct ostat *) ub;
1102 } */ *uap;
1103 register_t *retval;
1104 {
1105 struct stat sb;
1106 struct ostat osb;
1107 int error;
1108 struct nameidata nd;
1109
1110 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
1111 SCARG(uap, path), p);
1112 if (error = namei(&nd))
1113 return (error);
1114 error = vn_stat(nd.ni_vp, &sb, p);
1115 vput(nd.ni_vp);
1116 if (error)
1117 return (error);
1118 cvtstat(&sb, &osb);
1119 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1120 return (error);
1121 }
1122
1123 /*
1124 * Convert from an old to a new stat structure.
1125 */
1126 cvtstat(st, ost)
1127 struct stat *st;
1128 struct ostat *ost;
1129 {
1130
1131 ost->st_dev = st->st_dev;
1132 ost->st_ino = st->st_ino;
1133 ost->st_mode = st->st_mode;
1134 ost->st_nlink = st->st_nlink;
1135 ost->st_uid = st->st_uid;
1136 ost->st_gid = st->st_gid;
1137 ost->st_rdev = st->st_rdev;
1138 if (st->st_size < (quad_t)1 << 32)
1139 ost->st_size = st->st_size;
1140 else
1141 ost->st_size = -2;
1142 ost->st_atime = st->st_atime;
1143 ost->st_mtime = st->st_mtime;
1144 ost->st_ctime = st->st_ctime;
1145 ost->st_blksize = st->st_blksize;
1146 ost->st_blocks = st->st_blocks;
1147 ost->st_flags = st->st_flags;
1148 ost->st_gen = st->st_gen;
1149 }
1150 #endif /* COMPAT_43 || COMPAT_SUNOS || COMPAT_IBCS2 */
1151
1152 /*
1153 * Get file status; this version follows links.
1154 */
1155 /* ARGSUSED */
1156 stat(p, uap, retval)
1157 struct proc *p;
1158 register struct stat_args /* {
1159 syscallarg(char *) path;
1160 syscallarg(struct stat *) ub;
1161 } */ *uap;
1162 register_t *retval;
1163 {
1164 struct stat sb;
1165 int error;
1166 struct nameidata nd;
1167
1168 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1169 SCARG(uap, path), p);
1170 if (error = namei(&nd))
1171 return (error);
1172 error = vn_stat(nd.ni_vp, &sb, p);
1173 vput(nd.ni_vp);
1174 if (error)
1175 return (error);
1176 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1177 return (error);
1178 }
1179
1180 /*
1181 * Get file status; this version does not follow links.
1182 */
1183 /* ARGSUSED */
1184 lstat(p, uap, retval)
1185 struct proc *p;
1186 register struct lstat_args /* {
1187 syscallarg(char *) path;
1188 syscallarg(struct stat *) ub;
1189 } */ *uap;
1190 register_t *retval;
1191 {
1192 int error;
1193 struct vnode *vp, *dvp;
1194 struct stat sb, sb1;
1195 struct nameidata nd;
1196
1197 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
1198 SCARG(uap, path), p);
1199 if (error = namei(&nd))
1200 return (error);
1201 /*
1202 * For symbolic links, always return the attributes of its
1203 * containing directory, except for mode, size, and links.
1204 */
1205 vp = nd.ni_vp;
1206 dvp = nd.ni_dvp;
1207 if (vp->v_type != VLNK) {
1208 if (dvp == vp)
1209 vrele(dvp);
1210 else
1211 vput(dvp);
1212 error = vn_stat(vp, &sb, p);
1213 vput(vp);
1214 if (error)
1215 return (error);
1216 } else {
1217 error = vn_stat(dvp, &sb, p);
1218 vput(dvp);
1219 if (error) {
1220 vput(vp);
1221 return (error);
1222 }
1223 error = vn_stat(vp, &sb1, p);
1224 vput(vp);
1225 if (error)
1226 return (error);
1227 sb.st_mode &= ~S_IFDIR;
1228 sb.st_mode |= S_IFLNK;
1229 sb.st_nlink = sb1.st_nlink;
1230 sb.st_size = sb1.st_size;
1231 sb.st_blocks = sb1.st_blocks;
1232 }
1233 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1234 return (error);
1235 }
1236
1237 /*
1238 * Get configurable pathname variables.
1239 */
1240 /* ARGSUSED */
1241 pathconf(p, uap, retval)
1242 struct proc *p;
1243 register struct pathconf_args /* {
1244 syscallarg(char *) path;
1245 syscallarg(int) name;
1246 } */ *uap;
1247 register_t *retval;
1248 {
1249 int error;
1250 struct nameidata nd;
1251
1252 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1253 SCARG(uap, path), p);
1254 if (error = namei(&nd))
1255 return (error);
1256 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
1257 vput(nd.ni_vp);
1258 return (error);
1259 }
1260
1261 /*
1262 * Return target name of a symbolic link.
1263 */
1264 /* ARGSUSED */
1265 readlink(p, uap, retval)
1266 struct proc *p;
1267 register struct readlink_args /* {
1268 syscallarg(char *) path;
1269 syscallarg(char *) buf;
1270 syscallarg(int) count;
1271 } */ *uap;
1272 register_t *retval;
1273 {
1274 register struct vnode *vp;
1275 struct iovec aiov;
1276 struct uio auio;
1277 int error;
1278 struct nameidata nd;
1279
1280 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
1281 SCARG(uap, path), p);
1282 if (error = namei(&nd))
1283 return (error);
1284 vp = nd.ni_vp;
1285 if (vp->v_type != VLNK)
1286 error = EINVAL;
1287 else {
1288 aiov.iov_base = SCARG(uap, buf);
1289 aiov.iov_len = SCARG(uap, count);
1290 auio.uio_iov = &aiov;
1291 auio.uio_iovcnt = 1;
1292 auio.uio_offset = 0;
1293 auio.uio_rw = UIO_READ;
1294 auio.uio_segflg = UIO_USERSPACE;
1295 auio.uio_procp = p;
1296 auio.uio_resid = SCARG(uap, count);
1297 error = VOP_READLINK(vp, &auio, p->p_ucred);
1298 }
1299 vput(vp);
1300 *retval = SCARG(uap, count) - auio.uio_resid;
1301 return (error);
1302 }
1303
1304 /*
1305 * Change flags of a file given a path name.
1306 */
1307 /* ARGSUSED */
1308 chflags(p, uap, retval)
1309 struct proc *p;
1310 register struct chflags_args /* {
1311 syscallarg(char *) path;
1312 syscallarg(int) flags;
1313 } */ *uap;
1314 register_t *retval;
1315 {
1316 register struct vnode *vp;
1317 struct vattr vattr;
1318 int error;
1319 struct nameidata nd;
1320
1321 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1322 if (error = namei(&nd))
1323 return (error);
1324 vp = nd.ni_vp;
1325 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1326 VOP_LOCK(vp);
1327 if (vp->v_mount->mnt_flag & MNT_RDONLY)
1328 error = EROFS;
1329 else {
1330 VATTR_NULL(&vattr);
1331 vattr.va_flags = SCARG(uap, flags);
1332 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1333 }
1334 vput(vp);
1335 return (error);
1336 }
1337
1338 /*
1339 * Change flags of a file given a file descriptor.
1340 */
1341 /* ARGSUSED */
1342 fchflags(p, uap, retval)
1343 struct proc *p;
1344 register struct fchflags_args /* {
1345 syscallarg(int) fd;
1346 syscallarg(int) flags;
1347 } */ *uap;
1348 register_t *retval;
1349 {
1350 struct vattr vattr;
1351 struct vnode *vp;
1352 struct file *fp;
1353 int error;
1354
1355 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1356 return (error);
1357 vp = (struct vnode *)fp->f_data;
1358 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1359 VOP_LOCK(vp);
1360 if (vp->v_mount->mnt_flag & MNT_RDONLY)
1361 error = EROFS;
1362 else {
1363 VATTR_NULL(&vattr);
1364 vattr.va_flags = SCARG(uap, flags);
1365 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1366 }
1367 VOP_UNLOCK(vp);
1368 return (error);
1369 }
1370
1371 /*
1372 * Change mode of a file given path name.
1373 */
1374 /* ARGSUSED */
1375 chmod(p, uap, retval)
1376 struct proc *p;
1377 register struct chmod_args /* {
1378 syscallarg(char *) path;
1379 syscallarg(int) mode;
1380 } */ *uap;
1381 register_t *retval;
1382 {
1383 register struct vnode *vp;
1384 struct vattr vattr;
1385 int error;
1386 struct nameidata nd;
1387
1388 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1389 if (error = namei(&nd))
1390 return (error);
1391 vp = nd.ni_vp;
1392 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1393 VOP_LOCK(vp);
1394 if (vp->v_mount->mnt_flag & MNT_RDONLY)
1395 error = EROFS;
1396 else {
1397 VATTR_NULL(&vattr);
1398 vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
1399 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1400 }
1401 vput(vp);
1402 return (error);
1403 }
1404
1405 /*
1406 * Change mode of a file given a file descriptor.
1407 */
1408 /* ARGSUSED */
1409 fchmod(p, uap, retval)
1410 struct proc *p;
1411 register struct fchmod_args /* {
1412 syscallarg(int) fd;
1413 syscallarg(int) mode;
1414 } */ *uap;
1415 register_t *retval;
1416 {
1417 struct vattr vattr;
1418 struct vnode *vp;
1419 struct file *fp;
1420 int error;
1421
1422 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1423 return (error);
1424 vp = (struct vnode *)fp->f_data;
1425 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1426 VOP_LOCK(vp);
1427 if (vp->v_mount->mnt_flag & MNT_RDONLY)
1428 error = EROFS;
1429 else {
1430 VATTR_NULL(&vattr);
1431 vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
1432 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1433 }
1434 VOP_UNLOCK(vp);
1435 return (error);
1436 }
1437
1438 /*
1439 * Set ownership given a path name.
1440 */
1441 /* ARGSUSED */
1442 chown(p, uap, retval)
1443 struct proc *p;
1444 register struct chown_args /* {
1445 syscallarg(char *) path;
1446 syscallarg(int) uid;
1447 syscallarg(int) gid;
1448 } */ *uap;
1449 register_t *retval;
1450 {
1451 register struct vnode *vp;
1452 struct vattr vattr;
1453 int error;
1454 struct nameidata nd;
1455
1456 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1457 if (error = namei(&nd))
1458 return (error);
1459 vp = nd.ni_vp;
1460 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1461 VOP_LOCK(vp);
1462 if (vp->v_mount->mnt_flag & MNT_RDONLY)
1463 error = EROFS;
1464 else {
1465 VATTR_NULL(&vattr);
1466 vattr.va_uid = SCARG(uap, uid);
1467 vattr.va_gid = SCARG(uap, gid);
1468 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1469 }
1470 vput(vp);
1471 return (error);
1472 }
1473
1474 /*
1475 * Set ownership given a file descriptor.
1476 */
1477 /* ARGSUSED */
1478 fchown(p, uap, retval)
1479 struct proc *p;
1480 register struct fchown_args /* {
1481 syscallarg(int) fd;
1482 syscallarg(int) uid;
1483 syscallarg(int) gid;
1484 } */ *uap;
1485 register_t *retval;
1486 {
1487 struct vattr vattr;
1488 struct vnode *vp;
1489 struct file *fp;
1490 int error;
1491
1492 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1493 return (error);
1494 vp = (struct vnode *)fp->f_data;
1495 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1496 VOP_LOCK(vp);
1497 if (vp->v_mount->mnt_flag & MNT_RDONLY)
1498 error = EROFS;
1499 else {
1500 VATTR_NULL(&vattr);
1501 vattr.va_uid = SCARG(uap, uid);
1502 vattr.va_gid = SCARG(uap, gid);
1503 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1504 }
1505 VOP_UNLOCK(vp);
1506 return (error);
1507 }
1508
1509 /*
1510 * Set the access and modification times of a file.
1511 */
1512 /* ARGSUSED */
1513 utimes(p, uap, retval)
1514 struct proc *p;
1515 register struct utimes_args /* {
1516 syscallarg(char *) path;
1517 syscallarg(struct timeval *) tptr;
1518 } */ *uap;
1519 register_t *retval;
1520 {
1521 register struct vnode *vp;
1522 struct timeval tv[2];
1523 struct vattr vattr;
1524 int error;
1525 struct nameidata nd;
1526
1527 VATTR_NULL(&vattr);
1528 if (SCARG(uap, tptr) == NULL) {
1529 microtime(&tv[0]);
1530 tv[1] = tv[0];
1531 vattr.va_vaflags |= VA_UTIMES_NULL;
1532 } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
1533 sizeof (tv)))
1534 return (error);
1535 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1536 if (error = namei(&nd))
1537 return (error);
1538 vp = nd.ni_vp;
1539 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1540 VOP_LOCK(vp);
1541 if (vp->v_mount->mnt_flag & MNT_RDONLY)
1542 error = EROFS;
1543 else {
1544 vattr.va_atime.ts_sec = tv[0].tv_sec;
1545 vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;
1546 vattr.va_mtime.ts_sec = tv[1].tv_sec;
1547 vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;
1548 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1549 }
1550 vput(vp);
1551 return (error);
1552 }
1553
1554 /*
1555 * Truncate a file given its path name.
1556 */
1557 /* ARGSUSED */
1558 truncate(p, uap, retval)
1559 struct proc *p;
1560 register struct truncate_args /* {
1561 syscallarg(char *) path;
1562 syscallarg(int) pad;
1563 syscallarg(off_t) length;
1564 } */ *uap;
1565 register_t *retval;
1566 {
1567 register struct vnode *vp;
1568 struct vattr vattr;
1569 int error;
1570 struct nameidata nd;
1571
1572 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1573 if (error = namei(&nd))
1574 return (error);
1575 vp = nd.ni_vp;
1576 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1577 VOP_LOCK(vp);
1578 if (vp->v_type == VDIR)
1579 error = EISDIR;
1580 else if ((error = vn_writechk(vp)) == 0 &&
1581 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
1582 VATTR_NULL(&vattr);
1583 vattr.va_size = SCARG(uap, length);
1584 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1585 }
1586 vput(vp);
1587 return (error);
1588 }
1589
1590 /*
1591 * Truncate a file given a file descriptor.
1592 */
1593 /* ARGSUSED */
1594 ftruncate(p, uap, retval)
1595 struct proc *p;
1596 register struct ftruncate_args /* {
1597 syscallarg(int) fd;
1598 syscallarg(int) pad;
1599 syscallarg(off_t) length;
1600 } */ *uap;
1601 register_t *retval;
1602 {
1603 struct vattr vattr;
1604 struct vnode *vp;
1605 struct file *fp;
1606 int error;
1607
1608 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1609 return (error);
1610 if ((fp->f_flag & FWRITE) == 0)
1611 return (EINVAL);
1612 vp = (struct vnode *)fp->f_data;
1613 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1614 VOP_LOCK(vp);
1615 if (vp->v_type == VDIR)
1616 error = EISDIR;
1617 else if ((error = vn_writechk(vp)) == 0) {
1618 VATTR_NULL(&vattr);
1619 vattr.va_size = SCARG(uap, length);
1620 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
1621 }
1622 VOP_UNLOCK(vp);
1623 return (error);
1624 }
1625
1626 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1627 /*
1628 * Truncate a file given its path name.
1629 */
1630 /* ARGSUSED */
1631 compat_43_truncate(p, uap, retval)
1632 struct proc *p;
1633 register struct compat_43_truncate_args /* {
1634 syscallarg(char *) path;
1635 syscallarg(long) length;
1636 } */ *uap;
1637 register_t *retval;
1638 {
1639 struct truncate_args nuap;
1640
1641 SCARG(&nuap, path) = SCARG(uap, path);
1642 SCARG(&nuap, length) = SCARG(uap, length);
1643 return (truncate(p, &nuap, retval));
1644 }
1645
1646 /*
1647 * Truncate a file given a file descriptor.
1648 */
1649 /* ARGSUSED */
1650 compat_43_ftruncate(p, uap, retval)
1651 struct proc *p;
1652 register struct compat_43_ftruncate_args /* {
1653 syscallarg(int) fd;
1654 syscallarg(long) length;
1655 } */ *uap;
1656 register_t *retval;
1657 {
1658 struct ftruncate_args nuap;
1659
1660 SCARG(&nuap, fd) = SCARG(uap, fd);
1661 SCARG(&nuap, length) = SCARG(uap, length);
1662 return (ftruncate(p, &nuap, retval));
1663 }
1664 #endif /* COMPAT_43 || COMPAT_SUNOS */
1665
1666 /*
1667 * Sync an open file.
1668 */
1669 /* ARGSUSED */
1670 fsync(p, uap, retval)
1671 struct proc *p;
1672 struct fsync_args /* {
1673 syscallarg(int) fd;
1674 } */ *uap;
1675 register_t *retval;
1676 {
1677 register struct vnode *vp;
1678 struct file *fp;
1679 int error;
1680
1681 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1682 return (error);
1683 vp = (struct vnode *)fp->f_data;
1684 VOP_LOCK(vp);
1685 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
1686 VOP_UNLOCK(vp);
1687 return (error);
1688 }
1689
1690 /*
1691 * Rename files. Source and destination must either both be directories,
1692 * or both not be directories. If target is a directory, it must be empty.
1693 */
1694 /* ARGSUSED */
1695 rename(p, uap, retval)
1696 struct proc *p;
1697 register struct rename_args /* {
1698 syscallarg(char *) from;
1699 syscallarg(char *) to;
1700 } */ *uap;
1701 register_t *retval;
1702 {
1703 register struct vnode *tvp, *fvp, *tdvp;
1704 struct nameidata fromnd, tond;
1705 int error;
1706
1707 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
1708 SCARG(uap, from), p);
1709 if (error = namei(&fromnd))
1710 return (error);
1711 fvp = fromnd.ni_vp;
1712 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
1713 UIO_USERSPACE, SCARG(uap, to), p);
1714 if (error = namei(&tond)) {
1715 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1716 vrele(fromnd.ni_dvp);
1717 vrele(fvp);
1718 goto out1;
1719 }
1720 tdvp = tond.ni_dvp;
1721 tvp = tond.ni_vp;
1722 if (tvp != NULL) {
1723 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1724 error = ENOTDIR;
1725 goto out;
1726 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1727 error = EISDIR;
1728 goto out;
1729 }
1730 }
1731 if (fvp == tdvp)
1732 error = EINVAL;
1733 /*
1734 * If source is the same as the destination (that is the
1735 * same inode number with the same name in the same directory),
1736 * then there is nothing to do.
1737 */
1738 if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1739 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1740 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1741 fromnd.ni_cnd.cn_namelen))
1742 error = -1;
1743 out:
1744 if (!error) {
1745 LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE);
1746 if (fromnd.ni_dvp != tdvp)
1747 LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1748 if (tvp)
1749 LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE);
1750 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1751 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1752 } else {
1753 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
1754 if (tdvp == tvp)
1755 vrele(tdvp);
1756 else
1757 vput(tdvp);
1758 if (tvp)
1759 vput(tvp);
1760 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1761 vrele(fromnd.ni_dvp);
1762 vrele(fvp);
1763 }
1764 vrele(tond.ni_startdir);
1765 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
1766 out1:
1767 if (fromnd.ni_startdir)
1768 vrele(fromnd.ni_startdir);
1769 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
1770 if (error == -1)
1771 return (0);
1772 return (error);
1773 }
1774
1775 /*
1776 * Make a directory file.
1777 */
1778 /* ARGSUSED */
1779 mkdir(p, uap, retval)
1780 struct proc *p;
1781 register struct mkdir_args /* {
1782 syscallarg(char *) path;
1783 syscallarg(int) mode;
1784 } */ *uap;
1785 register_t *retval;
1786 {
1787 register struct vnode *vp;
1788 struct vattr vattr;
1789 int error;
1790 struct nameidata nd;
1791
1792 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1793 if (error = namei(&nd))
1794 return (error);
1795 vp = nd.ni_vp;
1796 if (vp != NULL) {
1797 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1798 if (nd.ni_dvp == vp)
1799 vrele(nd.ni_dvp);
1800 else
1801 vput(nd.ni_dvp);
1802 vrele(vp);
1803 return (EEXIST);
1804 }
1805 VATTR_NULL(&vattr);
1806 vattr.va_type = VDIR;
1807 vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
1808 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1809 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1810 if (!error)
1811 vput(nd.ni_vp);
1812 return (error);
1813 }
1814
1815 /*
1816 * Remove a directory file.
1817 */
1818 /* ARGSUSED */
1819 rmdir(p, uap, retval)
1820 struct proc *p;
1821 struct rmdir_args /* {
1822 syscallarg(char *) path;
1823 } */ *uap;
1824 register_t *retval;
1825 {
1826 register struct vnode *vp;
1827 int error;
1828 struct nameidata nd;
1829
1830 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
1831 SCARG(uap, path), p);
1832 if (error = namei(&nd))
1833 return (error);
1834 vp = nd.ni_vp;
1835 if (vp->v_type != VDIR) {
1836 error = ENOTDIR;
1837 goto out;
1838 }
1839 /*
1840 * No rmdir "." please.
1841 */
1842 if (nd.ni_dvp == vp) {
1843 error = EINVAL;
1844 goto out;
1845 }
1846 /*
1847 * The root of a mounted filesystem cannot be deleted.
1848 */
1849 if (vp->v_flag & VROOT)
1850 error = EBUSY;
1851 out:
1852 if (!error) {
1853 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1854 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1855 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1856 } else {
1857 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1858 if (nd.ni_dvp == vp)
1859 vrele(nd.ni_dvp);
1860 else
1861 vput(nd.ni_dvp);
1862 vput(vp);
1863 }
1864 return (error);
1865 }
1866
1867 #if defined(COMPAT_43) || defined(COMPAT_HPUX)
1868 /*
1869 * Read a block of directory entries in a file system independent format.
1870 */
1871 compat_43_getdirentries(p, uap, retval)
1872 struct proc *p;
1873 register struct compat_43_getdirentries_args /* {
1874 syscallarg(int) fd;
1875 syscallarg(char *) buf;
1876 syscallarg(u_int) count;
1877 syscallarg(long *) basep;
1878 } */ *uap;
1879 register_t *retval;
1880 {
1881 register struct vnode *vp;
1882 struct file *fp;
1883 struct uio auio, kuio;
1884 struct iovec aiov, kiov;
1885 struct dirent *dp, *edp;
1886 caddr_t dirbuf;
1887 int error, eofflag, readcnt;
1888 long loff;
1889
1890 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1891 return (error);
1892 if ((fp->f_flag & FREAD) == 0)
1893 return (EBADF);
1894 vp = (struct vnode *)fp->f_data;
1895 unionread:
1896 if (vp->v_type != VDIR)
1897 return (EINVAL);
1898 aiov.iov_base = SCARG(uap, buf);
1899 aiov.iov_len = SCARG(uap, count);
1900 auio.uio_iov = &aiov;
1901 auio.uio_iovcnt = 1;
1902 auio.uio_rw = UIO_READ;
1903 auio.uio_segflg = UIO_USERSPACE;
1904 auio.uio_procp = p;
1905 auio.uio_resid = SCARG(uap, count);
1906 VOP_LOCK(vp);
1907 loff = auio.uio_offset = fp->f_offset;
1908 # if (BYTE_ORDER != LITTLE_ENDIAN)
1909 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
1910 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
1911 (u_long *)0, 0);
1912 fp->f_offset = auio.uio_offset;
1913 } else
1914 # endif
1915 {
1916 kuio = auio;
1917 kuio.uio_iov = &kiov;
1918 kuio.uio_segflg = UIO_SYSSPACE;
1919 kiov.iov_len = SCARG(uap, count);
1920 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
1921 kiov.iov_base = dirbuf;
1922 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
1923 (u_long *)0, 0);
1924 fp->f_offset = kuio.uio_offset;
1925 if (error == 0) {
1926 readcnt = SCARG(uap, count) - kuio.uio_resid;
1927 edp = (struct dirent *)&dirbuf[readcnt];
1928 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
1929 # if (BYTE_ORDER == LITTLE_ENDIAN)
1930 /*
1931 * The expected low byte of
1932 * dp->d_namlen is our dp->d_type.
1933 * The high MBZ byte of dp->d_namlen
1934 * is our dp->d_namlen.
1935 */
1936 dp->d_type = dp->d_namlen;
1937 dp->d_namlen = 0;
1938 # else
1939 /*
1940 * The dp->d_type is the high byte
1941 * of the expected dp->d_namlen,
1942 * so must be zero'ed.
1943 */
1944 dp->d_type = 0;
1945 # endif
1946 if (dp->d_reclen > 0) {
1947 dp = (struct dirent *)
1948 ((char *)dp + dp->d_reclen);
1949 } else {
1950 error = EIO;
1951 break;
1952 }
1953 }
1954 if (dp >= edp)
1955 error = uiomove(dirbuf, readcnt, &auio);
1956 }
1957 FREE(dirbuf, M_TEMP);
1958 }
1959 VOP_UNLOCK(vp);
1960 if (error)
1961 return (error);
1962
1963 #ifdef UNION
1964 {
1965 extern int (**union_vnodeop_p)();
1966 extern struct vnode *union_lowervp __P((struct vnode *));
1967
1968 if ((SCARG(uap, count) == auio.uio_resid) &&
1969 (vp->v_op == union_vnodeop_p)) {
1970 struct vnode *lvp;
1971
1972 lvp = union_lowervp(vp);
1973 if (lvp != NULLVP) {
1974 VOP_LOCK(lvp);
1975 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
1976 VOP_UNLOCK(lvp);
1977
1978 if (error) {
1979 vrele(lvp);
1980 return (error);
1981 }
1982 fp->f_data = (caddr_t) lvp;
1983 fp->f_offset = 0;
1984 error = vn_close(vp, FREAD, fp->f_cred, p);
1985 if (error)
1986 return (error);
1987 vp = lvp;
1988 goto unionread;
1989 }
1990 }
1991 }
1992 #endif /* UNION */
1993
1994 if ((SCARG(uap, count) == auio.uio_resid) &&
1995 (vp->v_flag & VROOT) && (vp->v_mount->mnt_flag & MNT_UNION)) {
1996 struct vnode *tvp = vp;
1997 vp = vp->v_mount->mnt_vnodecovered;
1998 VREF(vp);
1999 fp->f_data = (caddr_t) vp;
2000 fp->f_offset = 0;
2001 vrele(tvp);
2002 goto unionread;
2003 }
2004 error =
2005 copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), sizeof(long));
2006 *retval = SCARG(uap, count) - auio.uio_resid;
2007 return (error);
2008 }
2009 #endif /* COMPAT_43 */
2010
2011 /*
2012 * Read a block of directory entries in a file system independent format.
2013 */
2014 getdirentries(p, uap, retval)
2015 struct proc *p;
2016 register struct getdirentries_args /* {
2017 syscallarg(int) fd;
2018 syscallarg(char *) buf;
2019 syscallarg(u_int) count;
2020 syscallarg(long *) basep;
2021 } */ *uap;
2022 register_t *retval;
2023 {
2024 register struct vnode *vp;
2025 struct file *fp;
2026 struct uio auio;
2027 struct iovec aiov;
2028 long loff;
2029 int error, eofflag;
2030
2031 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
2032 return (error);
2033 if ((fp->f_flag & FREAD) == 0)
2034 return (EBADF);
2035 vp = (struct vnode *)fp->f_data;
2036 unionread:
2037 if (vp->v_type != VDIR)
2038 return (EINVAL);
2039 aiov.iov_base = SCARG(uap, buf);
2040 aiov.iov_len = SCARG(uap, count);
2041 auio.uio_iov = &aiov;
2042 auio.uio_iovcnt = 1;
2043 auio.uio_rw = UIO_READ;
2044 auio.uio_segflg = UIO_USERSPACE;
2045 auio.uio_procp = p;
2046 auio.uio_resid = SCARG(uap, count);
2047 VOP_LOCK(vp);
2048 loff = auio.uio_offset = fp->f_offset;
2049 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (u_long *)0, 0);
2050 fp->f_offset = auio.uio_offset;
2051 VOP_UNLOCK(vp);
2052 if (error)
2053 return (error);
2054
2055 #ifdef UNION
2056 {
2057 extern int (**union_vnodeop_p)();
2058 extern struct vnode *union_lowervp __P((struct vnode *));
2059
2060 if ((SCARG(uap, count) == auio.uio_resid) &&
2061 (vp->v_op == union_vnodeop_p)) {
2062 struct vnode *lvp;
2063
2064 lvp = union_lowervp(vp);
2065 if (lvp != NULLVP) {
2066 VOP_LOCK(lvp);
2067 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
2068 VOP_UNLOCK(lvp);
2069
2070 if (error) {
2071 vrele(lvp);
2072 return (error);
2073 }
2074 fp->f_data = (caddr_t) lvp;
2075 fp->f_offset = 0;
2076 error = vn_close(vp, FREAD, fp->f_cred, p);
2077 if (error)
2078 return (error);
2079 vp = lvp;
2080 goto unionread;
2081 }
2082 }
2083 }
2084 #endif /* UNION */
2085
2086 if ((SCARG(uap, count) == auio.uio_resid) &&
2087 (vp->v_flag & VROOT) && (vp->v_mount->mnt_flag & MNT_UNION)) {
2088 struct vnode *tvp = vp;
2089 vp = vp->v_mount->mnt_vnodecovered;
2090 VREF(vp);
2091 fp->f_data = (caddr_t) vp;
2092 fp->f_offset = 0;
2093 vrele(tvp);
2094 goto unionread;
2095 }
2096 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2097 sizeof(long));
2098 *retval = SCARG(uap, count) - auio.uio_resid;
2099 return (error);
2100 }
2101
2102 /*
2103 * Set the mode mask for creation of filesystem nodes.
2104 */
2105 mode_t /* XXX */
2106 umask(p, uap, retval)
2107 struct proc *p;
2108 struct umask_args /* {
2109 syscallarg(int) newmask;
2110 } */ *uap;
2111 register_t *retval;
2112 {
2113 register struct filedesc *fdp;
2114
2115 fdp = p->p_fd;
2116 *retval = fdp->fd_cmask;
2117 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
2118 return (0);
2119 }
2120
2121 /*
2122 * Void all references to file by ripping underlying filesystem
2123 * away from vnode.
2124 */
2125 /* ARGSUSED */
2126 revoke(p, uap, retval)
2127 struct proc *p;
2128 register struct revoke_args /* {
2129 syscallarg(char *) path;
2130 } */ *uap;
2131 register_t *retval;
2132 {
2133 register struct vnode *vp;
2134 struct vattr vattr;
2135 int error;
2136 struct nameidata nd;
2137
2138 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2139 if (error = namei(&nd))
2140 return (error);
2141 vp = nd.ni_vp;
2142 if (vp->v_type != VCHR && vp->v_type != VBLK) {
2143 error = EINVAL;
2144 goto out;
2145 }
2146 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
2147 goto out;
2148 if (p->p_ucred->cr_uid != vattr.va_uid &&
2149 (error = suser(p->p_ucred, &p->p_acflag)))
2150 goto out;
2151 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
2152 vgoneall(vp);
2153 out:
2154 vrele(vp);
2155 return (error);
2156 }
2157
2158 /*
2159 * Convert a user file descriptor to a kernel file entry.
2160 */
2161 getvnode(fdp, fd, fpp)
2162 struct filedesc *fdp;
2163 struct file **fpp;
2164 int fd;
2165 {
2166 struct file *fp;
2167
2168 if ((u_int)fd >= fdp->fd_nfiles ||
2169 (fp = fdp->fd_ofiles[fd]) == NULL)
2170 return (EBADF);
2171 if (fp->f_type != DTYPE_VNODE)
2172 return (EINVAL);
2173 *fpp = fp;
2174 return (0);
2175 }
2176