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