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