787bec0f1df50e3a19c7ee876d935a315d7874bc
[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. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *      @(#)vfs_syscalls.c      8.13 (Berkeley) 4/15/94
35  * $FreeBSD: src/sys/kern/vfs_syscalls.c,v 1.151.2.18 2003/04/04 20:35:58 tegge Exp $
36  */
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/buf.h>
41 #include <sys/conf.h>
42 #include <sys/sysent.h>
43 #include <sys/malloc.h>
44 #include <sys/mount.h>
45 #include <sys/mountctl.h>
46 #include <sys/sysproto.h>
47 #include <sys/filedesc.h>
48 #include <sys/kernel.h>
49 #include <sys/fcntl.h>
50 #include <sys/file.h>
51 #include <sys/linker.h>
52 #include <sys/stat.h>
53 #include <sys/unistd.h>
54 #include <sys/vnode.h>
55 #include <sys/proc.h>
56 #include <sys/priv.h>
57 #include <sys/jail.h>
58 #include <sys/namei.h>
59 #include <sys/nlookup.h>
60 #include <sys/dirent.h>
61 #include <sys/extattr.h>
62 #include <sys/spinlock.h>
63 #include <sys/kern_syscall.h>
64 #include <sys/objcache.h>
65 #include <sys/sysctl.h>
66
67 #include <sys/buf2.h>
68 #include <sys/file2.h>
69 #include <sys/spinlock2.h>
70
71 #include <vm/vm.h>
72 #include <vm/vm_object.h>
73 #include <vm/vm_page.h>
74
75 #include <machine/limits.h>
76 #include <machine/stdarg.h>
77
78 static void mount_warning(struct mount *mp, const char *ctl, ...)
79                 __printflike(2, 3);
80 static int mount_path(struct proc *p, struct mount *mp, char **rb, char **fb);
81 static int checkvp_chdir (struct vnode *vn, struct thread *td);
82 static void checkdirs (struct nchandle *old_nch, struct nchandle *new_nch);
83 static int chroot_refuse_vdir_fds (struct filedesc *fdp);
84 static int chroot_visible_mnt(struct mount *mp, struct proc *p);
85 static int getutimes (struct timeval *, struct timespec *);
86 static int getutimens (const struct timespec *, struct timespec *, int *);
87 static int setfown (struct mount *, struct vnode *, uid_t, gid_t);
88 static int setfmode (struct vnode *, int);
89 static int setfflags (struct vnode *, int);
90 static int setutimes (struct vnode *, struct vattr *,
91                         const struct timespec *, int);
92 static int      usermount = 0;  /* if 1, non-root can mount fs. */
93
94 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0,
95     "Allow non-root users to mount filesystems");
96
97 /*
98  * Virtual File System System Calls
99  */
100
101 /*
102  * Mount a file system.
103  *
104  * mount_args(char *type, char *path, int flags, caddr_t data)
105  *
106  * MPALMOSTSAFE
107  */
108 int
109 sys_mount(struct mount_args *uap)
110 {
111         struct thread *td = curthread;
112         struct vnode *vp;
113         struct nchandle nch;
114         struct mount *mp, *nullmp;
115         struct vfsconf *vfsp;
116         int error, flag = 0, flag2 = 0;
117         int hasmount;
118         struct vattr va;
119         struct nlookupdata nd;
120         char fstypename[MFSNAMELEN];
121         struct ucred *cred;
122
123         cred = td->td_ucred;
124         if (jailed(cred)) {
125                 error = EPERM;
126                 goto done;
127         }
128         if (usermount == 0 && (error = priv_check(td, PRIV_ROOT)))
129                 goto done;
130
131         /*
132          * Do not allow NFS export by non-root users.
133          */
134         if (uap->flags & MNT_EXPORTED) {
135                 error = priv_check(td, PRIV_ROOT);
136                 if (error)
137                         goto done;
138         }
139         /*
140          * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users
141          */
142         if (priv_check(td, PRIV_ROOT)) 
143                 uap->flags |= MNT_NOSUID | MNT_NODEV;
144
145         /*
146          * Lookup the requested path and extract the nch and vnode.
147          */
148         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
149         if (error == 0) {
150                 if ((error = nlookup(&nd)) == 0) {
151                         if (nd.nl_nch.ncp->nc_vp == NULL)
152                                 error = ENOENT;
153                 }
154         }
155         if (error) {
156                 nlookup_done(&nd);
157                 goto done;
158         }
159
160         /*
161          * If the target filesystem is resolved via a nullfs mount, then
162          * nd.nl_nch.mount will be pointing to the nullfs mount structure
163          * instead of the target file system. We need it in case we are
164          * doing an update.
165          */
166         nullmp = nd.nl_nch.mount;
167
168         /*
169          * Extract the locked+refd ncp and cleanup the nd structure
170          */
171         nch = nd.nl_nch;
172         cache_zero(&nd.nl_nch);
173         nlookup_done(&nd);
174
175         if ((nch.ncp->nc_flag & NCF_ISMOUNTPT) &&
176             (mp = cache_findmount(&nch)) != NULL) {
177                 cache_dropmount(mp);
178                 hasmount = 1;
179         } else {
180                 hasmount = 0;
181         }
182
183
184         /*
185          * now we have the locked ref'd nch and unreferenced vnode.
186          */
187         vp = nch.ncp->nc_vp;
188         if ((error = vget(vp, LK_EXCLUSIVE)) != 0) {
189                 cache_put(&nch);
190                 goto done;
191         }
192         cache_unlock(&nch);
193
194         /*
195          * Extract the file system type. We need to know this early, to take
196          * appropriate actions if we are dealing with a nullfs.
197          */
198         if ((error = copyinstr(uap->type, fstypename, MFSNAMELEN, NULL)) != 0) {
199                 cache_drop(&nch);
200                 vput(vp);
201                 goto done;
202         }
203
204         /*
205          * Now we have an unlocked ref'd nch and a locked ref'd vp
206          */
207         if (uap->flags & MNT_UPDATE) {
208                 if ((vp->v_flag & (VROOT|VPFSROOT)) == 0) {
209                         cache_drop(&nch);
210                         vput(vp);
211                         error = EINVAL;
212                         goto done;
213                 }
214
215                 if (strncmp(fstypename, "null", 5) == 0) {
216                         KKASSERT(nullmp);
217                         mp = nullmp;
218                 } else {
219                         mp = vp->v_mount;
220                 }
221
222                 flag = mp->mnt_flag;
223                 flag2 = mp->mnt_kern_flag;
224                 /*
225                  * We only allow the filesystem to be reloaded if it
226                  * is currently mounted read-only.
227                  */
228                 if ((uap->flags & MNT_RELOAD) &&
229                     ((mp->mnt_flag & MNT_RDONLY) == 0)) {
230                         cache_drop(&nch);
231                         vput(vp);
232                         error = EOPNOTSUPP;     /* Needs translation */
233                         goto done;
234                 }
235                 /*
236                  * Only root, or the user that did the original mount is
237                  * permitted to update it.
238                  */
239                 if (mp->mnt_stat.f_owner != cred->cr_uid &&
240                     (error = priv_check(td, PRIV_ROOT))) {
241                         cache_drop(&nch);
242                         vput(vp);
243                         goto done;
244                 }
245                 if (vfs_busy(mp, LK_NOWAIT)) {
246                         cache_drop(&nch);
247                         vput(vp);
248                         error = EBUSY;
249                         goto done;
250                 }
251                 if (hasmount) {
252                         cache_drop(&nch);
253                         vfs_unbusy(mp);
254                         vput(vp);
255                         error = EBUSY;
256                         goto done;
257                 }
258                 mp->mnt_flag |=
259                     uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
260                 lwkt_gettoken(&mp->mnt_token);
261                 vn_unlock(vp);
262                 vfsp = mp->mnt_vfc;
263                 goto update;
264         }
265
266         /*
267          * If the user is not root, ensure that they own the directory
268          * onto which we are attempting to mount.
269          */
270         if ((error = VOP_GETATTR(vp, &va)) ||
271             (va.va_uid != cred->cr_uid &&
272              (error = priv_check(td, PRIV_ROOT)))) {
273                 cache_drop(&nch);
274                 vput(vp);
275                 goto done;
276         }
277         if ((error = vinvalbuf(vp, V_SAVE, 0, 0)) != 0) {
278                 cache_drop(&nch);
279                 vput(vp);
280                 goto done;
281         }
282         if (vp->v_type != VDIR) {
283                 cache_drop(&nch);
284                 vput(vp);
285                 error = ENOTDIR;
286                 goto done;
287         }
288         if (vp->v_mount->mnt_kern_flag & MNTK_NOSTKMNT) {
289                 cache_drop(&nch);
290                 vput(vp);
291                 error = EPERM;
292                 goto done;
293         }
294         vfsp = vfsconf_find_by_name(fstypename);
295         if (vfsp == NULL) {
296                 linker_file_t lf;
297
298                 /* Only load modules for root (very important!) */
299                 if ((error = priv_check(td, PRIV_ROOT)) != 0) {
300                         cache_drop(&nch);
301                         vput(vp);
302                         goto done;
303                 }
304                 error = linker_load_file(fstypename, &lf);
305                 if (error || lf == NULL) {
306                         cache_drop(&nch);
307                         vput(vp);
308                         if (lf == NULL)
309                                 error = ENODEV;
310                         goto done;
311                 }
312                 lf->userrefs++;
313                 /* lookup again, see if the VFS was loaded */
314                 vfsp = vfsconf_find_by_name(fstypename);
315                 if (vfsp == NULL) {
316                         lf->userrefs--;
317                         linker_file_unload(lf);
318                         cache_drop(&nch);
319                         vput(vp);
320                         error = ENODEV;
321                         goto done;
322                 }
323         }
324         if (hasmount) {
325                 cache_drop(&nch);
326                 vput(vp);
327                 error = EBUSY;
328                 goto done;
329         }
330
331         /*
332          * Allocate and initialize the filesystem.
333          */
334         mp = kmalloc(sizeof(struct mount), M_MOUNT, M_ZERO|M_WAITOK);
335         mount_init(mp);
336         vfs_busy(mp, LK_NOWAIT);
337         mp->mnt_op = vfsp->vfc_vfsops;
338         mp->mnt_vfc = vfsp;
339         mp->mnt_pbuf_count = nswbuf_kva / NSWBUF_SPLIT;
340         vfsp->vfc_refcount++;
341         mp->mnt_stat.f_type = vfsp->vfc_typenum;
342         mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
343         strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
344         mp->mnt_stat.f_owner = cred->cr_uid;
345         lwkt_gettoken(&mp->mnt_token);
346         vn_unlock(vp);
347 update:
348         /*
349          * (per-mount token acquired at this point)
350          *
351          * Set the mount level flags.
352          */
353         if (uap->flags & MNT_RDONLY)
354                 mp->mnt_flag |= MNT_RDONLY;
355         else if (mp->mnt_flag & MNT_RDONLY)
356                 mp->mnt_kern_flag |= MNTK_WANTRDWR;
357         mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
358             MNT_SYNCHRONOUS | MNT_ASYNC | MNT_NOATIME |
359             MNT_NOSYMFOLLOW | MNT_IGNORE | MNT_TRIM |
360             MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR |
361             MNT_AUTOMOUNTED);
362         mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC |
363             MNT_NODEV | MNT_SYNCHRONOUS | MNT_ASYNC | MNT_FORCE |
364             MNT_NOSYMFOLLOW | MNT_IGNORE | MNT_TRIM |
365             MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR |
366             MNT_AUTOMOUNTED);
367
368         /*
369          * Pre-set the mount's ALL_MPSAFE flags if specified in the vfsconf.
370          * This way the initial VFS_MOUNT() call will also be MPSAFE.
371          */
372         if (vfsp->vfc_flags & VFCF_MPSAFE)
373                 mp->mnt_kern_flag |= MNTK_ALL_MPSAFE;
374
375         /*
376          * Mount the filesystem.
377          * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
378          * get. 
379          */
380         error = VFS_MOUNT(mp, uap->path, uap->data, cred);
381         if (mp->mnt_flag & MNT_UPDATE) {
382                 if (mp->mnt_kern_flag & MNTK_WANTRDWR)
383                         mp->mnt_flag &= ~MNT_RDONLY;
384                 mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE);
385                 mp->mnt_kern_flag &=~ MNTK_WANTRDWR;
386                 if (error) {
387                         mp->mnt_flag = flag;
388                         mp->mnt_kern_flag = flag2;
389                 }
390                 lwkt_reltoken(&mp->mnt_token);
391                 vfs_unbusy(mp);
392                 vrele(vp);
393                 cache_drop(&nch);
394                 goto done;
395         }
396         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
397
398         /*
399          * Put the new filesystem on the mount list after root.  The mount
400          * point gets its own mnt_ncmountpt (unless the VFS already set one
401          * up) which represents the root of the mount.  The lookup code
402          * detects the mount point going forward and checks the root of
403          * the mount going backwards.
404          *
405          * It is not necessary to invalidate or purge the vnode underneath
406          * because elements under the mount will be given their own glue
407          * namecache record.
408          */
409         if (!error) {
410                 if (mp->mnt_ncmountpt.ncp == NULL) {
411                         /* 
412                          * Allocate, then unlock, but leave the ref intact.
413                          * This is the mnt_refs (1) that we will retain
414                          * through to the unmount.
415                          */
416                         cache_allocroot(&mp->mnt_ncmountpt, mp, NULL);
417                         cache_unlock(&mp->mnt_ncmountpt);
418                 }
419                 vn_unlock(vp);
420                 mp->mnt_ncmounton = nch;                /* inherits ref */
421                 cache_lock(&nch);
422                 nch.ncp->nc_flag |= NCF_ISMOUNTPT;
423                 cache_unlock(&nch);
424                 cache_ismounting(mp);
425                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
426
427                 mountlist_insert(mp, MNTINS_LAST);
428                 vn_unlock(vp);
429                 checkdirs(&mp->mnt_ncmounton, &mp->mnt_ncmountpt);
430                 error = vfs_allocate_syncvnode(mp);
431                 lwkt_reltoken(&mp->mnt_token);
432                 vfs_unbusy(mp);
433                 error = VFS_START(mp, 0);
434                 vrele(vp);
435                 KNOTE(&fs_klist, VQ_MOUNT);
436         } else {
437                 vn_syncer_thr_stop(mp);
438                 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_coherency_ops);
439                 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_journal_ops);
440                 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_norm_ops);
441                 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_spec_ops);
442                 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_fifo_ops);
443                 mp->mnt_vfc->vfc_refcount--;
444                 lwkt_reltoken(&mp->mnt_token);
445                 vfs_unbusy(mp);
446                 kfree(mp, M_MOUNT);
447                 cache_drop(&nch);
448                 vput(vp);
449         }
450 done:
451         return (error);
452 }
453
454 /*
455  * Scan all active processes to see if any of them have a current
456  * or root directory onto which the new filesystem has just been
457  * mounted. If so, replace them with the new mount point.
458  *
459  * Both old_nch and new_nch are ref'd on call but not locked.
460  * new_nch must be temporarily locked so it can be associated with the
461  * vnode representing the root of the mount point.
462  */
463 struct checkdirs_info {
464         struct nchandle old_nch;
465         struct nchandle new_nch;
466         struct vnode *old_vp;
467         struct vnode *new_vp;
468 };
469
470 static int checkdirs_callback(struct proc *p, void *data);
471
472 static void
473 checkdirs(struct nchandle *old_nch, struct nchandle *new_nch)
474 {
475         struct checkdirs_info info;
476         struct vnode *olddp;
477         struct vnode *newdp;
478         struct mount *mp;
479
480         /*
481          * If the old mount point's vnode has a usecount of 1, it is not
482          * being held as a descriptor anywhere.
483          */
484         olddp = old_nch->ncp->nc_vp;
485         if (olddp == NULL || VREFCNT(olddp) == 1)
486                 return;
487
488         /*
489          * Force the root vnode of the new mount point to be resolved
490          * so we can update any matching processes.
491          */
492         mp = new_nch->mount;
493         if (VFS_ROOT(mp, &newdp))
494                 panic("mount: lost mount");
495         vn_unlock(newdp);
496         cache_lock(new_nch);
497         vn_lock(newdp, LK_EXCLUSIVE | LK_RETRY);
498         cache_setunresolved(new_nch);
499         cache_setvp(new_nch, newdp);
500         cache_unlock(new_nch);
501
502         /*
503          * Special handling of the root node
504          */
505         if (rootvnode == olddp) {
506                 vref(newdp);
507                 vfs_cache_setroot(newdp, cache_hold(new_nch));
508         }
509
510         /*
511          * Pass newdp separately so the callback does not have to access
512          * it via new_nch->ncp->nc_vp.
513          */
514         info.old_nch = *old_nch;
515         info.new_nch = *new_nch;
516         info.new_vp = newdp;
517         allproc_scan(checkdirs_callback, &info);
518         vput(newdp);
519 }
520
521 /*
522  * NOTE: callback is not MP safe because the scanned process's filedesc
523  * structure can be ripped out from under us, amoung other things.
524  */
525 static int
526 checkdirs_callback(struct proc *p, void *data)
527 {
528         struct checkdirs_info *info = data;
529         struct filedesc *fdp;
530         struct nchandle ncdrop1;
531         struct nchandle ncdrop2;
532         struct vnode *vprele1;
533         struct vnode *vprele2;
534
535         if ((fdp = p->p_fd) != NULL) {
536                 cache_zero(&ncdrop1);
537                 cache_zero(&ncdrop2);
538                 vprele1 = NULL;
539                 vprele2 = NULL;
540
541                 /*
542                  * MPUNSAFE - XXX fdp can be pulled out from under a
543                  * foreign process.
544                  *
545                  * A shared filedesc is ok, we don't have to copy it
546                  * because we are making this change globally.
547                  */
548                 spin_lock(&fdp->fd_spin);
549                 if (fdp->fd_ncdir.mount == info->old_nch.mount &&
550                     fdp->fd_ncdir.ncp == info->old_nch.ncp) {
551                         vprele1 = fdp->fd_cdir;
552                         vref(info->new_vp);
553                         fdp->fd_cdir = info->new_vp;
554                         ncdrop1 = fdp->fd_ncdir;
555                         cache_copy(&info->new_nch, &fdp->fd_ncdir);
556                 }
557                 if (fdp->fd_nrdir.mount == info->old_nch.mount &&
558                     fdp->fd_nrdir.ncp == info->old_nch.ncp) {
559                         vprele2 = fdp->fd_rdir;
560                         vref(info->new_vp);
561                         fdp->fd_rdir = info->new_vp;
562                         ncdrop2 = fdp->fd_nrdir;
563                         cache_copy(&info->new_nch, &fdp->fd_nrdir);
564                 }
565                 spin_unlock(&fdp->fd_spin);
566                 if (ncdrop1.ncp)
567                         cache_drop(&ncdrop1);
568                 if (ncdrop2.ncp)
569                         cache_drop(&ncdrop2);
570                 if (vprele1)
571                         vrele(vprele1);
572                 if (vprele2)
573                         vrele(vprele2);
574         }
575         return(0);
576 }
577
578 /*
579  * Unmount a file system.
580  *
581  * Note: unmount takes a path to the vnode mounted on as argument,
582  * not special file (as before).
583  *
584  * umount_args(char *path, int flags)
585  *
586  * MPALMOSTSAFE
587  */
588 int
589 sys_unmount(struct unmount_args *uap)
590 {
591         struct thread *td = curthread;
592         struct proc *p __debugvar = td->td_proc;
593         struct mount *mp = NULL;
594         struct nlookupdata nd;
595         int error;
596
597         KKASSERT(p);
598         if (td->td_ucred->cr_prison != NULL) {
599                 error = EPERM;
600                 goto done;
601         }
602         if (usermount == 0 && (error = priv_check(td, PRIV_ROOT)))
603                 goto done;
604
605         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
606         if (error == 0)
607                 error = nlookup(&nd);
608         if (error)
609                 goto out;
610
611         mp = nd.nl_nch.mount;
612
613         /*
614          * Only root, or the user that did the original mount is
615          * permitted to unmount this filesystem.
616          */
617         if ((mp->mnt_stat.f_owner != td->td_ucred->cr_uid) &&
618             (error = priv_check(td, PRIV_ROOT)))
619                 goto out;
620
621         /*
622          * Don't allow unmounting the root file system.
623          */
624         if (mp->mnt_flag & MNT_ROOTFS) {
625                 error = EINVAL;
626                 goto out;
627         }
628
629         /*
630          * Must be the root of the filesystem
631          */
632         if (nd.nl_nch.ncp != mp->mnt_ncmountpt.ncp) {
633                 error = EINVAL;
634                 goto out;
635         }
636
637         /*
638          * If no error try to issue the unmount.  We lose our cache
639          * ref when we call nlookup_done so we must hold the mount point
640          * to prevent use-after-free races.
641          */
642 out:
643         if (error == 0) {
644                 mount_hold(mp);
645                 nlookup_done(&nd);
646                 error = dounmount(mp, uap->flags);
647                 mount_drop(mp);
648         } else {
649                 nlookup_done(&nd);
650         }
651 done:
652         return (error);
653 }
654
655 /*
656  * Do the actual file system unmount (interlocked against the mountlist
657  * token and mp->mnt_token).
658  */
659 static int
660 dounmount_interlock(struct mount *mp)
661 {
662         if (mp->mnt_kern_flag & MNTK_UNMOUNT)
663                 return (EBUSY);
664         mp->mnt_kern_flag |= MNTK_UNMOUNT;
665         return(0);
666 }
667
668 static int
669 unmount_allproc_cb(struct proc *p, void *arg)
670 {
671         struct mount *mp;
672
673         if (p->p_textnch.ncp == NULL)
674                 return 0;
675
676         mp = (struct mount *)arg;
677         if (p->p_textnch.mount == mp)
678                 cache_drop(&p->p_textnch);
679
680         return 0;
681 }
682
683 /*
684  * The guts of the unmount code.  The mount owns one ref and one hold
685  * count.  If we successfully interlock the unmount, those refs are ours.
686  * (The ref is from mnt_ncmountpt).
687  */
688 int
689 dounmount(struct mount *mp, int flags)
690 {
691         struct namecache *ncp;
692         struct nchandle nch;
693         struct vnode *vp;
694         int error;
695         int async_flag;
696         int lflags;
697         int freeok = 1;
698         int retry;
699
700         lwkt_gettoken(&mp->mnt_token);
701
702         /*
703          * Exclusive access for unmounting purposes.
704          */
705         if ((error = mountlist_interlock(dounmount_interlock, mp)) != 0)
706                 goto out;
707
708         /*
709          * We now 'own' the last mp->mnt_refs
710          *
711          * Allow filesystems to detect that a forced unmount is in progress.
712          */
713         if (flags & MNT_FORCE)
714                 mp->mnt_kern_flag |= MNTK_UNMOUNTF;
715         lflags = LK_EXCLUSIVE | ((flags & MNT_FORCE) ? 0 : LK_TIMELOCK);
716         error = lockmgr(&mp->mnt_lock, lflags);
717         if (error) {
718                 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
719                 if (mp->mnt_kern_flag & MNTK_MWAIT) {
720                         mp->mnt_kern_flag &= ~MNTK_MWAIT;
721                         wakeup(mp);
722                 }
723                 goto out;
724         }
725
726         if (mp->mnt_flag & MNT_EXPUBLIC)
727                 vfs_setpublicfs(NULL, NULL, NULL);
728
729         vfs_msync(mp, MNT_WAIT);
730         async_flag = mp->mnt_flag & MNT_ASYNC;
731         mp->mnt_flag &=~ MNT_ASYNC;
732
733         /*
734          * If this filesystem isn't aliasing other filesystems,
735          * try to invalidate any remaining namecache entries and
736          * check the count afterwords.
737          *
738          * We own the last mnt_refs by owning mnt_ncmountpt.
739          */
740         if ((mp->mnt_kern_flag & MNTK_NCALIASED) == 0) {
741                 cache_lock(&mp->mnt_ncmountpt);
742                 cache_inval(&mp->mnt_ncmountpt, CINV_DESTROY|CINV_CHILDREN);
743                 cache_unlock(&mp->mnt_ncmountpt);
744
745                 cache_clearmntcache();
746                 if ((ncp = mp->mnt_ncmountpt.ncp) != NULL &&
747                     (ncp->nc_refs != 1 || TAILQ_FIRST(&ncp->nc_list))) {
748                         allproc_scan(&unmount_allproc_cb, mp);
749                 }
750
751                 cache_clearmntcache();
752                 if ((ncp = mp->mnt_ncmountpt.ncp) != NULL &&
753                     (ncp->nc_refs != 1 || TAILQ_FIRST(&ncp->nc_list))) {
754
755                         if ((flags & MNT_FORCE) == 0) {
756                                 error = EBUSY;
757                                 mount_warning(mp, "Cannot unmount: "
758                                                   "%d namecache "
759                                                   "references still "
760                                                   "present",
761                                                   ncp->nc_refs - 1);
762                         } else {
763                                 mount_warning(mp, "Forced unmount: "
764                                                   "%d namecache "
765                                                   "references still "
766                                                   "present",
767                                                   ncp->nc_refs - 1);
768                                 freeok = 0;
769                         }
770                 }
771         }
772
773         /*
774          * Decomission our special mnt_syncer vnode.  This also stops
775          * the vnlru code.  If we are unable to unmount we recommission
776          * the vnode.
777          *
778          * Then sync the filesystem.
779          */
780         if ((vp = mp->mnt_syncer) != NULL) {
781                 mp->mnt_syncer = NULL;
782                 atomic_set_int(&vp->v_refcnt, VREF_FINALIZE);
783                 vrele(vp);
784         }
785         if ((mp->mnt_flag & MNT_RDONLY) == 0)
786                 VFS_SYNC(mp, MNT_WAIT);
787
788         /*
789          * nchandle records ref the mount structure.  Expect a count of 1
790          * (our mount->mnt_ncmountpt).
791          *
792          * Scans can get temporary refs on a mountpoint (thought really
793          * heavy duty stuff like cache_findmount() do not).
794          */
795         if (mp->mnt_refs != 1)
796                 cache_clearmntcache();
797         for (retry = 0; retry < 10 && mp->mnt_refs != 1; ++retry) {
798                 cache_unmounting(mp);
799                 tsleep(&mp->mnt_refs, 0, "mntbsy", hz / 10 + 1);
800                 cache_clearmntcache();
801         }
802         if (mp->mnt_refs != 1) {
803                 if ((flags & MNT_FORCE) == 0) {
804                         mount_warning(mp, "Cannot unmount: "
805                                           "%d mount refs still present",
806                                           mp->mnt_refs - 1);
807                         error = EBUSY;
808                 } else {
809                         mount_warning(mp, "Forced unmount: "
810                                           "%d mount refs still present",
811                                           mp->mnt_refs - 1);
812                         freeok = 0;
813                 }
814         }
815
816         /*
817          * So far so good, sync the filesystem once more and
818          * call the VFS unmount code if the sync succeeds.
819          */
820         if (error == 0) {
821                 if (mp->mnt_flag & MNT_RDONLY) {
822                         error = VFS_UNMOUNT(mp, flags);
823                 } else {
824                         error = VFS_SYNC(mp, MNT_WAIT);
825                         if ((error == 0) ||
826                             (error == EOPNOTSUPP) || /* No sync */
827                             (flags & MNT_FORCE)) {
828                                 error = VFS_UNMOUNT(mp, flags);
829                         }
830                 }
831         }
832
833         /*
834          * If an error occurred we can still recover, restoring the
835          * syncer vnode and misc flags.
836          */
837         if (error) {
838                 if (mp->mnt_syncer == NULL)
839                         vfs_allocate_syncvnode(mp);
840                 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
841                 mp->mnt_flag |= async_flag;
842                 lockmgr(&mp->mnt_lock, LK_RELEASE);
843                 if (mp->mnt_kern_flag & MNTK_MWAIT) {
844                         mp->mnt_kern_flag &= ~MNTK_MWAIT;
845                         wakeup(mp);
846                 }
847                 goto out;
848         }
849         /*
850          * Clean up any journals still associated with the mount after
851          * filesystem activity has ceased.
852          */
853         journal_remove_all_journals(mp, 
854             ((flags & MNT_FORCE) ? MC_JOURNAL_STOP_IMM : 0));
855
856         mountlist_remove(mp);
857
858         /*
859          * Remove any installed vnode ops here so the individual VFSs don't
860          * have to.
861          *
862          * mnt_refs should go to zero when we scrap mnt_ncmountpt.
863          */
864         vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_coherency_ops);
865         vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_journal_ops);
866         vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_norm_ops);
867         vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_spec_ops);
868         vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_fifo_ops);
869
870         if (mp->mnt_ncmountpt.ncp != NULL) {
871                 nch = mp->mnt_ncmountpt;
872                 cache_zero(&mp->mnt_ncmountpt);
873                 cache_clrmountpt(&nch);
874                 cache_drop(&nch);
875         }
876         if (mp->mnt_ncmounton.ncp != NULL) {
877                 cache_unmounting(mp);
878                 nch = mp->mnt_ncmounton;
879                 cache_zero(&mp->mnt_ncmounton);
880                 cache_clrmountpt(&nch);
881                 cache_drop(&nch);
882         }
883
884         mp->mnt_vfc->vfc_refcount--;
885         if (!TAILQ_EMPTY(&mp->mnt_nvnodelist))
886                 panic("unmount: dangling vnode");
887
888         /*
889          * Release the lock
890          */
891         lockmgr(&mp->mnt_lock, LK_RELEASE);
892         if (mp->mnt_kern_flag & MNTK_MWAIT) {
893                 mp->mnt_kern_flag &= ~MNTK_MWAIT;
894                 wakeup(mp);
895         }
896
897         /*
898          * If we reach here and freeok != 0 we must free the mount.
899          * mnt_refs should already have dropped to 0, so if it is not
900          * zero we must cycle the caches and wait.
901          *
902          * When we are satisfied that the mount has disconnected we can
903          * drop the hold on the mp that represented the mount (though the
904          * caller might actually have another, so the caller's drop may
905          * do the actual free).
906          */
907         if (freeok) {
908                 if (mp->mnt_refs > 0)
909                         cache_clearmntcache();
910                 while (mp->mnt_refs > 0) {
911                         cache_unmounting(mp);
912                         wakeup(mp);
913                         tsleep(&mp->mnt_refs, 0, "umntrwait", hz / 10 + 1);
914                         cache_clearmntcache();
915                 }
916                 lwkt_reltoken(&mp->mnt_token);
917                 mount_drop(mp);
918                 mp = NULL;
919         }
920         error = 0;
921         KNOTE(&fs_klist, VQ_UNMOUNT);
922 out:
923         if (mp)
924                 lwkt_reltoken(&mp->mnt_token);
925         return (error);
926 }
927
928 static
929 void
930 mount_warning(struct mount *mp, const char *ctl, ...)
931 {
932         char *ptr;
933         char *buf;
934         __va_list va;
935
936         __va_start(va, ctl);
937         if (cache_fullpath(NULL, &mp->mnt_ncmounton, NULL,
938                            &ptr, &buf, 0) == 0) {
939                 kprintf("unmount(%s): ", ptr);
940                 kvprintf(ctl, va);
941                 kprintf("\n");
942                 kfree(buf, M_TEMP);
943         } else {
944                 kprintf("unmount(%p", mp);
945                 if (mp->mnt_ncmounton.ncp && mp->mnt_ncmounton.ncp->nc_name)
946                         kprintf(",%s", mp->mnt_ncmounton.ncp->nc_name);
947                 kprintf("): ");
948                 kvprintf(ctl, va);
949                 kprintf("\n");
950         }
951         __va_end(va);
952 }
953
954 /*
955  * Shim cache_fullpath() to handle the case where a process is chrooted into
956  * a subdirectory of a mount.  In this case if the root mount matches the
957  * process root directory's mount we have to specify the process's root
958  * directory instead of the mount point, because the mount point might
959  * be above the root directory.
960  */
961 static
962 int
963 mount_path(struct proc *p, struct mount *mp, char **rb, char **fb)
964 {
965         struct nchandle *nch;
966
967         if (p && p->p_fd->fd_nrdir.mount == mp)
968                 nch = &p->p_fd->fd_nrdir;
969         else
970                 nch = &mp->mnt_ncmountpt;
971         return(cache_fullpath(p, nch, NULL, rb, fb, 0));
972 }
973
974 /*
975  * Sync each mounted filesystem.
976  */
977
978 #ifdef DEBUG
979 static int syncprt = 0;
980 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
981 #endif /* DEBUG */
982
983 static int sync_callback(struct mount *mp, void *data);
984
985 int
986 sys_sync(struct sync_args *uap)
987 {
988         mountlist_scan(sync_callback, NULL, MNTSCAN_FORWARD);
989         return (0);
990 }
991
992 static
993 int
994 sync_callback(struct mount *mp, void *data __unused)
995 {
996         int asyncflag;
997
998         if ((mp->mnt_flag & MNT_RDONLY) == 0) {
999                 asyncflag = mp->mnt_flag & MNT_ASYNC;
1000                 mp->mnt_flag &= ~MNT_ASYNC;
1001                 vfs_msync(mp, MNT_NOWAIT);
1002                 VFS_SYNC(mp, MNT_NOWAIT);
1003                 mp->mnt_flag |= asyncflag;
1004         }
1005         return(0);
1006 }
1007
1008 /* XXX PRISON: could be per prison flag */
1009 static int prison_quotas;
1010 #if 0
1011 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
1012 #endif
1013
1014 /*
1015  *  quotactl_args(char *path, int fcmd, int uid, caddr_t arg)
1016  *
1017  * Change filesystem quotas.
1018  *
1019  * MPALMOSTSAFE
1020  */
1021 int
1022 sys_quotactl(struct quotactl_args *uap)
1023 {
1024         struct nlookupdata nd;
1025         struct thread *td;
1026         struct mount *mp;
1027         int error;
1028
1029         td = curthread;
1030         if (td->td_ucred->cr_prison && !prison_quotas) {
1031                 error = EPERM;
1032                 goto done;
1033         }
1034
1035         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
1036         if (error == 0)
1037                 error = nlookup(&nd);
1038         if (error == 0) {
1039                 mp = nd.nl_nch.mount;
1040                 error = VFS_QUOTACTL(mp, uap->cmd, uap->uid,
1041                                     uap->arg, nd.nl_cred);
1042         }
1043         nlookup_done(&nd);
1044 done:
1045         return (error);
1046 }
1047
1048 /*
1049  * mountctl(char *path, int op, int fd, const void *ctl, int ctllen,
1050  *              void *buf, int buflen)
1051  *
1052  * This function operates on a mount point and executes the specified
1053  * operation using the specified control data, and possibly returns data.
1054  *
1055  * The actual number of bytes stored in the result buffer is returned, 0
1056  * if none, otherwise an error is returned.
1057  *
1058  * MPALMOSTSAFE
1059  */
1060 int
1061 sys_mountctl(struct mountctl_args *uap)
1062 {
1063         struct thread *td = curthread;
1064         struct proc *p = td->td_proc;
1065         struct file *fp;
1066         void *ctl = NULL;
1067         void *buf = NULL;
1068         char *path = NULL;
1069         int error;
1070
1071         /*
1072          * Sanity and permissions checks.  We must be root.
1073          */
1074         KKASSERT(p);
1075         if (td->td_ucred->cr_prison != NULL)
1076                 return (EPERM);
1077         if ((uap->op != MOUNTCTL_MOUNTFLAGS) &&
1078             (error = priv_check(td, PRIV_ROOT)) != 0)
1079                 return (error);
1080
1081         /*
1082          * Argument length checks
1083          */
1084         if (uap->ctllen < 0 || uap->ctllen > 1024)
1085                 return (EINVAL);
1086         if (uap->buflen < 0 || uap->buflen > 16 * 1024)
1087                 return (EINVAL);
1088         if (uap->path == NULL)
1089                 return (EINVAL);
1090
1091         /*
1092          * Allocate the necessary buffers and copyin data
1093          */
1094         path = objcache_get(namei_oc, M_WAITOK);
1095         error = copyinstr(uap->path, path, MAXPATHLEN, NULL);
1096         if (error)
1097                 goto done;
1098
1099         if (uap->ctllen) {
1100                 ctl = kmalloc(uap->ctllen + 1, M_TEMP, M_WAITOK|M_ZERO);
1101                 error = copyin(uap->ctl, ctl, uap->ctllen);
1102                 if (error)
1103                         goto done;
1104         }
1105         if (uap->buflen)
1106                 buf = kmalloc(uap->buflen + 1, M_TEMP, M_WAITOK|M_ZERO);
1107
1108         /*
1109          * Validate the descriptor
1110          */
1111         if (uap->fd >= 0) {
1112                 fp = holdfp(p->p_fd, uap->fd, -1);
1113                 if (fp == NULL) {
1114                         error = EBADF;
1115                         goto done;
1116                 }
1117         } else {
1118                 fp = NULL;
1119         }
1120
1121         /*
1122          * Execute the internal kernel function and clean up.
1123          */
1124         error = kern_mountctl(path, uap->op, fp, ctl, uap->ctllen, buf, uap->buflen, &uap->sysmsg_result);
1125         if (fp)
1126                 fdrop(fp);
1127         if (error == 0 && uap->sysmsg_result > 0)
1128                 error = copyout(buf, uap->buf, uap->sysmsg_result);
1129 done:
1130         if (path)
1131                 objcache_put(namei_oc, path);
1132         if (ctl)
1133                 kfree(ctl, M_TEMP);
1134         if (buf)
1135                 kfree(buf, M_TEMP);
1136         return (error);
1137 }
1138
1139 /*
1140  * Execute a mount control operation by resolving the path to a mount point
1141  * and calling vop_mountctl().  
1142  *
1143  * Use the mount point from the nch instead of the vnode so nullfs mounts
1144  * can properly spike the VOP.
1145  */
1146 int
1147 kern_mountctl(const char *path, int op, struct file *fp, 
1148                 const void *ctl, int ctllen, 
1149                 void *buf, int buflen, int *res)
1150 {
1151         struct vnode *vp;
1152         struct nlookupdata nd;
1153         struct nchandle nch;
1154         struct mount *mp;
1155         int error;
1156
1157         *res = 0;
1158         vp = NULL;
1159         error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1160         if (error)
1161                 return (error);
1162         error = nlookup(&nd);
1163         if (error) {
1164                 nlookup_done(&nd);
1165                 return (error);
1166         }
1167         error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
1168         if (error) {
1169                 nlookup_done(&nd);
1170                 return (error);
1171         }
1172
1173         /*
1174          * Yes, all this is needed to use the nch.mount below, because
1175          * we must maintain a ref on the mount to avoid ripouts (e.g.
1176          * due to heavy mount/unmount use by synth or poudriere).
1177          */
1178         nch = nd.nl_nch;
1179         cache_zero(&nd.nl_nch);
1180         cache_unlock(&nch);
1181         nlookup_done(&nd);
1182         vn_unlock(vp);
1183
1184         mp = nch.mount;
1185
1186         /*
1187          * Must be the root of the filesystem
1188          */
1189         if ((vp->v_flag & (VROOT|VPFSROOT)) == 0) {
1190                 cache_drop(&nch);
1191                 vrele(vp);
1192                 return (EINVAL);
1193         }
1194         if (mp == NULL || mp->mnt_kern_flag & MNTK_UNMOUNT) {
1195                 kprintf("kern_mountctl: Warning, \"%s\" racing unmount\n",
1196                         path);
1197                 cache_drop(&nch);
1198                 vrele(vp);
1199                 return (EINVAL);
1200         }
1201         error = vop_mountctl(mp->mnt_vn_use_ops, vp, op, fp, ctl, ctllen,
1202                              buf, buflen, res);
1203         vrele(vp);
1204         cache_drop(&nch);
1205
1206         return (error);
1207 }
1208
1209 int
1210 kern_statfs(struct nlookupdata *nd, struct statfs *buf)
1211 {
1212         struct thread *td = curthread;
1213         struct proc *p = td->td_proc;
1214         struct mount *mp;
1215         struct statfs *sp;
1216         char *fullpath, *freepath;
1217         int error;
1218
1219         if ((error = nlookup(nd)) != 0)
1220                 return (error);
1221         mp = nd->nl_nch.mount;
1222         sp = &mp->mnt_stat;
1223         if ((error = VFS_STATFS(mp, sp, nd->nl_cred)) != 0)
1224                 return (error);
1225
1226         error = mount_path(p, mp, &fullpath, &freepath);
1227         if (error)
1228                 return(error);
1229         bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
1230         strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname));
1231         kfree(freepath, M_TEMP);
1232
1233         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1234         bcopy(sp, buf, sizeof(*buf));
1235         /* Only root should have access to the fsid's. */
1236         if (priv_check(td, PRIV_ROOT))
1237                 buf->f_fsid.val[0] = buf->f_fsid.val[1] = 0;
1238         return (0);
1239 }
1240
1241 /*
1242  * statfs_args(char *path, struct statfs *buf)
1243  *
1244  * Get filesystem statistics.
1245  */
1246 int
1247 sys_statfs(struct statfs_args *uap)
1248 {
1249         struct nlookupdata nd;
1250         struct statfs buf;
1251         int error;
1252
1253         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
1254         if (error == 0)
1255                 error = kern_statfs(&nd, &buf);
1256         nlookup_done(&nd);
1257         if (error == 0)
1258                 error = copyout(&buf, uap->buf, sizeof(*uap->buf));
1259         return (error);
1260 }
1261
1262 int
1263 kern_fstatfs(int fd, struct statfs *buf)
1264 {
1265         struct thread *td = curthread;
1266         struct proc *p = td->td_proc;
1267         struct file *fp;
1268         struct mount *mp;
1269         struct statfs *sp;
1270         char *fullpath, *freepath;
1271         int error;
1272
1273         KKASSERT(p);
1274         if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
1275                 return (error);
1276
1277         /*
1278          * Try to use mount info from any overlays rather than the
1279          * mount info for the underlying vnode, otherwise we will
1280          * fail when operating on null-mounted paths inside a chroot.
1281          */
1282         if ((mp = fp->f_nchandle.mount) == NULL)
1283                 mp = ((struct vnode *)fp->f_data)->v_mount;
1284         if (mp == NULL) {
1285                 error = EBADF;
1286                 goto done;
1287         }
1288         if (fp->f_cred == NULL) {
1289                 error = EINVAL;
1290                 goto done;
1291         }
1292         sp = &mp->mnt_stat;
1293         if ((error = VFS_STATFS(mp, sp, fp->f_cred)) != 0)
1294                 goto done;
1295
1296         if ((error = mount_path(p, mp, &fullpath, &freepath)) != 0)
1297                 goto done;
1298         bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
1299         strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname));
1300         kfree(freepath, M_TEMP);
1301
1302         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1303         bcopy(sp, buf, sizeof(*buf));
1304
1305         /* Only root should have access to the fsid's. */
1306         if (priv_check(td, PRIV_ROOT))
1307                 buf->f_fsid.val[0] = buf->f_fsid.val[1] = 0;
1308         error = 0;
1309 done:
1310         fdrop(fp);
1311         return (error);
1312 }
1313
1314 /*
1315  * fstatfs_args(int fd, struct statfs *buf)
1316  *
1317  * Get filesystem statistics.
1318  */
1319 int
1320 sys_fstatfs(struct fstatfs_args *uap)
1321 {
1322         struct statfs buf;
1323         int error;
1324
1325         error = kern_fstatfs(uap->fd, &buf);
1326
1327         if (error == 0)
1328                 error = copyout(&buf, uap->buf, sizeof(*uap->buf));
1329         return (error);
1330 }
1331
1332 int
1333 kern_statvfs(struct nlookupdata *nd, struct statvfs *buf)
1334 {
1335         struct mount *mp;
1336         struct statvfs *sp;
1337         int error;
1338
1339         if ((error = nlookup(nd)) != 0)
1340                 return (error);
1341         mp = nd->nl_nch.mount;
1342         sp = &mp->mnt_vstat;
1343         if ((error = VFS_STATVFS(mp, sp, nd->nl_cred)) != 0)
1344                 return (error);
1345
1346         sp->f_flag = 0;
1347         if (mp->mnt_flag & MNT_RDONLY)
1348                 sp->f_flag |= ST_RDONLY;
1349         if (mp->mnt_flag & MNT_NOSUID)
1350                 sp->f_flag |= ST_NOSUID;
1351         bcopy(sp, buf, sizeof(*buf));
1352         return (0);
1353 }
1354
1355 /*
1356  * statfs_args(char *path, struct statfs *buf)
1357  *
1358  * Get filesystem statistics.
1359  */
1360 int
1361 sys_statvfs(struct statvfs_args *uap)
1362 {
1363         struct nlookupdata nd;
1364         struct statvfs buf;
1365         int error;
1366
1367         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
1368         if (error == 0)
1369                 error = kern_statvfs(&nd, &buf);
1370         nlookup_done(&nd);
1371         if (error == 0)
1372                 error = copyout(&buf, uap->buf, sizeof(*uap->buf));
1373         return (error);
1374 }
1375
1376 int
1377 kern_fstatvfs(int fd, struct statvfs *buf)
1378 {
1379         struct thread *td = curthread;
1380         struct proc *p = td->td_proc;
1381         struct file *fp;
1382         struct mount *mp;
1383         struct statvfs *sp;
1384         int error;
1385
1386         KKASSERT(p);
1387         if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
1388                 return (error);
1389         if ((mp = fp->f_nchandle.mount) == NULL)
1390                 mp = ((struct vnode *)fp->f_data)->v_mount;
1391         if (mp == NULL) {
1392                 error = EBADF;
1393                 goto done;
1394         }
1395         if (fp->f_cred == NULL) {
1396                 error = EINVAL;
1397                 goto done;
1398         }
1399         sp = &mp->mnt_vstat;
1400         if ((error = VFS_STATVFS(mp, sp, fp->f_cred)) != 0)
1401                 goto done;
1402
1403         sp->f_flag = 0;
1404         if (mp->mnt_flag & MNT_RDONLY)
1405                 sp->f_flag |= ST_RDONLY;
1406         if (mp->mnt_flag & MNT_NOSUID)
1407                 sp->f_flag |= ST_NOSUID;
1408
1409         bcopy(sp, buf, sizeof(*buf));
1410         error = 0;
1411 done:
1412         fdrop(fp);
1413         return (error);
1414 }
1415
1416 /*
1417  * fstatfs_args(int fd, struct statfs *buf)
1418  *
1419  * Get filesystem statistics.
1420  */
1421 int
1422 sys_fstatvfs(struct fstatvfs_args *uap)
1423 {
1424         struct statvfs buf;
1425         int error;
1426
1427         error = kern_fstatvfs(uap->fd, &buf);
1428
1429         if (error == 0)
1430                 error = copyout(&buf, uap->buf, sizeof(*uap->buf));
1431         return (error);
1432 }
1433
1434 /*
1435  * getfsstat_args(struct statfs *buf, long bufsize, int flags)
1436  *
1437  * Get statistics on all filesystems.
1438  */
1439
1440 struct getfsstat_info {
1441         struct statfs *sfsp;
1442         long count;
1443         long maxcount;
1444         int error;
1445         int flags;
1446         struct thread *td;
1447 };
1448
1449 static int getfsstat_callback(struct mount *, void *);
1450
1451 int
1452 sys_getfsstat(struct getfsstat_args *uap)
1453 {
1454         struct thread *td = curthread;
1455         struct getfsstat_info info;
1456
1457         bzero(&info, sizeof(info));
1458
1459         info.maxcount = uap->bufsize / sizeof(struct statfs);
1460         info.sfsp = uap->buf;
1461         info.count = 0;
1462         info.flags = uap->flags;
1463         info.td = td;
1464
1465         mountlist_scan(getfsstat_callback, &info, MNTSCAN_FORWARD);
1466         if (info.sfsp && info.count > info.maxcount)
1467                 uap->sysmsg_result = info.maxcount;
1468         else
1469                 uap->sysmsg_result = info.count;
1470         return (info.error);
1471 }
1472
1473 static int
1474 getfsstat_callback(struct mount *mp, void *data)
1475 {
1476         struct getfsstat_info *info = data;
1477         struct statfs *sp;
1478         char *freepath;
1479         char *fullpath;
1480         int error;
1481
1482         if (info->sfsp && info->count < info->maxcount) {
1483                 if (info->td->td_proc &&
1484                     !chroot_visible_mnt(mp, info->td->td_proc)) {
1485                         return(0);
1486                 }
1487                 sp = &mp->mnt_stat;
1488
1489                 /*
1490                  * If MNT_NOWAIT or MNT_LAZY is specified, do not
1491                  * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
1492                  * overrides MNT_WAIT.
1493                  */
1494                 if (((info->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
1495                     (info->flags & MNT_WAIT)) &&
1496                     (error = VFS_STATFS(mp, sp, info->td->td_ucred))) {
1497                         return(0);
1498                 }
1499                 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1500
1501                 error = mount_path(info->td->td_proc, mp, &fullpath, &freepath);
1502                 if (error) {
1503                         info->error = error;
1504                         return(-1);
1505                 }
1506                 bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
1507                 strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname));
1508                 kfree(freepath, M_TEMP);
1509
1510                 error = copyout(sp, info->sfsp, sizeof(*sp));
1511                 if (error) {
1512                         info->error = error;
1513                         return (-1);
1514                 }
1515                 ++info->sfsp;
1516         }
1517         info->count++;
1518         return(0);
1519 }
1520
1521 /*
1522  * getvfsstat_args(struct statfs *buf, struct statvfs *vbuf,
1523                    long bufsize, int flags)
1524  *
1525  * Get statistics on all filesystems.
1526  */
1527
1528 struct getvfsstat_info {
1529         struct statfs *sfsp;
1530         struct statvfs *vsfsp;
1531         long count;
1532         long maxcount;
1533         int error;
1534         int flags;
1535         struct thread *td;
1536 };
1537
1538 static int getvfsstat_callback(struct mount *, void *);
1539
1540 int
1541 sys_getvfsstat(struct getvfsstat_args *uap)
1542 {
1543         struct thread *td = curthread;
1544         struct getvfsstat_info info;
1545
1546         bzero(&info, sizeof(info));
1547
1548         info.maxcount = uap->vbufsize / sizeof(struct statvfs);
1549         info.sfsp = uap->buf;
1550         info.vsfsp = uap->vbuf;
1551         info.count = 0;
1552         info.flags = uap->flags;
1553         info.td = td;
1554
1555         mountlist_scan(getvfsstat_callback, &info, MNTSCAN_FORWARD);
1556         if (info.vsfsp && info.count > info.maxcount)
1557                 uap->sysmsg_result = info.maxcount;
1558         else
1559                 uap->sysmsg_result = info.count;
1560         return (info.error);
1561 }
1562
1563 static int
1564 getvfsstat_callback(struct mount *mp, void *data)
1565 {
1566         struct getvfsstat_info *info = data;
1567         struct statfs *sp;
1568         struct statvfs *vsp;
1569         char *freepath;
1570         char *fullpath;
1571         int error;
1572
1573         if (info->vsfsp && info->count < info->maxcount) {
1574                 if (info->td->td_proc &&
1575                     !chroot_visible_mnt(mp, info->td->td_proc)) {
1576                         return(0);
1577                 }
1578                 sp = &mp->mnt_stat;
1579                 vsp = &mp->mnt_vstat;
1580
1581                 /*
1582                  * If MNT_NOWAIT or MNT_LAZY is specified, do not
1583                  * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
1584                  * overrides MNT_WAIT.
1585                  */
1586                 if (((info->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
1587                     (info->flags & MNT_WAIT)) &&
1588                     (error = VFS_STATFS(mp, sp, info->td->td_ucred))) {
1589                         return(0);
1590                 }
1591                 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1592
1593                 if (((info->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
1594                     (info->flags & MNT_WAIT)) &&
1595                     (error = VFS_STATVFS(mp, vsp, info->td->td_ucred))) {
1596                         return(0);
1597                 }
1598                 vsp->f_flag = 0;
1599                 if (mp->mnt_flag & MNT_RDONLY)
1600                         vsp->f_flag |= ST_RDONLY;
1601                 if (mp->mnt_flag & MNT_NOSUID)
1602                         vsp->f_flag |= ST_NOSUID;
1603
1604                 error = mount_path(info->td->td_proc, mp, &fullpath, &freepath);
1605                 if (error) {
1606                         info->error = error;
1607                         return(-1);
1608                 }
1609                 bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
1610                 strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname));
1611                 kfree(freepath, M_TEMP);
1612
1613                 error = copyout(sp, info->sfsp, sizeof(*sp));
1614                 if (error == 0)
1615                         error = copyout(vsp, info->vsfsp, sizeof(*vsp));
1616                 if (error) {
1617                         info->error = error;
1618                         return (-1);
1619                 }
1620                 ++info->sfsp;
1621                 ++info->vsfsp;
1622         }
1623         info->count++;
1624         return(0);
1625 }
1626
1627
1628 /*
1629  * fchdir_args(int fd)
1630  *
1631  * Change current working directory to a given file descriptor.
1632  */
1633 int
1634 sys_fchdir(struct fchdir_args *uap)
1635 {
1636         struct thread *td = curthread;
1637         struct proc *p = td->td_proc;
1638         struct filedesc *fdp = p->p_fd;
1639         struct vnode *vp, *ovp;
1640         struct mount *mp;
1641         struct file *fp;
1642         struct nchandle nch, onch, tnch;
1643         int error;
1644
1645         if ((error = holdvnode(fdp, uap->fd, &fp)) != 0)
1646                 return (error);
1647         lwkt_gettoken(&p->p_token);
1648         vp = (struct vnode *)fp->f_data;
1649         vref(vp);
1650         vn_lock(vp, LK_SHARED | LK_RETRY);
1651         if (fp->f_nchandle.ncp == NULL)
1652                 error = ENOTDIR;
1653         else
1654                 error = checkvp_chdir(vp, td);
1655         if (error) {
1656                 vput(vp);
1657                 goto done;
1658         }
1659         cache_copy(&fp->f_nchandle, &nch);
1660
1661         /*
1662          * If the ncp has become a mount point, traverse through
1663          * the mount point.
1664          */
1665
1666         while (!error && (nch.ncp->nc_flag & NCF_ISMOUNTPT) &&
1667                (mp = cache_findmount(&nch)) != NULL
1668         ) {
1669                 error = nlookup_mp(mp, &tnch);
1670                 if (error == 0) {
1671                         cache_unlock(&tnch);    /* leave ref intact */
1672                         vput(vp);
1673                         vp = tnch.ncp->nc_vp;
1674                         error = vget(vp, LK_SHARED);
1675                         KKASSERT(error == 0);
1676                         cache_drop(&nch);
1677                         nch = tnch;
1678                 }
1679                 cache_dropmount(mp);
1680         }
1681         if (error == 0) {
1682                 spin_lock(&fdp->fd_spin);
1683                 ovp = fdp->fd_cdir;
1684                 onch = fdp->fd_ncdir;
1685                 fdp->fd_cdir = vp;
1686                 fdp->fd_ncdir = nch;
1687                 spin_unlock(&fdp->fd_spin);
1688                 vn_unlock(vp);          /* leave ref intact */
1689                 cache_drop(&onch);
1690                 vrele(ovp);
1691         } else {
1692                 cache_drop(&nch);
1693                 vput(vp);
1694         }
1695         fdrop(fp);
1696 done:
1697         lwkt_reltoken(&p->p_token);
1698         return (error);
1699 }
1700
1701 int
1702 kern_chdir(struct nlookupdata *nd)
1703 {
1704         struct thread *td = curthread;
1705         struct proc *p = td->td_proc;
1706         struct filedesc *fdp = p->p_fd;
1707         struct vnode *vp, *ovp;
1708         struct nchandle onch;
1709         int error;
1710
1711         nd->nl_flags |= NLC_SHAREDLOCK;
1712         if ((error = nlookup(nd)) != 0)
1713                 return (error);
1714         if ((vp = nd->nl_nch.ncp->nc_vp) == NULL)
1715                 return (ENOENT);
1716         if ((error = vget(vp, LK_SHARED)) != 0)
1717                 return (error);
1718
1719         lwkt_gettoken(&p->p_token);
1720         error = checkvp_chdir(vp, td);
1721         vn_unlock(vp);
1722         if (error == 0) {
1723                 spin_lock(&fdp->fd_spin);
1724                 ovp = fdp->fd_cdir;
1725                 onch = fdp->fd_ncdir;
1726                 fdp->fd_ncdir = nd->nl_nch;
1727                 fdp->fd_cdir = vp;
1728                 spin_unlock(&fdp->fd_spin);
1729                 cache_unlock(&nd->nl_nch);      /* leave reference intact */
1730                 cache_drop(&onch);
1731                 vrele(ovp);
1732                 cache_zero(&nd->nl_nch);
1733         } else {
1734                 vrele(vp);
1735         }
1736         lwkt_reltoken(&p->p_token);
1737         return (error);
1738 }
1739
1740 /*
1741  * chdir_args(char *path)
1742  *
1743  * Change current working directory (``.'').
1744  */
1745 int
1746 sys_chdir(struct chdir_args *uap)
1747 {
1748         struct nlookupdata nd;
1749         int error;
1750
1751         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
1752         if (error == 0)
1753                 error = kern_chdir(&nd);
1754         nlookup_done(&nd);
1755         return (error);
1756 }
1757
1758 /*
1759  * Helper function for raised chroot(2) security function:  Refuse if
1760  * any filedescriptors are open directories.
1761  */
1762 static int
1763 chroot_refuse_vdir_fds(struct filedesc *fdp)
1764 {
1765         struct vnode *vp;
1766         struct file *fp;
1767         int error;
1768         int fd;
1769
1770         for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
1771                 if ((error = holdvnode(fdp, fd, &fp)) != 0)
1772                         continue;
1773                 vp = (struct vnode *)fp->f_data;
1774                 if (vp->v_type != VDIR) {
1775                         fdrop(fp);
1776                         continue;
1777                 }
1778                 fdrop(fp);
1779                 return(EPERM);
1780         }
1781         return (0);
1782 }
1783
1784 /*
1785  * This sysctl determines if we will allow a process to chroot(2) if it
1786  * has a directory open:
1787  *      0: disallowed for all processes.
1788  *      1: allowed for processes that were not already chroot(2)'ed.
1789  *      2: allowed for all processes.
1790  */
1791
1792 static int chroot_allow_open_directories = 1;
1793
1794 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
1795      &chroot_allow_open_directories, 0, "");
1796
1797 /*
1798  * chroot to the specified namecache entry.  We obtain the vp from the
1799  * namecache data.  The passed ncp must be locked and referenced and will
1800  * remain locked and referenced on return.
1801  */
1802 int
1803 kern_chroot(struct nchandle *nch)
1804 {
1805         struct thread *td = curthread;
1806         struct proc *p = td->td_proc;
1807         struct filedesc *fdp = p->p_fd;
1808         struct vnode *vp;
1809         int error;
1810
1811         /*
1812          * Only privileged user can chroot
1813          */
1814         error = priv_check_cred(td->td_ucred, PRIV_VFS_CHROOT, 0);
1815         if (error)
1816                 return (error);
1817
1818         /*
1819          * Disallow open directory descriptors (fchdir() breakouts).
1820          */
1821         if (chroot_allow_open_directories == 0 ||
1822            (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
1823                 if ((error = chroot_refuse_vdir_fds(fdp)) != 0)
1824                         return (error);
1825         }
1826         if ((vp = nch->ncp->nc_vp) == NULL)
1827                 return (ENOENT);
1828
1829         if ((error = vget(vp, LK_SHARED)) != 0)
1830                 return (error);
1831
1832         /*
1833          * Check the validity of vp as a directory to change to and 
1834          * associate it with rdir/jdir.
1835          */
1836         error = checkvp_chdir(vp, td);
1837         vn_unlock(vp);                  /* leave reference intact */
1838         if (error == 0) {
1839                 lwkt_gettoken(&p->p_token);
1840                 vrele(fdp->fd_rdir);
1841                 fdp->fd_rdir = vp;      /* reference inherited by fd_rdir */
1842                 cache_drop(&fdp->fd_nrdir);
1843                 cache_copy(nch, &fdp->fd_nrdir);
1844                 if (fdp->fd_jdir == NULL) {
1845                         fdp->fd_jdir = vp;
1846                         vref(fdp->fd_jdir);
1847                         cache_copy(nch, &fdp->fd_njdir);
1848                 }
1849                 if ((p->p_flags & P_DIDCHROOT) == 0) {
1850                         p->p_flags |= P_DIDCHROOT;
1851                         if (p->p_depth <= 65535 - 32)
1852                                 p->p_depth += 32;
1853                 }
1854                 lwkt_reltoken(&p->p_token);
1855         } else {
1856                 vrele(vp);
1857         }
1858         return (error);
1859 }
1860
1861 /*
1862  * chroot_args(char *path)
1863  *
1864  * Change notion of root (``/'') directory.
1865  */
1866 int
1867 sys_chroot(struct chroot_args *uap)
1868 {
1869         struct thread *td __debugvar = curthread;
1870         struct nlookupdata nd;
1871         int error;
1872
1873         KKASSERT(td->td_proc);
1874         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
1875         if (error == 0) {
1876                 nd.nl_flags |= NLC_EXEC;
1877                 error = nlookup(&nd);
1878                 if (error == 0)
1879                         error = kern_chroot(&nd.nl_nch);
1880         }
1881         nlookup_done(&nd);
1882         return(error);
1883 }
1884
1885 int
1886 sys_chroot_kernel(struct chroot_kernel_args *uap)
1887 {
1888         struct thread *td = curthread;
1889         struct nlookupdata nd;
1890         struct nchandle *nch;
1891         struct vnode *vp;
1892         int error;
1893
1894         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
1895         if (error)
1896                 goto error_nond;
1897
1898         error = nlookup(&nd);
1899         if (error)
1900                 goto error_out;
1901
1902         nch = &nd.nl_nch;
1903
1904         error = priv_check_cred(td->td_ucred, PRIV_VFS_CHROOT, 0);
1905         if (error)
1906                 goto error_out;
1907
1908         if ((vp = nch->ncp->nc_vp) == NULL) {
1909                 error = ENOENT;
1910                 goto error_out;
1911         }
1912
1913         if ((error = cache_vref(nch, nd.nl_cred, &vp)) != 0)
1914                 goto error_out;
1915
1916         kprintf("chroot_kernel: set new rootnch/rootvnode to %s\n", uap->path);
1917         vfs_cache_setroot(vp, cache_hold(nch));
1918
1919 error_out:
1920         nlookup_done(&nd);
1921 error_nond:
1922         return(error);
1923 }
1924
1925 /*
1926  * Common routine for chroot and chdir.  Given a locked, referenced vnode,
1927  * determine whether it is legal to chdir to the vnode.  The vnode's state
1928  * is not changed by this call.
1929  */
1930 static int
1931 checkvp_chdir(struct vnode *vp, struct thread *td)
1932 {
1933         int error;
1934
1935         if (vp->v_type != VDIR)
1936                 error = ENOTDIR;
1937         else
1938                 error = VOP_EACCESS(vp, VEXEC, td->td_ucred);
1939         return (error);
1940 }
1941
1942 int
1943 kern_open(struct nlookupdata *nd, int oflags, int mode, int *res)
1944 {
1945         struct thread *td = curthread;
1946         struct proc *p = td->td_proc;
1947         struct lwp *lp = td->td_lwp;
1948         struct filedesc *fdp = p->p_fd;
1949         int cmode, flags;
1950         struct file *nfp;
1951         struct file *fp;
1952         struct vnode *vp;
1953         int type, indx, error = 0;
1954         struct flock lf;
1955
1956         if ((oflags & O_ACCMODE) == O_ACCMODE)
1957                 return (EINVAL);
1958         flags = FFLAGS(oflags);
1959         error = falloc(lp, &nfp, NULL);
1960         if (error)
1961                 return (error);
1962         fp = nfp;
1963         cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT;
1964
1965         /*
1966          * XXX p_dupfd is a real mess.  It allows a device to return a
1967          * file descriptor to be duplicated rather then doing the open
1968          * itself.
1969          */
1970         lp->lwp_dupfd = -1;
1971
1972         /*
1973          * Call vn_open() to do the lookup and assign the vnode to the 
1974          * file pointer.  vn_open() does not change the ref count on fp
1975          * and the vnode, on success, will be inherited by the file pointer
1976          * and unlocked.
1977          *
1978          * Request a shared lock on the vnode if possible.
1979          *
1980          * Executable binaries can race VTEXT against O_RDWR opens, so
1981          * use an exclusive lock for O_RDWR opens as well.
1982          *
1983          * NOTE: We need a flag to separate terminal vnode locking from
1984          *       parent locking.  O_CREAT needs parent locking, but O_TRUNC
1985          *       and O_RDWR only need to lock the terminal vnode exclusively.
1986          */
1987         nd->nl_flags |= NLC_LOCKVP;
1988         if ((flags & (O_CREAT|O_TRUNC|O_RDWR)) == 0)
1989                 nd->nl_flags |= NLC_SHAREDLOCK;
1990
1991         error = vn_open(nd, fp, flags, cmode);
1992         nlookup_done(nd);
1993
1994         if (error) {
1995                 /*
1996                  * handle special fdopen() case.  bleh.  dupfdopen() is
1997                  * responsible for dropping the old contents of ofiles[indx]
1998                  * if it succeeds.
1999                  *
2000                  * Note that fsetfd() will add a ref to fp which represents
2001                  * the fd_files[] assignment.  We must still drop our
2002                  * reference.
2003                  */
2004                 if ((error == ENODEV || error == ENXIO) && lp->lwp_dupfd >= 0) {
2005                         if (fdalloc(p, 0, &indx) == 0) {
2006                                 error = dupfdopen(fdp, indx, lp->lwp_dupfd, flags, error);
2007                                 if (error == 0) {
2008                                         *res = indx;
2009                                         fdrop(fp);      /* our ref */
2010                                         return (0);
2011                                 }
2012                                 fsetfd(fdp, NULL, indx);
2013                         }
2014                 }
2015                 fdrop(fp);      /* our ref */
2016                 if (error == ERESTART)
2017                         error = EINTR;
2018                 return (error);
2019         }
2020
2021         /*
2022          * ref the vnode for ourselves so it can't be ripped out from under
2023          * is.  XXX need an ND flag to request that the vnode be returned
2024          * anyway.
2025          *
2026          * Reserve a file descriptor but do not assign it until the open
2027          * succeeds.
2028          */
2029         vp = (struct vnode *)fp->f_data;
2030         vref(vp);
2031         if ((error = fdalloc(p, 0, &indx)) != 0) {
2032                 fdrop(fp);
2033                 vrele(vp);
2034                 return (error);
2035         }
2036
2037         /*
2038          * If no error occurs the vp will have been assigned to the file
2039          * pointer.
2040          */
2041         lp->lwp_dupfd = 0;
2042
2043         if (flags & (O_EXLOCK | O_SHLOCK)) {
2044                 lf.l_whence = SEEK_SET;
2045                 lf.l_start = 0;
2046                 lf.l_len = 0;
2047                 if (flags & O_EXLOCK)
2048                         lf.l_type = F_WRLCK;
2049                 else
2050                         lf.l_type = F_RDLCK;
2051                 if (flags & FNONBLOCK)
2052                         type = 0;
2053                 else
2054                         type = F_WAIT;
2055
2056                 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
2057                         /*
2058                          * lock request failed.  Clean up the reserved
2059                          * descriptor.
2060                          */
2061                         vrele(vp);
2062                         fsetfd(fdp, NULL, indx);
2063                         fdrop(fp);
2064                         return (error);
2065                 }
2066                 atomic_set_int(&fp->f_flag, FHASLOCK); /* race ok */
2067         }
2068 #if 0
2069         /*
2070          * Assert that all regular file vnodes were created with a object.
2071          */
2072         KASSERT(vp->v_type != VREG || vp->v_object != NULL,
2073                 ("open: regular file has no backing object after vn_open"));
2074 #endif
2075
2076         vrele(vp);
2077
2078         /*
2079          * release our private reference, leaving the one associated with the
2080          * descriptor table intact.
2081          */
2082         if (oflags & O_CLOEXEC)
2083                 fdp->fd_files[indx].fileflags |= UF_EXCLOSE;
2084         fsetfd(fdp, fp, indx);
2085         fdrop(fp);
2086         *res = indx;
2087         return (error);
2088 }
2089
2090 /*
2091  * open_args(char *path, int flags, int mode)
2092  *
2093  * Check permissions, allocate an open file structure,
2094  * and call the device open routine if any.
2095  */
2096 int
2097 sys_open(struct open_args *uap)
2098 {
2099         struct nlookupdata nd;
2100         int error;
2101
2102         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2103         if (error == 0) {
2104                 error = kern_open(&nd, uap->flags,
2105                                     uap->mode, &uap->sysmsg_result);
2106         }
2107         nlookup_done(&nd);
2108         return (error);
2109 }
2110
2111 /*
2112  * openat_args(int fd, char *path, int flags, int mode)
2113  */
2114 int
2115 sys_openat(struct openat_args *uap)
2116 {
2117         struct nlookupdata nd;
2118         int error;
2119         struct file *fp;
2120
2121         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0);
2122         if (error == 0) {
2123                 error = kern_open(&nd, uap->flags, uap->mode, 
2124                                         &uap->sysmsg_result);
2125         }
2126         nlookup_done_at(&nd, fp);
2127         return (error);
2128 }
2129
2130 int
2131 kern_mknod(struct nlookupdata *nd, int mode, int rmajor, int rminor)
2132 {
2133         struct thread *td = curthread;
2134         struct proc *p = td->td_proc;
2135         struct vnode *vp;
2136         struct vattr vattr;
2137         int error;
2138         int whiteout = 0;
2139
2140         KKASSERT(p);
2141
2142         VATTR_NULL(&vattr);
2143         vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask;
2144         vattr.va_rmajor = rmajor;
2145         vattr.va_rminor = rminor;
2146
2147         switch (mode & S_IFMT) {
2148         case S_IFMT:    /* used by badsect to flag bad sectors */
2149                 error = priv_check_cred(td->td_ucred, PRIV_VFS_MKNOD_BAD, 0);
2150                 vattr.va_type = VBAD;
2151                 break;
2152         case S_IFCHR:
2153                 error = priv_check(td, PRIV_VFS_MKNOD_DEV);
2154                 vattr.va_type = VCHR;
2155                 break;
2156         case S_IFBLK:
2157                 error = priv_check(td, PRIV_VFS_MKNOD_DEV);
2158                 vattr.va_type = VBLK;
2159                 break;
2160         case S_IFWHT:
2161                 error = priv_check_cred(td->td_ucred, PRIV_VFS_MKNOD_WHT, 0);
2162                 whiteout = 1;
2163                 break;
2164         case S_IFDIR:   /* special directories support for HAMMER */
2165                 error = priv_check_cred(td->td_ucred, PRIV_VFS_MKNOD_DIR, 0);
2166                 vattr.va_type = VDIR;
2167                 break;
2168         default:
2169                 error = EINVAL;
2170                 break;
2171         }
2172
2173         if (error)
2174                 return (error);
2175
2176         bwillinode(1);
2177         nd->nl_flags |= NLC_CREATE | NLC_REFDVP;
2178         if ((error = nlookup(nd)) != 0)
2179                 return (error);
2180         if (nd->nl_nch.ncp->nc_vp)
2181                 return (EEXIST);
2182         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
2183                 return (error);
2184
2185         if (whiteout) {
2186                 error = VOP_NWHITEOUT(&nd->nl_nch, nd->nl_dvp,
2187                                       nd->nl_cred, NAMEI_CREATE);
2188         } else {
2189                 vp = NULL;
2190                 error = VOP_NMKNOD(&nd->nl_nch, nd->nl_dvp,
2191                                    &vp, nd->nl_cred, &vattr);
2192                 if (error == 0)
2193                         vput(vp);
2194         }
2195         return (error);
2196 }
2197
2198 /*
2199  * mknod_args(char *path, int mode, int dev)
2200  *
2201  * Create a special file.
2202  */
2203 int
2204 sys_mknod(struct mknod_args *uap)
2205 {
2206         struct nlookupdata nd;
2207         int error;
2208
2209         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2210         if (error == 0) {
2211                 error = kern_mknod(&nd, uap->mode,
2212                                    umajor(uap->dev), uminor(uap->dev));
2213         }
2214         nlookup_done(&nd);
2215         return (error);
2216 }
2217
2218 /*
2219  * mknodat_args(int fd, char *path, mode_t mode, dev_t dev)
2220  *
2221  * Create a special file.  The path is relative to the directory associated
2222  * with fd.
2223  */
2224 int
2225 sys_mknodat(struct mknodat_args *uap)
2226 {
2227         struct nlookupdata nd;
2228         struct file *fp;
2229         int error;
2230
2231         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0);
2232         if (error == 0) {
2233                 error = kern_mknod(&nd, uap->mode,
2234                                    umajor(uap->dev), uminor(uap->dev));
2235         }
2236         nlookup_done_at(&nd, fp);
2237         return (error);
2238 }
2239
2240 int
2241 kern_mkfifo(struct nlookupdata *nd, int mode)
2242 {
2243         struct thread *td = curthread;
2244         struct proc *p = td->td_proc;
2245         struct vattr vattr;
2246         struct vnode *vp;
2247         int error;
2248
2249         bwillinode(1);
2250
2251         nd->nl_flags |= NLC_CREATE | NLC_REFDVP;
2252         if ((error = nlookup(nd)) != 0)
2253                 return (error);
2254         if (nd->nl_nch.ncp->nc_vp)
2255                 return (EEXIST);
2256         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
2257                 return (error);
2258
2259         VATTR_NULL(&vattr);
2260         vattr.va_type = VFIFO;
2261         vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask;
2262         vp = NULL;
2263         error = VOP_NMKNOD(&nd->nl_nch, nd->nl_dvp, &vp, nd->nl_cred, &vattr);
2264         if (error == 0)
2265                 vput(vp);
2266         return (error);
2267 }
2268
2269 /*
2270  * mkfifo_args(char *path, int mode)
2271  *
2272  * Create a named pipe.
2273  */
2274 int
2275 sys_mkfifo(struct mkfifo_args *uap)
2276 {
2277         struct nlookupdata nd;
2278         int error;
2279
2280         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2281         if (error == 0)
2282                 error = kern_mkfifo(&nd, uap->mode);
2283         nlookup_done(&nd);
2284         return (error);
2285 }
2286
2287 /*
2288  * mkfifoat_args(int fd, char *path, mode_t mode)
2289  *
2290  * Create a named pipe.  The path is relative to the directory associated
2291  * with fd.
2292  */
2293 int
2294 sys_mkfifoat(struct mkfifoat_args *uap)
2295 {
2296         struct nlookupdata nd;
2297         struct file *fp;
2298         int error;
2299
2300         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0);
2301         if (error == 0)
2302                 error = kern_mkfifo(&nd, uap->mode);
2303         nlookup_done_at(&nd, fp);
2304         return (error);
2305 }
2306
2307 static int hardlink_check_uid = 0;
2308 SYSCTL_INT(_security, OID_AUTO, hardlink_check_uid, CTLFLAG_RW,
2309     &hardlink_check_uid, 0, 
2310     "Unprivileged processes cannot create hard links to files owned by other "
2311     "users");
2312 static int hardlink_check_gid = 0;
2313 SYSCTL_INT(_security, OID_AUTO, hardlink_check_gid, CTLFLAG_RW,
2314     &hardlink_check_gid, 0,
2315     "Unprivileged processes cannot create hard links to files owned by other "
2316     "groups");
2317
2318 static int
2319 can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred)
2320 {
2321         struct vattr va;
2322         int error;
2323
2324         /*
2325          * Shortcut if disabled
2326          */
2327         if (hardlink_check_uid == 0 && hardlink_check_gid == 0)
2328                 return (0);
2329
2330         /*
2331          * Privileged user can always hardlink
2332          */
2333         if (priv_check_cred(cred, PRIV_VFS_LINK, 0) == 0)
2334                 return (0);
2335
2336         /*
2337          * Otherwise only if the originating file is owned by the
2338          * same user or group.  Note that any group is allowed if
2339          * the file is owned by the caller.
2340          */
2341         error = VOP_GETATTR(vp, &va);
2342         if (error != 0)
2343                 return (error);
2344         
2345         if (hardlink_check_uid) {
2346                 if (cred->cr_uid != va.va_uid)
2347                         return (EPERM);
2348         }
2349         
2350         if (hardlink_check_gid) {
2351                 if (cred->cr_uid != va.va_uid && !groupmember(va.va_gid, cred))
2352                         return (EPERM);
2353         }
2354
2355         return (0);
2356 }
2357
2358 int
2359 kern_link(struct nlookupdata *nd, struct nlookupdata *linknd)
2360 {
2361         struct thread *td = curthread;
2362         struct vnode *vp;
2363         int error;
2364
2365         /*
2366          * Lookup the source and obtained a locked vnode.
2367          *
2368          * You may only hardlink a file which you have write permission
2369          * on or which you own.
2370          *
2371          * XXX relookup on vget failure / race ?
2372          */
2373         bwillinode(1);
2374         nd->nl_flags |= NLC_WRITE | NLC_OWN | NLC_HLINK;
2375         if ((error = nlookup(nd)) != 0)
2376                 return (error);
2377         vp = nd->nl_nch.ncp->nc_vp;
2378         KKASSERT(vp != NULL);
2379         if (vp->v_type == VDIR)
2380                 return (EPERM);         /* POSIX */
2381         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
2382                 return (error);
2383         if ((error = vget(vp, LK_EXCLUSIVE)) != 0)
2384                 return (error);
2385
2386         /*
2387          * Unlock the source so we can lookup the target without deadlocking
2388          * (XXX vp is locked already, possible other deadlock?).  The target
2389          * must not exist.
2390          */
2391         KKASSERT(nd->nl_flags & NLC_NCPISLOCKED);
2392         nd->nl_flags &= ~NLC_NCPISLOCKED;
2393         cache_unlock(&nd->nl_nch);
2394         vn_unlock(vp);
2395
2396         linknd->nl_flags |= NLC_CREATE | NLC_REFDVP;
2397         if ((error = nlookup(linknd)) != 0) {
2398                 vrele(vp);
2399                 return (error);
2400         }
2401         if (linknd->nl_nch.ncp->nc_vp) {
2402                 vrele(vp);
2403                 return (EEXIST);
2404         }
2405         error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_FAILRECLAIM);
2406         if (error) {
2407                 vrele(vp);
2408                 return (error);
2409         }
2410
2411         /*
2412          * Finally run the new API VOP.
2413          */
2414         error = can_hardlink(vp, td, td->td_ucred);
2415         if (error == 0) {
2416                 error = VOP_NLINK(&linknd->nl_nch, linknd->nl_dvp,
2417                                   vp, linknd->nl_cred);
2418         }
2419         vput(vp);
2420         return (error);
2421 }
2422
2423 /*
2424  * link_args(char *path, char *link)
2425  *
2426  * Make a hard file link.
2427  */
2428 int
2429 sys_link(struct link_args *uap)
2430 {
2431         struct nlookupdata nd, linknd;
2432         int error;
2433
2434         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
2435         if (error == 0) {
2436                 error = nlookup_init(&linknd, uap->link, UIO_USERSPACE, 0);
2437                 if (error == 0)
2438                         error = kern_link(&nd, &linknd);
2439                 nlookup_done(&linknd);
2440         }
2441         nlookup_done(&nd);
2442         return (error);
2443 }
2444
2445 /*
2446  * linkat_args(int fd1, char *path1, int fd2, char *path2, int flags)
2447  *
2448  * Make a hard file link. The path1 argument is relative to the directory
2449  * associated with fd1, and similarly the path2 argument is relative to
2450  * the directory associated with fd2.
2451  */
2452 int
2453 sys_linkat(struct linkat_args *uap)
2454 {
2455         struct nlookupdata nd, linknd;
2456         struct file *fp1, *fp2;
2457         int error;
2458
2459         error = nlookup_init_at(&nd, &fp1, uap->fd1, uap->path1, UIO_USERSPACE,
2460             (uap->flags & AT_SYMLINK_FOLLOW) ? NLC_FOLLOW : 0);
2461         if (error == 0) {
2462                 error = nlookup_init_at(&linknd, &fp2, uap->fd2,
2463                     uap->path2, UIO_USERSPACE, 0);
2464                 if (error == 0)
2465                         error = kern_link(&nd, &linknd);
2466                 nlookup_done_at(&linknd, fp2);
2467         }
2468         nlookup_done_at(&nd, fp1);
2469         return (error);
2470 }
2471
2472 int
2473 kern_symlink(struct nlookupdata *nd, char *path, int mode)
2474 {
2475         struct vattr vattr;
2476         struct vnode *vp;
2477         struct vnode *dvp;
2478         int error;
2479
2480         bwillinode(1);
2481         nd->nl_flags |= NLC_CREATE | NLC_REFDVP;
2482         if ((error = nlookup(nd)) != 0)
2483                 return (error);
2484         if (nd->nl_nch.ncp->nc_vp)
2485                 return (EEXIST);
2486         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
2487                 return (error);
2488         dvp = nd->nl_dvp;
2489         VATTR_NULL(&vattr);
2490         vattr.va_mode = mode;
2491         error = VOP_NSYMLINK(&nd->nl_nch, dvp, &vp, nd->nl_cred, &vattr, path);
2492         if (error == 0)
2493                 vput(vp);
2494         return (error);
2495 }
2496
2497 /*
2498  * symlink(char *path, char *link)
2499  *
2500  * Make a symbolic link.
2501  */
2502 int
2503 sys_symlink(struct symlink_args *uap)
2504 {
2505         struct thread *td = curthread;
2506         struct nlookupdata nd;
2507         char *path;
2508         int error;
2509         int mode;
2510
2511         path = objcache_get(namei_oc, M_WAITOK);
2512         error = copyinstr(uap->path, path, MAXPATHLEN, NULL);
2513         if (error == 0) {
2514                 error = nlookup_init(&nd, uap->link, UIO_USERSPACE, 0);
2515                 if (error == 0) {
2516                         mode = ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask;
2517                         error = kern_symlink(&nd, path, mode);
2518                 }
2519                 nlookup_done(&nd);
2520         }
2521         objcache_put(namei_oc, path);
2522         return (error);
2523 }
2524
2525 /*
2526  * symlinkat_args(char *path1, int fd, char *path2)
2527  *
2528  * Make a symbolic link.  The path2 argument is relative to the directory
2529  * associated with fd.
2530  */
2531 int
2532 sys_symlinkat(struct symlinkat_args *uap)
2533 {
2534         struct thread *td = curthread;
2535         struct nlookupdata nd;
2536         struct file *fp;
2537         char *path1;
2538         int error;
2539         int mode;
2540
2541         path1 = objcache_get(namei_oc, M_WAITOK);
2542         error = copyinstr(uap->path1, path1, MAXPATHLEN, NULL);
2543         if (error == 0) {
2544                 error = nlookup_init_at(&nd, &fp, uap->fd, uap->path2,
2545                     UIO_USERSPACE, 0);
2546                 if (error == 0) {
2547                         mode = ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask;
2548                         error = kern_symlink(&nd, path1, mode);
2549                 }
2550                 nlookup_done_at(&nd, fp);
2551         }
2552         objcache_put(namei_oc, path1);
2553         return (error);
2554 }
2555
2556 /*
2557  * undelete_args(char *path)
2558  *
2559  * Delete a whiteout from the filesystem.
2560  */
2561 int
2562 sys_undelete(struct undelete_args *uap)
2563 {
2564         struct nlookupdata nd;
2565         int error;
2566
2567         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2568         bwillinode(1);
2569         nd.nl_flags |= NLC_DELETE | NLC_REFDVP;
2570         if (error == 0)
2571                 error = nlookup(&nd);
2572         if (error == 0)
2573                 error = ncp_writechk(&nd.nl_nch);
2574         if (error == 0) {
2575                 error = VOP_NWHITEOUT(&nd.nl_nch, nd.nl_dvp, nd.nl_cred,
2576                                       NAMEI_DELETE);
2577         }
2578         nlookup_done(&nd);
2579         return (error);
2580 }
2581
2582 int
2583 kern_unlink(struct nlookupdata *nd)
2584 {
2585         int error;
2586
2587         bwillinode(1);
2588         nd->nl_flags |= NLC_DELETE | NLC_REFDVP;
2589         if ((error = nlookup(nd)) != 0)
2590                 return (error);
2591         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
2592                 return (error);
2593         error = VOP_NREMOVE(&nd->nl_nch, nd->nl_dvp, nd->nl_cred);
2594         return (error);
2595 }
2596
2597 /*
2598  * unlink_args(char *path)
2599  *
2600  * Delete a name from the filesystem.
2601  */
2602 int
2603 sys_unlink(struct unlink_args *uap)
2604 {
2605         struct nlookupdata nd;
2606         int error;
2607
2608         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2609         if (error == 0)
2610                 error = kern_unlink(&nd);
2611         nlookup_done(&nd);
2612         return (error);
2613 }
2614
2615
2616 /*
2617  * unlinkat_args(int fd, char *path, int flags)
2618  *
2619  * Delete the file or directory entry pointed to by fd/path.
2620  */
2621 int
2622 sys_unlinkat(struct unlinkat_args *uap)
2623 {
2624         struct nlookupdata nd;
2625         struct file *fp;
2626         int error;
2627
2628         if (uap->flags & ~AT_REMOVEDIR)
2629                 return (EINVAL);
2630
2631         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0);
2632         if (error == 0) {
2633                 if (uap->flags & AT_REMOVEDIR)
2634                         error = kern_rmdir(&nd);
2635                 else
2636                         error = kern_unlink(&nd);
2637         }
2638         nlookup_done_at(&nd, fp);
2639         return (error);
2640 }
2641
2642 int
2643 kern_lseek(int fd, off_t offset, int whence, off_t *res)
2644 {
2645         struct thread *td = curthread;
2646         struct proc *p = td->td_proc;
2647         struct file *fp;
2648         struct vnode *vp;
2649         struct vattr vattr;
2650         off_t new_offset;
2651         int error;
2652
2653         fp = holdfp(p->p_fd, fd, -1);
2654         if (fp == NULL)
2655                 return (EBADF);
2656         if (fp->f_type != DTYPE_VNODE) {
2657                 error = ESPIPE;
2658                 goto done;
2659         }
2660         vp = (struct vnode *)fp->f_data;
2661
2662         switch (whence) {
2663         case L_INCR:
2664                 spin_lock(&fp->f_spin);
2665                 new_offset = fp->f_offset + offset;
2666                 error = 0;
2667                 break;
2668         case L_XTND:
2669                 error = VOP_GETATTR(vp, &vattr);
2670                 spin_lock(&fp->f_spin);
2671                 new_offset = offset + vattr.va_size;
2672                 break;
2673         case L_SET:
2674                 new_offset = offset;
2675                 error = 0;
2676                 spin_lock(&fp->f_spin);
2677                 break;
2678         default:
2679                 new_offset = 0;
2680                 error = EINVAL;
2681                 spin_lock(&fp->f_spin);
2682                 break;
2683         }
2684
2685         /*
2686          * Validate the seek position.  Negative offsets are not allowed
2687          * for regular files or directories.
2688          *
2689          * Normally we would also not want to allow negative offsets for
2690          * character and block-special devices.  However kvm addresses
2691          * on 64 bit architectures might appear to be negative and must
2692          * be allowed.
2693          */
2694         if (error == 0) {
2695                 if (new_offset < 0 &&
2696                     (vp->v_type == VREG || vp->v_type == VDIR)) {
2697                         error = EINVAL;
2698                 } else {
2699                         fp->f_offset = new_offset;
2700                 }
2701         }
2702         *res = fp->f_offset;
2703         spin_unlock(&fp->f_spin);
2704 done:
2705         fdrop(fp);
2706         return (error);
2707 }
2708
2709 /*
2710  * lseek_args(int fd, int pad, off_t offset, int whence)
2711  *
2712  * Reposition read/write file offset.
2713  */
2714 int
2715 sys_lseek(struct lseek_args *uap)
2716 {
2717         int error;
2718
2719         error = kern_lseek(uap->fd, uap->offset, uap->whence,
2720                            &uap->sysmsg_offset);
2721
2722         return (error);
2723 }
2724
2725 /*
2726  * Check if current process can access given file.  amode is a bitmask of *_OK
2727  * access bits.  flags is a bitmask of AT_* flags.
2728  */
2729 int
2730 kern_access(struct nlookupdata *nd, int amode, int flags)
2731 {
2732         struct vnode *vp;
2733         int error, mode;
2734
2735         if (flags & ~AT_EACCESS)
2736                 return (EINVAL);
2737         nd->nl_flags |= NLC_SHAREDLOCK;
2738         if ((error = nlookup(nd)) != 0)
2739                 return (error);
2740 retry:
2741         error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_SHARED, &vp);
2742         if (error)
2743                 return (error);
2744
2745         /* Flags == 0 means only check for existence. */
2746         if (amode) {
2747                 mode = 0;
2748                 if (amode & R_OK)
2749                         mode |= VREAD;
2750                 if (amode & W_OK)
2751                         mode |= VWRITE;
2752                 if (amode & X_OK)
2753                         mode |= VEXEC;
2754                 if ((mode & VWRITE) == 0 || 
2755                     (error = vn_writechk(vp, &nd->nl_nch)) == 0)
2756                         error = VOP_ACCESS_FLAGS(vp, mode, flags, nd->nl_cred);
2757
2758                 /*
2759                  * If the file handle is stale we have to re-resolve the
2760                  * entry with the ncp held exclusively.  This is a hack
2761                  * at the moment.
2762                  */
2763                 if (error == ESTALE) {
2764                         vput(vp);
2765                         cache_unlock(&nd->nl_nch);
2766                         cache_lock(&nd->nl_nch);
2767                         cache_setunresolved(&nd->nl_nch);
2768                         error = cache_resolve(&nd->nl_nch, nd->nl_cred);
2769                         if (error == 0) {
2770                                 vp = NULL;
2771                                 goto retry;
2772                         }
2773                         return(error);
2774                 }
2775         }
2776         vput(vp);
2777         return (error);
2778 }
2779
2780 /*
2781  * access_args(char *path, int flags)
2782  *
2783  * Check access permissions.
2784  */
2785 int
2786 sys_access(struct access_args *uap)
2787 {
2788         struct nlookupdata nd;
2789         int error;
2790
2791         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
2792         if (error == 0)
2793                 error = kern_access(&nd, uap->flags, 0);
2794         nlookup_done(&nd);
2795         return (error);
2796 }
2797
2798
2799 /*
2800  * eaccess_args(char *path, int flags)
2801  *
2802  * Check access permissions.
2803  */
2804 int
2805 sys_eaccess(struct eaccess_args *uap)
2806 {
2807         struct nlookupdata nd;
2808         int error;
2809
2810         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
2811         if (error == 0)
2812                 error = kern_access(&nd, uap->flags, AT_EACCESS);
2813         nlookup_done(&nd);
2814         return (error);
2815 }
2816
2817
2818 /*
2819  * faccessat_args(int fd, char *path, int amode, int flags)
2820  *
2821  * Check access permissions.
2822  */
2823 int
2824 sys_faccessat(struct faccessat_args *uap)
2825 {
2826         struct nlookupdata nd;
2827         struct file *fp;
2828         int error;
2829
2830         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 
2831                                 NLC_FOLLOW);
2832         if (error == 0)
2833                 error = kern_access(&nd, uap->amode, uap->flags);
2834         nlookup_done_at(&nd, fp);
2835         return (error);
2836 }
2837
2838 int
2839 kern_stat(struct nlookupdata *nd, struct stat *st)
2840 {
2841         int error;
2842         struct vnode *vp;
2843
2844         nd->nl_flags |= NLC_SHAREDLOCK;
2845         if ((error = nlookup(nd)) != 0)
2846                 return (error);
2847 again:
2848         if ((vp = nd->nl_nch.ncp->nc_vp) == NULL)
2849                 return (ENOENT);
2850
2851         if ((error = vget(vp, LK_SHARED)) != 0)
2852                 return (error);
2853         error = vn_stat(vp, st, nd->nl_cred);
2854
2855         /*
2856          * If the file handle is stale we have to re-resolve the
2857          * entry with the ncp held exclusively.  This is a hack
2858          * at the moment.
2859          */
2860         if (error == ESTALE) {
2861                 vput(vp);
2862                 cache_unlock(&nd->nl_nch);
2863                 cache_lock(&nd->nl_nch);
2864                 cache_setunresolved(&nd->nl_nch);
2865                 error = cache_resolve(&nd->nl_nch, nd->nl_cred);
2866                 if (error == 0)
2867                         goto again;
2868         } else {
2869                 vput(vp);
2870         }
2871         return (error);
2872 }
2873
2874 /*
2875  * stat_args(char *path, struct stat *ub)
2876  *
2877  * Get file status; this version follows links.
2878  */
2879 int
2880 sys_stat(struct stat_args *uap)
2881 {
2882         struct nlookupdata nd;
2883         struct stat st;
2884         int error;
2885
2886         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
2887         if (error == 0) {
2888                 error = kern_stat(&nd, &st);
2889                 if (error == 0)
2890                         error = copyout(&st, uap->ub, sizeof(*uap->ub));
2891         }
2892         nlookup_done(&nd);
2893         return (error);
2894 }
2895
2896 /*
2897  * lstat_args(char *path, struct stat *ub)
2898  *
2899  * Get file status; this version does not follow links.
2900  */
2901 int
2902 sys_lstat(struct lstat_args *uap)
2903 {
2904         struct nlookupdata nd;
2905         struct stat st;
2906         int error;
2907
2908         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2909         if (error == 0) {
2910                 error = kern_stat(&nd, &st);
2911                 if (error == 0)
2912                         error = copyout(&st, uap->ub, sizeof(*uap->ub));
2913         }
2914         nlookup_done(&nd);
2915         return (error);
2916 }
2917
2918 /*
2919  * fstatat_args(int fd, char *path, struct stat *sb, int flags)
2920  *
2921  * Get status of file pointed to by fd/path.
2922  */
2923 int
2924 sys_fstatat(struct fstatat_args *uap)
2925 {
2926         struct nlookupdata nd;
2927         struct stat st;
2928         int error;
2929         int flags;
2930         struct file *fp;
2931
2932         if (uap->flags & ~AT_SYMLINK_NOFOLLOW)
2933                 return (EINVAL);
2934
2935         flags = (uap->flags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW;
2936
2937         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, 
2938                                 UIO_USERSPACE, flags);
2939         if (error == 0) {
2940                 error = kern_stat(&nd, &st);
2941                 if (error == 0)
2942                         error = copyout(&st, uap->sb, sizeof(*uap->sb));
2943         }
2944         nlookup_done_at(&nd, fp);
2945         return (error);
2946 }
2947
2948 static int
2949 kern_pathconf(char *path, int name, int flags, register_t *sysmsg_regp)
2950 {
2951         struct nlookupdata nd;
2952         struct vnode *vp;
2953         int error;
2954
2955         vp = NULL;
2956         error = nlookup_init(&nd, path, UIO_USERSPACE, flags);
2957         if (error == 0)
2958                 error = nlookup(&nd);
2959         if (error == 0)
2960                 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
2961         nlookup_done(&nd);
2962         if (error == 0) {
2963                 error = VOP_PATHCONF(vp, name, sysmsg_regp);
2964                 vput(vp);
2965         }
2966         return (error);
2967 }
2968
2969 /*
2970  * pathconf_Args(char *path, int name)
2971  *
2972  * Get configurable pathname variables.
2973  */
2974 int
2975 sys_pathconf(struct pathconf_args *uap)
2976 {
2977         return (kern_pathconf(uap->path, uap->name, NLC_FOLLOW,
2978                 &uap->sysmsg_reg));
2979 }
2980
2981 /*
2982  * lpathconf_Args(char *path, int name)
2983  *
2984  * Get configurable pathname variables, but don't follow symlinks.
2985  */
2986 int
2987 sys_lpathconf(struct lpathconf_args *uap)
2988 {
2989         return (kern_pathconf(uap->path, uap->name, 0, &uap->sysmsg_reg));
2990 }
2991
2992 /*
2993  * XXX: daver
2994  * kern_readlink isn't properly split yet.  There is a copyin burried
2995  * in VOP_READLINK().
2996  */
2997 int
2998 kern_readlink(struct nlookupdata *nd, char *buf, int count, int *res)
2999 {
3000         struct thread *td = curthread;
3001         struct vnode *vp;
3002         struct iovec aiov;
3003         struct uio auio;
3004         int error;
3005
3006         nd->nl_flags |= NLC_SHAREDLOCK;
3007         if ((error = nlookup(nd)) != 0)
3008                 return (error);
3009         error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_SHARED, &vp);
3010         if (error)
3011                 return (error);
3012         if (vp->v_type != VLNK) {
3013                 error = EINVAL;
3014         } else {
3015                 aiov.iov_base = buf;
3016                 aiov.iov_len = count;
3017                 auio.uio_iov = &aiov;
3018                 auio.uio_iovcnt = 1;
3019                 auio.uio_offset = 0;
3020                 auio.uio_rw = UIO_READ;
3021                 auio.uio_segflg = UIO_USERSPACE;
3022                 auio.uio_td = td;
3023                 auio.uio_resid = count;
3024                 error = VOP_READLINK(vp, &auio, td->td_ucred);
3025         }
3026         vput(vp);
3027         *res = count - auio.uio_resid;
3028         return (error);
3029 }
3030
3031 /*
3032  * readlink_args(char *path, char *buf, int count)
3033  *
3034  * Return target name of a symbolic link.
3035  */
3036 int
3037 sys_readlink(struct readlink_args *uap)
3038 {
3039         struct nlookupdata nd;
3040         int error;
3041
3042         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
3043         if (error == 0) {
3044                 error = kern_readlink(&nd, uap->buf, uap->count,
3045                                         &uap->sysmsg_result);
3046         }
3047         nlookup_done(&nd);
3048         return (error);
3049 }
3050
3051 /*
3052  * readlinkat_args(int fd, char *path, char *buf, size_t bufsize)
3053  *
3054  * Return target name of a symbolic link.  The path is relative to the
3055  * directory associated with fd.
3056  */
3057 int
3058 sys_readlinkat(struct readlinkat_args *uap)
3059 {
3060         struct nlookupdata nd;
3061         struct file *fp;
3062         int error;
3063
3064         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0);
3065         if (error == 0) {
3066                 error = kern_readlink(&nd, uap->buf, uap->bufsize,
3067                                         &uap->sysmsg_result);
3068         }
3069         nlookup_done_at(&nd, fp);
3070         return (error);
3071 }
3072
3073 static int
3074 setfflags(struct vnode *vp, int flags)
3075 {
3076         struct thread *td = curthread;
3077         int error;
3078         struct vattr vattr;
3079
3080         /*
3081          * Prevent non-root users from setting flags on devices.  When
3082          * a device is reused, users can retain ownership of the device
3083          * if they are allowed to set flags and programs assume that
3084          * chown can't fail when done as root.
3085          */
3086         if ((vp->v_type == VCHR || vp->v_type == VBLK) && 
3087             ((error = priv_check_cred(td->td_ucred, PRIV_VFS_CHFLAGS_DEV, 0)) != 0))
3088                 return (error);
3089
3090         /*
3091          * note: vget is required for any operation that might mod the vnode
3092          * so VINACTIVE is properly cleared.
3093          */
3094         if ((error = vget(vp, LK_EXCLUSIVE)) == 0) {
3095                 VATTR_NULL(&vattr);
3096                 vattr.va_flags = flags;
3097                 error = VOP_SETATTR(vp, &vattr, td->td_ucred);
3098                 vput(vp);
3099         }
3100         return (error);
3101 }
3102
3103 /*
3104  * chflags(char *path, int flags)
3105  *
3106  * Change flags of a file given a path name.
3107  */
3108 int
3109 sys_chflags(struct chflags_args *uap)
3110 {
3111         struct nlookupdata nd;
3112         struct vnode *vp;
3113         int error;
3114
3115         vp = NULL;
3116         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
3117         if (error == 0)
3118                 error = nlookup(&nd);
3119         if (error == 0)
3120                 error = ncp_writechk(&nd.nl_nch);
3121         if (error == 0)
3122                 error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
3123         nlookup_done(&nd);
3124         if (error == 0) {
3125                 error = setfflags(vp, uap->flags);
3126                 vrele(vp);
3127         }
3128         return (error);
3129 }
3130
3131 /*
3132  * lchflags(char *path, int flags)
3133  *
3134  * Change flags of a file given a path name, but don't follow symlinks.
3135  */
3136 int
3137 sys_lchflags(struct lchflags_args *uap)
3138 {
3139         struct nlookupdata nd;
3140         struct vnode *vp;
3141         int error;
3142
3143         vp = NULL;
3144         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
3145         if (error == 0)
3146                 error = nlookup(&nd);
3147         if (error == 0)
3148                 error = ncp_writechk(&nd.nl_nch);
3149         if (error == 0)
3150                 error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
3151         nlookup_done(&nd);
3152         if (error == 0) {
3153                 error = setfflags(vp, uap->flags);
3154                 vrele(vp);
3155         }
3156         return (error);
3157 }
3158
3159 /*
3160  * fchflags_args(int fd, int flags)
3161  *
3162  * Change flags of a file given a file descriptor.
3163  */
3164 int
3165 sys_fchflags(struct fchflags_args *uap)
3166 {
3167         struct thread *td = curthread;
3168         struct proc *p = td->td_proc;
3169         struct file *fp;
3170         int error;
3171
3172         if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
3173                 return (error);
3174         if (fp->f_nchandle.ncp)
3175                 error = ncp_writechk(&fp->f_nchandle);
3176         if (error == 0)
3177                 error = setfflags((struct vnode *) fp->f_data, uap->flags);
3178         fdrop(fp);
3179         return (error);
3180 }
3181
3182 /*
3183  * chflagsat_args(int fd, const char *path, int flags, int atflags)
3184  * change flags given a pathname relative to a filedescriptor
3185  */
3186 int sys_chflagsat(struct chflagsat_args *uap)
3187 {
3188         struct nlookupdata nd;
3189         struct vnode *vp;
3190         struct file *fp;
3191         int error;
3192         int lookupflags;
3193
3194         if (uap->atflags & ~AT_SYMLINK_NOFOLLOW)
3195                 return (EINVAL);
3196
3197         lookupflags = (uap->atflags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW;
3198
3199         vp = NULL;
3200         error = nlookup_init_at(&nd, &fp, uap->fd,  uap->path, UIO_USERSPACE, lookupflags);
3201         if (error == 0)
3202                 error = nlookup(&nd);
3203         if (error == 0)
3204                 error = ncp_writechk(&nd.nl_nch);
3205         if (error == 0)
3206                 error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
3207         nlookup_done_at(&nd, fp);
3208         if (error == 0) {
3209                 error = setfflags(vp, uap->flags);
3210                 vrele(vp);
3211         }
3212         return (error);
3213 }
3214
3215
3216 static int
3217 setfmode(struct vnode *vp, int mode)
3218 {
3219         struct thread *td = curthread;
3220         int error;
3221         struct vattr vattr;
3222
3223         /*
3224          * note: vget is required for any operation that might mod the vnode
3225          * so VINACTIVE is properly cleared.
3226          */
3227         if ((error = vget(vp, LK_EXCLUSIVE)) == 0) {
3228                 VATTR_NULL(&vattr);
3229                 vattr.va_mode = mode & ALLPERMS;
3230                 error = VOP_SETATTR(vp, &vattr, td->td_ucred);
3231                 cache_inval_wxok(vp);
3232                 vput(vp);
3233         }
3234         return error;
3235 }
3236
3237 int
3238 kern_chmod(struct nlookupdata *nd, int mode)
3239 {
3240         struct vnode *vp;
3241         int error;
3242
3243         if ((error = nlookup(nd)) != 0)
3244                 return (error);
3245         if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
3246                 return (error);
3247         if ((error = ncp_writechk(&nd->nl_nch)) == 0)
3248                 error = setfmode(vp, mode);
3249         vrele(vp);
3250         return (error);
3251 }
3252
3253 /*
3254  * chmod_args(char *path, int mode)
3255  *
3256  * Change mode of a file given path name.
3257  */
3258 int
3259 sys_chmod(struct chmod_args *uap)
3260 {
3261         struct nlookupdata nd;
3262         int error;
3263
3264         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
3265         if (error == 0)
3266                 error = kern_chmod(&nd, uap->mode);
3267         nlookup_done(&nd);
3268         return (error);
3269 }
3270
3271 /*
3272  * lchmod_args(char *path, int mode)
3273  *
3274  * Change mode of a file given path name (don't follow links.)
3275  */
3276 int
3277 sys_lchmod(struct lchmod_args *uap)
3278 {
3279         struct nlookupdata nd;
3280         int error;
3281
3282         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
3283         if (error == 0)
3284                 error = kern_chmod(&nd, uap->mode);
3285         nlookup_done(&nd);
3286         return (error);
3287 }
3288
3289 /*
3290  * fchmod_args(int fd, int mode)
3291  *
3292  * Change mode of a file given a file descriptor.
3293  */
3294 int
3295 sys_fchmod(struct fchmod_args *uap)
3296 {
3297         struct thread *td = curthread;
3298         struct proc *p = td->td_proc;
3299         struct file *fp;
3300         int error;
3301
3302         if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
3303                 return (error);
3304         if (fp->f_nchandle.ncp)
3305                 error = ncp_writechk(&fp->f_nchandle);
3306         if (error == 0)
3307                 error = setfmode((struct vnode *)fp->f_data, uap->mode);
3308         fdrop(fp);
3309         return (error);
3310 }
3311
3312 /*
3313  * fchmodat_args(char *path, int mode)
3314  *
3315  * Change mode of a file pointed to by fd/path.
3316  */
3317 int
3318 sys_fchmodat(struct fchmodat_args *uap)
3319 {
3320         struct nlookupdata nd;
3321         struct file *fp;
3322         int error;
3323         int flags;
3324
3325         if (uap->flags & ~AT_SYMLINK_NOFOLLOW)
3326                 return (EINVAL);
3327         flags = (uap->flags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW;
3328
3329         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, 
3330                                 UIO_USERSPACE, flags);
3331         if (error == 0)
3332                 error = kern_chmod(&nd, uap->mode);
3333         nlookup_done_at(&nd, fp);
3334         return (error);
3335 }
3336
3337 static int
3338 setfown(struct mount *mp, struct vnode *vp, uid_t uid, gid_t gid)
3339 {
3340         struct thread *td = curthread;
3341         int error;
3342         struct vattr vattr;
3343         uid_t o_uid;
3344         gid_t o_gid;
3345         uint64_t size;
3346
3347         /*
3348          * note: vget is required for any operation that might mod the vnode
3349          * so VINACTIVE is properly cleared.
3350          */
3351         if ((error = vget(vp, LK_EXCLUSIVE)) == 0) {
3352                 if ((error = VOP_GETATTR(vp, &vattr)) != 0)
3353                         return error;
3354                 o_uid = vattr.va_uid;
3355                 o_gid = vattr.va_gid;
3356                 size = vattr.va_size;
3357
3358                 VATTR_NULL(&vattr);
3359                 vattr.va_uid = uid;
3360                 vattr.va_gid = gid;
3361                 error = VOP_SETATTR(vp, &vattr, td->td_ucred);
3362                 vput(vp);
3363         }
3364
3365         if (error == 0) {
3366                 if (uid == -1)
3367                         uid = o_uid;
3368                 if (gid == -1)
3369                         gid = o_gid;
3370                 VFS_ACCOUNT(mp, o_uid, o_gid, -size);
3371                 VFS_ACCOUNT(mp,   uid,   gid,  size);
3372         }
3373
3374         return error;
3375 }
3376
3377 int
3378 kern_chown(struct nlookupdata *nd, int uid, int gid)
3379 {
3380         struct vnode *vp;
3381         int error;
3382
3383         if ((error = nlookup(nd)) != 0)
3384                 return (error);
3385         if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
3386                 return (error);
3387         if ((error = ncp_writechk(&nd->nl_nch)) == 0)
3388                 error = setfown(nd->nl_nch.mount, vp, uid, gid);
3389         vrele(vp);
3390         return (error);
3391 }
3392
3393 /*
3394  * chown(char *path, int uid, int gid)
3395  *
3396  * Set ownership given a path name.
3397  */
3398 int
3399 sys_chown(struct chown_args *uap)
3400 {
3401         struct nlookupdata nd;
3402         int error;
3403
3404         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
3405         if (error == 0)
3406                 error = kern_chown(&nd, uap->uid, uap->gid);
3407         nlookup_done(&nd);
3408         return (error);
3409 }
3410
3411 /*
3412  * lchown_args(char *path, int uid, int gid)
3413  *
3414  * Set ownership given a path name, do not cross symlinks.
3415  */
3416 int
3417 sys_lchown(struct lchown_args *uap)
3418 {
3419         struct nlookupdata nd;
3420         int error;
3421
3422         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
3423         if (error == 0)
3424                 error = kern_chown(&nd, uap->uid, uap->gid);
3425         nlookup_done(&nd);
3426         return (error);
3427 }
3428
3429 /*
3430  * fchown_args(int fd, int uid, int gid)
3431  *
3432  * Set ownership given a file descriptor.
3433  */
3434 int
3435 sys_fchown(struct fchown_args *uap)
3436 {
3437         struct thread *td = curthread;
3438         struct proc *p = td->td_proc;
3439         struct file *fp;
3440         int error;
3441
3442         if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
3443                 return (error);
3444         if (fp->f_nchandle.ncp)
3445                 error = ncp_writechk(&fp->f_nchandle);
3446         if (error == 0)
3447                 error = setfown(p->p_fd->fd_ncdir.mount,
3448                         (struct vnode *)fp->f_data, uap->uid, uap->gid);
3449         fdrop(fp);
3450         return (error);
3451 }
3452
3453 /*
3454  * fchownat(int fd, char *path, int uid, int gid, int flags)
3455  *
3456  * Set ownership of file pointed to by fd/path.
3457  */
3458 int
3459 sys_fchownat(struct fchownat_args *uap)
3460 {
3461         struct nlookupdata nd;
3462         struct file *fp;
3463         int error;
3464         int flags;
3465
3466         if (uap->flags & ~AT_SYMLINK_NOFOLLOW)
3467                 return (EINVAL);
3468         flags = (uap->flags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW;
3469
3470         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, 
3471                                 UIO_USERSPACE, flags);
3472         if (error == 0)
3473                 error = kern_chown(&nd, uap->uid, uap->gid);
3474         nlookup_done_at(&nd, fp);
3475         return (error);
3476 }
3477
3478
3479 static int
3480 getutimes(struct timeval *tvp, struct timespec *tsp)
3481 {
3482         struct timeval tv[2];
3483         int error;
3484
3485         if (tvp == NULL) {
3486                 microtime(&tv[0]);
3487                 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
3488                 tsp[1] = tsp[0];
3489         } else {
3490                 if ((error = itimerfix(tvp)) != 0)
3491                         return (error);
3492                 TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]);
3493                 TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]);
3494         }
3495         return 0;
3496 }
3497
3498 static int
3499 getutimens(const struct timespec *ts, struct timespec *newts, int *nullflag)
3500 {
3501         struct timespec tsnow;
3502         int error;
3503
3504         *nullflag = 0;
3505         nanotime(&tsnow);
3506         if (ts == NULL) {
3507                 newts[0] = tsnow;
3508                 newts[1] = tsnow;
3509                 *nullflag = 1;
3510                 return (0);
3511         }
3512
3513         newts[0] = ts[0];
3514         newts[1] = ts[1];
3515         if (newts[0].tv_nsec == UTIME_OMIT && newts[1].tv_nsec == UTIME_OMIT)
3516                 return (0);
3517         if (newts[0].tv_nsec == UTIME_NOW && newts[1].tv_nsec == UTIME_NOW)
3518                 *nullflag = 1;
3519
3520         if (newts[0].tv_nsec == UTIME_OMIT)
3521                 newts[0].tv_sec = VNOVAL;
3522         else if (newts[0].tv_nsec == UTIME_NOW)
3523                 newts[0] = tsnow;
3524         else if ((error = itimespecfix(&newts[0])) != 0)
3525                 return (error);
3526
3527         if (newts[1].tv_nsec == UTIME_OMIT)
3528                 newts[1].tv_sec = VNOVAL;
3529         else if (newts[1].tv_nsec == UTIME_NOW)
3530                 newts[1] = tsnow;
3531         else if ((error = itimespecfix(&newts[1])) != 0)
3532                 return (error);
3533
3534         return (0);
3535 }
3536
3537 static int
3538 setutimes(struct vnode *vp, struct vattr *vattr,
3539           const struct timespec *ts, int nullflag)
3540 {
3541         struct thread *td = curthread;
3542         int error;
3543
3544         VATTR_NULL(vattr);
3545         vattr->va_atime = ts[0];
3546         vattr->va_mtime = ts[1];
3547         if (nullflag)
3548                 vattr->va_vaflags |= VA_UTIMES_NULL;
3549         error = VOP_SETATTR(vp, vattr, td->td_ucred);
3550
3551         return error;
3552 }
3553
3554 int
3555 kern_utimes(struct nlookupdata *nd, struct timeval *tptr)
3556 {
3557         struct timespec ts[2];
3558         int error;
3559
3560         if (tptr) {
3561                 if ((error = getutimes(tptr, ts)) != 0)
3562                         return (error);
3563         }
3564         error = kern_utimensat(nd, tptr ? ts : NULL, 0);
3565         return (error);
3566 }
3567
3568 /*
3569  * utimes_args(char *path, struct timeval *tptr)
3570  *
3571  * Set the access and modification times of a file.
3572  */
3573 int
3574 sys_utimes(struct utimes_args *uap)
3575 {
3576         struct timeval tv[2];
3577         struct nlookupdata nd;
3578         int error;
3579
3580         if (uap->tptr) {
3581                 error = copyin(uap->tptr, tv, sizeof(tv));
3582                 if (error)
3583                         return (error);
3584         }
3585         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
3586         if (error == 0)
3587                 error = kern_utimes(&nd, uap->tptr ? tv : NULL);
3588         nlookup_done(&nd);
3589         return (error);
3590 }
3591
3592 /*
3593  * lutimes_args(char *path, struct timeval *tptr)
3594  *
3595  * Set the access and modification times of a file.
3596  */
3597 int
3598 sys_lutimes(struct lutimes_args *uap)
3599 {
3600         struct timeval tv[2];
3601         struct nlookupdata nd;
3602         int error;
3603
3604         if (uap->tptr) {
3605                 error = copyin(uap->tptr, tv, sizeof(tv));
3606                 if (error)
3607                         return (error);
3608         }
3609         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
3610         if (error == 0)
3611                 error = kern_utimes(&nd, uap->tptr ? tv : NULL);
3612         nlookup_done(&nd);
3613         return (error);
3614 }
3615
3616 /*
3617  * Set utimes on a file descriptor.  The creds used to open the
3618  * file are used to determine whether the operation is allowed
3619  * or not.
3620  */
3621 int
3622 kern_futimens(int fd, struct timespec *ts)
3623 {
3624         struct thread *td = curthread;
3625         struct proc *p = td->td_proc;
3626         struct timespec newts[2];
3627         struct file *fp;
3628         struct vnode *vp;
3629         struct vattr vattr;
3630         int nullflag;
3631         int error;
3632
3633         error = getutimens(ts, newts, &nullflag);
3634         if (error)
3635                 return (error);
3636         if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
3637                 return (error);
3638         if (fp->f_nchandle.ncp)
3639                 error = ncp_writechk(&fp->f_nchandle);
3640         if (error == 0) {
3641                 vp = fp->f_data;
3642                 error = vget(vp, LK_EXCLUSIVE);
3643                 if (error == 0) {
3644                         error = VOP_GETATTR(vp, &vattr);
3645                         if (error == 0) {
3646                                 error = naccess_va(&vattr, NLC_OWN | NLC_WRITE,
3647                                                    fp->f_cred);
3648                         }
3649                         if (error == 0) {
3650                                 error = setutimes(vp, &vattr, newts, nullflag);
3651                         }
3652                         vput(vp);
3653                 }
3654         }
3655         fdrop(fp);
3656         return (error);
3657 }
3658
3659 /*
3660  * futimens_args(int fd, struct timespec *ts)
3661  *
3662  * Set the access and modification times of a file.
3663  */
3664 int
3665 sys_futimens(struct futimens_args *uap)
3666 {
3667         struct timespec ts[2];
3668         int error;
3669
3670         if (uap->ts) {
3671                 error = copyin(uap->ts, ts, sizeof(ts));
3672                 if (error)
3673                         return (error);
3674         }
3675         error = kern_futimens(uap->fd, uap->ts ? ts : NULL);
3676         return (error);
3677 }
3678
3679 int
3680 kern_futimes(int fd, struct timeval *tptr)
3681 {
3682         struct timespec ts[2];
3683         int error;
3684
3685         if (tptr) {
3686                 if ((error = getutimes(tptr, ts)) != 0)
3687                         return (error);
3688         }
3689         error = kern_futimens(fd, tptr ? ts : NULL);
3690         return (error);
3691 }
3692
3693 /*
3694  * futimes_args(int fd, struct timeval *tptr)
3695  *
3696  * Set the access and modification times of a file.
3697  */
3698 int
3699 sys_futimes(struct futimes_args *uap)
3700 {
3701         struct timeval tv[2];
3702         int error;
3703
3704         if (uap->tptr) {
3705                 error = copyin(uap->tptr, tv, sizeof(tv));
3706                 if (error)
3707                         return (error);
3708         }
3709         error = kern_futimes(uap->fd, uap->tptr ? tv : NULL);
3710         return (error);
3711 }
3712
3713 int
3714 kern_utimensat(struct nlookupdata *nd, const struct timespec *ts, int flags)
3715 {
3716         struct timespec newts[2];
3717         struct vnode *vp;
3718         struct vattr vattr;
3719         int nullflag;
3720         int error;
3721
3722         if (flags & ~AT_SYMLINK_NOFOLLOW)
3723                 return (EINVAL);
3724
3725         error = getutimens(ts, newts, &nullflag);
3726         if (error)
3727                 return (error);
3728
3729         nd->nl_flags |= NLC_OWN | NLC_WRITE;
3730         if ((error = nlookup(nd)) != 0)
3731                 return (error);
3732         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
3733                 return (error);
3734         if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
3735                 return (error);
3736         if ((error = vn_writechk(vp, &nd->nl_nch)) == 0) {
3737                 error = vget(vp, LK_EXCLUSIVE);
3738                 if (error == 0) {
3739                         error = setutimes(vp, &vattr, newts, nullflag);
3740                         vput(vp);
3741                 }
3742         }
3743         vrele(vp);
3744         return (error);
3745 }
3746
3747 /*
3748  * utimensat_args(int fd, const char *path, const struct timespec *ts, int flags);
3749  *
3750  * Set file access and modification times of a file.
3751  */
3752 int
3753 sys_utimensat(struct utimensat_args *uap)
3754 {
3755         struct timespec ts[2];
3756         struct nlookupdata nd;
3757         struct file *fp;
3758         int error;
3759         int flags;
3760
3761         if (uap->ts) {
3762                 error = copyin(uap->ts, ts, sizeof(ts));
3763                 if (error)
3764                         return (error);
3765         }
3766
3767         flags = (uap->flags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW;
3768         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path,
3769                                 UIO_USERSPACE, flags);
3770         if (error == 0)
3771                 error = kern_utimensat(&nd, uap->ts ? ts : NULL, uap->flags);
3772         nlookup_done_at(&nd, fp);
3773         return (error);
3774 }
3775
3776 int
3777 kern_truncate(struct nlookupdata *nd, off_t length)
3778 {
3779         struct vnode *vp;
3780         struct vattr vattr;
3781         int error;
3782         uid_t uid = 0;
3783         gid_t gid = 0;
3784         uint64_t old_size = 0;
3785
3786         if (length < 0)
3787                 return(EINVAL);
3788         nd->nl_flags |= NLC_WRITE | NLC_TRUNCATE;
3789         if ((error = nlookup(nd)) != 0)
3790                 return (error);
3791         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
3792                 return (error);
3793         if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
3794                 return (error);
3795         error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_FAILRECLAIM);
3796         if (error) {
3797                 vrele(vp);
3798                 return (error);
3799         }
3800         if (vp->v_type == VDIR) {
3801                 error = EISDIR;
3802                 goto done;
3803         }
3804         if (vfs_quota_enabled) {
3805                 error = VOP_GETATTR(vp, &vattr);
3806                 KASSERT(error == 0, ("kern_truncate(): VOP_GETATTR didn't return 0"));
3807                 uid = vattr.va_uid;
3808                 gid = vattr.va_gid;
3809                 old_size = vattr.va_size;
3810         }
3811
3812         if ((error = vn_writechk(vp, &nd->nl_nch)) == 0) {
3813                 VATTR_NULL(&vattr);
3814                 vattr.va_size = length;
3815                 error = VOP_SETATTR(vp, &vattr, nd->nl_cred);
3816                 VFS_ACCOUNT(nd->nl_nch.mount, uid, gid, length - old_size);
3817         }
3818 done:
3819         vput(vp);
3820         return (error);
3821 }
3822
3823 /*
3824  * truncate(char *path, int pad, off_t length)
3825  *
3826  * Truncate a file given its path name.
3827  */
3828 int
3829 sys_truncate(struct truncate_args *uap)
3830 {
3831         struct nlookupdata nd;
3832         int error;
3833
3834         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
3835         if (error == 0)
3836                 error = kern_truncate(&nd, uap->length);
3837         nlookup_done(&nd);
3838         return error;
3839 }
3840
3841 int
3842 kern_ftruncate(int fd, off_t length)
3843 {
3844         struct thread *td = curthread;
3845         struct proc *p = td->td_proc;
3846         struct vattr vattr;
3847         struct vnode *vp;
3848         struct file *fp;
3849         int error;
3850         uid_t uid = 0;
3851         gid_t gid = 0;
3852         uint64_t old_size = 0;
3853         struct mount *mp;
3854
3855         if (length < 0)
3856                 return(EINVAL);
3857         if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
3858                 return (error);
3859         if (fp->f_nchandle.ncp) {
3860                 error = ncp_writechk(&fp->f_nchandle);
3861                 if (error)
3862                         goto done;
3863         }
3864         if ((fp->f_flag & FWRITE) == 0) {
3865                 error = EINVAL;
3866                 goto done;
3867         }
3868         if (fp->f_flag & FAPPENDONLY) { /* inode was set s/uapnd */
3869                 error = EINVAL;
3870                 goto done;
3871         }
3872         vp = (struct vnode *)fp->f_data;
3873         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3874         if (vp->v_type == VDIR) {
3875                 error = EISDIR;
3876                 vn_unlock(vp);
3877                 goto done;
3878         }
3879
3880         if (vfs_quota_enabled) {
3881                 error = VOP_GETATTR(vp, &vattr);
3882                 KASSERT(error == 0, ("kern_ftruncate(): VOP_GETATTR didn't return 0"));
3883                 uid = vattr.va_uid;
3884                 gid = vattr.va_gid;
3885                 old_size = vattr.va_size;
3886         }
3887
3888         if ((error = vn_writechk(vp, NULL)) == 0) {
3889                 VATTR_NULL(&vattr);
3890                 vattr.va_size = length;
3891                 error = VOP_SETATTR(vp, &vattr, fp->f_cred);
3892                 mp = vq_vptomp(vp);
3893                 VFS_ACCOUNT(mp, uid, gid, length - old_size);
3894         }
3895         vn_unlock(vp);
3896 done:
3897         fdrop(fp);
3898         return (error);
3899 }
3900
3901 /*
3902  * ftruncate_args(int fd, int pad, off_t length)
3903  *
3904  * Truncate a file given a file descriptor.
3905  */
3906 int
3907 sys_ftruncate(struct ftruncate_args *uap)
3908 {
3909         int error;
3910
3911         error = kern_ftruncate(uap->fd, uap->length);
3912
3913         return (error);
3914 }
3915
3916 /*
3917  * fsync(int fd)
3918  *
3919  * Sync an open file.
3920  */
3921 int
3922 sys_fsync(struct fsync_args *uap)
3923 {
3924         struct thread *td = curthread;
3925         struct proc *p = td->td_proc;
3926         struct vnode *vp;
3927         struct file *fp;
3928         vm_object_t obj;
3929         int error;
3930
3931         if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
3932                 return (error);
3933         vp = (struct vnode *)fp->f_data;
3934         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3935         if ((obj = vp->v_object) != NULL) {
3936                 if (vp->v_mount == NULL ||
3937                     (vp->v_mount->mnt_kern_flag & MNTK_NOMSYNC) == 0) {
3938                         vm_object_page_clean(obj, 0, 0, 0);
3939                 }
3940         }
3941         error = VOP_FSYNC(vp, MNT_WAIT, VOP_FSYNC_SYSCALL);
3942         if (error == 0 && vp->v_mount)
3943                 error = buf_fsync(vp);
3944         vn_unlock(vp);
3945         fdrop(fp);
3946
3947         return (error);
3948 }
3949
3950 int
3951 kern_rename(struct nlookupdata *fromnd, struct nlookupdata *tond)
3952 {
3953         struct nchandle fnchd;
3954         struct nchandle tnchd;
3955         struct namecache *ncp;
3956         struct vnode *fdvp;
3957         struct vnode *tdvp;
3958         struct mount *mp;
3959         int error;
3960         u_int fncp_gen;
3961         u_int tncp_gen;
3962
3963         bwillinode(1);
3964         fromnd->nl_flags |= NLC_REFDVP | NLC_RENAME_SRC;
3965         if ((error = nlookup(fromnd)) != 0)
3966                 return (error);
3967         if ((fnchd.ncp = fromnd->nl_nch.ncp->nc_parent) == NULL)
3968                 return (ENOENT);
3969         fnchd.mount = fromnd->nl_nch.mount;
3970         cache_hold(&fnchd);
3971
3972         /*
3973          * unlock the source nch so we can lookup the target nch without
3974          * deadlocking.  The target may or may not exist so we do not check
3975          * for a target vp like kern_mkdir() and other creation functions do.
3976          *
3977          * The source and target directories are ref'd and rechecked after
3978          * everything is relocked to determine if the source or target file
3979          * has been renamed.
3980          */
3981         KKASSERT(fromnd->nl_flags & NLC_NCPISLOCKED);
3982         fromnd->nl_flags &= ~NLC_NCPISLOCKED;
3983
3984         fncp_gen = fromnd->nl_nch.ncp->nc_generation;
3985
3986         cache_unlock(&fromnd->nl_nch);
3987
3988         tond->nl_flags |= NLC_RENAME_DST | NLC_REFDVP;
3989         if ((error = nlookup(tond)) != 0) {
3990                 cache_drop(&fnchd);
3991                 return (error);
3992         }
3993         tncp_gen = tond->nl_nch.ncp->nc_generation;
3994
3995         if ((tnchd.ncp = tond->nl_nch.ncp->nc_parent) == NULL) {
3996                 cache_drop(&fnchd);
3997                 return (ENOENT);
3998         }
3999         tnchd.mount = tond->nl_nch.mount;
4000         cache_hold(&tnchd);
4001
4002         /*
4003          * If the source and target are the same there is nothing to do
4004          */
4005         if (fromnd->nl_nch.ncp == tond->nl_nch.ncp) {
4006                 cache_drop(&fnchd);
4007                 cache_drop(&tnchd);
4008                 return (0);
4009         }
4010
4011         /*
4012          * Mount points cannot be renamed or overwritten
4013          */
4014         if ((fromnd->nl_nch.ncp->nc_flag | tond->nl_nch.ncp->nc_flag) &
4015             NCF_ISMOUNTPT
4016         ) {
4017                 cache_drop(&fnchd);
4018                 cache_drop(&tnchd);
4019                 return (EINVAL);
4020         }
4021
4022         /*
4023          * Relock the source ncp.  cache_relock() will deal with any
4024          * deadlocks against the already-locked tond and will also
4025          * make sure both are resolved.
4026          *
4027          * NOTE AFTER RELOCKING: The source or target ncp may have become
4028          * invalid while they were unlocked, nc_vp and nc_mount could
4029          * be NULL.
4030          */
4031         cache_relock(&fromnd->nl_nch, fromnd->nl_cred,
4032                      &tond->nl_nch, tond->nl_cred);
4033         fromnd->nl_flags |= NLC_NCPISLOCKED;
4034
4035         /*
4036          * If the namecache generation changed for either fromnd or tond,
4037          * we must retry.
4038          */
4039         if (fromnd->nl_nch.ncp->nc_generation != fncp_gen ||
4040             tond->nl_nch.ncp->nc_generation != tncp_gen) {
4041                 kprintf("kern_rename: retry due to gen on: "
4042                         "\"%s\" -> \"%s\"\n",
4043                         fromnd->nl_nch.ncp->nc_name,
4044                         tond->nl_nch.ncp->nc_name);
4045                 cache_drop(&fnchd);
4046                 cache_drop(&tnchd);
4047                 return (EAGAIN);
4048         }
4049
4050         /*
4051          * If either fromnd or tond are marked destroyed a ripout occured
4052          * out from under us and we must retry.
4053          */
4054         if ((fromnd->nl_nch.ncp->nc_flag & (NCF_DESTROYED | NCF_UNRESOLVED)) ||
4055             fromnd->nl_nch.ncp->nc_vp == NULL ||
4056             (tond->nl_nch.ncp->nc_flag & NCF_DESTROYED)) {
4057                 kprintf("kern_rename: retry due to ripout on: "
4058                         "\"%s\" -> \"%s\"\n",
4059                         fromnd->nl_nch.ncp->nc_name,
4060                         tond->nl_nch.ncp->nc_name);
4061                 cache_drop(&fnchd);
4062                 cache_drop(&tnchd);
4063                 return (EAGAIN);
4064         }
4065
4066         /*
4067          * Make sure the parent directories linkages are the same.
4068          * XXX shouldn't be needed any more w/ generation check above.
4069          */
4070         if (fnchd.ncp != fromnd->nl_nch.ncp->nc_parent ||
4071             tnchd.ncp != tond->nl_nch.ncp->nc_parent) {
4072                 cache_drop(&fnchd);
4073                 cache_drop(&tnchd);
4074                 return (ENOENT);
4075         }
4076
4077         /*
4078          * Both the source and target must be within the same filesystem and
4079          * in the same filesystem as their parent directories within the
4080          * namecache topology.
4081          *
4082          * NOTE: fromnd's nc_mount or nc_vp could be NULL.
4083          */
4084         mp = fnchd.mount;
4085         if (mp != tnchd.mount || mp != fromnd->nl_nch.mount ||
4086             mp != tond->nl_nch.mount) {
4087                 cache_drop(&fnchd);
4088                 cache_drop(&tnchd);
4089                 return (EXDEV);
4090         }
4091
4092         /*
4093          * Make sure the mount point is writable
4094          */
4095         if ((error = ncp_writechk(&tond->nl_nch)) != 0) {
4096                 cache_drop(&fnchd);
4097                 cache_drop(&tnchd);
4098                 return (error);
4099         }
4100
4101         /*
4102          * If the target exists and either the source or target is a directory,
4103          * then both must be directories.
4104          *
4105          * Due to relocking of the source, fromnd->nl_nch.ncp->nc_vp might h
4106          * have become NULL.
4107          */
4108         if (tond->nl_nch.ncp->nc_vp) {
4109                 if (fromnd->nl_nch.ncp->nc_vp == NULL) {
4110                         error = ENOENT;
4111                 } else if (fromnd->nl_nch.ncp->nc_vp->v_type == VDIR) {
4112                         if (tond->nl_nch.ncp->nc_vp->v_type != VDIR)
4113                                 error = ENOTDIR;
4114                 } else if (tond->nl_nch.ncp->nc_vp->v_type == VDIR) {
4115                         error = EISDIR;
4116                 }
4117         }
4118
4119         /*
4120          * You cannot rename a source into itself or a subdirectory of itself.
4121          * We check this by travsersing the target directory upwards looking
4122          * for a match against the source.
4123          *
4124          * XXX MPSAFE
4125          */
4126         if (error == 0) {
4127                 for (ncp = tnchd.ncp; ncp; ncp = ncp->nc_parent) {
4128                         if (fromnd->nl_nch.ncp == ncp) {
4129                                 error = EINVAL;
4130                                 break;
4131                         }
4132                 }
4133         }
4134
4135         cache_drop(&fnchd);
4136         cache_drop(&tnchd);
4137
4138         /*
4139          * Even though the namespaces are different, they may still represent
4140          * hardlinks to the same file.  The filesystem might have a hard time
4141          * with this so we issue a NREMOVE of the source instead of a NRENAME
4142          * when we detect the situation.
4143          */
4144         if (error == 0) {
4145                 fdvp = fromnd->nl_dvp;
4146                 tdvp = tond->nl_dvp;
4147                 if (fdvp == NULL || tdvp == NULL) {
4148                         error = EPERM;
4149                 } else if (fromnd->nl_nch.ncp->nc_vp == tond->nl_nch.ncp->nc_vp) {
4150                         error = VOP_NREMOVE(&fromnd->nl_nch, fdvp,
4151                                             fromnd->nl_cred);
4152                 } else {
4153                         error = VOP_NRENAME(&fromnd->nl_nch, &tond->nl_nch, 
4154                                             fdvp, tdvp, tond->nl_cred);
4155                 }
4156         }
4157         return (error);
4158 }
4159
4160 /*
4161  * rename_args(char *from, char *to)
4162  *
4163  * Rename files.  Source and destination must either both be directories,
4164  * or both not be directories.  If target is a directory, it must be empty.
4165  */
4166 int
4167 sys_rename(struct rename_args *uap)
4168 {
4169         struct nlookupdata fromnd, tond;
4170         int error;
4171
4172         do {
4173                 error = nlookup_init(&fromnd, uap->from, UIO_USERSPACE, 0);
4174                 if (error == 0) {
4175                         error = nlookup_init(&tond, uap->to, UIO_USERSPACE, 0);
4176                         if (error == 0)
4177                                 error = kern_rename(&fromnd, &tond);
4178                         nlookup_done(&tond);
4179                 }
4180                 nlookup_done(&fromnd);
4181         } while (error == EAGAIN);
4182         return (error);
4183 }
4184
4185 /*
4186  * renameat_args(int oldfd, char *old, int newfd, char *new)
4187  *
4188  * Rename files using paths relative to the directories associated with
4189  * oldfd and newfd.  Source and destination must either both be directories,
4190  * or both not be directories.  If target is a directory, it must be empty.
4191  */
4192 int
4193 sys_renameat(struct renameat_args *uap)
4194 {
4195         struct nlookupdata oldnd, newnd;
4196         struct file *oldfp, *newfp;
4197         int error;
4198
4199         do {
4200                 error = nlookup_init_at(&oldnd, &oldfp,
4201                                         uap->oldfd, uap->old,
4202                                         UIO_USERSPACE, 0);
4203                 if (error == 0) {
4204                         error = nlookup_init_at(&newnd, &newfp,
4205                                                 uap->newfd, uap->new,
4206                                                 UIO_USERSPACE, 0);
4207                         if (error == 0)
4208                                 error = kern_rename(&oldnd, &newnd);
4209                         nlookup_done_at(&newnd, newfp);
4210                 }
4211                 nlookup_done_at(&oldnd, oldfp);
4212         } while (error == EAGAIN);
4213         return (error);
4214 }
4215
4216 int
4217 kern_mkdir(struct nlookupdata *nd, int mode)
4218 {
4219         struct thread *td = curthread;
4220         struct proc *p = td->td_proc;
4221         struct vnode *vp;
4222         struct vattr vattr;
4223         int error;
4224
4225         bwillinode(1);
4226         nd->nl_flags |= NLC_WILLBEDIR | NLC_CREATE | NLC_REFDVP;
4227         if ((error = nlookup(nd)) != 0)
4228                 return (error);
4229
4230         if (nd->nl_nch.ncp->nc_vp)
4231                 return (EEXIST);
4232         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
4233                 return (error);
4234         VATTR_NULL(&vattr);
4235         vattr.va_type = VDIR;
4236         vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
4237
4238         vp = NULL;
4239         error = VOP_NMKDIR(&nd->nl_nch, nd->nl_dvp, &vp, td->td_ucred, &vattr);
4240         if (error == 0)
4241                 vput(vp);
4242         return (error);
4243 }
4244
4245 /*
4246  * mkdir_args(char *path, int mode)
4247  *
4248  * Make a directory file.
4249  */
4250 int
4251 sys_mkdir(struct mkdir_args *uap)
4252 {
4253         struct nlookupdata nd;
4254         int error;
4255
4256         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
4257         if (error == 0)
4258                 error = kern_mkdir(&nd, uap->mode);
4259         nlookup_done(&nd);
4260         return (error);
4261 }
4262
4263 /*
4264  * mkdirat_args(int fd, char *path, mode_t mode)
4265  *
4266  * Make a directory file.  The path is relative to the directory associated
4267  * with fd.
4268  */
4269 int
4270 sys_mkdirat(struct mkdirat_args *uap)
4271 {
4272         struct nlookupdata nd;
4273         struct file *fp;
4274         int error;
4275
4276         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0);
4277         if (error == 0)
4278                 error = kern_mkdir(&nd, uap->mode);
4279         nlookup_done_at(&nd, fp);
4280         return (error);
4281 }
4282
4283 int
4284 kern_rmdir(struct nlookupdata *nd)
4285 {
4286         int error;
4287
4288         bwillinode(1);
4289         nd->nl_flags |= NLC_DELETE | NLC_REFDVP;
4290         if ((error = nlookup(nd)) != 0)
4291                 return (error);
4292
4293         /*
4294          * Do not allow directories representing mount points to be
4295          * deleted, even if empty.  Check write perms on mount point
4296          * in case the vnode is aliased (aka nullfs).
4297          */
4298         if (nd->nl_nch.ncp->nc_flag & (NCF_ISMOUNTPT))
4299                 return (EBUSY);
4300         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
4301                 return (error);
4302         error = VOP_NRMDIR(&nd->nl_nch, nd->nl_dvp, nd->nl_cred);
4303         return (error);
4304 }
4305
4306 /*
4307  * rmdir_args(char *path)
4308  *
4309  * Remove a directory file.
4310  */
4311 int
4312 sys_rmdir(struct rmdir_args *uap)
4313 {
4314         struct nlookupdata nd;
4315         int error;
4316
4317         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
4318         if (error == 0)
4319                 error = kern_rmdir(&nd);
4320         nlookup_done(&nd);
4321         return (error);
4322 }
4323
4324 int
4325 kern_getdirentries(int fd, char *buf, u_int count, long *basep, int *res,
4326                    enum uio_seg direction)
4327 {
4328         struct thread *td = curthread;
4329         struct proc *p = td->td_proc;
4330         struct vnode *vp;
4331         struct file *fp;
4332         struct uio auio;
4333         struct iovec aiov;
4334         off_t loff;
4335         int error, eofflag;
4336
4337         if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
4338                 return (error);
4339         if ((fp->f_flag & FREAD) == 0) {
4340                 error = EBADF;
4341                 goto done;
4342         }
4343         vp = (struct vnode *)fp->f_data;
4344         if (vp->v_type != VDIR) {
4345                 error = EINVAL;
4346                 goto done;
4347         }
4348         aiov.iov_base = buf;
4349         aiov.iov_len = count;
4350         auio.uio_iov = &aiov;
4351         auio.uio_iovcnt = 1;
4352         auio.uio_rw = UIO_READ;
4353         auio.uio_segflg = direction;
4354         auio.uio_td = td;
4355         auio.uio_resid = count;
4356         loff = auio.uio_offset = fp->f_offset;
4357         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
4358         fp->f_offset = auio.uio_offset;
4359         if (error)
4360                 goto done;
4361
4362         /*
4363          * WARNING!  *basep may not be wide enough to accomodate the
4364          * seek offset.   XXX should we hack this to return the upper 32 bits
4365          * for offsets greater then 4G?
4366          */
4367         if (basep) {
4368                 *basep = (long)loff;
4369         }
4370         *res = count - auio.uio_resid;
4371 done:
4372         fdrop(fp);
4373         return (error);
4374 }
4375
4376 /*
4377  * getdirentries_args(int fd, char *buf, u_int conut, long *basep)
4378  *
4379  * Read a block of directory entries in a file system independent format.
4380  */
4381 int
4382 sys_getdirentries(struct getdirentries_args *uap)
4383 {
4384         long base;
4385         int error;
4386
4387         error = kern_getdirentries(uap->fd, uap->buf, uap->count, &base,
4388                                    &uap->sysmsg_result, UIO_USERSPACE);
4389
4390         if (error == 0 && uap->basep)
4391                 error = copyout(&base, uap->basep, sizeof(*uap->basep));
4392         return (error);
4393 }
4394
4395 /*
4396  * getdents_args(int fd, char *buf, size_t count)
4397  */
4398 int
4399 sys_getdents(struct getdents_args *uap)
4400 {
4401         int error;
4402
4403         error = kern_getdirentries(uap->fd, uap->buf, uap->count, NULL,
4404                                    &uap->sysmsg_result, UIO_USERSPACE);
4405
4406         return (error);
4407 }
4408
4409 /*
4410  * Set the mode mask for creation of filesystem nodes.
4411  *
4412  * umask(int newmask)
4413  */
4414 int
4415 sys_umask(struct umask_args *uap)
4416 {
4417         struct thread *td = curthread;
4418         struct proc *p = td->td_proc;
4419         struct filedesc *fdp;
4420
4421         fdp = p->p_fd;
4422         uap->sysmsg_result = fdp->fd_cmask;
4423         fdp->fd_cmask = uap->newmask & ALLPERMS;
4424         return (0);
4425 }
4426
4427 /*
4428  * revoke(char *path)
4429  *
4430  * Void all references to file by ripping underlying filesystem
4431  * away from vnode.
4432  */
4433 int
4434 sys_revoke(struct revoke_args *uap)
4435 {
4436         struct nlookupdata nd;
4437         struct vattr vattr;
4438         struct vnode *vp;
4439         struct ucred *cred;
4440         int error;
4441
4442         vp = NULL;
4443         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
4444         if (error == 0)
4445                 error = nlookup(&nd);
4446         if (error == 0)
4447                 error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
4448         cred = crhold(nd.nl_cred);
4449         nlookup_done(&nd);
4450         if (error == 0) {
4451                 if (error == 0)
4452                         error = VOP_GETATTR(vp, &vattr);
4453                 if (error == 0 && cred->cr_uid != vattr.va_uid)
4454                         error = priv_check_cred(cred, PRIV_VFS_REVOKE, 0);
4455                 if (error == 0 && (vp->v_type == VCHR || vp->v_type == VBLK)) {
4456                         if (vcount(vp) > 0)
4457                                 error = vrevoke(vp, cred);
4458                 } else if (error == 0) {
4459                         error = vrevoke(vp, cred);
4460                 }
4461                 vrele(vp);
4462         }
4463         if (cred)
4464                 crfree(cred);
4465         return (error);
4466 }
4467
4468 /*
4469  * getfh_args(char *fname, fhandle_t *fhp)
4470  *
4471  * Get (NFS) file handle
4472  *
4473  * NOTE: We use the fsid of the covering mount, even if it is a nullfs
4474  * mount.  This allows nullfs mounts to be explicitly exported. 
4475  *
4476  * WARNING: nullfs mounts of HAMMER PFS ROOTs are safe.
4477  *
4478  *          nullfs mounts of subdirectories are not safe.  That is, it will
4479  *          work, but you do not really have protection against access to
4480  *          the related parent directories.
4481  */
4482 int
4483 sys_getfh(struct getfh_args *uap)
4484 {
4485         struct thread *td = curthread;
4486         struct nlookupdata nd;
4487         fhandle_t fh;
4488         struct vnode *vp;
4489         struct mount *mp;
4490         int error;
4491
4492         /*
4493          * Must be super user
4494          */
4495         if ((error = priv_check(td, PRIV_ROOT)) != 0)
4496                 return (error);
4497
4498         vp = NULL;
4499         error = nlookup_init(&nd, uap->fname, UIO_USERSPACE, NLC_FOLLOW);
4500         if (error == 0)
4501                 error = nlookup(&nd);
4502         if (error == 0)
4503                 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
4504         mp = nd.nl_nch.mount;
4505         nlookup_done(&nd);
4506         if (error == 0) {
4507                 bzero(&fh, sizeof(fh));
4508                 fh.fh_fsid = mp->mnt_stat.f_fsid;
4509                 error = VFS_VPTOFH(vp, &fh.fh_fid);
4510                 vput(vp);
4511                 if (error == 0)
4512                         error = copyout(&fh, uap->fhp, sizeof(fh));
4513         }
4514         return (error);
4515 }
4516
4517 /*
4518  * fhopen_args(const struct fhandle *u_fhp, int flags)
4519  *
4520  * syscall for the rpc.lockd to use to translate a NFS file handle into
4521  * an open descriptor.
4522  *
4523  * warning: do not remove the priv_check() call or this becomes one giant
4524  * security hole.
4525  */
4526 int
4527 sys_fhopen(struct fhopen_args *uap)
4528 {
4529         struct thread *td = curthread;
4530         struct filedesc *fdp = td->td_proc->p_fd;
4531         struct mount *mp;
4532         struct vnode *vp;
4533         struct fhandle fhp;
4534         struct vattr vat;
4535         struct vattr *vap = &vat;
4536         struct flock lf;
4537         int fmode, mode, error = 0, type;
4538         struct file *nfp; 
4539         struct file *fp;
4540         int indx;
4541
4542         /*
4543          * Must be super user
4544          */
4545         error = priv_check(td, PRIV_ROOT);
4546         if (error)
4547                 return (error);
4548
4549         fmode = FFLAGS(uap->flags);
4550
4551         /*
4552          * Why not allow a non-read/write open for our lockd?
4553          */
4554         if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
4555                 return (EINVAL);
4556         error = copyin(uap->u_fhp, &fhp, sizeof(fhp));
4557         if (error)
4558                 return(error);
4559
4560         /*
4561          * Find the mount point
4562          */
4563         mp = vfs_getvfs(&fhp.fh_fsid);
4564         if (mp == NULL) {
4565                 error = ESTALE;
4566                 goto  done;
4567         }
4568         /* now give me my vnode, it gets returned to me locked */
4569         error = VFS_FHTOVP(mp, NULL, &fhp.fh_fid, &vp);
4570         if (error)
4571                 goto done;
4572         /*
4573          * from now on we have to make sure not
4574          * to forget about the vnode
4575          * any error that causes an abort must vput(vp) 
4576          * just set error = err and 'goto bad;'.
4577          */
4578
4579         /* 
4580          * from vn_open 
4581          */
4582         if (vp->v_type == VLNK) {
4583                 error = EMLINK;
4584                 goto bad;
4585         }
4586         if (vp->v_type == VSOCK) {
4587                 error = EOPNOTSUPP;
4588                 goto bad;
4589         }
4590         mode = 0;
4591         if (fmode & (FWRITE | O_TRUNC)) {
4592                 if (vp->v_type == VDIR) {
4593                         error = EISDIR;
4594                         goto bad;
4595                 }
4596                 error = vn_writechk(vp, NULL);
4597                 if (error)
4598                         goto bad;
4599                 mode |= VWRITE;
4600         }
4601         if (fmode & FREAD)
4602                 mode |= VREAD;
4603         if (mode) {
4604                 error = VOP_ACCESS(vp, mode, td->td_ucred);
4605                 if (error)
4606                         goto bad;
4607         }
4608         if (fmode & O_TRUNC) {
4609                 vn_unlock(vp);                          /* XXX */
4610                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);   /* XXX */
4611                 VATTR_NULL(vap);
4612                 vap->va_size = 0;
4613                 error = VOP_SETATTR(vp, vap, td->td_ucred);
4614                 if (error)
4615                         goto bad;
4616         }
4617
4618         /*
4619          * VOP_OPEN needs the file pointer so it can potentially override
4620          * it.
4621          *
4622          * WARNING! no f_nchandle will be associated when fhopen()ing a
4623          * directory.  XXX
4624          */
4625         if ((error = falloc(td->td_lwp, &nfp, &indx)) != 0)
4626                 goto bad;
4627         fp = nfp;
4628
4629         error = VOP_OPEN(vp, fmode, td->td_ucred, fp);
4630         if (error) {
4631                 /*
4632                  * setting f_ops this way prevents VOP_CLOSE from being
4633                  * called or fdrop() releasing the vp from v_data.   Since
4634                  * the VOP_OPEN failed we don't want to VOP_CLOSE.
4635                  */
4636                 fp->f_ops = &badfileops;
4637                 fp->f_data = NULL;
4638                 goto bad_drop;
4639         }
4640
4641         /*
4642          * The fp is given its own reference, we still have our ref and lock.
4643          *
4644          * Assert that all regular files must be created with a VM object.
4645          */
4646         if (vp->v_type == VREG && vp->v_object == NULL) {
4647                 kprintf("fhopen: regular file did not have VM object: %p\n", vp);
4648                 goto bad_drop;
4649         }
4650
4651         /*
4652          * The open was successful.  Handle any locking requirements.
4653          */
4654         if (fmode & (O_EXLOCK | O_SHLOCK)) {
4655                 lf.l_whence = SEEK_SET;
4656                 lf.l_start = 0;
4657                 lf.l_len = 0;
4658                 if (fmode & O_EXLOCK)
4659                         lf.l_type = F_WRLCK;
4660                 else
4661                         lf.l_type = F_RDLCK;
4662                 if (fmode & FNONBLOCK)
4663                         type = 0;
4664                 else
4665                         type = F_WAIT;
4666                 vn_unlock(vp);
4667                 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
4668                         /*
4669                          * release our private reference.
4670                          */
4671                         fsetfd(fdp, NULL, indx);
4672                         fdrop(fp);
4673                         vrele(vp);
4674                         goto done;
4675                 }
4676                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
4677                 atomic_set_int(&fp->f_flag, FHASLOCK);  /* race ok */
4678         }
4679
4680         /*
4681          * Clean up.  Associate the file pointer with the previously
4682          * reserved descriptor and return it.
4683          */
4684         vput(vp);
4685         if (uap->flags & O_CLOEXEC)
4686                 fdp->fd_files[indx].fileflags |= UF_EXCLOSE;
4687         fsetfd(fdp, fp, indx);
4688         fdrop(fp);
4689         uap->sysmsg_result = indx;
4690         return (error);
4691
4692 bad_drop:
4693         fsetfd(fdp, NULL, indx);
4694         fdrop(fp);
4695 bad:
4696         vput(vp);
4697 done:
4698         return (error);
4699 }
4700
4701 /*
4702  * fhstat_args(struct fhandle *u_fhp, struct stat *sb)
4703  */
4704 int
4705 sys_fhstat(struct fhstat_args *uap)
4706 {
4707         struct thread *td = curthread;
4708         struct stat sb;
4709         fhandle_t fh;
4710         struct mount *mp;
4711         struct vnode *vp;
4712         int error;
4713
4714         /*
4715          * Must be super user
4716          */
4717         error = priv_check(td, PRIV_ROOT);
4718         if (error)
4719                 return (error);
4720         
4721         error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
4722         if (error)
4723                 return (error);
4724
4725         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
4726                 error = ESTALE;
4727         if (error == 0) {
4728                 if ((error = VFS_FHTOVP(mp, NULL, &fh.fh_fid, &vp)) == 0) {
4729                         error = vn_stat(vp, &sb, td->td_ucred);
4730                         vput(vp);
4731                 }
4732         }
4733         if (error == 0)
4734                 error = copyout(&sb, uap->sb, sizeof(sb));
4735         return (error);
4736 }
4737
4738 /*
4739  * fhstatfs_args(struct fhandle *u_fhp, struct statfs *buf)
4740  */
4741 int
4742 sys_fhstatfs(struct fhstatfs_args *uap)
4743 {
4744         struct thread *td = curthread;
4745         struct proc *p = td->td_proc;
4746         struct statfs *sp;
4747         struct mount *mp;
4748         struct vnode *vp;
4749         struct statfs sb;
4750         char *fullpath, *freepath;
4751         fhandle_t fh;
4752         int error;
4753
4754         /*
4755          * Must be super user
4756          */
4757         if ((error = priv_check(td, PRIV_ROOT)))
4758                 return (error);
4759
4760         if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
4761                 return (error);
4762
4763         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
4764                 error = ESTALE;
4765                 goto done;
4766         }
4767         if (p != NULL && !chroot_visible_mnt(mp, p)) {
4768                 error = ESTALE;
4769                 goto done;
4770         }
4771
4772         if ((error = VFS_FHTOVP(mp, NULL, &fh.fh_fid, &vp)) != 0)
4773                 goto done;
4774         mp = vp->v_mount;
4775         sp = &mp->mnt_stat;
4776         vput(vp);
4777         if ((error = VFS_STATFS(mp, sp, td->td_ucred)) != 0)
4778                 goto done;
4779
4780         error = mount_path(p, mp, &fullpath, &freepath);
4781         if (error)
4782                 goto done;
4783         bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
4784         strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname));
4785         kfree(freepath, M_TEMP);
4786
4787         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
4788         if (priv_check(td, PRIV_ROOT)) {
4789                 bcopy(sp, &sb, sizeof(sb));
4790                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
4791                 sp = &sb;
4792         }
4793         error = copyout(sp, uap->buf, sizeof(*sp));
4794 done:
4795         return (error);
4796 }
4797
4798 /*
4799  * fhstatvfs_args(struct fhandle *u_fhp, struct statvfs *buf)
4800  */
4801 int
4802 sys_fhstatvfs(struct fhstatvfs_args *uap)
4803 {
4804         struct thread *td = curthread;
4805         struct proc *p = td->td_proc;
4806         struct statvfs *sp;
4807         struct mount *mp;
4808         struct vnode *vp;
4809         fhandle_t fh;
4810         int error;
4811
4812         /*
4813          * Must be super user
4814          */
4815         if ((error = priv_check(td, PRIV_ROOT)))
4816                 return (error);
4817
4818         if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
4819                 return (error);
4820
4821         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
4822                 error = ESTALE;
4823                 goto done;
4824         }
4825         if (p != NULL && !chroot_visible_mnt(mp, p)) {
4826                 error = ESTALE;
4827                 goto done;
4828         }
4829
4830         if ((error = VFS_FHTOVP(mp, NULL, &fh.fh_fid, &vp)))
4831                 goto done;
4832         mp = vp->v_mount;
4833         sp = &mp->mnt_vstat;
4834         vput(vp);
4835         if ((error = VFS_STATVFS(mp, sp, td->td_ucred)) != 0)
4836                 goto done;
4837
4838         sp->f_flag = 0;
4839         if (mp->mnt_flag & MNT_RDONLY)
4840                 sp->f_flag |= ST_RDONLY;
4841         if (mp->mnt_flag & MNT_NOSUID)
4842                 sp->f_flag |= ST_NOSUID;
4843         error = copyout(sp, uap->buf, sizeof(*sp));
4844 done:
4845         return (error);
4846 }
4847
4848
4849 /*
4850  * Syscall to push extended attribute configuration information into the
4851  * VFS.  Accepts a path, which it converts to a mountpoint, as well as
4852  * a command (int cmd), and attribute name and misc data.  For now, the
4853  * attribute name is left in userspace for consumption by the VFS_op.
4854  * It will probably be changed to be copied into sysspace by the
4855  * syscall in the future, once issues with various consumers of the
4856  * attribute code have raised their hands.
4857  *
4858  * Currently this is used only by UFS Extended Attributes.
4859  */
4860 int
4861 sys_extattrctl(struct extattrctl_args *uap)
4862 {
4863         struct nlookupdata nd;
4864         struct vnode *vp;
4865         char attrname[EXTATTR_MAXNAMELEN];
4866         int error;
4867         size_t size;
4868
4869         attrname[0] = 0;
4870         vp = NULL;
4871         error = 0;
4872
4873         if (error == 0 && uap->filename) {
4874                 error = nlookup_init(&nd, uap->filename, UIO_USERSPACE,
4875                                      NLC_FOLLOW);
4876                 if (error == 0)
4877                         error = nlookup(&nd);
4878                 if (error == 0)
4879                         error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
4880                 nlookup_done(&nd);
4881         }
4882
4883         if (error == 0 && uap->attrname) {
4884                 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN,
4885                                   &size);
4886         }
4887
4888         if (error == 0) {
4889                 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
4890                 if (error == 0)
4891                         error = nlookup(&nd);
4892                 if (error == 0)
4893                         error = ncp_writechk(&nd.nl_nch);
4894                 if (error == 0) {
4895                         error = VFS_EXTATTRCTL(nd.nl_nch.mount, uap->cmd, vp,
4896                                                uap->attrnamespace,
4897                                                uap->attrname, nd.nl_cred);
4898                 }
4899                 nlookup_done(&nd);
4900         }
4901
4902         return (error);
4903 }
4904
4905 /*
4906  * Syscall to get a named extended attribute on a file or directory.
4907  */
4908 int
4909 sys_extattr_set_file(struct extattr_set_file_args *uap)
4910 {
4911         char attrname[EXTATTR_MAXNAMELEN];
4912         struct nlookupdata nd;
4913         struct vnode *vp;
4914         struct uio auio;
4915         struct iovec aiov;
4916         int error;
4917
4918         error = copyin(uap->attrname, attrname, EXTATTR_MAXNAMELEN);
4919         if (error)
4920                 return (error);
4921
4922         vp = NULL;
4923
4924         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
4925         if (error == 0)
4926                 error = nlookup(&nd);
4927         if (error == 0)
4928                 error = ncp_writechk(&nd.nl_nch);
4929         if (error == 0)
4930                 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
4931         if (error) {
4932                 nlookup_done(&nd);
4933                 return (error);
4934         }
4935
4936         bzero(&auio, sizeof(auio));
4937         aiov.iov_base = uap->data;
4938         aiov.iov_len = uap->nbytes;
4939         auio.uio_iov = &aiov;
4940         auio.uio_iovcnt = 1;
4941         auio.uio_offset = 0;
4942         auio.uio_resid = uap->nbytes;
4943         auio.uio_rw = UIO_WRITE;
4944         auio.uio_td = curthread;
4945
4946         error = VOP_SETEXTATTR(vp, uap->attrnamespace, attrname,
4947                                &auio, nd.nl_cred);
4948
4949         vput(vp);
4950         nlookup_done(&nd);
4951         return (error);
4952 }
4953
4954 /*
4955  * Syscall to get a named extended attribute on a file or directory.
4956  */
4957 int
4958 sys_extattr_get_file(struct extattr_get_file_args *uap)
4959 {
4960         char attrname[EXTATTR_MAXNAMELEN];
4961         struct nlookupdata nd;
4962         struct uio auio;
4963         struct iovec aiov;
4964         struct vnode *vp;
4965         int error;
4966
4967         error = copyin(uap->attrname, attrname, EXTATTR_MAXNAMELEN);
4968         if (error)
4969                 return (error);
4970
4971         vp = NULL;
4972
4973         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
4974         if (error == 0)
4975                 error = nlookup(&nd);
4976         if (error == 0)
4977                 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_SHARED, &vp);
4978         if (error) {
4979                 nlookup_done(&nd);
4980                 return (error);
4981         }
4982
4983         bzero(&auio, sizeof(auio));
4984         aiov.iov_base = uap->data;
4985         aiov.iov_len = uap->nbytes;
4986         auio.uio_iov = &aiov;
4987         auio.uio_iovcnt = 1;
4988         auio.uio_offset = 0;
4989         auio.uio_resid = uap->nbytes;
4990         auio.uio_rw = UIO_READ;
4991         auio.uio_td = curthread;
4992
4993         error = VOP_GETEXTATTR(vp, uap->attrnamespace, attrname,
4994                                 &auio, nd.nl_cred);
4995         uap->sysmsg_result = uap->nbytes - auio.uio_resid;
4996
4997         vput(vp);
4998         nlookup_done(&nd);
4999         return(error);
5000 }
5001
5002 /*
5003  * Syscall to delete a named extended attribute from a file or directory.
5004  * Accepts attribute name.  The real work happens in VOP_SETEXTATTR().
5005  */
5006 int
5007 sys_extattr_delete_file(struct extattr_delete_file_args *uap)
5008 {
5009         char attrname[EXTATTR_MAXNAMELEN];
5010         struct nlookupdata nd;
5011         struct vnode *vp;
5012         int error;
5013
5014         error = copyin(uap->attrname, attrname, EXTATTR_MAXNAMELEN);
5015         if (error)
5016                 return(error);
5017
5018         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
5019         if (error == 0)
5020                 error = nlookup(&nd);
5021         if (error == 0)
5022                 error = ncp_writechk(&nd.nl_nch);
5023         if (error == 0) {
5024                 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
5025                 if (error == 0) {
5026                         error = VOP_SETEXTATTR(vp, uap->attrnamespace,
5027                                                attrname, NULL, nd.nl_cred);
5028                         vput(vp);
5029                 }
5030         }
5031         nlookup_done(&nd);
5032         return(error);
5033 }
5034
5035 /*
5036  * Determine if the mount is visible to the process.
5037  */
5038 static int
5039 chroot_visible_mnt(struct mount *mp, struct proc *p)
5040 {
5041         struct nchandle nch;
5042
5043         /*
5044          * Traverse from the mount point upwards.  If we hit the process
5045          * root then the mount point is visible to the process.
5046          */
5047         nch = mp->mnt_ncmountpt;
5048         while (nch.ncp) {
5049                 if (nch.mount == p->p_fd->fd_nrdir.mount &&
5050                     nch.ncp == p->p_fd->fd_nrdir.ncp) {
5051                         return(1);
5052                 }
5053                 if (nch.ncp == nch.mount->mnt_ncmountpt.ncp) {
5054                         nch = nch.mount->mnt_ncmounton;
5055                 } else {
5056                         nch.ncp = nch.ncp->nc_parent;
5057                 }
5058         }
5059
5060         /*
5061          * If the mount point is not visible to the process, but the
5062          * process root is in a subdirectory of the mount, return
5063          * TRUE anyway.
5064          */
5065         if (p->p_fd->fd_nrdir.mount == mp)
5066                 return(1);
5067
5068         return(0);
5069 }
5070