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