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