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