]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/kern/vfs_extattr.c
Add MAP_NOSYNC feature to mmap(), and MADV_NOSYNC and MADV_AUTOSYNC to
[FreeBSD/FreeBSD.git] / sys / kern / vfs_extattr.c
1 /*
2  * Copyright (c) 1989, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  * (c) UNIX System Laboratories, Inc.
5  * All or some portions of this file are derived from material licensed
6  * to the University of California by American Telephone and Telegraph
7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8  * the permission of UNIX System Laboratories, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by the University of
21  *      California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *      @(#)vfs_syscalls.c      8.13 (Berkeley) 4/15/94
39  * $FreeBSD$
40  */
41
42 /* For 4.3 integer FS ID compatibility */
43 #include "opt_compat.h"
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/buf.h>
48 #include <sys/sysent.h>
49 #include <sys/malloc.h>
50 #include <sys/mount.h>
51 #include <sys/sysproto.h>
52 #include <sys/namei.h>
53 #include <sys/filedesc.h>
54 #include <sys/kernel.h>
55 #include <sys/fcntl.h>
56 #include <sys/file.h>
57 #include <sys/linker.h>
58 #include <sys/stat.h>
59 #include <sys/unistd.h>
60 #include <sys/vnode.h>
61 #include <sys/proc.h>
62 #include <sys/dirent.h>
63
64 #include <miscfs/union/union.h>
65
66 #include <vm/vm.h>
67 #include <vm/vm_object.h>
68 #include <vm/vm_zone.h>
69 #include <sys/sysctl.h>
70
71 static int change_dir __P((struct nameidata *ndp, struct proc *p));
72 static void checkdirs __P((struct vnode *olddp));
73 static int chroot_refuse_vdir_fds __P((struct filedesc *fdp));
74 static int getutimes __P((const struct timeval *, struct timespec *));
75 static int setfown __P((struct proc *, struct vnode *, uid_t, gid_t));
76 static int setfmode __P((struct proc *, struct vnode *, int));
77 static int setfflags __P((struct proc *, struct vnode *, int));
78 static int setutimes __P((struct proc *, struct vnode *,
79     const struct timespec *, int));
80 static int      usermount = 0;  /* if 1, non-root can mount fs. */
81
82 int (*union_dircheckp) __P((struct proc *, struct vnode **, struct file *));
83
84 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, "");
85
86 /*
87  * Virtual File System System Calls
88  */
89
90 /*
91  * Mount a file system.
92  */
93 #ifndef _SYS_SYSPROTO_H_
94 struct mount_args {
95         char    *type;
96         char    *path;
97         int     flags;
98         caddr_t data;
99 };
100 #endif
101 /* ARGSUSED */
102 int
103 mount(p, uap)
104         struct proc *p;
105         register struct mount_args /* {
106                 syscallarg(char *) type;
107                 syscallarg(char *) path;
108                 syscallarg(int) flags;
109                 syscallarg(caddr_t) data;
110         } */ *uap;
111 {
112         struct vnode *vp;
113         struct mount *mp;
114         struct vfsconf *vfsp;
115         int error, flag = 0, flag2 = 0;
116         struct vattr va;
117 #ifdef COMPAT_43
118         u_long fstypenum;
119 #endif
120         struct nameidata nd;
121         char fstypename[MFSNAMELEN];
122
123         if (usermount == 0 && (error = suser(p)))
124                 return (error);
125         /*
126          * Do not allow NFS export by non-root users.
127          */
128         if (SCARG(uap, flags) & MNT_EXPORTED) {
129                 error = suser(p);
130                 if (error)
131                         return (error);
132         }
133         /*
134          * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users
135          */
136         if (suser_xxx(p->p_ucred, 0, 0)) 
137                 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
138         /*
139          * Get vnode to be covered
140          */
141         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
142             SCARG(uap, path), p);
143         if ((error = namei(&nd)) != 0)
144                 return (error);
145         vp = nd.ni_vp;
146         if (SCARG(uap, flags) & MNT_UPDATE) {
147                 if ((vp->v_flag & VROOT) == 0) {
148                         vput(vp);
149                         return (EINVAL);
150                 }
151                 mp = vp->v_mount;
152                 flag = mp->mnt_flag;
153                 flag2 = mp->mnt_kern_flag;
154                 /*
155                  * We only allow the filesystem to be reloaded if it
156                  * is currently mounted read-only.
157                  */
158                 if ((SCARG(uap, flags) & MNT_RELOAD) &&
159                     ((mp->mnt_flag & MNT_RDONLY) == 0)) {
160                         vput(vp);
161                         return (EOPNOTSUPP);    /* Needs translation */
162                 }
163                 mp->mnt_flag |=
164                     SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
165                 /*
166                  * Only root, or the user that did the original mount is
167                  * permitted to update it.
168                  */
169                 if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
170                     (error = suser(p))) {
171                         vput(vp);
172                         return (error);
173                 }
174                 if (vfs_busy(mp, LK_NOWAIT, 0, p)) {
175                         vput(vp);
176                         return (EBUSY);
177                 }
178                 VOP_UNLOCK(vp, 0, p);
179                 goto update;
180         }
181         /*
182          * If the user is not root, ensure that they own the directory
183          * onto which we are attempting to mount.
184          */
185         if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
186             (va.va_uid != p->p_ucred->cr_uid &&
187              (error = suser(p)))) {
188                 vput(vp);
189                 return (error);
190         }
191         if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
192                 return (error);
193         if (vp->v_type != VDIR) {
194                 vput(vp);
195                 return (ENOTDIR);
196         }
197 #ifdef COMPAT_43
198         /*
199          * Historically filesystem types were identified by number. If we
200          * get an integer for the filesystem type instead of a string, we
201          * check to see if it matches one of the historic filesystem types.
202          */
203         fstypenum = (uintptr_t)SCARG(uap, type);
204         if (fstypenum < maxvfsconf) {
205                 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
206                         if (vfsp->vfc_typenum == fstypenum)
207                                 break;
208                 if (vfsp == NULL) {
209                         vput(vp);
210                         return (ENODEV);
211                 }
212                 strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN);
213         } else
214 #endif /* COMPAT_43 */
215         if ((error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) != 0) {
216                 vput(vp);
217                 return (error);
218         }
219         for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
220                 if (!strcmp(vfsp->vfc_name, fstypename))
221                         break;
222         if (vfsp == NULL) {
223                 linker_file_t lf;
224
225                 /* Refuse to load modules if securelevel raised */
226                 if (securelevel > 0) {
227                         vput(vp);
228                         return EPERM; 
229                 }
230                 /* Only load modules for root (very important!) */
231                 if ((error = suser(p)) != 0) {
232                         vput(vp);
233                         return error;
234                 }
235                 error = linker_load_file(fstypename, &lf);
236                 if (error || lf == NULL) {
237                         vput(vp);
238                         if (lf == NULL)
239                                 error = ENODEV;
240                         return error;
241                 }
242                 lf->userrefs++;
243                 /* lookup again, see if the VFS was loaded */
244                 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
245                         if (!strcmp(vfsp->vfc_name, fstypename))
246                                 break;
247                 if (vfsp == NULL) {
248                         lf->userrefs--;
249                         linker_file_unload(lf);
250                         vput(vp);
251                         return (ENODEV);
252                 }
253         }
254         simple_lock(&vp->v_interlock);
255         if ((vp->v_flag & VMOUNT) != 0 ||
256             vp->v_mountedhere != NULL) {
257                 simple_unlock(&vp->v_interlock);
258                 vput(vp);
259                 return (EBUSY);
260         }
261         vp->v_flag |= VMOUNT;
262         simple_unlock(&vp->v_interlock);
263
264         /*
265          * Allocate and initialize the filesystem.
266          */
267         mp = (struct mount *)malloc((u_long)sizeof(struct mount),
268                 M_MOUNT, M_WAITOK);
269         bzero((char *)mp, (u_long)sizeof(struct mount));
270         lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, LK_NOPAUSE);
271         (void)vfs_busy(mp, LK_NOWAIT, 0, p);
272         mp->mnt_op = vfsp->vfc_vfsops;
273         mp->mnt_vfc = vfsp;
274         vfsp->vfc_refcount++;
275         mp->mnt_stat.f_type = vfsp->vfc_typenum;
276         mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
277         strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
278         mp->mnt_vnodecovered = vp;
279         mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
280         mp->mnt_iosize_max = DFLTPHYS;
281         VOP_UNLOCK(vp, 0, p);
282 update:
283         /*
284          * Set the mount level flags.
285          */
286         if (SCARG(uap, flags) & MNT_RDONLY)
287                 mp->mnt_flag |= MNT_RDONLY;
288         else if (mp->mnt_flag & MNT_RDONLY)
289                 mp->mnt_kern_flag |= MNTK_WANTRDWR;
290         mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
291             MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME |
292             MNT_NOSYMFOLLOW | MNT_IGNORE |
293             MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
294         mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
295             MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE |
296             MNT_NOSYMFOLLOW | MNT_IGNORE |
297             MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
298         /*
299          * Mount the filesystem.
300          */
301         error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
302         if (mp->mnt_flag & MNT_UPDATE) {
303                 vrele(vp);
304                 if (mp->mnt_kern_flag & MNTK_WANTRDWR)
305                         mp->mnt_flag &= ~MNT_RDONLY;
306                 mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE);
307                 mp->mnt_kern_flag &=~ MNTK_WANTRDWR;
308                 if (error) {
309                         mp->mnt_flag = flag;
310                         mp->mnt_kern_flag = flag2;
311                 }
312                 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
313                         if (mp->mnt_syncer == NULL)
314                                 error = vfs_allocate_syncvnode(mp);
315                 } else {
316                         if (mp->mnt_syncer != NULL)
317                                 vrele(mp->mnt_syncer);
318                         mp->mnt_syncer = NULL;
319                 }
320                 vfs_unbusy(mp, p);
321                 return (error);
322         }
323         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
324         /*
325          * Put the new filesystem on the mount list after root.
326          */
327         cache_purge(vp);
328         if (!error) {
329                 simple_lock(&vp->v_interlock);
330                 vp->v_flag &= ~VMOUNT;
331                 vp->v_mountedhere = mp;
332                 simple_unlock(&vp->v_interlock);
333                 simple_lock(&mountlist_slock);
334                 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
335                 simple_unlock(&mountlist_slock);
336                 checkdirs(vp);
337                 VOP_UNLOCK(vp, 0, p);
338                 if ((mp->mnt_flag & MNT_RDONLY) == 0)
339                         error = vfs_allocate_syncvnode(mp);
340                 vfs_unbusy(mp, p);
341                 if ((error = VFS_START(mp, 0, p)) != 0)
342                         vrele(vp);
343         } else {
344                 simple_lock(&vp->v_interlock);
345                 vp->v_flag &= ~VMOUNT;
346                 simple_unlock(&vp->v_interlock);
347                 mp->mnt_vfc->vfc_refcount--;
348                 vfs_unbusy(mp, p);
349                 free((caddr_t)mp, M_MOUNT);
350                 vput(vp);
351         }
352         return (error);
353 }
354
355 /*
356  * Scan all active processes to see if any of them have a current
357  * or root directory onto which the new filesystem has just been
358  * mounted. If so, replace them with the new mount point.
359  */
360 static void
361 checkdirs(olddp)
362         struct vnode *olddp;
363 {
364         struct filedesc *fdp;
365         struct vnode *newdp;
366         struct proc *p;
367
368         if (olddp->v_usecount == 1)
369                 return;
370         if (VFS_ROOT(olddp->v_mountedhere, &newdp))
371                 panic("mount: lost mount");
372         LIST_FOREACH(p, &allproc, p_list) {
373                 fdp = p->p_fd;
374                 if (fdp->fd_cdir == olddp) {
375                         vrele(fdp->fd_cdir);
376                         VREF(newdp);
377                         fdp->fd_cdir = newdp;
378                 }
379                 if (fdp->fd_rdir == olddp) {
380                         vrele(fdp->fd_rdir);
381                         VREF(newdp);
382                         fdp->fd_rdir = newdp;
383                 }
384         }
385         if (rootvnode == olddp) {
386                 vrele(rootvnode);
387                 VREF(newdp);
388                 rootvnode = newdp;
389         }
390         vput(newdp);
391 }
392
393 /*
394  * Unmount a file system.
395  *
396  * Note: unmount takes a path to the vnode mounted on as argument,
397  * not special file (as before).
398  */
399 #ifndef _SYS_SYSPROTO_H_
400 struct unmount_args {
401         char    *path;
402         int     flags;
403 };
404 #endif
405 /* ARGSUSED */
406 int
407 unmount(p, uap)
408         struct proc *p;
409         register struct unmount_args /* {
410                 syscallarg(char *) path;
411                 syscallarg(int) flags;
412         } */ *uap;
413 {
414         register struct vnode *vp;
415         struct mount *mp;
416         int error;
417         struct nameidata nd;
418
419         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
420             SCARG(uap, path), p);
421         if ((error = namei(&nd)) != 0)
422                 return (error);
423         vp = nd.ni_vp;
424         mp = vp->v_mount;
425
426         /*
427          * Only root, or the user that did the original mount is
428          * permitted to unmount this filesystem.
429          */
430         if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
431             (error = suser(p))) {
432                 vput(vp);
433                 return (error);
434         }
435
436         /*
437          * Don't allow unmounting the root file system.
438          */
439         if (mp->mnt_flag & MNT_ROOTFS) {
440                 vput(vp);
441                 return (EINVAL);
442         }
443
444         /*
445          * Must be the root of the filesystem
446          */
447         if ((vp->v_flag & VROOT) == 0) {
448                 vput(vp);
449                 return (EINVAL);
450         }
451         vput(vp);
452         return (dounmount(mp, SCARG(uap, flags), p));
453 }
454
455 /*
456  * Do the actual file system unmount.
457  */
458 int
459 dounmount(mp, flags, p)
460         register struct mount *mp;
461         int flags;
462         struct proc *p;
463 {
464         struct vnode *coveredvp;
465         int error;
466         int async_flag;
467
468         simple_lock(&mountlist_slock);
469         mp->mnt_kern_flag |= MNTK_UNMOUNT;
470         lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p);
471
472         if (mp->mnt_flag & MNT_EXPUBLIC)
473                 vfs_setpublicfs(NULL, NULL, NULL);
474
475         vfs_msync(mp, MNT_WAIT);
476         async_flag = mp->mnt_flag & MNT_ASYNC;
477         mp->mnt_flag &=~ MNT_ASYNC;
478         cache_purgevfs(mp);     /* remove cache entries for this file sys */
479         if (mp->mnt_syncer != NULL)
480                 vrele(mp->mnt_syncer);
481         if (((mp->mnt_flag & MNT_RDONLY) ||
482              (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
483             (flags & MNT_FORCE))
484                 error = VFS_UNMOUNT(mp, flags, p);
485         simple_lock(&mountlist_slock);
486         if (error) {
487                 if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
488                         (void) vfs_allocate_syncvnode(mp);
489                 mp->mnt_kern_flag &= ~MNTK_UNMOUNT;
490                 mp->mnt_flag |= async_flag;
491                 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
492                     &mountlist_slock, p);
493                 if (mp->mnt_kern_flag & MNTK_MWAIT)
494                         wakeup((caddr_t)mp);
495                 return (error);
496         }
497         TAILQ_REMOVE(&mountlist, mp, mnt_list);
498         if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
499                 coveredvp->v_mountedhere = (struct mount *)0;
500                 vrele(coveredvp);
501         }
502         mp->mnt_vfc->vfc_refcount--;
503         if (!LIST_EMPTY(&mp->mnt_vnodelist))
504                 panic("unmount: dangling vnode");
505         lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p);
506         if (mp->mnt_kern_flag & MNTK_MWAIT)
507                 wakeup((caddr_t)mp);
508         free((caddr_t)mp, M_MOUNT);
509         return (0);
510 }
511
512 /*
513  * Sync each mounted filesystem.
514  */
515 #ifndef _SYS_SYSPROTO_H_
516 struct sync_args {
517         int     dummy;
518 };
519 #endif
520
521 #ifdef DEBUG
522 static int syncprt = 0;
523 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
524 #endif
525
526 /* ARGSUSED */
527 int
528 sync(p, uap)
529         struct proc *p;
530         struct sync_args *uap;
531 {
532         register struct mount *mp, *nmp;
533         int asyncflag;
534
535         simple_lock(&mountlist_slock);
536         for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
537                 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
538                         nmp = TAILQ_NEXT(mp, mnt_list);
539                         continue;
540                 }
541                 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
542                         asyncflag = mp->mnt_flag & MNT_ASYNC;
543                         mp->mnt_flag &= ~MNT_ASYNC;
544                         vfs_msync(mp, MNT_NOWAIT);
545                         VFS_SYNC(mp, MNT_NOWAIT,
546                                 ((p != NULL) ? p->p_ucred : NOCRED), p);
547                         mp->mnt_flag |= asyncflag;
548                 }
549                 simple_lock(&mountlist_slock);
550                 nmp = TAILQ_NEXT(mp, mnt_list);
551                 vfs_unbusy(mp, p);
552         }
553         simple_unlock(&mountlist_slock);
554 #if 0
555 /*
556  * XXX don't call vfs_bufstats() yet because that routine
557  * was not imported in the Lite2 merge.
558  */
559 #ifdef DIAGNOSTIC
560         if (syncprt)
561                 vfs_bufstats();
562 #endif /* DIAGNOSTIC */
563 #endif
564         return (0);
565 }
566
567 /* XXX PRISON: could be per prison flag */
568 static int prison_quotas;
569 #if 0
570 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
571 #endif
572
573 /*
574  * Change filesystem quotas.
575  */
576 #ifndef _SYS_SYSPROTO_H_
577 struct quotactl_args {
578         char *path;
579         int cmd;
580         int uid;
581         caddr_t arg;
582 };
583 #endif
584 /* ARGSUSED */
585 int
586 quotactl(p, uap)
587         struct proc *p;
588         register struct quotactl_args /* {
589                 syscallarg(char *) path;
590                 syscallarg(int) cmd;
591                 syscallarg(int) uid;
592                 syscallarg(caddr_t) arg;
593         } */ *uap;
594 {
595         register struct mount *mp;
596         int error;
597         struct nameidata nd;
598
599         if (p->p_prison && !prison_quotas)
600                 return (EPERM);
601         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
602         if ((error = namei(&nd)) != 0)
603                 return (error);
604         mp = nd.ni_vp->v_mount;
605         vrele(nd.ni_vp);
606         return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
607             SCARG(uap, arg), p));
608 }
609
610 /*
611  * Get filesystem statistics.
612  */
613 #ifndef _SYS_SYSPROTO_H_
614 struct statfs_args {
615         char *path;
616         struct statfs *buf;
617 };
618 #endif
619 /* ARGSUSED */
620 int
621 statfs(p, uap)
622         struct proc *p;
623         register struct statfs_args /* {
624                 syscallarg(char *) path;
625                 syscallarg(struct statfs *) buf;
626         } */ *uap;
627 {
628         register struct mount *mp;
629         register struct statfs *sp;
630         int error;
631         struct nameidata nd;
632         struct statfs sb;
633
634         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
635         if ((error = namei(&nd)) != 0)
636                 return (error);
637         mp = nd.ni_vp->v_mount;
638         sp = &mp->mnt_stat;
639         vrele(nd.ni_vp);
640         error = VFS_STATFS(mp, sp, p);
641         if (error)
642                 return (error);
643         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
644         if (suser_xxx(p->p_ucred, 0, 0)) {
645                 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
646                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
647                 sp = &sb;
648         }
649         return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
650 }
651
652 /*
653  * Get filesystem statistics.
654  */
655 #ifndef _SYS_SYSPROTO_H_
656 struct fstatfs_args {
657         int fd;
658         struct statfs *buf;
659 };
660 #endif
661 /* ARGSUSED */
662 int
663 fstatfs(p, uap)
664         struct proc *p;
665         register struct fstatfs_args /* {
666                 syscallarg(int) fd;
667                 syscallarg(struct statfs *) buf;
668         } */ *uap;
669 {
670         struct file *fp;
671         struct mount *mp;
672         register struct statfs *sp;
673         int error;
674         struct statfs sb;
675
676         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
677                 return (error);
678         mp = ((struct vnode *)fp->f_data)->v_mount;
679         sp = &mp->mnt_stat;
680         error = VFS_STATFS(mp, sp, p);
681         if (error)
682                 return (error);
683         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
684         if (suser_xxx(p->p_ucred, 0, 0)) {
685                 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
686                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
687                 sp = &sb;
688         }
689         return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
690 }
691
692 /*
693  * Get statistics on all filesystems.
694  */
695 #ifndef _SYS_SYSPROTO_H_
696 struct getfsstat_args {
697         struct statfs *buf;
698         long bufsize;
699         int flags;
700 };
701 #endif
702 int
703 getfsstat(p, uap)
704         struct proc *p;
705         register struct getfsstat_args /* {
706                 syscallarg(struct statfs *) buf;
707                 syscallarg(long) bufsize;
708                 syscallarg(int) flags;
709         } */ *uap;
710 {
711         register struct mount *mp, *nmp;
712         register struct statfs *sp;
713         caddr_t sfsp;
714         long count, maxcount, error;
715
716         maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
717         sfsp = (caddr_t)SCARG(uap, buf);
718         count = 0;
719         simple_lock(&mountlist_slock);
720         for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
721                 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
722                         nmp = TAILQ_NEXT(mp, mnt_list);
723                         continue;
724                 }
725                 if (sfsp && count < maxcount) {
726                         sp = &mp->mnt_stat;
727                         /*
728                          * If MNT_NOWAIT or MNT_LAZY is specified, do not
729                          * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
730                          * overrides MNT_WAIT.
731                          */
732                         if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
733                             (SCARG(uap, flags) & MNT_WAIT)) &&
734                             (error = VFS_STATFS(mp, sp, p))) {
735                                 simple_lock(&mountlist_slock);
736                                 nmp = TAILQ_NEXT(mp, mnt_list);
737                                 vfs_unbusy(mp, p);
738                                 continue;
739                         }
740                         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
741                         error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
742                         if (error) {
743                                 vfs_unbusy(mp, p);
744                                 return (error);
745                         }
746                         sfsp += sizeof(*sp);
747                 }
748                 count++;
749                 simple_lock(&mountlist_slock);
750                 nmp = TAILQ_NEXT(mp, mnt_list);
751                 vfs_unbusy(mp, p);
752         }
753         simple_unlock(&mountlist_slock);
754         if (sfsp && count > maxcount)
755                 p->p_retval[0] = maxcount;
756         else
757                 p->p_retval[0] = count;
758         return (0);
759 }
760
761 /*
762  * Change current working directory to a given file descriptor.
763  */
764 #ifndef _SYS_SYSPROTO_H_
765 struct fchdir_args {
766         int     fd;
767 };
768 #endif
769 /* ARGSUSED */
770 int
771 fchdir(p, uap)
772         struct proc *p;
773         struct fchdir_args /* {
774                 syscallarg(int) fd;
775         } */ *uap;
776 {
777         register struct filedesc *fdp = p->p_fd;
778         struct vnode *vp, *tdp;
779         struct mount *mp;
780         struct file *fp;
781         int error;
782
783         if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
784                 return (error);
785         vp = (struct vnode *)fp->f_data;
786         VREF(vp);
787         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
788         if (vp->v_type != VDIR)
789                 error = ENOTDIR;
790         else
791                 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
792         while (!error && (mp = vp->v_mountedhere) != NULL) {
793                 if (vfs_busy(mp, 0, 0, p))
794                         continue;
795                 error = VFS_ROOT(mp, &tdp);
796                 vfs_unbusy(mp, p);
797                 if (error)
798                         break;
799                 vput(vp);
800                 vp = tdp;
801         }
802         if (error) {
803                 vput(vp);
804                 return (error);
805         }
806         VOP_UNLOCK(vp, 0, p);
807         vrele(fdp->fd_cdir);
808         fdp->fd_cdir = vp;
809         return (0);
810 }
811
812 /*
813  * Change current working directory (``.'').
814  */
815 #ifndef _SYS_SYSPROTO_H_
816 struct chdir_args {
817         char    *path;
818 };
819 #endif
820 /* ARGSUSED */
821 int
822 chdir(p, uap)
823         struct proc *p;
824         struct chdir_args /* {
825                 syscallarg(char *) path;
826         } */ *uap;
827 {
828         register struct filedesc *fdp = p->p_fd;
829         int error;
830         struct nameidata nd;
831
832         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
833             SCARG(uap, path), p);
834         if ((error = change_dir(&nd, p)) != 0)
835                 return (error);
836         vrele(fdp->fd_cdir);
837         fdp->fd_cdir = nd.ni_vp;
838         return (0);
839 }
840
841 /*
842  * Helper function for raised chroot(2) security function:  Refuse if
843  * any filedescriptors are open directories.
844  */
845 static int
846 chroot_refuse_vdir_fds(fdp)
847         struct filedesc *fdp;
848 {
849         struct vnode *vp;
850         struct file *fp;
851         int error;
852         int fd;
853
854         for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
855                 error = getvnode(fdp, fd, &fp);
856                 if (error)
857                         continue;
858                 vp = (struct vnode *)fp->f_data;
859                 if (vp->v_type != VDIR)
860                         continue;
861                 return(EPERM);
862         }
863         return (0);
864 }
865
866 /*
867  * This sysctl determines if we will allow a process to chroot(2) if it
868  * has a directory open:
869  *      0: disallowed for all processes.
870  *      1: allowed for processes that were not already chroot(2)'ed.
871  *      2: allowed for all processes.
872  */
873
874 static int chroot_allow_open_directories = 1;
875
876 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
877      &chroot_allow_open_directories, 0, "");
878
879 /*
880  * Change notion of root (``/'') directory.
881  */
882 #ifndef _SYS_SYSPROTO_H_
883 struct chroot_args {
884         char    *path;
885 };
886 #endif
887 /* ARGSUSED */
888 int
889 chroot(p, uap)
890         struct proc *p;
891         struct chroot_args /* {
892                 syscallarg(char *) path;
893         } */ *uap;
894 {
895         register struct filedesc *fdp = p->p_fd;
896         int error;
897         struct nameidata nd;
898
899         error = suser_xxx(0, p, PRISON_ROOT);
900         if (error)
901                 return (error);
902         if (chroot_allow_open_directories == 0 ||
903             (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode))
904                 error = chroot_refuse_vdir_fds(fdp);
905         if (error)
906                 return (error);
907         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
908             SCARG(uap, path), p);
909         if ((error = change_dir(&nd, p)) != 0)
910                 return (error);
911         vrele(fdp->fd_rdir);
912         fdp->fd_rdir = nd.ni_vp;
913         if (!fdp->fd_jdir) {
914                 fdp->fd_jdir = nd.ni_vp;
915                 VREF(fdp->fd_jdir);
916         }
917         return (0);
918 }
919
920 /*
921  * Common routine for chroot and chdir.
922  */
923 static int
924 change_dir(ndp, p)
925         register struct nameidata *ndp;
926         struct proc *p;
927 {
928         struct vnode *vp;
929         int error;
930
931         error = namei(ndp);
932         if (error)
933                 return (error);
934         vp = ndp->ni_vp;
935         if (vp->v_type != VDIR)
936                 error = ENOTDIR;
937         else
938                 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
939         if (error)
940                 vput(vp);
941         else
942                 VOP_UNLOCK(vp, 0, p);
943         return (error);
944 }
945
946 /*
947  * Check permissions, allocate an open file structure,
948  * and call the device open routine if any.
949  */
950 #ifndef _SYS_SYSPROTO_H_
951 struct open_args {
952         char    *path;
953         int     flags;
954         int     mode;
955 };
956 #endif
957 int
958 open(p, uap)
959         struct proc *p;
960         register struct open_args /* {
961                 syscallarg(char *) path;
962                 syscallarg(int) flags;
963                 syscallarg(int) mode;
964         } */ *uap;
965 {
966         register struct filedesc *fdp = p->p_fd;
967         register struct file *fp;
968         register struct vnode *vp;
969         int cmode, flags, oflags;
970         struct file *nfp;
971         int type, indx, error;
972         struct flock lf;
973         struct nameidata nd;
974
975         oflags = SCARG(uap, flags);
976         if ((oflags & O_ACCMODE) == O_ACCMODE)
977                 return (EINVAL);
978         flags = FFLAGS(oflags);
979         error = falloc(p, &nfp, &indx);
980         if (error)
981                 return (error);
982         fp = nfp;
983         cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
984         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
985         p->p_dupfd = -indx - 1;                 /* XXX check for fdopen */
986         error = vn_open(&nd, flags, cmode);
987         if (error) {
988                 ffree(fp);
989                 if ((error == ENODEV || error == ENXIO) &&
990                     p->p_dupfd >= 0 &&                  /* XXX from fdopen */
991                     (error =
992                         dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
993                         p->p_retval[0] = indx;
994                         return (0);
995                 }
996                 if (error == ERESTART)
997                         error = EINTR;
998                 fdp->fd_ofiles[indx] = NULL;
999                 return (error);
1000         }
1001         p->p_dupfd = 0;
1002         vp = nd.ni_vp;
1003
1004         fp->f_data = (caddr_t)vp;
1005         fp->f_flag = flags & FMASK;
1006         fp->f_ops = &vnops;
1007         fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
1008         if (flags & (O_EXLOCK | O_SHLOCK)) {
1009                 lf.l_whence = SEEK_SET;
1010                 lf.l_start = 0;
1011                 lf.l_len = 0;
1012                 if (flags & O_EXLOCK)
1013                         lf.l_type = F_WRLCK;
1014                 else
1015                         lf.l_type = F_RDLCK;
1016                 type = F_FLOCK;
1017                 if ((flags & FNONBLOCK) == 0)
1018                         type |= F_WAIT;
1019                 VOP_UNLOCK(vp, 0, p);
1020                 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
1021                         (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
1022                         ffree(fp);
1023                         fdp->fd_ofiles[indx] = NULL;
1024                         return (error);
1025                 }
1026                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1027                 fp->f_flag |= FHASLOCK;
1028         }
1029         /* assert that vn_open created a backing object if one is needed */
1030         KASSERT(!vn_canvmio(vp) || vp->v_object != NULL,
1031                 ("open: vmio vnode has no backing object after vn_open"));
1032         VOP_UNLOCK(vp, 0, p);
1033         p->p_retval[0] = indx;
1034         return (0);
1035 }
1036
1037 #ifdef COMPAT_43
1038 /*
1039  * Create a file.
1040  */
1041 #ifndef _SYS_SYSPROTO_H_
1042 struct ocreat_args {
1043         char    *path;
1044         int     mode;
1045 };
1046 #endif
1047 int
1048 ocreat(p, uap)
1049         struct proc *p;
1050         register struct ocreat_args /* {
1051                 syscallarg(char *) path;
1052                 syscallarg(int) mode;
1053         } */ *uap;
1054 {
1055         struct open_args /* {
1056                 syscallarg(char *) path;
1057                 syscallarg(int) flags;
1058                 syscallarg(int) mode;
1059         } */ nuap;
1060
1061         SCARG(&nuap, path) = SCARG(uap, path);
1062         SCARG(&nuap, mode) = SCARG(uap, mode);
1063         SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
1064         return (open(p, &nuap));
1065 }
1066 #endif /* COMPAT_43 */
1067
1068 /*
1069  * Create a special file.
1070  */
1071 #ifndef _SYS_SYSPROTO_H_
1072 struct mknod_args {
1073         char    *path;
1074         int     mode;
1075         int     dev;
1076 };
1077 #endif
1078 /* ARGSUSED */
1079 int
1080 mknod(p, uap)
1081         struct proc *p;
1082         register struct mknod_args /* {
1083                 syscallarg(char *) path;
1084                 syscallarg(int) mode;
1085                 syscallarg(int) dev;
1086         } */ *uap;
1087 {
1088         register struct vnode *vp;
1089         struct vattr vattr;
1090         int error;
1091         int whiteout = 0;
1092         struct nameidata nd;
1093
1094         switch (SCARG(uap, mode) & S_IFMT) {
1095         case S_IFCHR:
1096         case S_IFBLK:
1097                 error = suser(p);
1098                 break;
1099         default:
1100                 error = suser_xxx(0, p, PRISON_ROOT);
1101                 break;
1102         }
1103         if (error)
1104                 return (error);
1105         NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1106         if ((error = namei(&nd)) != 0)
1107                 return (error);
1108         vp = nd.ni_vp;
1109         if (vp != NULL)
1110                 error = EEXIST;
1111         else {
1112                 VATTR_NULL(&vattr);
1113                 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1114                 vattr.va_rdev = SCARG(uap, dev);
1115                 whiteout = 0;
1116
1117                 switch (SCARG(uap, mode) & S_IFMT) {
1118                 case S_IFMT:    /* used by badsect to flag bad sectors */
1119                         vattr.va_type = VBAD;
1120                         break;
1121                 case S_IFCHR:
1122                         vattr.va_type = VCHR;
1123                         break;
1124                 case S_IFBLK:
1125                         vattr.va_type = VBLK;
1126                         break;
1127                 case S_IFWHT:
1128                         whiteout = 1;
1129                         break;
1130                 default:
1131                         error = EINVAL;
1132                         break;
1133                 }
1134         }
1135         if (!error) {
1136                 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1137                 if (whiteout) {
1138                         error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
1139                         if (error)
1140                                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1141                         vput(nd.ni_dvp);
1142                 } else {
1143                         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1144                                                 &nd.ni_cnd, &vattr);
1145                         if (error == 0)
1146                                 vput(nd.ni_vp);
1147                         vput(nd.ni_dvp);
1148                 }
1149         } else {
1150                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1151                 if (nd.ni_dvp == vp)
1152                         vrele(nd.ni_dvp);
1153                 else
1154                         vput(nd.ni_dvp);
1155                 if (vp)
1156                         vrele(vp);
1157         }
1158         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod");
1159         ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod");
1160         return (error);
1161 }
1162
1163 /*
1164  * Create a named pipe.
1165  */
1166 #ifndef _SYS_SYSPROTO_H_
1167 struct mkfifo_args {
1168         char    *path;
1169         int     mode;
1170 };
1171 #endif
1172 /* ARGSUSED */
1173 int
1174 mkfifo(p, uap)
1175         struct proc *p;
1176         register struct mkfifo_args /* {
1177                 syscallarg(char *) path;
1178                 syscallarg(int) mode;
1179         } */ *uap;
1180 {
1181         struct vattr vattr;
1182         int error;
1183         struct nameidata nd;
1184
1185         NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1186         if ((error = namei(&nd)) != 0)
1187                 return (error);
1188         if (nd.ni_vp != NULL) {
1189                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1190                 if (nd.ni_dvp == nd.ni_vp)
1191                         vrele(nd.ni_dvp);
1192                 else
1193                         vput(nd.ni_dvp);
1194                 vrele(nd.ni_vp);
1195                 return (EEXIST);
1196         }
1197         VATTR_NULL(&vattr);
1198         vattr.va_type = VFIFO;
1199         vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1200         VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1201         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1202         if (error == 0)
1203                 vput(nd.ni_vp);
1204         vput(nd.ni_dvp);
1205         return (error);
1206 }
1207
1208 /*
1209  * Make a hard file link.
1210  */
1211 #ifndef _SYS_SYSPROTO_H_
1212 struct link_args {
1213         char    *path;
1214         char    *link;
1215 };
1216 #endif
1217 /* ARGSUSED */
1218 int
1219 link(p, uap)
1220         struct proc *p;
1221         register struct link_args /* {
1222                 syscallarg(char *) path;
1223                 syscallarg(char *) link;
1224         } */ *uap;
1225 {
1226         register struct vnode *vp;
1227         struct nameidata nd;
1228         int error;
1229
1230         NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), p);
1231         if ((error = namei(&nd)) != 0)
1232                 return (error);
1233         vp = nd.ni_vp;
1234         if (vp->v_type == VDIR)
1235                 error = EPERM;          /* POSIX */
1236         else {
1237                 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
1238                 error = namei(&nd);
1239                 if (!error) {
1240                         if (nd.ni_vp != NULL) {
1241                                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1242                                 if (nd.ni_vp)
1243                                         vrele(nd.ni_vp);
1244                                 error = EEXIST;
1245                         } else {
1246                                 VOP_LEASE(nd.ni_dvp, p, p->p_ucred,
1247                                     LEASE_WRITE);
1248                                 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1249                                 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1250                         }
1251                         if (nd.ni_dvp == nd.ni_vp)
1252                                 vrele(nd.ni_dvp);
1253                         else
1254                                 vput(nd.ni_dvp);
1255                 }
1256         }
1257         vrele(vp);
1258         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link");
1259         ASSERT_VOP_UNLOCKED(nd.ni_vp, "link");
1260         return (error);
1261 }
1262
1263 /*
1264  * Make a symbolic link.
1265  */
1266 #ifndef _SYS_SYSPROTO_H_
1267 struct symlink_args {
1268         char    *path;
1269         char    *link;
1270 };
1271 #endif
1272 /* ARGSUSED */
1273 int
1274 symlink(p, uap)
1275         struct proc *p;
1276         register struct symlink_args /* {
1277                 syscallarg(char *) path;
1278                 syscallarg(char *) link;
1279         } */ *uap;
1280 {
1281         struct vattr vattr;
1282         char *path;
1283         int error;
1284         struct nameidata nd;
1285
1286         path = zalloc(namei_zone);
1287         if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0)
1288                 goto out;
1289         NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
1290         if ((error = namei(&nd)) != 0)
1291                 goto out;
1292         if (nd.ni_vp) {
1293                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1294                 if (nd.ni_dvp == nd.ni_vp)
1295                         vrele(nd.ni_dvp);
1296                 else
1297                         vput(nd.ni_dvp);
1298                 vrele(nd.ni_vp);
1299                 error = EEXIST;
1300                 goto out;
1301         }
1302         VATTR_NULL(&vattr);
1303         vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
1304         VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1305         error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
1306         if (error == 0)
1307                 vput(nd.ni_vp);
1308         vput(nd.ni_dvp);
1309         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink");
1310         if (error == 0)
1311                 ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink");
1312 out:
1313         zfree(namei_zone, path);
1314         return (error);
1315 }
1316
1317 /*
1318  * Delete a whiteout from the filesystem.
1319  */
1320 /* ARGSUSED */
1321 int
1322 undelete(p, uap)
1323         struct proc *p;
1324         register struct undelete_args /* {
1325                 syscallarg(char *) path;
1326         } */ *uap;
1327 {
1328         int error;
1329         struct nameidata nd;
1330
1331         NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
1332             SCARG(uap, path), p);
1333         error = namei(&nd);
1334         if (error)
1335                 return (error);
1336
1337         if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1338                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1339                 if (nd.ni_dvp == nd.ni_vp)
1340                         vrele(nd.ni_dvp);
1341                 else
1342                         vput(nd.ni_dvp);
1343                 if (nd.ni_vp)
1344                         vrele(nd.ni_vp);
1345                 return (EEXIST);
1346         }
1347
1348         VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1349         if ((error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) != 0)
1350                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1351         vput(nd.ni_dvp);
1352         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete");
1353         ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete");
1354         return (error);
1355 }
1356
1357 /*
1358  * Delete a name from the filesystem.
1359  */
1360 #ifndef _SYS_SYSPROTO_H_
1361 struct unlink_args {
1362         char    *path;
1363 };
1364 #endif
1365 /* ARGSUSED */
1366 int
1367 unlink(p, uap)
1368         struct proc *p;
1369         struct unlink_args /* {
1370                 syscallarg(char *) path;
1371         } */ *uap;
1372 {
1373         register struct vnode *vp;
1374         int error;
1375         struct nameidata nd;
1376
1377         NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1378         if ((error = namei(&nd)) != 0)
1379                 return (error);
1380         vp = nd.ni_vp;
1381         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1382         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1383
1384         if (vp->v_type == VDIR)
1385                 error = EPERM;          /* POSIX */
1386         else {
1387                 /*
1388                  * The root of a mounted filesystem cannot be deleted.
1389                  *
1390                  * XXX: can this only be a VDIR case?
1391                  */
1392                 if (vp->v_flag & VROOT)
1393                         error = EBUSY;
1394         }
1395
1396         if (!error) {
1397                 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1398                 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
1399         } else {
1400                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1401         }
1402         if (nd.ni_dvp == vp)
1403                 vrele(nd.ni_dvp);
1404         else
1405                 vput(nd.ni_dvp);
1406         if (vp != NULLVP)
1407                 vput(vp);
1408         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
1409         ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
1410         return (error);
1411 }
1412
1413 /*
1414  * Reposition read/write file offset.
1415  */
1416 #ifndef _SYS_SYSPROTO_H_
1417 struct lseek_args {
1418         int     fd;
1419         int     pad;
1420         off_t   offset;
1421         int     whence;
1422 };
1423 #endif
1424 int
1425 lseek(p, uap)
1426         struct proc *p;
1427         register struct lseek_args /* {
1428                 syscallarg(int) fd;
1429                 syscallarg(int) pad;
1430                 syscallarg(off_t) offset;
1431                 syscallarg(int) whence;
1432         } */ *uap;
1433 {
1434         struct ucred *cred = p->p_ucred;
1435         register struct filedesc *fdp = p->p_fd;
1436         register struct file *fp;
1437         struct vattr vattr;
1438         int error;
1439
1440         if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
1441             (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
1442                 return (EBADF);
1443         if (fp->f_type != DTYPE_VNODE)
1444                 return (ESPIPE);
1445         switch (SCARG(uap, whence)) {
1446         case L_INCR:
1447                 fp->f_offset += SCARG(uap, offset);
1448                 break;
1449         case L_XTND:
1450                 error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p);
1451                 if (error)
1452                         return (error);
1453                 fp->f_offset = SCARG(uap, offset) + vattr.va_size;
1454                 break;
1455         case L_SET:
1456                 fp->f_offset = SCARG(uap, offset);
1457                 break;
1458         default:
1459                 return (EINVAL);
1460         }
1461         *(off_t *)(p->p_retval) = fp->f_offset;
1462         return (0);
1463 }
1464
1465 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1466 /*
1467  * Reposition read/write file offset.
1468  */
1469 #ifndef _SYS_SYSPROTO_H_
1470 struct olseek_args {
1471         int     fd;
1472         long    offset;
1473         int     whence;
1474 };
1475 #endif
1476 int
1477 olseek(p, uap)
1478         struct proc *p;
1479         register struct olseek_args /* {
1480                 syscallarg(int) fd;
1481                 syscallarg(long) offset;
1482                 syscallarg(int) whence;
1483         } */ *uap;
1484 {
1485         struct lseek_args /* {
1486                 syscallarg(int) fd;
1487                 syscallarg(int) pad;
1488                 syscallarg(off_t) offset;
1489                 syscallarg(int) whence;
1490         } */ nuap;
1491         int error;
1492
1493         SCARG(&nuap, fd) = SCARG(uap, fd);
1494         SCARG(&nuap, offset) = SCARG(uap, offset);
1495         SCARG(&nuap, whence) = SCARG(uap, whence);
1496         error = lseek(p, &nuap);
1497         return (error);
1498 }
1499 #endif /* COMPAT_43 */
1500
1501 /*
1502  * Check access permissions.
1503  */
1504 #ifndef _SYS_SYSPROTO_H_
1505 struct access_args {
1506         char    *path;
1507         int     flags;
1508 };
1509 #endif
1510 int
1511 access(p, uap)
1512         struct proc *p;
1513         register struct access_args /* {
1514                 syscallarg(char *) path;
1515                 syscallarg(int) flags;
1516         } */ *uap;
1517 {
1518         register struct ucred *cred = p->p_ucred;
1519         register struct vnode *vp;
1520         int error, flags, t_gid, t_uid;
1521         struct nameidata nd;
1522
1523         t_uid = cred->cr_uid;
1524         t_gid = cred->cr_groups[0];
1525         cred->cr_uid = p->p_cred->p_ruid;
1526         cred->cr_groups[0] = p->p_cred->p_rgid;
1527         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1528             SCARG(uap, path), p);
1529         if ((error = namei(&nd)) != 0)
1530                 goto out1;
1531         vp = nd.ni_vp;
1532
1533         /* Flags == 0 means only check for existence. */
1534         if (SCARG(uap, flags)) {
1535                 flags = 0;
1536                 if (SCARG(uap, flags) & R_OK)
1537                         flags |= VREAD;
1538                 if (SCARG(uap, flags) & W_OK)
1539                         flags |= VWRITE;
1540                 if (SCARG(uap, flags) & X_OK)
1541                         flags |= VEXEC;
1542                 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1543                         error = VOP_ACCESS(vp, flags, cred, p);
1544         }
1545         vput(vp);
1546 out1:
1547         cred->cr_uid = t_uid;
1548         cred->cr_groups[0] = t_gid;
1549         return (error);
1550 }
1551
1552 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1553 /*
1554  * Get file status; this version follows links.
1555  */
1556 #ifndef _SYS_SYSPROTO_H_
1557 struct ostat_args {
1558         char    *path;
1559         struct ostat *ub;
1560 };
1561 #endif
1562 /* ARGSUSED */
1563 int
1564 ostat(p, uap)
1565         struct proc *p;
1566         register struct ostat_args /* {
1567                 syscallarg(char *) path;
1568                 syscallarg(struct ostat *) ub;
1569         } */ *uap;
1570 {
1571         struct stat sb;
1572         struct ostat osb;
1573         int error;
1574         struct nameidata nd;
1575
1576         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1577             SCARG(uap, path), p);
1578         if ((error = namei(&nd)) != 0)
1579                 return (error);
1580         error = vn_stat(nd.ni_vp, &sb, p);
1581         vput(nd.ni_vp);
1582         if (error)
1583                 return (error);
1584         cvtstat(&sb, &osb);
1585         error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1586         return (error);
1587 }
1588
1589 /*
1590  * Get file status; this version does not follow links.
1591  */
1592 #ifndef _SYS_SYSPROTO_H_
1593 struct olstat_args {
1594         char    *path;
1595         struct ostat *ub;
1596 };
1597 #endif
1598 /* ARGSUSED */
1599 int
1600 olstat(p, uap)
1601         struct proc *p;
1602         register struct olstat_args /* {
1603                 syscallarg(char *) path;
1604                 syscallarg(struct ostat *) ub;
1605         } */ *uap;
1606 {
1607         struct vnode *vp;
1608         struct stat sb;
1609         struct ostat osb;
1610         int error;
1611         struct nameidata nd;
1612
1613         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1614             SCARG(uap, path), p);
1615         if ((error = namei(&nd)) != 0)
1616                 return (error);
1617         vp = nd.ni_vp;
1618         error = vn_stat(vp, &sb, p);
1619         vput(vp);
1620         if (error)
1621                 return (error);
1622         cvtstat(&sb, &osb);
1623         error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1624         return (error);
1625 }
1626
1627 /*
1628  * Convert from an old to a new stat structure.
1629  */
1630 void
1631 cvtstat(st, ost)
1632         struct stat *st;
1633         struct ostat *ost;
1634 {
1635
1636         ost->st_dev = st->st_dev;
1637         ost->st_ino = st->st_ino;
1638         ost->st_mode = st->st_mode;
1639         ost->st_nlink = st->st_nlink;
1640         ost->st_uid = st->st_uid;
1641         ost->st_gid = st->st_gid;
1642         ost->st_rdev = st->st_rdev;
1643         if (st->st_size < (quad_t)1 << 32)
1644                 ost->st_size = st->st_size;
1645         else
1646                 ost->st_size = -2;
1647         ost->st_atime = st->st_atime;
1648         ost->st_mtime = st->st_mtime;
1649         ost->st_ctime = st->st_ctime;
1650         ost->st_blksize = st->st_blksize;
1651         ost->st_blocks = st->st_blocks;
1652         ost->st_flags = st->st_flags;
1653         ost->st_gen = st->st_gen;
1654 }
1655 #endif /* COMPAT_43 || COMPAT_SUNOS */
1656
1657 /*
1658  * Get file status; this version follows links.
1659  */
1660 #ifndef _SYS_SYSPROTO_H_
1661 struct stat_args {
1662         char    *path;
1663         struct stat *ub;
1664 };
1665 #endif
1666 /* ARGSUSED */
1667 int
1668 stat(p, uap)
1669         struct proc *p;
1670         register struct stat_args /* {
1671                 syscallarg(char *) path;
1672                 syscallarg(struct stat *) ub;
1673         } */ *uap;
1674 {
1675         struct stat sb;
1676         int error;
1677         struct nameidata nd;
1678
1679         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1680             SCARG(uap, path), p);
1681         if ((error = namei(&nd)) != 0)
1682                 return (error);
1683         error = vn_stat(nd.ni_vp, &sb, p);
1684         vput(nd.ni_vp);
1685         if (error)
1686                 return (error);
1687         error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1688         return (error);
1689 }
1690
1691 /*
1692  * Get file status; this version does not follow links.
1693  */
1694 #ifndef _SYS_SYSPROTO_H_
1695 struct lstat_args {
1696         char    *path;
1697         struct stat *ub;
1698 };
1699 #endif
1700 /* ARGSUSED */
1701 int
1702 lstat(p, uap)
1703         struct proc *p;
1704         register struct lstat_args /* {
1705                 syscallarg(char *) path;
1706                 syscallarg(struct stat *) ub;
1707         } */ *uap;
1708 {
1709         int error;
1710         struct vnode *vp;
1711         struct stat sb;
1712         struct nameidata nd;
1713
1714         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1715             SCARG(uap, path), p);
1716         if ((error = namei(&nd)) != 0)
1717                 return (error);
1718         vp = nd.ni_vp;
1719         error = vn_stat(vp, &sb, p);
1720         vput(vp);
1721         if (error)
1722                 return (error);
1723         error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1724         return (error);
1725 }
1726
1727 void
1728 cvtnstat(sb, nsb)
1729         struct stat *sb;
1730         struct nstat *nsb;
1731 {
1732         nsb->st_dev = sb->st_dev;
1733         nsb->st_ino = sb->st_ino;
1734         nsb->st_mode = sb->st_mode;
1735         nsb->st_nlink = sb->st_nlink;
1736         nsb->st_uid = sb->st_uid;
1737         nsb->st_gid = sb->st_gid;
1738         nsb->st_rdev = sb->st_rdev;
1739         nsb->st_atimespec = sb->st_atimespec;
1740         nsb->st_mtimespec = sb->st_mtimespec;
1741         nsb->st_ctimespec = sb->st_ctimespec;
1742         nsb->st_size = sb->st_size;
1743         nsb->st_blocks = sb->st_blocks;
1744         nsb->st_blksize = sb->st_blksize;
1745         nsb->st_flags = sb->st_flags;
1746         nsb->st_gen = sb->st_gen;
1747         nsb->st_qspare[0] = sb->st_qspare[0];
1748         nsb->st_qspare[1] = sb->st_qspare[1];
1749 }
1750
1751 #ifndef _SYS_SYSPROTO_H_
1752 struct nstat_args {
1753         char    *path;
1754         struct nstat *ub;
1755 };
1756 #endif
1757 /* ARGSUSED */
1758 int
1759 nstat(p, uap)
1760         struct proc *p;
1761         register struct nstat_args /* {
1762                 syscallarg(char *) path;
1763                 syscallarg(struct nstat *) ub;
1764         } */ *uap;
1765 {
1766         struct stat sb;
1767         struct nstat nsb;
1768         int error;
1769         struct nameidata nd;
1770
1771         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1772             SCARG(uap, path), p);
1773         if ((error = namei(&nd)) != 0)
1774                 return (error);
1775         error = vn_stat(nd.ni_vp, &sb, p);
1776         vput(nd.ni_vp);
1777         if (error)
1778                 return (error);
1779         cvtnstat(&sb, &nsb);
1780         error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
1781         return (error);
1782 }
1783
1784 /*
1785  * Get file status; this version does not follow links.
1786  */
1787 #ifndef _SYS_SYSPROTO_H_
1788 struct lstat_args {
1789         char    *path;
1790         struct stat *ub;
1791 };
1792 #endif
1793 /* ARGSUSED */
1794 int
1795 nlstat(p, uap)
1796         struct proc *p;
1797         register struct nlstat_args /* {
1798                 syscallarg(char *) path;
1799                 syscallarg(struct nstat *) ub;
1800         } */ *uap;
1801 {
1802         int error;
1803         struct vnode *vp;
1804         struct stat sb;
1805         struct nstat nsb;
1806         struct nameidata nd;
1807
1808         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1809             SCARG(uap, path), p);
1810         if ((error = namei(&nd)) != 0)
1811                 return (error);
1812         vp = nd.ni_vp;
1813         error = vn_stat(vp, &sb, p);
1814         vput(vp);
1815         if (error)
1816                 return (error);
1817         cvtnstat(&sb, &nsb);
1818         error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
1819         return (error);
1820 }
1821
1822 /*
1823  * Get configurable pathname variables.
1824  */
1825 #ifndef _SYS_SYSPROTO_H_
1826 struct pathconf_args {
1827         char    *path;
1828         int     name;
1829 };
1830 #endif
1831 /* ARGSUSED */
1832 int
1833 pathconf(p, uap)
1834         struct proc *p;
1835         register struct pathconf_args /* {
1836                 syscallarg(char *) path;
1837                 syscallarg(int) name;
1838         } */ *uap;
1839 {
1840         int error;
1841         struct nameidata nd;
1842
1843         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1844             SCARG(uap, path), p);
1845         if ((error = namei(&nd)) != 0)
1846                 return (error);
1847         error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), p->p_retval);
1848         vput(nd.ni_vp);
1849         return (error);
1850 }
1851
1852 /*
1853  * Return target name of a symbolic link.
1854  */
1855 #ifndef _SYS_SYSPROTO_H_
1856 struct readlink_args {
1857         char    *path;
1858         char    *buf;
1859         int     count;
1860 };
1861 #endif
1862 /* ARGSUSED */
1863 int
1864 readlink(p, uap)
1865         struct proc *p;
1866         register struct readlink_args /* {
1867                 syscallarg(char *) path;
1868                 syscallarg(char *) buf;
1869                 syscallarg(int) count;
1870         } */ *uap;
1871 {
1872         register struct vnode *vp;
1873         struct iovec aiov;
1874         struct uio auio;
1875         int error;
1876         struct nameidata nd;
1877
1878         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1879             SCARG(uap, path), p);
1880         if ((error = namei(&nd)) != 0)
1881                 return (error);
1882         vp = nd.ni_vp;
1883         if (vp->v_type != VLNK)
1884                 error = EINVAL;
1885         else {
1886                 aiov.iov_base = SCARG(uap, buf);
1887                 aiov.iov_len = SCARG(uap, count);
1888                 auio.uio_iov = &aiov;
1889                 auio.uio_iovcnt = 1;
1890                 auio.uio_offset = 0;
1891                 auio.uio_rw = UIO_READ;
1892                 auio.uio_segflg = UIO_USERSPACE;
1893                 auio.uio_procp = p;
1894                 auio.uio_resid = SCARG(uap, count);
1895                 error = VOP_READLINK(vp, &auio, p->p_ucred);
1896         }
1897         vput(vp);
1898         p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
1899         return (error);
1900 }
1901
1902 static int
1903 setfflags(p, vp, flags)
1904         struct proc *p;
1905         struct vnode *vp;
1906         int flags;
1907 {
1908         int error;
1909         struct vattr vattr;
1910
1911         /*
1912          * Prevent non-root users from setting flags on devices.  When
1913          * a device is reused, users can retain ownership of the device
1914          * if they are allowed to set flags and programs assume that
1915          * chown can't fail when done as root.
1916          */
1917         if ((vp->v_type == VCHR || vp->v_type == VBLK) && 
1918             ((error = suser_xxx(p->p_ucred, p, PRISON_ROOT)) != 0))
1919                 return (error);
1920
1921         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1922         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1923         VATTR_NULL(&vattr);
1924         vattr.va_flags = flags;
1925         error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1926         VOP_UNLOCK(vp, 0, p);
1927         return (error);
1928 }
1929
1930 /*
1931  * Change flags of a file given a path name.
1932  */
1933 #ifndef _SYS_SYSPROTO_H_
1934 struct chflags_args {
1935         char    *path;
1936         int     flags;
1937 };
1938 #endif
1939 /* ARGSUSED */
1940 int
1941 chflags(p, uap)
1942         struct proc *p;
1943         register struct chflags_args /* {
1944                 syscallarg(char *) path;
1945                 syscallarg(int) flags;
1946         } */ *uap;
1947 {
1948         int error;
1949         struct nameidata nd;
1950
1951         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1952         if ((error = namei(&nd)) != 0)
1953                 return (error);
1954         error = setfflags(p, nd.ni_vp, SCARG(uap, flags));
1955         vrele(nd.ni_vp);
1956         return error;
1957 }
1958
1959 /*
1960  * Change flags of a file given a file descriptor.
1961  */
1962 #ifndef _SYS_SYSPROTO_H_
1963 struct fchflags_args {
1964         int     fd;
1965         int     flags;
1966 };
1967 #endif
1968 /* ARGSUSED */
1969 int
1970 fchflags(p, uap)
1971         struct proc *p;
1972         register struct fchflags_args /* {
1973                 syscallarg(int) fd;
1974                 syscallarg(int) flags;
1975         } */ *uap;
1976 {
1977         struct file *fp;
1978         int error;
1979
1980         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1981                 return (error);
1982         return setfflags(p, (struct vnode *) fp->f_data, SCARG(uap, flags));
1983 }
1984
1985 static int
1986 setfmode(p, vp, mode)
1987         struct proc *p;
1988         struct vnode *vp;
1989         int mode;
1990 {
1991         int error;
1992         struct vattr vattr;
1993
1994         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1995         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1996         VATTR_NULL(&vattr);
1997         vattr.va_mode = mode & ALLPERMS;
1998         error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1999         VOP_UNLOCK(vp, 0, p);
2000         return error;
2001 }
2002
2003 /*
2004  * Change mode of a file given path name.
2005  */
2006 #ifndef _SYS_SYSPROTO_H_
2007 struct chmod_args {
2008         char    *path;
2009         int     mode;
2010 };
2011 #endif
2012 /* ARGSUSED */
2013 int
2014 chmod(p, uap)
2015         struct proc *p;
2016         register struct chmod_args /* {
2017                 syscallarg(char *) path;
2018                 syscallarg(int) mode;
2019         } */ *uap;
2020 {
2021         int error;
2022         struct nameidata nd;
2023
2024         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2025         if ((error = namei(&nd)) != 0)
2026                 return (error);
2027         error = setfmode(p, nd.ni_vp, SCARG(uap, mode));
2028         vrele(nd.ni_vp);
2029         return error;
2030 }
2031
2032 /*
2033  * Change mode of a file given path name (don't follow links.)
2034  */
2035 #ifndef _SYS_SYSPROTO_H_
2036 struct lchmod_args {
2037         char    *path;
2038         int     mode;
2039 };
2040 #endif
2041 /* ARGSUSED */
2042 int
2043 lchmod(p, uap)
2044         struct proc *p;
2045         register struct lchmod_args /* {
2046                 syscallarg(char *) path;
2047                 syscallarg(int) mode;
2048         } */ *uap;
2049 {
2050         int error;
2051         struct nameidata nd;
2052
2053         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2054         if ((error = namei(&nd)) != 0)
2055                 return (error);
2056         error = setfmode(p, nd.ni_vp, SCARG(uap, mode));
2057         vrele(nd.ni_vp);
2058         return error;
2059 }
2060
2061 /*
2062  * Change mode of a file given a file descriptor.
2063  */
2064 #ifndef _SYS_SYSPROTO_H_
2065 struct fchmod_args {
2066         int     fd;
2067         int     mode;
2068 };
2069 #endif
2070 /* ARGSUSED */
2071 int
2072 fchmod(p, uap)
2073         struct proc *p;
2074         register struct fchmod_args /* {
2075                 syscallarg(int) fd;
2076                 syscallarg(int) mode;
2077         } */ *uap;
2078 {
2079         struct file *fp;
2080         int error;
2081
2082         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2083                 return (error);
2084         return setfmode(p, (struct vnode *)fp->f_data, SCARG(uap, mode));
2085 }
2086
2087 static int
2088 setfown(p, vp, uid, gid)
2089         struct proc *p;
2090         struct vnode *vp;
2091         uid_t uid;
2092         gid_t gid;
2093 {
2094         int error;
2095         struct vattr vattr;
2096
2097         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2098         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2099         VATTR_NULL(&vattr);
2100         vattr.va_uid = uid;
2101         vattr.va_gid = gid;
2102         error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2103         VOP_UNLOCK(vp, 0, p);
2104         return error;
2105 }
2106
2107 /*
2108  * Set ownership given a path name.
2109  */
2110 #ifndef _SYS_SYSPROTO_H_
2111 struct chown_args {
2112         char    *path;
2113         int     uid;
2114         int     gid;
2115 };
2116 #endif
2117 /* ARGSUSED */
2118 int
2119 chown(p, uap)
2120         struct proc *p;
2121         register struct chown_args /* {
2122                 syscallarg(char *) path;
2123                 syscallarg(int) uid;
2124                 syscallarg(int) gid;
2125         } */ *uap;
2126 {
2127         int error;
2128         struct nameidata nd;
2129
2130         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2131         if ((error = namei(&nd)) != 0)
2132                 return (error);
2133         error = setfown(p, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2134         vrele(nd.ni_vp);
2135
2136         return (error);
2137 }
2138
2139 /*
2140  * Set ownership given a path name, do not cross symlinks.
2141  */
2142 #ifndef _SYS_SYSPROTO_H_
2143 struct lchown_args {
2144         char    *path;
2145         int     uid;
2146         int     gid;
2147 };
2148 #endif
2149 /* ARGSUSED */
2150 int
2151 lchown(p, uap)
2152         struct proc *p;
2153         register struct lchown_args /* {
2154                 syscallarg(char *) path;
2155                 syscallarg(int) uid;
2156                 syscallarg(int) gid;
2157         } */ *uap;
2158 {
2159         int error;
2160         struct nameidata nd;
2161
2162         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2163         if ((error = namei(&nd)) != 0)
2164                 return (error);
2165         error = setfown(p, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2166         vrele(nd.ni_vp);
2167         return (error);
2168 }
2169
2170 /*
2171  * Set ownership given a file descriptor.
2172  */
2173 #ifndef _SYS_SYSPROTO_H_
2174 struct fchown_args {
2175         int     fd;
2176         int     uid;
2177         int     gid;
2178 };
2179 #endif
2180 /* ARGSUSED */
2181 int
2182 fchown(p, uap)
2183         struct proc *p;
2184         register struct fchown_args /* {
2185                 syscallarg(int) fd;
2186                 syscallarg(int) uid;
2187                 syscallarg(int) gid;
2188         } */ *uap;
2189 {
2190         struct file *fp;
2191         int error;
2192
2193         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2194                 return (error);
2195         return setfown(p, (struct vnode *)fp->f_data,
2196                 SCARG(uap, uid), SCARG(uap, gid));
2197 }
2198
2199 static int
2200 getutimes(usrtvp, tsp)
2201         const struct timeval *usrtvp;
2202         struct timespec *tsp;
2203 {
2204         struct timeval tv[2];
2205         int error;
2206
2207         if (usrtvp == NULL) {
2208                 microtime(&tv[0]);
2209                 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2210                 tsp[1] = tsp[0];
2211         } else {
2212                 if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0)
2213                         return (error);
2214                 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2215                 TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]);
2216         }
2217         return 0;
2218 }
2219
2220 static int
2221 setutimes(p, vp, ts, nullflag)
2222         struct proc *p;
2223         struct vnode *vp;
2224         const struct timespec *ts;
2225         int nullflag;
2226 {
2227         int error;
2228         struct vattr vattr;
2229
2230         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2231         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2232         VATTR_NULL(&vattr);
2233         vattr.va_atime = ts[0];
2234         vattr.va_mtime = ts[1];
2235         if (nullflag)
2236                 vattr.va_vaflags |= VA_UTIMES_NULL;
2237         error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2238         VOP_UNLOCK(vp, 0, p);
2239         return error;
2240 }
2241
2242 /*
2243  * Set the access and modification times of a file.
2244  */
2245 #ifndef _SYS_SYSPROTO_H_
2246 struct utimes_args {
2247         char    *path;
2248         struct  timeval *tptr;
2249 };
2250 #endif
2251 /* ARGSUSED */
2252 int
2253 utimes(p, uap)
2254         struct proc *p;
2255         register struct utimes_args /* {
2256                 syscallarg(char *) path;
2257                 syscallarg(struct timeval *) tptr;
2258         } */ *uap;
2259 {
2260         struct timespec ts[2];
2261         struct timeval *usrtvp;
2262         int error;
2263         struct nameidata nd;
2264
2265         usrtvp = SCARG(uap, tptr);
2266         if ((error = getutimes(usrtvp, ts)) != 0)
2267                 return (error);
2268         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2269         if ((error = namei(&nd)) != 0)
2270                 return (error);
2271         error = setutimes(p, nd.ni_vp, ts, usrtvp == NULL);
2272         vrele(nd.ni_vp);
2273         return (error);
2274 }
2275
2276 /*
2277  * Set the access and modification times of a file.
2278  */
2279 #ifndef _SYS_SYSPROTO_H_
2280 struct lutimes_args {
2281         char    *path;
2282         struct  timeval *tptr;
2283 };
2284 #endif
2285 /* ARGSUSED */
2286 int
2287 lutimes(p, uap)
2288         struct proc *p;
2289         register struct lutimes_args /* {
2290                 syscallarg(char *) path;
2291                 syscallarg(struct timeval *) tptr;
2292         } */ *uap;
2293 {
2294         struct timespec ts[2];
2295         struct timeval *usrtvp;
2296         int error;
2297         struct nameidata nd;
2298
2299         usrtvp = SCARG(uap, tptr);
2300         if ((error = getutimes(usrtvp, ts)) != 0)
2301                 return (error);
2302         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2303         if ((error = namei(&nd)) != 0)
2304                 return (error);
2305         error = setutimes(p, nd.ni_vp, ts, usrtvp == NULL);
2306         vrele(nd.ni_vp);
2307         return (error);
2308 }
2309
2310 /*
2311  * Set the access and modification times of a file.
2312  */
2313 #ifndef _SYS_SYSPROTO_H_
2314 struct futimes_args {
2315         int     fd;
2316         struct  timeval *tptr;
2317 };
2318 #endif
2319 /* ARGSUSED */
2320 int
2321 futimes(p, uap)
2322         struct proc *p;
2323         register struct futimes_args /* {
2324                 syscallarg(int ) fd;
2325                 syscallarg(struct timeval *) tptr;
2326         } */ *uap;
2327 {
2328         struct timespec ts[2];
2329         struct file *fp;
2330         struct timeval *usrtvp;
2331         int error;
2332
2333         usrtvp = SCARG(uap, tptr);
2334         if ((error = getutimes(usrtvp, ts)) != 0)
2335                 return (error);
2336         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2337                 return (error);
2338         return setutimes(p, (struct vnode *)fp->f_data, ts, usrtvp == NULL);
2339 }
2340
2341 /*
2342  * Truncate a file given its path name.
2343  */
2344 #ifndef _SYS_SYSPROTO_H_
2345 struct truncate_args {
2346         char    *path;
2347         int     pad;
2348         off_t   length;
2349 };
2350 #endif
2351 /* ARGSUSED */
2352 int
2353 truncate(p, uap)
2354         struct proc *p;
2355         register struct truncate_args /* {
2356                 syscallarg(char *) path;
2357                 syscallarg(int) pad;
2358                 syscallarg(off_t) length;
2359         } */ *uap;
2360 {
2361         register struct vnode *vp;
2362         struct vattr vattr;
2363         int error;
2364         struct nameidata nd;
2365
2366         if (uap->length < 0)
2367                 return(EINVAL);
2368         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2369         if ((error = namei(&nd)) != 0)
2370                 return (error);
2371         vp = nd.ni_vp;
2372         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2373         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2374         if (vp->v_type == VDIR)
2375                 error = EISDIR;
2376         else if ((error = vn_writechk(vp)) == 0 &&
2377             (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
2378                 VATTR_NULL(&vattr);
2379                 vattr.va_size = SCARG(uap, length);
2380                 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2381         }
2382         vput(vp);
2383         return (error);
2384 }
2385
2386 /*
2387  * Truncate a file given a file descriptor.
2388  */
2389 #ifndef _SYS_SYSPROTO_H_
2390 struct ftruncate_args {
2391         int     fd;
2392         int     pad;
2393         off_t   length;
2394 };
2395 #endif
2396 /* ARGSUSED */
2397 int
2398 ftruncate(p, uap)
2399         struct proc *p;
2400         register struct ftruncate_args /* {
2401                 syscallarg(int) fd;
2402                 syscallarg(int) pad;
2403                 syscallarg(off_t) length;
2404         } */ *uap;
2405 {
2406         struct vattr vattr;
2407         struct vnode *vp;
2408         struct file *fp;
2409         int error;
2410
2411         if (uap->length < 0)
2412                 return(EINVAL);
2413         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2414                 return (error);
2415         if ((fp->f_flag & FWRITE) == 0)
2416                 return (EINVAL);
2417         vp = (struct vnode *)fp->f_data;
2418         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2419         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2420         if (vp->v_type == VDIR)
2421                 error = EISDIR;
2422         else if ((error = vn_writechk(vp)) == 0) {
2423                 VATTR_NULL(&vattr);
2424                 vattr.va_size = SCARG(uap, length);
2425                 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
2426         }
2427         VOP_UNLOCK(vp, 0, p);
2428         return (error);
2429 }
2430
2431 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2432 /*
2433  * Truncate a file given its path name.
2434  */
2435 #ifndef _SYS_SYSPROTO_H_
2436 struct otruncate_args {
2437         char    *path;
2438         long    length;
2439 };
2440 #endif
2441 /* ARGSUSED */
2442 int
2443 otruncate(p, uap)
2444         struct proc *p;
2445         register struct otruncate_args /* {
2446                 syscallarg(char *) path;
2447                 syscallarg(long) length;
2448         } */ *uap;
2449 {
2450         struct truncate_args /* {
2451                 syscallarg(char *) path;
2452                 syscallarg(int) pad;
2453                 syscallarg(off_t) length;
2454         } */ nuap;
2455
2456         SCARG(&nuap, path) = SCARG(uap, path);
2457         SCARG(&nuap, length) = SCARG(uap, length);
2458         return (truncate(p, &nuap));
2459 }
2460
2461 /*
2462  * Truncate a file given a file descriptor.
2463  */
2464 #ifndef _SYS_SYSPROTO_H_
2465 struct oftruncate_args {
2466         int     fd;
2467         long    length;
2468 };
2469 #endif
2470 /* ARGSUSED */
2471 int
2472 oftruncate(p, uap)
2473         struct proc *p;
2474         register struct oftruncate_args /* {
2475                 syscallarg(int) fd;
2476                 syscallarg(long) length;
2477         } */ *uap;
2478 {
2479         struct ftruncate_args /* {
2480                 syscallarg(int) fd;
2481                 syscallarg(int) pad;
2482                 syscallarg(off_t) length;
2483         } */ nuap;
2484
2485         SCARG(&nuap, fd) = SCARG(uap, fd);
2486         SCARG(&nuap, length) = SCARG(uap, length);
2487         return (ftruncate(p, &nuap));
2488 }
2489 #endif /* COMPAT_43 || COMPAT_SUNOS */
2490
2491 /*
2492  * Sync an open file.
2493  */
2494 #ifndef _SYS_SYSPROTO_H_
2495 struct fsync_args {
2496         int     fd;
2497 };
2498 #endif
2499 /* ARGSUSED */
2500 int
2501 fsync(p, uap)
2502         struct proc *p;
2503         struct fsync_args /* {
2504                 syscallarg(int) fd;
2505         } */ *uap;
2506 {
2507         register struct vnode *vp;
2508         struct file *fp;
2509         int error;
2510
2511         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2512                 return (error);
2513         vp = (struct vnode *)fp->f_data;
2514         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2515         if (vp->v_object)
2516                 vm_object_page_clean(vp->v_object, 0, 0, 0);
2517         if ((error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p)) == 0 &&
2518             vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP) &&
2519             bioops.io_fsync)
2520                 error = (*bioops.io_fsync)(vp);
2521         VOP_UNLOCK(vp, 0, p);
2522         return (error);
2523 }
2524
2525 /*
2526  * Rename files.  Source and destination must either both be directories,
2527  * or both not be directories.  If target is a directory, it must be empty.
2528  */
2529 #ifndef _SYS_SYSPROTO_H_
2530 struct rename_args {
2531         char    *from;
2532         char    *to;
2533 };
2534 #endif
2535 /* ARGSUSED */
2536 int
2537 rename(p, uap)
2538         struct proc *p;
2539         register struct rename_args /* {
2540                 syscallarg(char *) from;
2541                 syscallarg(char *) to;
2542         } */ *uap;
2543 {
2544         register struct vnode *tvp, *fvp, *tdvp;
2545         struct nameidata fromnd, tond;
2546         int error;
2547
2548         NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
2549             SCARG(uap, from), p);
2550         if ((error = namei(&fromnd)) != 0)
2551                 return (error);
2552         fvp = fromnd.ni_vp;
2553         NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ,
2554             UIO_USERSPACE, SCARG(uap, to), p);
2555         if (fromnd.ni_vp->v_type == VDIR)
2556                 tond.ni_cnd.cn_flags |= WILLBEDIR;
2557         if ((error = namei(&tond)) != 0) {
2558                 /* Translate error code for rename("dir1", "dir2/."). */
2559                 if (error == EISDIR && fvp->v_type == VDIR)
2560                         error = EINVAL;
2561                 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2562                 vrele(fromnd.ni_dvp);
2563                 vrele(fvp);
2564                 goto out1;
2565         }
2566         tdvp = tond.ni_dvp;
2567         tvp = tond.ni_vp;
2568         if (tvp != NULL) {
2569                 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2570                         error = ENOTDIR;
2571                         goto out;
2572                 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2573                         error = EISDIR;
2574                         goto out;
2575                 }
2576         }
2577         if (fvp == tdvp)
2578                 error = EINVAL;
2579         /*
2580          * If source is the same as the destination (that is the
2581          * same inode number with the same name in the same directory),
2582          * then there is nothing to do.
2583          */
2584         if (fvp == tvp && fromnd.ni_dvp == tdvp &&
2585             fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
2586             !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
2587               fromnd.ni_cnd.cn_namelen))
2588                 error = -1;
2589 out:
2590         if (!error) {
2591                 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
2592                 if (fromnd.ni_dvp != tdvp) {
2593                         VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2594                 }
2595                 if (tvp) {
2596                         VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
2597                 }
2598                 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2599                                    tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2600         } else {
2601                 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
2602                 if (tdvp == tvp)
2603                         vrele(tdvp);
2604                 else
2605                         vput(tdvp);
2606                 if (tvp)
2607                         vput(tvp);
2608                 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2609                 vrele(fromnd.ni_dvp);
2610                 vrele(fvp);
2611         }
2612         vrele(tond.ni_startdir);
2613         ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename");
2614         ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename");
2615         ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename");
2616         ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename");
2617         zfree(namei_zone, tond.ni_cnd.cn_pnbuf);
2618 out1:
2619         if (fromnd.ni_startdir)
2620                 vrele(fromnd.ni_startdir);
2621         zfree(namei_zone, fromnd.ni_cnd.cn_pnbuf);
2622         if (error == -1)
2623                 return (0);
2624         return (error);
2625 }
2626
2627 /*
2628  * Make a directory file.
2629  */
2630 #ifndef _SYS_SYSPROTO_H_
2631 struct mkdir_args {
2632         char    *path;
2633         int     mode;
2634 };
2635 #endif
2636 /* ARGSUSED */
2637 int
2638 mkdir(p, uap)
2639         struct proc *p;
2640         register struct mkdir_args /* {
2641                 syscallarg(char *) path;
2642                 syscallarg(int) mode;
2643         } */ *uap;
2644 {
2645         register struct vnode *vp;
2646         struct vattr vattr;
2647         int error;
2648         struct nameidata nd;
2649
2650         NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
2651         nd.ni_cnd.cn_flags |= WILLBEDIR;
2652         if ((error = namei(&nd)) != 0)
2653                 return (error);
2654         vp = nd.ni_vp;
2655         if (vp != NULL) {
2656                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2657                 if (nd.ni_dvp == vp)
2658                         vrele(nd.ni_dvp);
2659                 else
2660                         vput(nd.ni_dvp);
2661                 vrele(vp);
2662                 return (EEXIST);
2663         }
2664         VATTR_NULL(&vattr);
2665         vattr.va_type = VDIR;
2666         vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
2667         VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2668         error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
2669         vput(nd.ni_dvp);
2670         if (!error)
2671                 vput(nd.ni_vp);
2672         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir");
2673         ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir");
2674         return (error);
2675 }
2676
2677 /*
2678  * Remove a directory file.
2679  */
2680 #ifndef _SYS_SYSPROTO_H_
2681 struct rmdir_args {
2682         char    *path;
2683 };
2684 #endif
2685 /* ARGSUSED */
2686 int
2687 rmdir(p, uap)
2688         struct proc *p;
2689         struct rmdir_args /* {
2690                 syscallarg(char *) path;
2691         } */ *uap;
2692 {
2693         register struct vnode *vp;
2694         int error;
2695         struct nameidata nd;
2696
2697         NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
2698             SCARG(uap, path), p);
2699         if ((error = namei(&nd)) != 0)
2700                 return (error);
2701         vp = nd.ni_vp;
2702         if (vp->v_type != VDIR) {
2703                 error = ENOTDIR;
2704                 goto out;
2705         }
2706         /*
2707          * No rmdir "." please.
2708          */
2709         if (nd.ni_dvp == vp) {
2710                 error = EINVAL;
2711                 goto out;
2712         }
2713         /*
2714          * The root of a mounted filesystem cannot be deleted.
2715          */
2716         if (vp->v_flag & VROOT)
2717                 error = EBUSY;
2718 out:
2719         if (!error) {
2720                 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2721                 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2722                 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2723         } else {
2724                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2725         }
2726         if (nd.ni_dvp == vp)
2727                 vrele(nd.ni_dvp);
2728         else
2729                 vput(nd.ni_dvp);
2730         if (vp != NULLVP)
2731                 vput(vp);
2732         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir");
2733         ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir");
2734         return (error);
2735 }
2736
2737 #ifdef COMPAT_43
2738 /*
2739  * Read a block of directory entries in a file system independent format.
2740  */
2741 #ifndef _SYS_SYSPROTO_H_
2742 struct ogetdirentries_args {
2743         int     fd;
2744         char    *buf;
2745         u_int   count;
2746         long    *basep;
2747 };
2748 #endif
2749 int
2750 ogetdirentries(p, uap)
2751         struct proc *p;
2752         register struct ogetdirentries_args /* {
2753                 syscallarg(int) fd;
2754                 syscallarg(char *) buf;
2755                 syscallarg(u_int) count;
2756                 syscallarg(long *) basep;
2757         } */ *uap;
2758 {
2759         struct vnode *vp;
2760         struct file *fp;
2761         struct uio auio, kuio;
2762         struct iovec aiov, kiov;
2763         struct dirent *dp, *edp;
2764         caddr_t dirbuf;
2765         int error, eofflag, readcnt;
2766         long loff;
2767
2768         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2769                 return (error);
2770         if ((fp->f_flag & FREAD) == 0)
2771                 return (EBADF);
2772         vp = (struct vnode *)fp->f_data;
2773 unionread:
2774         if (vp->v_type != VDIR)
2775                 return (EINVAL);
2776         aiov.iov_base = SCARG(uap, buf);
2777         aiov.iov_len = SCARG(uap, count);
2778         auio.uio_iov = &aiov;
2779         auio.uio_iovcnt = 1;
2780         auio.uio_rw = UIO_READ;
2781         auio.uio_segflg = UIO_USERSPACE;
2782         auio.uio_procp = p;
2783         auio.uio_resid = SCARG(uap, count);
2784         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2785         loff = auio.uio_offset = fp->f_offset;
2786 #       if (BYTE_ORDER != LITTLE_ENDIAN)
2787                 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
2788                         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
2789                             NULL, NULL);
2790                         fp->f_offset = auio.uio_offset;
2791                 } else
2792 #       endif
2793         {
2794                 kuio = auio;
2795                 kuio.uio_iov = &kiov;
2796                 kuio.uio_segflg = UIO_SYSSPACE;
2797                 kiov.iov_len = SCARG(uap, count);
2798                 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
2799                 kiov.iov_base = dirbuf;
2800                 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
2801                             NULL, NULL);
2802                 fp->f_offset = kuio.uio_offset;
2803                 if (error == 0) {
2804                         readcnt = SCARG(uap, count) - kuio.uio_resid;
2805                         edp = (struct dirent *)&dirbuf[readcnt];
2806                         for (dp = (struct dirent *)dirbuf; dp < edp; ) {
2807 #                               if (BYTE_ORDER == LITTLE_ENDIAN)
2808                                         /*
2809                                          * The expected low byte of
2810                                          * dp->d_namlen is our dp->d_type.
2811                                          * The high MBZ byte of dp->d_namlen
2812                                          * is our dp->d_namlen.
2813                                          */
2814                                         dp->d_type = dp->d_namlen;
2815                                         dp->d_namlen = 0;
2816 #                               else
2817                                         /*
2818                                          * The dp->d_type is the high byte
2819                                          * of the expected dp->d_namlen,
2820                                          * so must be zero'ed.
2821                                          */
2822                                         dp->d_type = 0;
2823 #                               endif
2824                                 if (dp->d_reclen > 0) {
2825                                         dp = (struct dirent *)
2826                                             ((char *)dp + dp->d_reclen);
2827                                 } else {
2828                                         error = EIO;
2829                                         break;
2830                                 }
2831                         }
2832                         if (dp >= edp)
2833                                 error = uiomove(dirbuf, readcnt, &auio);
2834                 }
2835                 FREE(dirbuf, M_TEMP);
2836         }
2837         VOP_UNLOCK(vp, 0, p);
2838         if (error)
2839                 return (error);
2840         if (SCARG(uap, count) == auio.uio_resid) {
2841                 if (union_dircheckp) {
2842                         error = union_dircheckp(p, &vp, fp);
2843                         if (error == -1)
2844                                 goto unionread;
2845                         if (error)
2846                                 return (error);
2847                 }
2848                 if ((vp->v_flag & VROOT) &&
2849                     (vp->v_mount->mnt_flag & MNT_UNION)) {
2850                         struct vnode *tvp = vp;
2851                         vp = vp->v_mount->mnt_vnodecovered;
2852                         VREF(vp);
2853                         fp->f_data = (caddr_t) vp;
2854                         fp->f_offset = 0;
2855                         vrele(tvp);
2856                         goto unionread;
2857                 }
2858         }
2859         error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2860             sizeof(long));
2861         p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
2862         return (error);
2863 }
2864 #endif /* COMPAT_43 */
2865
2866 /*
2867  * Read a block of directory entries in a file system independent format.
2868  */
2869 #ifndef _SYS_SYSPROTO_H_
2870 struct getdirentries_args {
2871         int     fd;
2872         char    *buf;
2873         u_int   count;
2874         long    *basep;
2875 };
2876 #endif
2877 int
2878 getdirentries(p, uap)
2879         struct proc *p;
2880         register struct getdirentries_args /* {
2881                 syscallarg(int) fd;
2882                 syscallarg(char *) buf;
2883                 syscallarg(u_int) count;
2884                 syscallarg(long *) basep;
2885         } */ *uap;
2886 {
2887         struct vnode *vp;
2888         struct file *fp;
2889         struct uio auio;
2890         struct iovec aiov;
2891         long loff;
2892         int error, eofflag;
2893
2894         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2895                 return (error);
2896         if ((fp->f_flag & FREAD) == 0)
2897                 return (EBADF);
2898         vp = (struct vnode *)fp->f_data;
2899 unionread:
2900         if (vp->v_type != VDIR)
2901                 return (EINVAL);
2902         aiov.iov_base = SCARG(uap, buf);
2903         aiov.iov_len = SCARG(uap, count);
2904         auio.uio_iov = &aiov;
2905         auio.uio_iovcnt = 1;
2906         auio.uio_rw = UIO_READ;
2907         auio.uio_segflg = UIO_USERSPACE;
2908         auio.uio_procp = p;
2909         auio.uio_resid = SCARG(uap, count);
2910         /* vn_lock(vp, LK_SHARED | LK_RETRY, p); */
2911         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2912         loff = auio.uio_offset = fp->f_offset;
2913         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
2914         fp->f_offset = auio.uio_offset;
2915         VOP_UNLOCK(vp, 0, p);
2916         if (error)
2917                 return (error);
2918         if (SCARG(uap, count) == auio.uio_resid) {
2919                 if (union_dircheckp) {
2920                         error = union_dircheckp(p, &vp, fp);
2921                         if (error == -1)
2922                                 goto unionread;
2923                         if (error)
2924                                 return (error);
2925                 }
2926                 if ((vp->v_flag & VROOT) &&
2927                     (vp->v_mount->mnt_flag & MNT_UNION)) {
2928                         struct vnode *tvp = vp;
2929                         vp = vp->v_mount->mnt_vnodecovered;
2930                         VREF(vp);
2931                         fp->f_data = (caddr_t) vp;
2932                         fp->f_offset = 0;
2933                         vrele(tvp);
2934                         goto unionread;
2935                 }
2936         }
2937         if (SCARG(uap, basep) != NULL) {
2938                 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2939                     sizeof(long));
2940         }
2941         p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
2942         return (error);
2943 }
2944 #ifndef _SYS_SYSPROTO_H_
2945 struct getdents_args {
2946         int fd;
2947         char *buf;
2948         size_t count;
2949 };
2950 #endif
2951 int
2952 getdents(p, uap)
2953         struct proc *p;
2954         register struct getdents_args /* {
2955                 syscallarg(int) fd;
2956                 syscallarg(char *) buf;
2957                 syscallarg(u_int) count;
2958         } */ *uap;
2959 {
2960         struct getdirentries_args ap;
2961         ap.fd = uap->fd;
2962         ap.buf = uap->buf;
2963         ap.count = uap->count;
2964         ap.basep = NULL;
2965         return getdirentries(p, &ap);
2966 }
2967
2968 /*
2969  * Set the mode mask for creation of filesystem nodes.
2970  */
2971 #ifndef _SYS_SYSPROTO_H_
2972 struct umask_args {
2973         int     newmask;
2974 };
2975 #endif
2976 int
2977 umask(p, uap)
2978         struct proc *p;
2979         struct umask_args /* {
2980                 syscallarg(int) newmask;
2981         } */ *uap;
2982 {
2983         register struct filedesc *fdp;
2984
2985         fdp = p->p_fd;
2986         p->p_retval[0] = fdp->fd_cmask;
2987         fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
2988         return (0);
2989 }
2990
2991 /*
2992  * Void all references to file by ripping underlying filesystem
2993  * away from vnode.
2994  */
2995 #ifndef _SYS_SYSPROTO_H_
2996 struct revoke_args {
2997         char    *path;
2998 };
2999 #endif
3000 /* ARGSUSED */
3001 int
3002 revoke(p, uap)
3003         struct proc *p;
3004         register struct revoke_args /* {
3005                 syscallarg(char *) path;
3006         } */ *uap;
3007 {
3008         register struct vnode *vp;
3009         struct vattr vattr;
3010         int error;
3011         struct nameidata nd;
3012
3013         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
3014         if ((error = namei(&nd)) != 0)
3015                 return (error);
3016         vp = nd.ni_vp;
3017         if (vp->v_type != VCHR && vp->v_type != VBLK) {
3018                 error = EINVAL;
3019                 goto out;
3020         }
3021         if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
3022                 goto out;
3023         if (p->p_ucred->cr_uid != vattr.va_uid &&
3024             (error = suser_xxx(0, p, PRISON_ROOT)))
3025                 goto out;
3026         if (vcount(vp) > 1)
3027                 VOP_REVOKE(vp, REVOKEALL);
3028 out:
3029         vrele(vp);
3030         return (error);
3031 }
3032
3033 /*
3034  * Convert a user file descriptor to a kernel file entry.
3035  */
3036 int
3037 getvnode(fdp, fd, fpp)
3038         struct filedesc *fdp;
3039         int fd;
3040         struct file **fpp;
3041 {
3042         struct file *fp;
3043
3044         if ((u_int)fd >= fdp->fd_nfiles ||
3045             (fp = fdp->fd_ofiles[fd]) == NULL)
3046                 return (EBADF);
3047         if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO)
3048                 return (EINVAL);
3049         *fpp = fp;
3050         return (0);
3051 }
3052 /*
3053  * Get (NFS) file handle
3054  */
3055 #ifndef _SYS_SYSPROTO_H_
3056 struct getfh_args {
3057         char    *fname;
3058         fhandle_t *fhp;
3059 };
3060 #endif
3061 int
3062 getfh(p, uap)
3063         struct proc *p;
3064         register struct getfh_args *uap;
3065 {
3066         struct nameidata nd;
3067         fhandle_t fh;
3068         register struct vnode *vp;
3069         int error;
3070
3071         /*
3072          * Must be super user
3073          */
3074         error = suser(p);
3075         if (error)
3076                 return (error);
3077         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
3078         error = namei(&nd);
3079         if (error)
3080                 return (error);
3081         vp = nd.ni_vp;
3082         bzero(&fh, sizeof(fh));
3083         fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
3084         error = VFS_VPTOFH(vp, &fh.fh_fid);
3085         vput(vp);
3086         if (error)
3087                 return (error);
3088         error = copyout(&fh, uap->fhp, sizeof (fh));
3089         return (error);
3090 }
3091
3092 /*
3093  * syscall for the rpc.lockd to use to translate a NFS file handle into
3094  * an open descriptor.
3095  *
3096  * warning: do not remove the suser() call or this becomes one giant
3097  * security hole.
3098  */
3099 #ifndef _SYS_SYSPROTO_H_
3100 struct fhopen_args {
3101         const struct fhandle *u_fhp;
3102         int flags;
3103 };
3104 #endif
3105 int
3106 fhopen(p, uap)
3107         struct proc *p;
3108         struct fhopen_args /* {
3109                 syscallarg(const struct fhandle *) u_fhp;
3110                 syscallarg(int) flags;
3111         } */ *uap;
3112 {
3113         struct mount *mp;
3114         struct vnode *vp;
3115         struct fhandle fhp;
3116         struct vattr vat;
3117         struct vattr *vap = &vat;
3118         struct flock lf;
3119         struct file *fp;
3120         register struct filedesc *fdp = p->p_fd;
3121         int fmode, mode, error, type;
3122         struct file *nfp; 
3123         int indx;
3124
3125         /*
3126          * Must be super user
3127          */
3128         error = suser(p);
3129         if (error)
3130                 return (error);
3131
3132         fmode = FFLAGS(SCARG(uap, flags));
3133         /* why not allow a non-read/write open for our lockd? */
3134         if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
3135                 return (EINVAL);
3136         error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp));
3137         if (error)
3138                 return(error);
3139         /* find the mount point */
3140         mp = vfs_getvfs(&fhp.fh_fsid);
3141         if (mp == NULL)
3142                 return (ESTALE);
3143         /* now give me my vnode, it gets returned to me locked */
3144         error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
3145         if (error)
3146                 return (error);
3147         /*
3148          * from now on we have to make sure not
3149          * to forget about the vnode
3150          * any error that causes an abort must vput(vp) 
3151          * just set error = err and 'goto bad;'.
3152          */
3153
3154         /* 
3155          * from vn_open 
3156          */
3157         if (vp->v_type == VLNK) {
3158                 error = EMLINK;
3159                 goto bad;
3160         }
3161         if (vp->v_type == VSOCK) {
3162                 error = EOPNOTSUPP;
3163                 goto bad;
3164         }
3165         mode = 0;
3166         if (fmode & (FWRITE | O_TRUNC)) {
3167                 if (vp->v_type == VDIR) {
3168                         error = EISDIR;
3169                         goto bad;
3170                 }
3171                 error = vn_writechk(vp);
3172                 if (error)
3173                         goto bad;
3174                 mode |= VWRITE;
3175         }
3176         if (fmode & FREAD)
3177                 mode |= VREAD;
3178         if (mode) {
3179                 error = VOP_ACCESS(vp, mode, p->p_ucred, p);
3180                 if (error)
3181                         goto bad;
3182         }
3183         if (fmode & O_TRUNC) {
3184                 VOP_UNLOCK(vp, 0, p);                           /* XXX */
3185                 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
3186                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);        /* XXX */
3187                 VATTR_NULL(vap);
3188                 vap->va_size = 0;
3189                 error = VOP_SETATTR(vp, vap, p->p_ucred, p);
3190                 if (error)
3191                         goto bad;
3192         }
3193         error = VOP_OPEN(vp, fmode, p->p_ucred, p);
3194         if (error)
3195                 goto bad;
3196         /*
3197          * Make sure that a VM object is created for VMIO support.
3198          */
3199         if (vn_canvmio(vp) == TRUE) {
3200                 if ((error = vfs_object_create(vp, p, p->p_ucred)) != 0)
3201                         goto bad;
3202         }
3203         if (fmode & FWRITE)
3204                 vp->v_writecount++;
3205
3206         /*
3207          * end of vn_open code 
3208          */
3209
3210         if ((error = falloc(p, &nfp, &indx)) != 0)
3211                 goto bad;
3212         fp = nfp;       
3213         nfp->f_data = (caddr_t)vp;
3214         nfp->f_flag = fmode & FMASK;
3215         nfp->f_ops = &vnops;
3216         nfp->f_type = DTYPE_VNODE;
3217         if (fmode & (O_EXLOCK | O_SHLOCK)) {
3218                 lf.l_whence = SEEK_SET;
3219                 lf.l_start = 0;
3220                 lf.l_len = 0;
3221                 if (fmode & O_EXLOCK)
3222                         lf.l_type = F_WRLCK;
3223                 else
3224                         lf.l_type = F_RDLCK;
3225                 type = F_FLOCK;
3226                 if ((fmode & FNONBLOCK) == 0)
3227                         type |= F_WAIT;
3228                 VOP_UNLOCK(vp, 0, p);
3229                 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
3230                         (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
3231                         ffree(fp);
3232                         fdp->fd_ofiles[indx] = NULL;
3233                         return (error);
3234                 }
3235                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
3236                 fp->f_flag |= FHASLOCK;
3237         }
3238         if ((vp->v_type == VREG) && (vp->v_object == NULL))
3239                 vfs_object_create(vp, p, p->p_ucred);
3240
3241         VOP_UNLOCK(vp, 0, p);
3242         p->p_retval[0] = indx;
3243         return (0);
3244
3245 bad:
3246         vput(vp);
3247         return (error);
3248 }
3249
3250 #ifndef _SYS_SYSPROTO_H_
3251 struct fhstat_args {
3252         struct fhandle *u_fhp;
3253         struct stat *sb;
3254 };
3255 #endif
3256 int
3257 fhstat(p, uap)
3258         struct proc *p;
3259         register struct fhstat_args /* {
3260                 syscallarg(struct fhandle *) u_fhp;
3261                 syscallarg(struct stat *) sb;
3262         } */ *uap;
3263 {
3264         struct stat sb;
3265         fhandle_t fh;
3266         struct mount *mp;
3267         struct vnode *vp;
3268         int error;
3269
3270         /*
3271          * Must be super user
3272          */
3273         error = suser(p);
3274         if (error)
3275                 return (error);
3276         
3277         error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t));
3278         if (error)
3279                 return (error);
3280
3281         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3282                 return (ESTALE);
3283         if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3284                 return (error);
3285         error = vn_stat(vp, &sb, p);
3286         vput(vp);
3287         if (error)
3288                 return (error);
3289         error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
3290         return (error);
3291 }
3292
3293 #ifndef _SYS_SYSPROTO_H_
3294 struct fhstatfs_args {
3295         struct fhandle *u_fhp;
3296         struct statfs *buf;
3297 };
3298 #endif
3299 int
3300 fhstatfs(p, uap)
3301         struct proc *p;
3302         struct fhstatfs_args /* {
3303                 syscallarg(struct fhandle) *u_fhp;
3304                 syscallarg(struct statfs) *buf;
3305         } */ *uap;
3306 {
3307         struct statfs *sp;
3308         struct mount *mp;
3309         struct vnode *vp;
3310         struct statfs sb;
3311         fhandle_t fh;
3312         int error;
3313
3314         /*
3315          * Must be super user
3316          */
3317         if ((error = suser(p)))
3318                 return (error);
3319
3320         if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0)
3321                 return (error);
3322
3323         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3324                 return (ESTALE);
3325         if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3326                 return (error);
3327         mp = vp->v_mount;
3328         sp = &mp->mnt_stat;
3329         vput(vp);
3330         if ((error = VFS_STATFS(mp, sp, p)) != 0)
3331                 return (error);
3332         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
3333         if (suser_xxx(p->p_ucred, 0, 0)) {
3334                 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
3335                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
3336                 sp = &sb;
3337         }
3338         return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
3339 }