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