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