]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/kern/vfs_syscalls.c
This commit was generated by cvs2svn to compensate for changes in r143731,
[FreeBSD/FreeBSD.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  * 4. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *      @(#)vfs_syscalls.c      8.13 (Berkeley) 4/15/94
35  */
36
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
39
40 #include "opt_compat.h"
41 #include "opt_mac.h"
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/bio.h>
46 #include <sys/buf.h>
47 #include <sys/sysent.h>
48 #include <sys/mac.h>
49 #include <sys/malloc.h>
50 #include <sys/mount.h>
51 #include <sys/mutex.h>
52 #include <sys/sysproto.h>
53 #include <sys/namei.h>
54 #include <sys/filedesc.h>
55 #include <sys/kernel.h>
56 #include <sys/fcntl.h>
57 #include <sys/file.h>
58 #include <sys/limits.h>
59 #include <sys/linker.h>
60 #include <sys/stat.h>
61 #include <sys/sx.h>
62 #include <sys/unistd.h>
63 #include <sys/vnode.h>
64 #include <sys/proc.h>
65 #include <sys/dirent.h>
66 #include <sys/extattr.h>
67 #include <sys/jail.h>
68 #include <sys/syscallsubr.h>
69 #include <sys/sysctl.h>
70
71 #include <machine/stdarg.h>
72
73 #include <vm/vm.h>
74 #include <vm/vm_object.h>
75 #include <vm/vm_page.h>
76 #include <vm/uma.h>
77
78 static int chroot_refuse_vdir_fds(struct filedesc *fdp);
79 static int getutimes(const struct timeval *, enum uio_seg, struct timespec *);
80 static int setfown(struct thread *td, struct vnode *, uid_t, gid_t);
81 static int setfmode(struct thread *td, struct vnode *, int);
82 static int setfflags(struct thread *td, struct vnode *, int);
83 static int setutimes(struct thread *td, struct vnode *,
84     const struct timespec *, int, int);
85 static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
86     struct thread *td);
87
88 static int extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
89     size_t nbytes, struct thread *td);
90
91 int (*union_dircheckp)(struct thread *td, struct vnode **, struct file *);
92
93 /*
94  * The module initialization routine for POSIX asynchronous I/O will
95  * set this to the version of AIO that it implements.  (Zero means
96  * that it is not implemented.)  This value is used here by pathconf()
97  * and in kern_descrip.c by fpathconf().
98  */
99 int async_io_version;
100
101 /*
102  * Sync each mounted filesystem.
103  */
104 #ifndef _SYS_SYSPROTO_H_
105 struct sync_args {
106         int     dummy;
107 };
108 #endif
109
110 #ifdef DEBUG
111 static int syncprt = 0;
112 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
113 #endif
114
115 /* ARGSUSED */
116 int
117 sync(td, uap)
118         struct thread *td;
119         struct sync_args *uap;
120 {
121         struct mount *mp, *nmp;
122         int asyncflag;
123
124         mtx_lock(&Giant);
125         mtx_lock(&mountlist_mtx);
126         for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
127                 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
128                         nmp = TAILQ_NEXT(mp, mnt_list);
129                         continue;
130                 }
131                 if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
132                     vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
133                         asyncflag = mp->mnt_flag & MNT_ASYNC;
134                         mp->mnt_flag &= ~MNT_ASYNC;
135                         vfs_msync(mp, MNT_NOWAIT);
136                         VFS_SYNC(mp, MNT_NOWAIT, td);
137                         mp->mnt_flag |= asyncflag;
138                         vn_finished_write(mp);
139                 }
140                 mtx_lock(&mountlist_mtx);
141                 nmp = TAILQ_NEXT(mp, mnt_list);
142                 vfs_unbusy(mp, td);
143         }
144         mtx_unlock(&mountlist_mtx);
145 #if 0
146 /*
147  * XXX don't call vfs_bufstats() yet because that routine
148  * was not imported in the Lite2 merge.
149  */
150 #ifdef DIAGNOSTIC
151         if (syncprt)
152                 vfs_bufstats();
153 #endif /* DIAGNOSTIC */
154 #endif
155         mtx_unlock(&Giant);
156         return (0);
157 }
158
159 /* XXX PRISON: could be per prison flag */
160 static int prison_quotas;
161 #if 0
162 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
163 #endif
164
165 /*
166  * Change filesystem quotas.
167  */
168 #ifndef _SYS_SYSPROTO_H_
169 struct quotactl_args {
170         char *path;
171         int cmd;
172         int uid;
173         caddr_t arg;
174 };
175 #endif
176 int
177 quotactl(td, uap)
178         struct thread *td;
179         register struct quotactl_args /* {
180                 char *path;
181                 int cmd;
182                 int uid;
183                 caddr_t arg;
184         } */ *uap;
185 {
186         struct mount *mp, *vmp;
187         int error;
188         struct nameidata nd;
189
190         if (jailed(td->td_ucred) && !prison_quotas)
191                 return (EPERM);
192         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
193         if ((error = namei(&nd)) != 0)
194                 return (error);
195         NDFREE(&nd, NDF_ONLY_PNBUF);
196         error = vn_start_write(nd.ni_vp, &vmp, V_WAIT | PCATCH);
197         mp = nd.ni_vp->v_mount;
198         vrele(nd.ni_vp);
199         if (error)
200                 return (error);
201         error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, td);
202         vn_finished_write(vmp);
203         return (error);
204 }
205
206 /*
207  * Get filesystem statistics.
208  */
209 #ifndef _SYS_SYSPROTO_H_
210 struct statfs_args {
211         char *path;
212         struct statfs *buf;
213 };
214 #endif
215 int
216 statfs(td, uap)
217         struct thread *td;
218         register struct statfs_args /* {
219                 char *path;
220                 struct statfs *buf;
221         } */ *uap;
222 {
223         struct statfs sf;
224         int error;
225
226         error = kern_statfs(td, uap->path, UIO_USERSPACE, &sf);
227         if (error == 0)
228                 error = copyout(&sf, uap->buf, sizeof(sf));
229         return (error);
230 }
231
232 int
233 kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
234     struct statfs *buf)
235 {
236         struct mount *mp;
237         struct statfs *sp, sb;
238         int error;
239         struct nameidata nd;
240
241         mtx_lock(&Giant);
242         NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
243         if ((error = namei(&nd)) != 0) {
244                 mtx_unlock(&Giant);
245                 return (error);
246         }
247         mp = nd.ni_vp->v_mount;
248         sp = &mp->mnt_stat;
249         NDFREE(&nd, NDF_ONLY_PNBUF);
250         vrele(nd.ni_vp);
251 #ifdef MAC
252         error = mac_check_mount_stat(td->td_ucred, mp);
253         if (error) {
254                 mtx_unlock(&Giant);
255                 return (error);
256         }
257 #endif
258         /*
259          * Set these in case the underlying filesystem fails to do so.
260          */
261         sp->f_version = STATFS_VERSION;
262         sp->f_namemax = NAME_MAX;
263         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
264         error = VFS_STATFS(mp, sp, td);
265         mtx_unlock(&Giant);
266         if (error)
267                 return (error);
268         if (suser(td)) {
269                 bcopy(sp, &sb, sizeof(sb));
270                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
271                 sp = &sb;
272         }
273         *buf = *sp;
274         return (0);
275 }
276
277 /*
278  * Get filesystem statistics.
279  */
280 #ifndef _SYS_SYSPROTO_H_
281 struct fstatfs_args {
282         int fd;
283         struct statfs *buf;
284 };
285 #endif
286 int
287 fstatfs(td, uap)
288         struct thread *td;
289         register struct fstatfs_args /* {
290                 int fd;
291                 struct statfs *buf;
292         } */ *uap;
293 {
294         struct statfs sf;
295         int error;
296
297         error = kern_fstatfs(td, uap->fd, &sf);
298         if (error == 0)
299                 error = copyout(&sf, uap->buf, sizeof(sf));
300         return (error);
301 }
302
303 int
304 kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
305 {
306         struct file *fp;
307         struct mount *mp;
308         struct statfs *sp, sb;
309         int error;
310
311         if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0)
312                 return (error);
313         mtx_lock(&Giant);
314         mp = fp->f_vnode->v_mount;
315         fdrop(fp, td);
316         if (mp == NULL) {
317                 mtx_unlock(&Giant);
318                 return (EBADF);
319         }
320 #ifdef MAC
321         error = mac_check_mount_stat(td->td_ucred, mp);
322         if (error) {
323                 mtx_unlock(&Giant);
324                 return (error);
325         }
326 #endif
327         sp = &mp->mnt_stat;
328         /*
329          * Set these in case the underlying filesystem fails to do so.
330          */
331         sp->f_version = STATFS_VERSION;
332         sp->f_namemax = NAME_MAX;
333         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
334         error = VFS_STATFS(mp, sp, td);
335         mtx_unlock(&Giant);
336         if (error)
337                 return (error);
338         if (suser(td)) {
339                 bcopy(sp, &sb, sizeof(sb));
340                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
341                 sp = &sb;
342         }
343         *buf = *sp;
344         return (0);
345 }
346
347 /*
348  * Get statistics on all filesystems.
349  */
350 #ifndef _SYS_SYSPROTO_H_
351 struct getfsstat_args {
352         struct statfs *buf;
353         long bufsize;
354         int flags;
355 };
356 #endif
357 int
358 getfsstat(td, uap)
359         struct thread *td;
360         register struct getfsstat_args /* {
361                 struct statfs *buf;
362                 long bufsize;
363                 int flags;
364         } */ *uap;
365 {
366         struct mount *mp, *nmp;
367         struct statfs *sp, sb;
368         caddr_t sfsp;
369         long count, maxcount, error;
370
371         maxcount = uap->bufsize / sizeof(struct statfs);
372         sfsp = (caddr_t)uap->buf;
373         count = 0;
374         mtx_lock(&Giant);
375         mtx_lock(&mountlist_mtx);
376         for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
377                 if (!prison_check_mount(td->td_ucred, mp)) {
378                         nmp = TAILQ_NEXT(mp, mnt_list);
379                         continue;
380                 }
381 #ifdef MAC
382                 if (mac_check_mount_stat(td->td_ucred, mp) != 0) {
383                         nmp = TAILQ_NEXT(mp, mnt_list);
384                         continue;
385                 }
386 #endif
387                 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
388                         nmp = TAILQ_NEXT(mp, mnt_list);
389                         continue;
390                 }
391                 if (sfsp && count < maxcount) {
392                         sp = &mp->mnt_stat;
393                         /*
394                          * Set these in case the underlying filesystem
395                          * fails to do so.
396                          */
397                         sp->f_version = STATFS_VERSION;
398                         sp->f_namemax = NAME_MAX;
399                         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
400                         /*
401                          * If MNT_NOWAIT or MNT_LAZY is specified, do not
402                          * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
403                          * overrides MNT_WAIT.
404                          */
405                         if (((uap->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
406                             (uap->flags & MNT_WAIT)) &&
407                             (error = VFS_STATFS(mp, sp, td))) {
408                                 mtx_lock(&mountlist_mtx);
409                                 nmp = TAILQ_NEXT(mp, mnt_list);
410                                 vfs_unbusy(mp, td);
411                                 continue;
412                         }
413                         if (suser(td)) {
414                                 bcopy(sp, &sb, sizeof(sb));
415                                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
416                                 sp = &sb;
417                         }
418                         error = copyout(sp, sfsp, sizeof(*sp));
419                         if (error) {
420                                 vfs_unbusy(mp, td);
421                                 mtx_unlock(&Giant);
422                                 return (error);
423                         }
424                         sfsp += sizeof(*sp);
425                 }
426                 count++;
427                 mtx_lock(&mountlist_mtx);
428                 nmp = TAILQ_NEXT(mp, mnt_list);
429                 vfs_unbusy(mp, td);
430         }
431         mtx_unlock(&mountlist_mtx);
432         mtx_unlock(&Giant);
433         if (sfsp && count > maxcount)
434                 td->td_retval[0] = maxcount;
435         else
436                 td->td_retval[0] = count;
437         return (0);
438 }
439
440 #ifdef COMPAT_FREEBSD4
441 /*
442  * Get old format filesystem statistics.
443  */
444 static void cvtstatfs(struct thread *, struct statfs *, struct ostatfs *);
445
446 #ifndef _SYS_SYSPROTO_H_
447 struct freebsd4_statfs_args {
448         char *path;
449         struct ostatfs *buf;
450 };
451 #endif
452 int
453 freebsd4_statfs(td, uap)
454         struct thread *td;
455         struct freebsd4_statfs_args /* {
456                 char *path;
457                 struct ostatfs *buf;
458         } */ *uap;
459 {
460         struct ostatfs osb;
461         struct statfs sf;
462         int error;
463
464         error = kern_statfs(td, uap->path, UIO_USERSPACE, &sf);
465         if (error)
466                 return (error);
467         cvtstatfs(td, &sf, &osb);
468         return (copyout(&osb, uap->buf, sizeof(osb)));
469 }
470
471 /*
472  * Get filesystem statistics.
473  */
474 #ifndef _SYS_SYSPROTO_H_
475 struct freebsd4_fstatfs_args {
476         int fd;
477         struct ostatfs *buf;
478 };
479 #endif
480 int
481 freebsd4_fstatfs(td, uap)
482         struct thread *td;
483         struct freebsd4_fstatfs_args /* {
484                 int fd;
485                 struct ostatfs *buf;
486         } */ *uap;
487 {
488         struct ostatfs osb;
489         struct statfs sf;
490         int error;
491
492         error = kern_fstatfs(td, uap->fd, &sf);
493         if (error)
494                 return (error);
495         cvtstatfs(td, &sf, &osb);
496         return (copyout(&osb, uap->buf, sizeof(osb)));
497 }
498
499 /*
500  * Get statistics on all filesystems.
501  */
502 #ifndef _SYS_SYSPROTO_H_
503 struct freebsd4_getfsstat_args {
504         struct ostatfs *buf;
505         long bufsize;
506         int flags;
507 };
508 #endif
509 int
510 freebsd4_getfsstat(td, uap)
511         struct thread *td;
512         register struct freebsd4_getfsstat_args /* {
513                 struct ostatfs *buf;
514                 long bufsize;
515                 int flags;
516         } */ *uap;
517 {
518         struct mount *mp, *nmp;
519         struct statfs *sp;
520         struct ostatfs osb;
521         caddr_t sfsp;
522         long count, maxcount, error;
523
524         maxcount = uap->bufsize / sizeof(struct ostatfs);
525         sfsp = (caddr_t)uap->buf;
526         count = 0;
527         mtx_lock(&mountlist_mtx);
528         for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
529                 if (!prison_check_mount(td->td_ucred, mp)) {
530                         nmp = TAILQ_NEXT(mp, mnt_list);
531                         continue;
532                 }
533 #ifdef MAC
534                 if (mac_check_mount_stat(td->td_ucred, mp) != 0) {
535                         nmp = TAILQ_NEXT(mp, mnt_list);
536                         continue;
537                 }
538 #endif
539                 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
540                         nmp = TAILQ_NEXT(mp, mnt_list);
541                         continue;
542                 }
543                 if (sfsp && count < maxcount) {
544                         sp = &mp->mnt_stat;
545                         /*
546                          * If MNT_NOWAIT or MNT_LAZY is specified, do not
547                          * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
548                          * overrides MNT_WAIT.
549                          */
550                         if (((uap->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
551                             (uap->flags & MNT_WAIT)) &&
552                             (error = VFS_STATFS(mp, sp, td))) {
553                                 mtx_lock(&mountlist_mtx);
554                                 nmp = TAILQ_NEXT(mp, mnt_list);
555                                 vfs_unbusy(mp, td);
556                                 continue;
557                         }
558                         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
559                         cvtstatfs(td, sp, &osb);
560                         error = copyout(&osb, sfsp, sizeof(osb));
561                         if (error) {
562                                 vfs_unbusy(mp, td);
563                                 return (error);
564                         }
565                         sfsp += sizeof(osb);
566                 }
567                 count++;
568                 mtx_lock(&mountlist_mtx);
569                 nmp = TAILQ_NEXT(mp, mnt_list);
570                 vfs_unbusy(mp, td);
571         }
572         mtx_unlock(&mountlist_mtx);
573         if (sfsp && count > maxcount)
574                 td->td_retval[0] = maxcount;
575         else
576                 td->td_retval[0] = count;
577         return (0);
578 }
579
580 /*
581  * Implement fstatfs() for (NFS) file handles.
582  */
583 #ifndef _SYS_SYSPROTO_H_
584 struct freebsd4_fhstatfs_args {
585         struct fhandle *u_fhp;
586         struct ostatfs *buf;
587 };
588 #endif
589 int
590 freebsd4_fhstatfs(td, uap)
591         struct thread *td;
592         struct freebsd4_fhstatfs_args /* {
593                 struct fhandle *u_fhp;
594                 struct ostatfs *buf;
595         } */ *uap;
596 {
597         struct ostatfs osb;
598         struct statfs sf;
599         fhandle_t fh;
600         int error;
601
602         if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
603                 return (error);
604         error = kern_fhstatfs(td, fh, &sf);
605         if (error)
606                 return (error);
607         cvtstatfs(td, &sf, &osb);
608         return (copyout(&osb, uap->buf, sizeof(osb)));
609 }
610
611 /*
612  * Convert a new format statfs structure to an old format statfs structure.
613  */
614 static void
615 cvtstatfs(td, nsp, osp)
616         struct thread *td;
617         struct statfs *nsp;
618         struct ostatfs *osp;
619 {
620
621         bzero(osp, sizeof(*osp));
622         osp->f_bsize = MIN(nsp->f_bsize, LONG_MAX);
623         osp->f_iosize = MIN(nsp->f_iosize, LONG_MAX);
624         osp->f_blocks = MIN(nsp->f_blocks, LONG_MAX);
625         osp->f_bfree = MIN(nsp->f_bfree, LONG_MAX);
626         osp->f_bavail = MIN(nsp->f_bavail, LONG_MAX);
627         osp->f_files = MIN(nsp->f_files, LONG_MAX);
628         osp->f_ffree = MIN(nsp->f_ffree, LONG_MAX);
629         osp->f_owner = nsp->f_owner;
630         osp->f_type = nsp->f_type;
631         osp->f_flags = nsp->f_flags;
632         osp->f_syncwrites = MIN(nsp->f_syncwrites, LONG_MAX);
633         osp->f_asyncwrites = MIN(nsp->f_asyncwrites, LONG_MAX);
634         osp->f_syncreads = MIN(nsp->f_syncreads, LONG_MAX);
635         osp->f_asyncreads = MIN(nsp->f_asyncreads, LONG_MAX);
636         bcopy(nsp->f_fstypename, osp->f_fstypename,
637             MIN(MFSNAMELEN, OMNAMELEN));
638         bcopy(nsp->f_mntonname, osp->f_mntonname,
639             MIN(MFSNAMELEN, OMNAMELEN));
640         bcopy(nsp->f_mntfromname, osp->f_mntfromname,
641             MIN(MFSNAMELEN, OMNAMELEN));
642         if (suser(td)) {
643                 osp->f_fsid.val[0] = osp->f_fsid.val[1] = 0;
644         } else {
645                 osp->f_fsid = nsp->f_fsid;
646         }
647 }
648 #endif /* COMPAT_FREEBSD4 */
649
650 /*
651  * Change current working directory to a given file descriptor.
652  */
653 #ifndef _SYS_SYSPROTO_H_
654 struct fchdir_args {
655         int     fd;
656 };
657 #endif
658 int
659 fchdir(td, uap)
660         struct thread *td;
661         struct fchdir_args /* {
662                 int fd;
663         } */ *uap;
664 {
665         register struct filedesc *fdp = td->td_proc->p_fd;
666         struct vnode *vp, *tdp, *vpold;
667         struct mount *mp;
668         struct file *fp;
669         int vfslocked;
670         int error;
671
672         if ((error = getvnode(fdp, uap->fd, &fp)) != 0)
673                 return (error);
674         vp = fp->f_vnode;
675         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
676         VREF(vp);
677         fdrop(fp, td);
678         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
679         if (vp->v_type != VDIR)
680                 error = ENOTDIR;
681 #ifdef MAC
682         else if ((error = mac_check_vnode_chdir(td->td_ucred, vp)) != 0) {
683         }
684 #endif
685         else
686                 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
687         while (!error && (mp = vp->v_mountedhere) != NULL) {
688                 int tvfslocked;
689                 if (vfs_busy(mp, 0, 0, td))
690                         continue;
691                 tvfslocked = VFS_LOCK_GIANT(mp);
692                 error = VFS_ROOT(mp, &tdp, td);
693                 vfs_unbusy(mp, td);
694                 if (error) {
695                         VFS_UNLOCK_GIANT(tvfslocked);
696                         break;
697                 }
698                 vput(vp);
699                 VFS_UNLOCK_GIANT(vfslocked);
700                 vp = tdp;
701                 vfslocked = tvfslocked;
702         }
703         if (error) {
704                 vput(vp);
705                 VFS_UNLOCK_GIANT(vfslocked);
706                 return (error);
707         }
708         VOP_UNLOCK(vp, 0, td);
709         FILEDESC_LOCK_FAST(fdp);
710         vpold = fdp->fd_cdir;
711         fdp->fd_cdir = vp;
712         FILEDESC_UNLOCK_FAST(fdp);
713         vrele(vpold);
714         VFS_UNLOCK_GIANT(vfslocked);
715         return (0);
716 }
717
718 /*
719  * Change current working directory (``.'').
720  */
721 #ifndef _SYS_SYSPROTO_H_
722 struct chdir_args {
723         char    *path;
724 };
725 #endif
726 int
727 chdir(td, uap)
728         struct thread *td;
729         struct chdir_args /* {
730                 char *path;
731         } */ *uap;
732 {
733
734         return (kern_chdir(td, uap->path, UIO_USERSPACE));
735 }
736
737 int
738 kern_chdir(struct thread *td, char *path, enum uio_seg pathseg)
739 {
740         register struct filedesc *fdp = td->td_proc->p_fd;
741         int error;
742         struct nameidata nd;
743         struct vnode *vp;
744         int vfslocked;
745
746         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE, pathseg, path, td);
747         if ((error = namei(&nd)) != 0)
748                 return (error);
749         vfslocked = NDHASGIANT(&nd);
750         if ((error = change_dir(nd.ni_vp, td)) != 0) {
751                 vput(nd.ni_vp);
752                 VFS_UNLOCK_GIANT(vfslocked);
753                 NDFREE(&nd, NDF_ONLY_PNBUF);
754                 return (error);
755         }
756         VOP_UNLOCK(nd.ni_vp, 0, td);
757         NDFREE(&nd, NDF_ONLY_PNBUF);
758         FILEDESC_LOCK_FAST(fdp);
759         vp = fdp->fd_cdir;
760         fdp->fd_cdir = nd.ni_vp;
761         FILEDESC_UNLOCK_FAST(fdp);
762         vrele(vp);
763         VFS_UNLOCK_GIANT(vfslocked);
764         return (0);
765 }
766
767 /*
768  * Helper function for raised chroot(2) security function:  Refuse if
769  * any filedescriptors are open directories.
770  */
771 static int
772 chroot_refuse_vdir_fds(fdp)
773         struct filedesc *fdp;
774 {
775         struct vnode *vp;
776         struct file *fp;
777         int fd;
778
779         FILEDESC_LOCK_ASSERT(fdp, MA_OWNED);
780         for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
781                 fp = fget_locked(fdp, fd);
782                 if (fp == NULL)
783                         continue;
784                 if (fp->f_type == DTYPE_VNODE) {
785                         vp = fp->f_vnode;
786                         if (vp->v_type == VDIR)
787                                 return (EPERM);
788                 }
789         }
790         return (0);
791 }
792
793 /*
794  * This sysctl determines if we will allow a process to chroot(2) if it
795  * has a directory open:
796  *      0: disallowed for all processes.
797  *      1: allowed for processes that were not already chroot(2)'ed.
798  *      2: allowed for all processes.
799  */
800
801 static int chroot_allow_open_directories = 1;
802
803 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
804      &chroot_allow_open_directories, 0, "");
805
806 /*
807  * Change notion of root (``/'') directory.
808  */
809 #ifndef _SYS_SYSPROTO_H_
810 struct chroot_args {
811         char    *path;
812 };
813 #endif
814 int
815 chroot(td, uap)
816         struct thread *td;
817         struct chroot_args /* {
818                 char *path;
819         } */ *uap;
820 {
821         int error;
822         struct nameidata nd;
823         int vfslocked;
824
825         error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
826         if (error)
827                 return (error);
828         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE,
829             UIO_USERSPACE, uap->path, td);
830         error = namei(&nd);
831         if (error)
832                 goto error;
833         vfslocked = NDHASGIANT(&nd);
834         if ((error = change_dir(nd.ni_vp, td)) != 0)
835                 goto e_vunlock;
836 #ifdef MAC
837         if ((error = mac_check_vnode_chroot(td->td_ucred, nd.ni_vp)))
838                 goto e_vunlock;
839 #endif
840         VOP_UNLOCK(nd.ni_vp, 0, td);
841         error = change_root(nd.ni_vp, td);
842         vrele(nd.ni_vp);
843         VFS_UNLOCK_GIANT(vfslocked);
844         NDFREE(&nd, NDF_ONLY_PNBUF);
845         return (error);
846 e_vunlock:
847         vput(nd.ni_vp);
848         VFS_UNLOCK_GIANT(vfslocked);
849 error:
850         NDFREE(&nd, NDF_ONLY_PNBUF);
851         return (error);
852 }
853
854 /*
855  * Common routine for chroot and chdir.  Callers must provide a locked vnode
856  * instance.
857  */
858 int
859 change_dir(vp, td)
860         struct vnode *vp;
861         struct thread *td;
862 {
863         int error;
864
865         ASSERT_VOP_LOCKED(vp, "change_dir(): vp not locked");
866         if (vp->v_type != VDIR)
867                 return (ENOTDIR);
868 #ifdef MAC
869         error = mac_check_vnode_chdir(td->td_ucred, vp);
870         if (error)
871                 return (error);
872 #endif
873         error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
874         return (error);
875 }
876
877 /*
878  * Common routine for kern_chroot() and jail_attach().  The caller is
879  * responsible for invoking suser() and mac_check_chroot() to authorize this
880  * operation.
881  */
882 int
883 change_root(vp, td)
884         struct vnode *vp;
885         struct thread *td;
886 {
887         struct filedesc *fdp;
888         struct vnode *oldvp;
889         int error;
890
891         VFS_ASSERT_GIANT(vp->v_mount);
892         fdp = td->td_proc->p_fd;
893         FILEDESC_LOCK(fdp);
894         if (chroot_allow_open_directories == 0 ||
895             (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
896                 error = chroot_refuse_vdir_fds(fdp);
897                 if (error) {
898                         FILEDESC_UNLOCK(fdp);
899                         return (error);
900                 }
901         }
902         oldvp = fdp->fd_rdir;
903         fdp->fd_rdir = vp;
904         VREF(fdp->fd_rdir);
905         if (!fdp->fd_jdir) {
906                 fdp->fd_jdir = vp;
907                 VREF(fdp->fd_jdir);
908         }
909         FILEDESC_UNLOCK(fdp);
910         vrele(oldvp);
911         return (0);
912 }
913
914 /*
915  * Check permissions, allocate an open file structure,
916  * and call the device open routine if any.
917  *
918  * MP SAFE
919  */
920 #ifndef _SYS_SYSPROTO_H_
921 struct open_args {
922         char    *path;
923         int     flags;
924         int     mode;
925 };
926 #endif
927 int
928 open(td, uap)
929         struct thread *td;
930         register struct open_args /* {
931                 char *path;
932                 int flags;
933                 int mode;
934         } */ *uap;
935 {
936         int error;
937
938         error = kern_open(td, uap->path, UIO_USERSPACE, uap->flags, uap->mode);
939         if (mtx_owned(&Giant))
940                 printf("open: %s: %d\n", uap->path, error);
941         return (error);
942 }
943
944 int
945 kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags,
946     int mode)
947 {
948         struct proc *p = td->td_proc;
949         struct filedesc *fdp = p->p_fd;
950         struct file *fp;
951         struct vnode *vp;
952         struct vattr vat;
953         struct mount *mp;
954         int cmode;
955         struct file *nfp;
956         int type, indx, error;
957         struct flock lf;
958         struct nameidata nd;
959         int vfslocked;
960
961         if ((flags & O_ACCMODE) == O_ACCMODE)
962                 return (EINVAL);
963         flags = FFLAGS(flags);
964         error = falloc(td, &nfp, &indx);
965         if (error)
966                 return (error);
967         /* An extra reference on `nfp' has been held for us by falloc(). */
968         fp = nfp;
969         cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
970         NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
971         td->td_dupfd = -1;              /* XXX check for fdopen */
972         error = vn_open(&nd, &flags, cmode, indx);
973         if (error) {
974                 /*
975                  * If the vn_open replaced the method vector, something
976                  * wonderous happened deep below and we just pass it up
977                  * pretending we know what we do.
978                  */
979                 if (error == ENXIO && fp->f_ops != &badfileops) {
980                         fdrop(fp, td);
981                         td->td_retval[0] = indx;
982                         return (0);
983                 }
984
985                 /*
986                  * release our own reference
987                  */
988                 fdrop(fp, td);
989
990                 /*
991                  * handle special fdopen() case.  bleh.  dupfdopen() is
992                  * responsible for dropping the old contents of ofiles[indx]
993                  * if it succeeds.
994                  */
995                 if ((error == ENODEV || error == ENXIO) &&
996                     td->td_dupfd >= 0 &&                /* XXX from fdopen */
997                     (error =
998                         dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) {
999                         td->td_retval[0] = indx;
1000                         return (0);
1001                 }
1002                 /*
1003                  * Clean up the descriptor, but only if another thread hadn't
1004                  * replaced or closed it.
1005                  */
1006                 fdclose(fdp, fp, indx, td);
1007
1008                 if (error == ERESTART)
1009                         error = EINTR;
1010                 return (error);
1011         }
1012         td->td_dupfd = 0;
1013         vfslocked = NDHASGIANT(&nd);
1014         NDFREE(&nd, NDF_ONLY_PNBUF);
1015         vp = nd.ni_vp;
1016
1017         /*
1018          * There should be 2 references on the file, one from the descriptor
1019          * table, and one for us.
1020          *
1021          * Handle the case where someone closed the file (via its file
1022          * descriptor) while we were blocked.  The end result should look
1023          * like opening the file succeeded but it was immediately closed.
1024          * We call vn_close() manually because we haven't yet hooked up
1025          * the various 'struct file' fields.
1026          */
1027         FILEDESC_LOCK(fdp);
1028         FILE_LOCK(fp);
1029         if (fp->f_count == 1) {
1030                 mp = vp->v_mount;
1031                 KASSERT(fdp->fd_ofiles[indx] != fp,
1032                     ("Open file descriptor lost all refs"));
1033                 FILE_UNLOCK(fp);
1034                 FILEDESC_UNLOCK(fdp);
1035                 VOP_UNLOCK(vp, 0, td);
1036                 vn_close(vp, flags & FMASK, fp->f_cred, td);
1037                 VFS_UNLOCK_GIANT(vfslocked);
1038                 fdrop(fp, td);
1039                 td->td_retval[0] = indx;
1040                 return (0);
1041         }
1042         fp->f_vnode = vp;
1043         if (fp->f_data == NULL)
1044                 fp->f_data = vp;
1045         fp->f_flag = flags & FMASK;
1046         if (fp->f_ops == &badfileops)
1047                 fp->f_ops = &vnops;
1048         fp->f_seqcount = 1;
1049         fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
1050         FILE_UNLOCK(fp);
1051         FILEDESC_UNLOCK(fdp);
1052
1053         VOP_UNLOCK(vp, 0, td);
1054         if (flags & (O_EXLOCK | O_SHLOCK)) {
1055                 lf.l_whence = SEEK_SET;
1056                 lf.l_start = 0;
1057                 lf.l_len = 0;
1058                 if (flags & O_EXLOCK)
1059                         lf.l_type = F_WRLCK;
1060                 else
1061                         lf.l_type = F_RDLCK;
1062                 type = F_FLOCK;
1063                 if ((flags & FNONBLOCK) == 0)
1064                         type |= F_WAIT;
1065                 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
1066                             type)) != 0)
1067                         goto bad;
1068                 fp->f_flag |= FHASLOCK;
1069         }
1070         if (flags & O_TRUNC) {
1071                 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
1072                         goto bad;
1073                 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1074                 VATTR_NULL(&vat);
1075                 vat.va_size = 0;
1076                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1077 #ifdef MAC
1078                 error = mac_check_vnode_write(td->td_ucred, fp->f_cred, vp);
1079                 if (error == 0)
1080 #endif
1081                         error = VOP_SETATTR(vp, &vat, td->td_ucred, td);
1082                 VOP_UNLOCK(vp, 0, td);
1083                 vn_finished_write(mp);
1084                 if (error)
1085                         goto bad;
1086         }
1087         VFS_UNLOCK_GIANT(vfslocked);
1088         /*
1089          * Release our private reference, leaving the one associated with
1090          * the descriptor table intact.
1091          */
1092         fdrop(fp, td);
1093         td->td_retval[0] = indx;
1094         return (0);
1095 bad:
1096         VFS_UNLOCK_GIANT(vfslocked);
1097         fdclose(fdp, fp, indx, td);
1098         fdrop(fp, td);
1099         return (error);
1100 }
1101
1102 #ifdef COMPAT_43
1103 /*
1104  * Create a file.
1105  *
1106  * MP SAFE
1107  */
1108 #ifndef _SYS_SYSPROTO_H_
1109 struct ocreat_args {
1110         char    *path;
1111         int     mode;
1112 };
1113 #endif
1114 int
1115 ocreat(td, uap)
1116         struct thread *td;
1117         register struct ocreat_args /* {
1118                 char *path;
1119                 int mode;
1120         } */ *uap;
1121 {
1122
1123         return (kern_open(td, uap->path, UIO_USERSPACE,
1124             O_WRONLY | O_CREAT | O_TRUNC, uap->mode));
1125 }
1126 #endif /* COMPAT_43 */
1127
1128 /*
1129  * Create a special file.
1130  */
1131 #ifndef _SYS_SYSPROTO_H_
1132 struct mknod_args {
1133         char    *path;
1134         int     mode;
1135         int     dev;
1136 };
1137 #endif
1138 int
1139 mknod(td, uap)
1140         struct thread *td;
1141         register struct mknod_args /* {
1142                 char *path;
1143                 int mode;
1144                 int dev;
1145         } */ *uap;
1146 {
1147
1148         return (kern_mknod(td, uap->path, UIO_USERSPACE, uap->mode, uap->dev));
1149 }
1150
1151 int
1152 kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode,
1153     int dev)
1154 {
1155         struct vnode *vp;
1156         struct mount *mp;
1157         struct vattr vattr;
1158         int error;
1159         int whiteout = 0;
1160         struct nameidata nd;
1161         int vfslocked;
1162
1163         switch (mode & S_IFMT) {
1164         case S_IFCHR:
1165         case S_IFBLK:
1166                 error = suser(td);
1167                 break;
1168         default:
1169                 error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
1170                 break;
1171         }
1172         if (error)
1173                 return (error);
1174 restart:
1175         bwillwrite();
1176         NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE, pathseg, path, td);
1177         if ((error = namei(&nd)) != 0)
1178                 return (error);
1179         vfslocked = NDHASGIANT(&nd);
1180         vp = nd.ni_vp;
1181         if (vp != NULL) {
1182                 NDFREE(&nd, NDF_ONLY_PNBUF);
1183                 vrele(vp);
1184                 if (vp == nd.ni_dvp)
1185                         vrele(nd.ni_dvp);
1186                 else
1187                         vput(nd.ni_dvp);
1188                 VFS_UNLOCK_GIANT(vfslocked);
1189                 return (EEXIST);
1190         } else {
1191                 VATTR_NULL(&vattr);
1192                 FILEDESC_LOCK_FAST(td->td_proc->p_fd);
1193                 vattr.va_mode = (mode & ALLPERMS) &
1194                     ~td->td_proc->p_fd->fd_cmask;
1195                 FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
1196                 vattr.va_rdev = dev;
1197                 whiteout = 0;
1198
1199                 switch (mode & S_IFMT) {
1200                 case S_IFMT:    /* used by badsect to flag bad sectors */
1201                         vattr.va_type = VBAD;
1202                         break;
1203                 case S_IFCHR:
1204                         vattr.va_type = VCHR;
1205                         break;
1206                 case S_IFBLK:
1207                         vattr.va_type = VBLK;
1208                         break;
1209                 case S_IFWHT:
1210                         whiteout = 1;
1211                         break;
1212                 default:
1213                         error = EINVAL;
1214                         break;
1215                 }
1216         }
1217         if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1218                 NDFREE(&nd, NDF_ONLY_PNBUF);
1219                 vput(nd.ni_dvp);
1220                 VFS_UNLOCK_GIANT(vfslocked);
1221                 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1222                         return (error);
1223                 goto restart;
1224         }
1225 #ifdef MAC
1226         if (error == 0 && !whiteout)
1227                 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp,
1228                     &nd.ni_cnd, &vattr);
1229 #endif
1230         if (!error) {
1231                 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1232                 if (whiteout)
1233                         error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
1234                 else {
1235                         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1236                                                 &nd.ni_cnd, &vattr);
1237                         if (error == 0)
1238                                 vput(nd.ni_vp);
1239                 }
1240         }
1241         NDFREE(&nd, NDF_ONLY_PNBUF);
1242         vput(nd.ni_dvp);
1243         vn_finished_write(mp);
1244         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod");
1245         ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod");
1246         VFS_UNLOCK_GIANT(vfslocked);
1247         return (error);
1248 }
1249
1250 /*
1251  * Create a named pipe.
1252  */
1253 #ifndef _SYS_SYSPROTO_H_
1254 struct mkfifo_args {
1255         char    *path;
1256         int     mode;
1257 };
1258 #endif
1259 int
1260 mkfifo(td, uap)
1261         struct thread *td;
1262         register struct mkfifo_args /* {
1263                 char *path;
1264                 int mode;
1265         } */ *uap;
1266 {
1267
1268         return (kern_mkfifo(td, uap->path, UIO_USERSPACE, uap->mode));
1269 }
1270
1271 int
1272 kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode)
1273 {
1274         struct mount *mp;
1275         struct vattr vattr;
1276         int error;
1277         struct nameidata nd;
1278         int vfslocked;
1279
1280 restart:
1281         bwillwrite();
1282         NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE, pathseg, path, td);
1283         if ((error = namei(&nd)) != 0)
1284                 return (error);
1285         vfslocked = NDHASGIANT(&nd);
1286         if (nd.ni_vp != NULL) {
1287                 NDFREE(&nd, NDF_ONLY_PNBUF);
1288                 vrele(nd.ni_vp);
1289                 if (nd.ni_vp == nd.ni_dvp)
1290                         vrele(nd.ni_dvp);
1291                 else
1292                         vput(nd.ni_dvp);
1293                 VFS_UNLOCK_GIANT(vfslocked);
1294                 return (EEXIST);
1295         }
1296         if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1297                 NDFREE(&nd, NDF_ONLY_PNBUF);
1298                 vput(nd.ni_dvp);
1299                 VFS_UNLOCK_GIANT(vfslocked);
1300                 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1301                         return (error);
1302                 goto restart;
1303         }
1304         VATTR_NULL(&vattr);
1305         vattr.va_type = VFIFO;
1306         FILEDESC_LOCK_FAST(td->td_proc->p_fd);
1307         vattr.va_mode = (mode & ALLPERMS) & ~td->td_proc->p_fd->fd_cmask;
1308         FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
1309 #ifdef MAC
1310         error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
1311             &vattr);
1312         if (error)
1313                 goto out;
1314 #endif
1315         VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1316         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1317         if (error == 0)
1318                 vput(nd.ni_vp);
1319 #ifdef MAC
1320 out:
1321 #endif
1322         vput(nd.ni_dvp);
1323         vn_finished_write(mp);
1324         VFS_UNLOCK_GIANT(vfslocked);
1325         NDFREE(&nd, NDF_ONLY_PNBUF);
1326         return (error);
1327 }
1328
1329 /*
1330  * Make a hard file link.
1331  */
1332 #ifndef _SYS_SYSPROTO_H_
1333 struct link_args {
1334         char    *path;
1335         char    *link;
1336 };
1337 #endif
1338 int
1339 link(td, uap)
1340         struct thread *td;
1341         register struct link_args /* {
1342                 char *path;
1343                 char *link;
1344         } */ *uap;
1345 {
1346         int error;
1347
1348         error = kern_link(td, uap->path, uap->link, UIO_USERSPACE);
1349         return (error);
1350 }
1351
1352 SYSCTL_DECL(_security_bsd);
1353
1354 static int hardlink_check_uid = 0;
1355 SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_uid, CTLFLAG_RW,
1356     &hardlink_check_uid, 0,
1357     "Unprivileged processes cannot create hard links to files owned by other "
1358     "users");
1359 static int hardlink_check_gid = 0;
1360 SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_gid, CTLFLAG_RW,
1361     &hardlink_check_gid, 0,
1362     "Unprivileged processes cannot create hard links to files owned by other "
1363     "groups");
1364
1365 static int
1366 can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred)
1367 {
1368         struct vattr va;
1369         int error;
1370
1371         if (suser_cred(cred, SUSER_ALLOWJAIL) == 0)
1372                 return (0);
1373
1374         if (!hardlink_check_uid && !hardlink_check_gid)
1375                 return (0);
1376
1377         error = VOP_GETATTR(vp, &va, cred, td);
1378         if (error != 0)
1379                 return (error);
1380
1381         if (hardlink_check_uid) {
1382                 if (cred->cr_uid != va.va_uid)
1383                         return (EPERM);
1384         }
1385
1386         if (hardlink_check_gid) {
1387                 if (!groupmember(va.va_gid, cred))
1388                         return (EPERM);
1389         }
1390
1391         return (0);
1392 }
1393
1394 int
1395 kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg)
1396 {
1397         struct vnode *vp;
1398         struct mount *mp;
1399         struct nameidata nd;
1400         int vfslocked;
1401         int lvfslocked;
1402         int error;
1403
1404         bwillwrite();
1405         NDINIT(&nd, LOOKUP, FOLLOW | NOOBJ | MPSAFE, segflg, path, td);
1406         if ((error = namei(&nd)) != 0)
1407                 return (error);
1408         vfslocked = NDHASGIANT(&nd);
1409         NDFREE(&nd, NDF_ONLY_PNBUF);
1410         vp = nd.ni_vp;
1411         if (vp->v_type == VDIR) {
1412                 vrele(vp);
1413                 VFS_UNLOCK_GIANT(vfslocked);
1414                 return (EPERM);         /* POSIX */
1415         }
1416         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
1417                 vrele(vp);
1418                 VFS_UNLOCK_GIANT(vfslocked);
1419                 return (error);
1420         }
1421         NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME, segflg, link, td);
1422         if ((error = namei(&nd)) == 0) {
1423                 lvfslocked = NDHASGIANT(&nd);
1424                 if (nd.ni_vp != NULL) {
1425                         vrele(nd.ni_vp);
1426                         if (nd.ni_dvp == nd.ni_vp)
1427                                 vrele(nd.ni_dvp);
1428                         else
1429                                 vput(nd.ni_dvp);
1430                         error = EEXIST;
1431                 } else if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td))
1432                     == 0) {
1433                         VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1434                         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1435                         error = can_hardlink(vp, td, td->td_ucred);
1436                         if (error == 0)
1437 #ifdef MAC
1438                                 error = mac_check_vnode_link(td->td_ucred,
1439                                     nd.ni_dvp, vp, &nd.ni_cnd);
1440                         if (error == 0)
1441 #endif
1442                                 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1443                         VOP_UNLOCK(vp, 0, td);
1444                         vput(nd.ni_dvp);
1445                 }
1446                 NDFREE(&nd, NDF_ONLY_PNBUF);
1447                 VFS_UNLOCK_GIANT(lvfslocked);
1448         }
1449         vrele(vp);
1450         vn_finished_write(mp);
1451         VFS_UNLOCK_GIANT(vfslocked);
1452         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link");
1453         ASSERT_VOP_UNLOCKED(nd.ni_vp, "link");
1454         return (error);
1455 }
1456
1457 /*
1458  * Make a symbolic link.
1459  */
1460 #ifndef _SYS_SYSPROTO_H_
1461 struct symlink_args {
1462         char    *path;
1463         char    *link;
1464 };
1465 #endif
1466 int
1467 symlink(td, uap)
1468         struct thread *td;
1469         register struct symlink_args /* {
1470                 char *path;
1471                 char *link;
1472         } */ *uap;
1473 {
1474
1475         return (kern_symlink(td, uap->path, uap->link, UIO_USERSPACE));
1476 }
1477
1478 int
1479 kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg)
1480 {
1481         struct mount *mp;
1482         struct vattr vattr;
1483         char *syspath;
1484         int error;
1485         struct nameidata nd;
1486         int vfslocked;
1487
1488         if (segflg == UIO_SYSSPACE) {
1489                 syspath = path;
1490         } else {
1491                 syspath = uma_zalloc(namei_zone, M_WAITOK);
1492                 if ((error = copyinstr(path, syspath, MAXPATHLEN, NULL)) != 0)
1493                         goto out;
1494         }
1495 restart:
1496         bwillwrite();
1497         NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME | MPSAFE,
1498             segflg, link, td);
1499         if ((error = namei(&nd)) != 0)
1500                 goto out;
1501         vfslocked = NDHASGIANT(&nd);
1502         if (nd.ni_vp) {
1503                 NDFREE(&nd, NDF_ONLY_PNBUF);
1504                 vrele(nd.ni_vp);
1505                 if (nd.ni_vp == nd.ni_dvp)
1506                         vrele(nd.ni_dvp);
1507                 else
1508                         vput(nd.ni_dvp);
1509                 VFS_UNLOCK_GIANT(vfslocked);
1510                 error = EEXIST;
1511                 goto out;
1512         }
1513         if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1514                 NDFREE(&nd, NDF_ONLY_PNBUF);
1515                 vput(nd.ni_dvp);
1516                 VFS_UNLOCK_GIANT(vfslocked);
1517                 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1518                         goto out;
1519                 goto restart;
1520         }
1521         VATTR_NULL(&vattr);
1522         FILEDESC_LOCK_FAST(td->td_proc->p_fd);
1523         vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask;
1524         FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
1525 #ifdef MAC
1526         vattr.va_type = VLNK;
1527         error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
1528             &vattr);
1529         if (error)
1530                 goto out2;
1531 #endif
1532         VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1533         error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath);
1534         if (error == 0)
1535                 vput(nd.ni_vp);
1536 #ifdef MAC
1537 out2:
1538 #endif
1539         NDFREE(&nd, NDF_ONLY_PNBUF);
1540         vput(nd.ni_dvp);
1541         vn_finished_write(mp);
1542         VFS_UNLOCK_GIANT(vfslocked);
1543         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink");
1544         ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink");
1545 out:
1546         if (segflg != UIO_SYSSPACE)
1547                 uma_zfree(namei_zone, syspath);
1548         return (error);
1549 }
1550
1551 /*
1552  * Delete a whiteout from the filesystem.
1553  */
1554 int
1555 undelete(td, uap)
1556         struct thread *td;
1557         register struct undelete_args /* {
1558                 char *path;
1559         } */ *uap;
1560 {
1561         int error;
1562         struct mount *mp;
1563         struct nameidata nd;
1564         int vfslocked;
1565
1566 restart:
1567         bwillwrite();
1568         NDINIT(&nd, DELETE, LOCKPARENT | DOWHITEOUT | MPSAFE, UIO_USERSPACE,
1569             uap->path, td);
1570         error = namei(&nd);
1571         if (error)
1572                 return (error);
1573         vfslocked = NDHASGIANT(&nd);
1574
1575         if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1576                 NDFREE(&nd, NDF_ONLY_PNBUF);
1577                 if (nd.ni_vp)
1578                         vrele(nd.ni_vp);
1579                 if (nd.ni_vp == nd.ni_dvp)
1580                         vrele(nd.ni_dvp);
1581                 else
1582                         vput(nd.ni_dvp);
1583                 VFS_UNLOCK_GIANT(vfslocked);
1584                 return (EEXIST);
1585         }
1586         if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1587                 NDFREE(&nd, NDF_ONLY_PNBUF);
1588                 vput(nd.ni_dvp);
1589                 VFS_UNLOCK_GIANT(vfslocked);
1590                 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1591                         return (error);
1592                 goto restart;
1593         }
1594         VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1595         error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
1596         NDFREE(&nd, NDF_ONLY_PNBUF);
1597         vput(nd.ni_dvp);
1598         vn_finished_write(mp);
1599         VFS_UNLOCK_GIANT(vfslocked);
1600         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete");
1601         ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete");
1602         return (error);
1603 }
1604
1605 /*
1606  * Delete a name from the filesystem.
1607  */
1608 #ifndef _SYS_SYSPROTO_H_
1609 struct unlink_args {
1610         char    *path;
1611 };
1612 #endif
1613 int
1614 unlink(td, uap)
1615         struct thread *td;
1616         struct unlink_args /* {
1617                 char *path;
1618         } */ *uap;
1619 {
1620         int error;
1621
1622         error = kern_unlink(td, uap->path, UIO_USERSPACE);
1623         return (error);
1624 }
1625
1626 int
1627 kern_unlink(struct thread *td, char *path, enum uio_seg pathseg)
1628 {
1629         struct mount *mp;
1630         struct vnode *vp;
1631         int error;
1632         struct nameidata nd;
1633         int vfslocked;
1634
1635 restart:
1636         bwillwrite();
1637         NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE, pathseg, path, td);
1638         if ((error = namei(&nd)) != 0)
1639                 return (error);
1640         vfslocked = NDHASGIANT(&nd);
1641         vp = nd.ni_vp;
1642         if (vp->v_type == VDIR)
1643                 error = EPERM;          /* POSIX */
1644         else {
1645                 /*
1646                  * The root of a mounted filesystem cannot be deleted.
1647                  *
1648                  * XXX: can this only be a VDIR case?
1649                  */
1650                 if (vp->v_vflag & VV_ROOT)
1651                         error = EBUSY;
1652         }
1653         if (error == 0) {
1654                 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1655                         NDFREE(&nd, NDF_ONLY_PNBUF);
1656                         if (vp == nd.ni_dvp)
1657                                 vrele(vp);
1658                         else
1659                                 vput(vp);
1660                         vput(nd.ni_dvp);
1661                         VFS_UNLOCK_GIANT(vfslocked);
1662                         if ((error = vn_start_write(NULL, &mp,
1663                             V_XSLEEP | PCATCH)) != 0)
1664                                 return (error);
1665                         goto restart;
1666                 }
1667 #ifdef MAC
1668                 error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp,
1669                     &nd.ni_cnd);
1670                 if (error)
1671                         goto out;
1672 #endif
1673                 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1674                 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
1675 #ifdef MAC
1676 out:
1677 #endif
1678                 vn_finished_write(mp);
1679         }
1680         NDFREE(&nd, NDF_ONLY_PNBUF);
1681         if (vp == nd.ni_dvp)
1682                 vrele(vp);
1683         else
1684                 vput(vp);
1685         vput(nd.ni_dvp);
1686         VFS_UNLOCK_GIANT(vfslocked);
1687         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
1688         ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
1689         return (error);
1690 }
1691
1692 /*
1693  * Reposition read/write file offset.
1694  */
1695 #ifndef _SYS_SYSPROTO_H_
1696 struct lseek_args {
1697         int     fd;
1698         int     pad;
1699         off_t   offset;
1700         int     whence;
1701 };
1702 #endif
1703 int
1704 lseek(td, uap)
1705         struct thread *td;
1706         register struct lseek_args /* {
1707                 int fd;
1708                 int pad;
1709                 off_t offset;
1710                 int whence;
1711         } */ *uap;
1712 {
1713         struct ucred *cred = td->td_ucred;
1714         struct file *fp;
1715         struct vnode *vp;
1716         struct vattr vattr;
1717         off_t offset;
1718         int error, noneg;
1719         int vfslocked;
1720
1721         if ((error = fget(td, uap->fd, &fp)) != 0)
1722                 return (error);
1723         if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) {
1724                 fdrop(fp, td);
1725                 return (ESPIPE);
1726         }
1727         vp = fp->f_vnode;
1728         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
1729         noneg = (vp->v_type != VCHR);
1730         offset = uap->offset;
1731         switch (uap->whence) {
1732         case L_INCR:
1733                 if (noneg &&
1734                     (fp->f_offset < 0 ||
1735                     (offset > 0 && fp->f_offset > OFF_MAX - offset))) {
1736                         error = EOVERFLOW;
1737                         break;
1738                 }
1739                 offset += fp->f_offset;
1740                 break;
1741         case L_XTND:
1742                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1743                 error = VOP_GETATTR(vp, &vattr, cred, td);
1744                 VOP_UNLOCK(vp, 0, td);
1745                 if (error)
1746                         break;
1747                 if (noneg &&
1748                     (vattr.va_size > OFF_MAX ||
1749                     (offset > 0 && vattr.va_size > OFF_MAX - offset))) {
1750                         error = EOVERFLOW;
1751                         break;
1752                 }
1753                 offset += vattr.va_size;
1754                 break;
1755         case L_SET:
1756                 break;
1757         default:
1758                 error = EINVAL;
1759         }
1760         if (error == 0 && noneg && offset < 0)
1761                 error = EINVAL;
1762         if (error != 0)
1763                 goto drop;
1764         fp->f_offset = offset;
1765         *(off_t *)(td->td_retval) = fp->f_offset;
1766 drop:
1767         fdrop(fp, td);
1768         VFS_UNLOCK_GIANT(vfslocked);
1769         return (error);
1770 }
1771
1772 #if defined(COMPAT_43)
1773 /*
1774  * Reposition read/write file offset.
1775  */
1776 #ifndef _SYS_SYSPROTO_H_
1777 struct olseek_args {
1778         int     fd;
1779         long    offset;
1780         int     whence;
1781 };
1782 #endif
1783 int
1784 olseek(td, uap)
1785         struct thread *td;
1786         register struct olseek_args /* {
1787                 int fd;
1788                 long offset;
1789                 int whence;
1790         } */ *uap;
1791 {
1792         struct lseek_args /* {
1793                 int fd;
1794                 int pad;
1795                 off_t offset;
1796                 int whence;
1797         } */ nuap;
1798         int error;
1799
1800         nuap.fd = uap->fd;
1801         nuap.offset = uap->offset;
1802         nuap.whence = uap->whence;
1803         error = lseek(td, &nuap);
1804         return (error);
1805 }
1806 #endif /* COMPAT_43 */
1807
1808 /*
1809  * Check access permissions using passed credentials.
1810  */
1811 static int
1812 vn_access(vp, user_flags, cred, td)
1813         struct vnode    *vp;
1814         int             user_flags;
1815         struct ucred    *cred;
1816         struct thread   *td;
1817 {
1818         int error, flags;
1819
1820         /* Flags == 0 means only check for existence. */
1821         error = 0;
1822         if (user_flags) {
1823                 flags = 0;
1824                 if (user_flags & R_OK)
1825                         flags |= VREAD;
1826                 if (user_flags & W_OK)
1827                         flags |= VWRITE;
1828                 if (user_flags & X_OK)
1829                         flags |= VEXEC;
1830 #ifdef MAC
1831                 error = mac_check_vnode_access(cred, vp, flags);
1832                 if (error)
1833                         return (error);
1834 #endif
1835                 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1836                         error = VOP_ACCESS(vp, flags, cred, td);
1837         }
1838         return (error);
1839 }
1840
1841 /*
1842  * Check access permissions using "real" credentials.
1843  */
1844 #ifndef _SYS_SYSPROTO_H_
1845 struct access_args {
1846         char    *path;
1847         int     flags;
1848 };
1849 #endif
1850 int
1851 access(td, uap)
1852         struct thread *td;
1853         register struct access_args /* {
1854                 char *path;
1855                 int flags;
1856         } */ *uap;
1857 {
1858
1859         return (kern_access(td, uap->path, UIO_USERSPACE, uap->flags));
1860 }
1861
1862 int
1863 kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags)
1864 {
1865         struct ucred *cred, *tmpcred;
1866         register struct vnode *vp;
1867         struct nameidata nd;
1868         int vfslocked;
1869         int error;
1870
1871         /*
1872          * Create and modify a temporary credential instead of one that
1873          * is potentially shared.  This could also mess up socket
1874          * buffer accounting which can run in an interrupt context.
1875          */
1876         cred = td->td_ucred;
1877         tmpcred = crdup(cred);
1878         tmpcred->cr_uid = cred->cr_ruid;
1879         tmpcred->cr_groups[0] = cred->cr_rgid;
1880         td->td_ucred = tmpcred;
1881         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ | MPSAFE, pathseg,
1882             path, td);
1883         if ((error = namei(&nd)) != 0)
1884                 goto out1;
1885         vfslocked = NDHASGIANT(&nd);
1886         vp = nd.ni_vp;
1887
1888         error = vn_access(vp, flags, tmpcred, td);
1889         NDFREE(&nd, NDF_ONLY_PNBUF);
1890         vput(vp);
1891         VFS_UNLOCK_GIANT(vfslocked);
1892 out1:
1893         td->td_ucred = cred;
1894         crfree(tmpcred);
1895         return (error);
1896 }
1897
1898 /*
1899  * Check access permissions using "effective" credentials.
1900  */
1901 #ifndef _SYS_SYSPROTO_H_
1902 struct eaccess_args {
1903         char    *path;
1904         int     flags;
1905 };
1906 #endif
1907 int
1908 eaccess(td, uap)
1909         struct thread *td;
1910         register struct eaccess_args /* {
1911                 char *path;
1912                 int flags;
1913         } */ *uap;
1914 {
1915         struct nameidata nd;
1916         struct vnode *vp;
1917         int vfslocked;
1918         int error;
1919
1920         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ | MPSAFE, UIO_USERSPACE,
1921             uap->path, td);
1922         if ((error = namei(&nd)) != 0)
1923                 return (error);
1924         vp = nd.ni_vp;
1925         vfslocked = NDHASGIANT(&nd);
1926         error = vn_access(vp, uap->flags, td->td_ucred, td);
1927         NDFREE(&nd, NDF_ONLY_PNBUF);
1928         vput(vp);
1929         VFS_UNLOCK_GIANT(vfslocked);
1930         return (error);
1931 }
1932
1933 #if defined(COMPAT_43)
1934 /*
1935  * Get file status; this version follows links.
1936  */
1937 #ifndef _SYS_SYSPROTO_H_
1938 struct ostat_args {
1939         char    *path;
1940         struct ostat *ub;
1941 };
1942 #endif
1943 int
1944 ostat(td, uap)
1945         struct thread *td;
1946         register struct ostat_args /* {
1947                 char *path;
1948                 struct ostat *ub;
1949         } */ *uap;
1950 {
1951         struct stat sb;
1952         struct ostat osb;
1953         int error;
1954
1955         error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1956         if (error)
1957                 return (error);
1958         cvtstat(&sb, &osb);
1959         error = copyout(&osb, uap->ub, sizeof (osb));
1960         return (error);
1961 }
1962
1963 /*
1964  * Get file status; this version does not follow links.
1965  */
1966 #ifndef _SYS_SYSPROTO_H_
1967 struct olstat_args {
1968         char    *path;
1969         struct ostat *ub;
1970 };
1971 #endif
1972 int
1973 olstat(td, uap)
1974         struct thread *td;
1975         register struct olstat_args /* {
1976                 char *path;
1977                 struct ostat *ub;
1978         } */ *uap;
1979 {
1980         struct stat sb;
1981         struct ostat osb;
1982         int error;
1983
1984         error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1985         if (error)
1986                 return (error);
1987         cvtstat(&sb, &osb);
1988         error = copyout(&osb, uap->ub, sizeof (osb));
1989         return (error);
1990 }
1991
1992 /*
1993  * Convert from an old to a new stat structure.
1994  */
1995 void
1996 cvtstat(st, ost)
1997         struct stat *st;
1998         struct ostat *ost;
1999 {
2000
2001         ost->st_dev = st->st_dev;
2002         ost->st_ino = st->st_ino;
2003         ost->st_mode = st->st_mode;
2004         ost->st_nlink = st->st_nlink;
2005         ost->st_uid = st->st_uid;
2006         ost->st_gid = st->st_gid;
2007         ost->st_rdev = st->st_rdev;
2008         if (st->st_size < (quad_t)1 << 32)
2009                 ost->st_size = st->st_size;
2010         else
2011                 ost->st_size = -2;
2012         ost->st_atime = st->st_atime;
2013         ost->st_mtime = st->st_mtime;
2014         ost->st_ctime = st->st_ctime;
2015         ost->st_blksize = st->st_blksize;
2016         ost->st_blocks = st->st_blocks;
2017         ost->st_flags = st->st_flags;
2018         ost->st_gen = st->st_gen;
2019 }
2020 #endif /* COMPAT_43 */
2021
2022 /*
2023  * Get file status; this version follows links.
2024  */
2025 #ifndef _SYS_SYSPROTO_H_
2026 struct stat_args {
2027         char    *path;
2028         struct stat *ub;
2029 };
2030 #endif
2031 int
2032 stat(td, uap)
2033         struct thread *td;
2034         register struct stat_args /* {
2035                 char *path;
2036                 struct stat *ub;
2037         } */ *uap;
2038 {
2039         struct stat sb;
2040         int error;
2041
2042         error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
2043         if (error == 0)
2044                 error = copyout(&sb, uap->ub, sizeof (sb));
2045         return (error);
2046 }
2047
2048 int
2049 kern_stat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp)
2050 {
2051         struct nameidata nd;
2052         struct stat sb;
2053         int error, vfslocked;
2054
2055 #ifdef LOOKUP_SHARED
2056         NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | NOOBJ | MPSAFE,
2057             pathseg, path, td);
2058 #else
2059         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ | MPSAFE, pathseg, path,
2060             td);
2061 #endif
2062         if ((error = namei(&nd)) != 0)
2063                 return (error);
2064         vfslocked = NDHASGIANT(&nd);
2065         error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
2066         NDFREE(&nd, NDF_ONLY_PNBUF);
2067         vput(nd.ni_vp);
2068         VFS_UNLOCK_GIANT(vfslocked);
2069         if (error)
2070                 return (error);
2071         *sbp = sb;
2072         return (0);
2073 }
2074
2075 /*
2076  * Get file status; this version does not follow links.
2077  */
2078 #ifndef _SYS_SYSPROTO_H_
2079 struct lstat_args {
2080         char    *path;
2081         struct stat *ub;
2082 };
2083 #endif
2084 int
2085 lstat(td, uap)
2086         struct thread *td;
2087         register struct lstat_args /* {
2088                 char *path;
2089                 struct stat *ub;
2090         } */ *uap;
2091 {
2092         struct stat sb;
2093         int error;
2094
2095         error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2096         if (error == 0)
2097                 error = copyout(&sb, uap->ub, sizeof (sb));
2098         return (error);
2099 }
2100
2101 int
2102 kern_lstat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp)
2103 {
2104         struct vnode *vp;
2105         struct stat sb;
2106         struct nameidata nd;
2107         int error, vfslocked;
2108
2109         /* XXX LOOKUP_SHARED? */
2110         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ | MPSAFE,
2111             pathseg, path, td);
2112         if ((error = namei(&nd)) != 0)
2113                 return (error);
2114         vfslocked = NDHASGIANT(&nd);
2115         vp = nd.ni_vp;
2116         error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
2117         NDFREE(&nd, NDF_ONLY_PNBUF);
2118         vput(vp);
2119         VFS_UNLOCK_GIANT(vfslocked);
2120         if (error)
2121                 return (error);
2122         *sbp = sb;
2123         return (0);
2124 }
2125
2126 /*
2127  * Implementation of the NetBSD [l]stat() functions.
2128  */
2129 void
2130 cvtnstat(sb, nsb)
2131         struct stat *sb;
2132         struct nstat *nsb;
2133 {
2134         bzero(nsb, sizeof *nsb);
2135         nsb->st_dev = sb->st_dev;
2136         nsb->st_ino = sb->st_ino;
2137         nsb->st_mode = sb->st_mode;
2138         nsb->st_nlink = sb->st_nlink;
2139         nsb->st_uid = sb->st_uid;
2140         nsb->st_gid = sb->st_gid;
2141         nsb->st_rdev = sb->st_rdev;
2142         nsb->st_atimespec = sb->st_atimespec;
2143         nsb->st_mtimespec = sb->st_mtimespec;
2144         nsb->st_ctimespec = sb->st_ctimespec;
2145         nsb->st_size = sb->st_size;
2146         nsb->st_blocks = sb->st_blocks;
2147         nsb->st_blksize = sb->st_blksize;
2148         nsb->st_flags = sb->st_flags;
2149         nsb->st_gen = sb->st_gen;
2150         nsb->st_birthtimespec = sb->st_birthtimespec;
2151 }
2152
2153 #ifndef _SYS_SYSPROTO_H_
2154 struct nstat_args {
2155         char    *path;
2156         struct nstat *ub;
2157 };
2158 #endif
2159 int
2160 nstat(td, uap)
2161         struct thread *td;
2162         register struct nstat_args /* {
2163                 char *path;
2164                 struct nstat *ub;
2165         } */ *uap;
2166 {
2167         struct stat sb;
2168         struct nstat nsb;
2169         int error;
2170
2171         error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
2172         if (error)
2173                 return (error);
2174         cvtnstat(&sb, &nsb);
2175         error = copyout(&nsb, uap->ub, sizeof (nsb));
2176         return (error);
2177 }
2178
2179 /*
2180  * NetBSD lstat.  Get file status; this version does not follow links.
2181  */
2182 #ifndef _SYS_SYSPROTO_H_
2183 struct lstat_args {
2184         char    *path;
2185         struct stat *ub;
2186 };
2187 #endif
2188 int
2189 nlstat(td, uap)
2190         struct thread *td;
2191         register struct nlstat_args /* {
2192                 char *path;
2193                 struct nstat *ub;
2194         } */ *uap;
2195 {
2196         struct stat sb;
2197         struct nstat nsb;
2198         int error;
2199
2200         error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2201         if (error)
2202                 return (error);
2203         cvtnstat(&sb, &nsb);
2204         error = copyout(&nsb, uap->ub, sizeof (nsb));
2205         return (error);
2206 }
2207
2208 /*
2209  * Get configurable pathname variables.
2210  */
2211 #ifndef _SYS_SYSPROTO_H_
2212 struct pathconf_args {
2213         char    *path;
2214         int     name;
2215 };
2216 #endif
2217 int
2218 pathconf(td, uap)
2219         struct thread *td;
2220         register struct pathconf_args /* {
2221                 char *path;
2222                 int name;
2223         } */ *uap;
2224 {
2225
2226         return (kern_pathconf(td, uap->path, UIO_USERSPACE, uap->name));
2227 }
2228
2229 int
2230 kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg, int name)
2231 {
2232         struct nameidata nd;
2233         int error, vfslocked;
2234
2235         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ | MPSAFE, pathseg, path,
2236             td);
2237         if ((error = namei(&nd)) != 0)
2238                 return (error);
2239         vfslocked = NDHASGIANT(&nd);
2240         NDFREE(&nd, NDF_ONLY_PNBUF);
2241
2242         /* If asynchronous I/O is available, it works for all files. */
2243         if (name == _PC_ASYNC_IO)
2244                 td->td_retval[0] = async_io_version;
2245         else
2246                 error = VOP_PATHCONF(nd.ni_vp, name, td->td_retval);
2247         vput(nd.ni_vp);
2248         VFS_UNLOCK_GIANT(vfslocked);
2249         return (error);
2250 }
2251
2252 /*
2253  * Return target name of a symbolic link.
2254  */
2255 #ifndef _SYS_SYSPROTO_H_
2256 struct readlink_args {
2257         char    *path;
2258         char    *buf;
2259         int     count;
2260 };
2261 #endif
2262 int
2263 readlink(td, uap)
2264         struct thread *td;
2265         register struct readlink_args /* {
2266                 char *path;
2267                 char *buf;
2268                 int count;
2269         } */ *uap;
2270 {
2271
2272         return (kern_readlink(td, uap->path, UIO_USERSPACE, uap->buf,
2273             UIO_USERSPACE, uap->count));
2274 }
2275
2276 int
2277 kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf,
2278     enum uio_seg bufseg, int count)
2279 {
2280         register struct vnode *vp;
2281         struct iovec aiov;
2282         struct uio auio;
2283         int error;
2284         struct nameidata nd;
2285         int vfslocked;
2286
2287         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ | MPSAFE,
2288             pathseg, path, td);
2289         if ((error = namei(&nd)) != 0)
2290                 return (error);
2291         NDFREE(&nd, NDF_ONLY_PNBUF);
2292         vfslocked = NDHASGIANT(&nd);
2293         vp = nd.ni_vp;
2294 #ifdef MAC
2295         error = mac_check_vnode_readlink(td->td_ucred, vp);
2296         if (error) {
2297                 vput(vp);
2298                 VFS_UNLOCK_GIANT(vfslocked);
2299                 return (error);
2300         }
2301 #endif
2302         if (vp->v_type != VLNK)
2303                 error = EINVAL;
2304         else {
2305                 aiov.iov_base = buf;
2306                 aiov.iov_len = count;
2307                 auio.uio_iov = &aiov;
2308                 auio.uio_iovcnt = 1;
2309                 auio.uio_offset = 0;
2310                 auio.uio_rw = UIO_READ;
2311                 auio.uio_segflg = bufseg;
2312                 auio.uio_td = td;
2313                 auio.uio_resid = count;
2314                 error = VOP_READLINK(vp, &auio, td->td_ucred);
2315         }
2316         vput(vp);
2317         VFS_UNLOCK_GIANT(vfslocked);
2318         td->td_retval[0] = count - auio.uio_resid;
2319         return (error);
2320 }
2321
2322 /*
2323  * Common implementation code for chflags() and fchflags().
2324  */
2325 static int
2326 setfflags(td, vp, flags)
2327         struct thread *td;
2328         struct vnode *vp;
2329         int flags;
2330 {
2331         int error;
2332         struct mount *mp;
2333         struct vattr vattr;
2334
2335         /*
2336          * Prevent non-root users from setting flags on devices.  When
2337          * a device is reused, users can retain ownership of the device
2338          * if they are allowed to set flags and programs assume that
2339          * chown can't fail when done as root.
2340          */
2341         if (vp->v_type == VCHR || vp->v_type == VBLK) {
2342                 error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
2343                 if (error)
2344                         return (error);
2345         }
2346
2347         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2348                 return (error);
2349         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2350         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2351         VATTR_NULL(&vattr);
2352         vattr.va_flags = flags;
2353 #ifdef MAC
2354         error = mac_check_vnode_setflags(td->td_ucred, vp, vattr.va_flags);
2355         if (error == 0)
2356 #endif
2357                 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2358         VOP_UNLOCK(vp, 0, td);
2359         vn_finished_write(mp);
2360         return (error);
2361 }
2362
2363 /*
2364  * Change flags of a file given a path name.
2365  */
2366 #ifndef _SYS_SYSPROTO_H_
2367 struct chflags_args {
2368         char    *path;
2369         int     flags;
2370 };
2371 #endif
2372 int
2373 chflags(td, uap)
2374         struct thread *td;
2375         register struct chflags_args /* {
2376                 char *path;
2377                 int flags;
2378         } */ *uap;
2379 {
2380         int error;
2381         struct nameidata nd;
2382         int vfslocked;
2383
2384         NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_USERSPACE, uap->path, td);
2385         if ((error = namei(&nd)) != 0)
2386                 return (error);
2387         NDFREE(&nd, NDF_ONLY_PNBUF);
2388         vfslocked = NDHASGIANT(&nd);
2389         error = setfflags(td, nd.ni_vp, uap->flags);
2390         vrele(nd.ni_vp);
2391         VFS_UNLOCK_GIANT(vfslocked);
2392         return (error);
2393 }
2394
2395 /*
2396  * Same as chflags() but doesn't follow symlinks.
2397  */
2398 int
2399 lchflags(td, uap)
2400         struct thread *td;
2401         register struct lchflags_args /* {
2402                 char *path;
2403                 int flags;
2404         } */ *uap;
2405 {
2406         int error;
2407         struct nameidata nd;
2408         int vfslocked;
2409
2410         NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_USERSPACE, uap->path, td);
2411         if ((error = namei(&nd)) != 0)
2412                 return (error);
2413         vfslocked = NDHASGIANT(&nd);
2414         NDFREE(&nd, NDF_ONLY_PNBUF);
2415         error = setfflags(td, nd.ni_vp, uap->flags);
2416         vrele(nd.ni_vp);
2417         VFS_UNLOCK_GIANT(vfslocked);
2418         return (error);
2419 }
2420
2421 /*
2422  * Change flags of a file given a file descriptor.
2423  */
2424 #ifndef _SYS_SYSPROTO_H_
2425 struct fchflags_args {
2426         int     fd;
2427         int     flags;
2428 };
2429 #endif
2430 int
2431 fchflags(td, uap)
2432         struct thread *td;
2433         register struct fchflags_args /* {
2434                 int fd;
2435                 int flags;
2436         } */ *uap;
2437 {
2438         struct file *fp;
2439         int vfslocked;
2440         int error;
2441
2442         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2443                 return (error);
2444         vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2445         error = setfflags(td, fp->f_vnode, uap->flags);
2446         fdrop(fp, td);
2447         VFS_UNLOCK_GIANT(vfslocked);
2448         return (error);
2449 }
2450
2451 /*
2452  * Common implementation code for chmod(), lchmod() and fchmod().
2453  */
2454 static int
2455 setfmode(td, vp, mode)
2456         struct thread *td;
2457         struct vnode *vp;
2458         int mode;
2459 {
2460         int error;
2461         struct mount *mp;
2462         struct vattr vattr;
2463
2464         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2465                 return (error);
2466         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2467         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2468         VATTR_NULL(&vattr);
2469         vattr.va_mode = mode & ALLPERMS;
2470 #ifdef MAC
2471         error = mac_check_vnode_setmode(td->td_ucred, vp, vattr.va_mode);
2472         if (error == 0)
2473 #endif
2474                 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2475         VOP_UNLOCK(vp, 0, td);
2476         vn_finished_write(mp);
2477         return (error);
2478 }
2479
2480 /*
2481  * Change mode of a file given path name.
2482  */
2483 #ifndef _SYS_SYSPROTO_H_
2484 struct chmod_args {
2485         char    *path;
2486         int     mode;
2487 };
2488 #endif
2489 int
2490 chmod(td, uap)
2491         struct thread *td;
2492         register struct chmod_args /* {
2493                 char *path;
2494                 int mode;
2495         } */ *uap;
2496 {
2497
2498         return (kern_chmod(td, uap->path, UIO_USERSPACE, uap->mode));
2499 }
2500
2501 int
2502 kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int mode)
2503 {
2504         int error;
2505         struct nameidata nd;
2506         int vfslocked;
2507
2508         NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, pathseg, path, td);
2509         if ((error = namei(&nd)) != 0)
2510                 return (error);
2511         vfslocked = NDHASGIANT(&nd);
2512         NDFREE(&nd, NDF_ONLY_PNBUF);
2513         error = setfmode(td, nd.ni_vp, mode);
2514         vrele(nd.ni_vp);
2515         VFS_UNLOCK_GIANT(vfslocked);
2516         return (error);
2517 }
2518
2519 /*
2520  * Change mode of a file given path name (don't follow links.)
2521  */
2522 #ifndef _SYS_SYSPROTO_H_
2523 struct lchmod_args {
2524         char    *path;
2525         int     mode;
2526 };
2527 #endif
2528 int
2529 lchmod(td, uap)
2530         struct thread *td;
2531         register struct lchmod_args /* {
2532                 char *path;
2533                 int mode;
2534         } */ *uap;
2535 {
2536         int error;
2537         struct nameidata nd;
2538         int vfslocked;
2539
2540         NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_USERSPACE, uap->path, td);
2541         if ((error = namei(&nd)) != 0)
2542                 return (error);
2543         vfslocked = NDHASGIANT(&nd);
2544         NDFREE(&nd, NDF_ONLY_PNBUF);
2545         error = setfmode(td, nd.ni_vp, uap->mode);
2546         vrele(nd.ni_vp);
2547         VFS_UNLOCK_GIANT(vfslocked);
2548         return (error);
2549 }
2550
2551 /*
2552  * Change mode of a file given a file descriptor.
2553  */
2554 #ifndef _SYS_SYSPROTO_H_
2555 struct fchmod_args {
2556         int     fd;
2557         int     mode;
2558 };
2559 #endif
2560 int
2561 fchmod(td, uap)
2562         struct thread *td;
2563         register struct fchmod_args /* {
2564                 int fd;
2565                 int mode;
2566         } */ *uap;
2567 {
2568         struct file *fp;
2569         int vfslocked;
2570         int error;
2571
2572         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2573                 return (error);
2574         vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2575         error = setfmode(td, fp->f_vnode, uap->mode);
2576         fdrop(fp, td);
2577         VFS_UNLOCK_GIANT(vfslocked);
2578         return (error);
2579 }
2580
2581 /*
2582  * Common implementation for chown(), lchown(), and fchown()
2583  */
2584 static int
2585 setfown(td, vp, uid, gid)
2586         struct thread *td;
2587         struct vnode *vp;
2588         uid_t uid;
2589         gid_t gid;
2590 {
2591         int error;
2592         struct mount *mp;
2593         struct vattr vattr;
2594
2595         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2596                 return (error);
2597         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2598         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2599         VATTR_NULL(&vattr);
2600         vattr.va_uid = uid;
2601         vattr.va_gid = gid;
2602 #ifdef MAC
2603         error = mac_check_vnode_setowner(td->td_ucred, vp, vattr.va_uid,
2604             vattr.va_gid);
2605         if (error == 0)
2606 #endif
2607                 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2608         VOP_UNLOCK(vp, 0, td);
2609         vn_finished_write(mp);
2610         return (error);
2611 }
2612
2613 /*
2614  * Set ownership given a path name.
2615  */
2616 #ifndef _SYS_SYSPROTO_H_
2617 struct chown_args {
2618         char    *path;
2619         int     uid;
2620         int     gid;
2621 };
2622 #endif
2623 int
2624 chown(td, uap)
2625         struct thread *td;
2626         register struct chown_args /* {
2627                 char *path;
2628                 int uid;
2629                 int gid;
2630         } */ *uap;
2631 {
2632
2633         return (kern_chown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid));
2634 }
2635
2636 int
2637 kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
2638     int gid)
2639 {
2640         int error;
2641         struct nameidata nd;
2642         int vfslocked;
2643
2644         NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, pathseg, path, td);
2645         if ((error = namei(&nd)) != 0)
2646                 return (error);
2647         vfslocked = NDHASGIANT(&nd);
2648         NDFREE(&nd, NDF_ONLY_PNBUF);
2649         error = setfown(td, nd.ni_vp, uid, gid);
2650         vrele(nd.ni_vp);
2651         VFS_UNLOCK_GIANT(vfslocked);
2652         return (error);
2653 }
2654
2655 /*
2656  * Set ownership given a path name, do not cross symlinks.
2657  */
2658 #ifndef _SYS_SYSPROTO_H_
2659 struct lchown_args {
2660         char    *path;
2661         int     uid;
2662         int     gid;
2663 };
2664 #endif
2665 int
2666 lchown(td, uap)
2667         struct thread *td;
2668         register struct lchown_args /* {
2669                 char *path;
2670                 int uid;
2671                 int gid;
2672         } */ *uap;
2673 {
2674
2675         return (kern_lchown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid));
2676 }
2677
2678 int
2679 kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
2680     int gid)
2681 {
2682         int error;
2683         struct nameidata nd;
2684         int vfslocked;
2685
2686         NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, pathseg, path, td);
2687         if ((error = namei(&nd)) != 0)
2688                 return (error);
2689         vfslocked = NDHASGIANT(&nd);
2690         NDFREE(&nd, NDF_ONLY_PNBUF);
2691         error = setfown(td, nd.ni_vp, uid, gid);
2692         vrele(nd.ni_vp);
2693         VFS_UNLOCK_GIANT(vfslocked);
2694         return (error);
2695 }
2696
2697 /*
2698  * Set ownership given a file descriptor.
2699  */
2700 #ifndef _SYS_SYSPROTO_H_
2701 struct fchown_args {
2702         int     fd;
2703         int     uid;
2704         int     gid;
2705 };
2706 #endif
2707 int
2708 fchown(td, uap)
2709         struct thread *td;
2710         register struct fchown_args /* {
2711                 int fd;
2712                 int uid;
2713                 int gid;
2714         } */ *uap;
2715 {
2716         struct file *fp;
2717         int vfslocked;
2718         int error;
2719
2720         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2721                 return (error);
2722         vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2723         error = setfown(td, fp->f_vnode, uap->uid, uap->gid);
2724         fdrop(fp, td);
2725         VFS_UNLOCK_GIANT(vfslocked);
2726         return (error);
2727 }
2728
2729 /*
2730  * Common implementation code for utimes(), lutimes(), and futimes().
2731  */
2732 static int
2733 getutimes(usrtvp, tvpseg, tsp)
2734         const struct timeval *usrtvp;
2735         enum uio_seg tvpseg;
2736         struct timespec *tsp;
2737 {
2738         struct timeval tv[2];
2739         const struct timeval *tvp;
2740         int error;
2741
2742         if (usrtvp == NULL) {
2743                 microtime(&tv[0]);
2744                 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2745                 tsp[1] = tsp[0];
2746         } else {
2747                 if (tvpseg == UIO_SYSSPACE) {
2748                         tvp = usrtvp;
2749                 } else {
2750                         if ((error = copyin(usrtvp, tv, sizeof(tv))) != 0)
2751                                 return (error);
2752                         tvp = tv;
2753                 }
2754
2755                 TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]);
2756                 TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]);
2757         }
2758         return (0);
2759 }
2760
2761 /*
2762  * Common implementation code for utimes(), lutimes(), and futimes().
2763  */
2764 static int
2765 setutimes(td, vp, ts, numtimes, nullflag)
2766         struct thread *td;
2767         struct vnode *vp;
2768         const struct timespec *ts;
2769         int numtimes;
2770         int nullflag;
2771 {
2772         int error, setbirthtime;
2773         struct mount *mp;
2774         struct vattr vattr;
2775
2776         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2777                 return (error);
2778         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2779         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2780         setbirthtime = 0;
2781         if (numtimes < 3 && VOP_GETATTR(vp, &vattr, td->td_ucred, td) == 0 &&
2782             timespeccmp(&ts[1], &vattr.va_birthtime, < ))
2783                 setbirthtime = 1;
2784         VATTR_NULL(&vattr);
2785         vattr.va_atime = ts[0];
2786         vattr.va_mtime = ts[1];
2787         if (setbirthtime)
2788                 vattr.va_birthtime = ts[1];
2789         if (numtimes > 2)
2790                 vattr.va_birthtime = ts[2];
2791         if (nullflag)
2792                 vattr.va_vaflags |= VA_UTIMES_NULL;
2793 #ifdef MAC
2794         error = mac_check_vnode_setutimes(td->td_ucred, vp, vattr.va_atime,
2795             vattr.va_mtime);
2796 #endif
2797         if (error == 0)
2798                 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2799         VOP_UNLOCK(vp, 0, td);
2800         vn_finished_write(mp);
2801         return (error);
2802 }
2803
2804 /*
2805  * Set the access and modification times of a file.
2806  */
2807 #ifndef _SYS_SYSPROTO_H_
2808 struct utimes_args {
2809         char    *path;
2810         struct  timeval *tptr;
2811 };
2812 #endif
2813 int
2814 utimes(td, uap)
2815         struct thread *td;
2816         register struct utimes_args /* {
2817                 char *path;
2818                 struct timeval *tptr;
2819         } */ *uap;
2820 {
2821
2822         return (kern_utimes(td, uap->path, UIO_USERSPACE, uap->tptr,
2823             UIO_USERSPACE));
2824 }
2825
2826 int
2827 kern_utimes(struct thread *td, char *path, enum uio_seg pathseg,
2828     struct timeval *tptr, enum uio_seg tptrseg)
2829 {
2830         struct timespec ts[2];
2831         int error;
2832         struct nameidata nd;
2833         int vfslocked;
2834
2835         if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2836                 return (error);
2837         NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, pathseg, path, td);
2838         if ((error = namei(&nd)) != 0)
2839                 return (error);
2840         vfslocked = NDHASGIANT(&nd);
2841         NDFREE(&nd, NDF_ONLY_PNBUF);
2842         error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
2843         vrele(nd.ni_vp);
2844         VFS_UNLOCK_GIANT(vfslocked);
2845         return (error);
2846 }
2847
2848 /*
2849  * Set the access and modification times of a file.
2850  */
2851 #ifndef _SYS_SYSPROTO_H_
2852 struct lutimes_args {
2853         char    *path;
2854         struct  timeval *tptr;
2855 };
2856 #endif
2857 int
2858 lutimes(td, uap)
2859         struct thread *td;
2860         register struct lutimes_args /* {
2861                 char *path;
2862                 struct timeval *tptr;
2863         } */ *uap;
2864 {
2865
2866         return (kern_lutimes(td, uap->path, UIO_USERSPACE, uap->tptr,
2867             UIO_USERSPACE));
2868 }
2869
2870 int
2871 kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg,
2872     struct timeval *tptr, enum uio_seg tptrseg)
2873 {
2874         struct timespec ts[2];
2875         int error;
2876         struct nameidata nd;
2877         int vfslocked;
2878
2879         if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2880                 return (error);
2881         NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, pathseg, path, td);
2882         if ((error = namei(&nd)) != 0)
2883                 return (error);
2884         vfslocked = NDHASGIANT(&nd);
2885         NDFREE(&nd, NDF_ONLY_PNBUF);
2886         error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
2887         vrele(nd.ni_vp);
2888         VFS_UNLOCK_GIANT(vfslocked);
2889         return (error);
2890 }
2891
2892 /*
2893  * Set the access and modification times of a file.
2894  */
2895 #ifndef _SYS_SYSPROTO_H_
2896 struct futimes_args {
2897         int     fd;
2898         struct  timeval *tptr;
2899 };
2900 #endif
2901 int
2902 futimes(td, uap)
2903         struct thread *td;
2904         register struct futimes_args /* {
2905                 int  fd;
2906                 struct timeval *tptr;
2907         } */ *uap;
2908 {
2909
2910         return (kern_futimes(td, uap->fd, uap->tptr, UIO_USERSPACE));
2911 }
2912
2913 int
2914 kern_futimes(struct thread *td, int fd, struct timeval *tptr,
2915     enum uio_seg tptrseg)
2916 {
2917         struct timespec ts[2];
2918         struct file *fp;
2919         int vfslocked;
2920         int error;
2921
2922         if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2923                 return (error);
2924         if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0)
2925                 return (error);
2926         vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2927         error = setutimes(td, fp->f_vnode, ts, 2, tptr == NULL);
2928         fdrop(fp, td);
2929         VFS_UNLOCK_GIANT(vfslocked);
2930         return (error);
2931 }
2932
2933 /*
2934  * Truncate a file given its path name.
2935  */
2936 #ifndef _SYS_SYSPROTO_H_
2937 struct truncate_args {
2938         char    *path;
2939         int     pad;
2940         off_t   length;
2941 };
2942 #endif
2943 int
2944 truncate(td, uap)
2945         struct thread *td;
2946         register struct truncate_args /* {
2947                 char *path;
2948                 int pad;
2949                 off_t length;
2950         } */ *uap;
2951 {
2952
2953         return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length));
2954 }
2955
2956 int
2957 kern_truncate(struct thread *td, char *path, enum uio_seg pathseg, off_t length)
2958 {
2959         struct mount *mp;
2960         struct vnode *vp;
2961         struct vattr vattr;
2962         int error;
2963         struct nameidata nd;
2964         int vfslocked;
2965
2966         if (length < 0)
2967                 return(EINVAL);
2968         NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, pathseg, path, td);
2969         if ((error = namei(&nd)) != 0)
2970                 return (error);
2971         vfslocked = NDHASGIANT(&nd);
2972         vp = nd.ni_vp;
2973         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2974                 vrele(vp);
2975                 VFS_UNLOCK_GIANT(vfslocked);
2976                 return (error);
2977         }
2978         NDFREE(&nd, NDF_ONLY_PNBUF);
2979         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2980         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2981         if (vp->v_type == VDIR)
2982                 error = EISDIR;
2983 #ifdef MAC
2984         else if ((error = mac_check_vnode_write(td->td_ucred, NOCRED, vp))) {
2985         }
2986 #endif
2987         else if ((error = vn_writechk(vp)) == 0 &&
2988             (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) {
2989                 VATTR_NULL(&vattr);
2990                 vattr.va_size = length;
2991                 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2992         }
2993         vput(vp);
2994         vn_finished_write(mp);
2995         VFS_UNLOCK_GIANT(vfslocked);
2996         return (error);
2997 }
2998
2999 /*
3000  * Truncate a file given a file descriptor.
3001  */
3002 #ifndef _SYS_SYSPROTO_H_
3003 struct ftruncate_args {
3004         int     fd;
3005         int     pad;
3006         off_t   length;
3007 };
3008 #endif
3009 int
3010 ftruncate(td, uap)
3011         struct thread *td;
3012         register struct ftruncate_args /* {
3013                 int fd;
3014                 int pad;
3015                 off_t length;
3016         } */ *uap;
3017 {
3018         struct mount *mp;
3019         struct vattr vattr;
3020         struct vnode *vp;
3021         struct file *fp;
3022         int vfslocked;
3023         int error;
3024
3025         if (uap->length < 0)
3026                 return(EINVAL);
3027         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3028                 return (error);
3029         if ((fp->f_flag & FWRITE) == 0) {
3030                 fdrop(fp, td);
3031                 return (EINVAL);
3032         }
3033         vp = fp->f_vnode;
3034         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
3035         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3036                 goto drop;
3037         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3038         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3039         if (vp->v_type == VDIR)
3040                 error = EISDIR;
3041 #ifdef MAC
3042         else if ((error = mac_check_vnode_write(td->td_ucred, fp->f_cred,
3043             vp))) {
3044         }
3045 #endif
3046         else if ((error = vn_writechk(vp)) == 0) {
3047                 VATTR_NULL(&vattr);
3048                 vattr.va_size = uap->length;
3049                 error = VOP_SETATTR(vp, &vattr, fp->f_cred, td);
3050         }
3051         VOP_UNLOCK(vp, 0, td);
3052         vn_finished_write(mp);
3053 drop:
3054         VFS_UNLOCK_GIANT(vfslocked);
3055         fdrop(fp, td);
3056         return (error);
3057 }
3058
3059 #if defined(COMPAT_43)
3060 /*
3061  * Truncate a file given its path name.
3062  */
3063 #ifndef _SYS_SYSPROTO_H_
3064 struct otruncate_args {
3065         char    *path;
3066         long    length;
3067 };
3068 #endif
3069 int
3070 otruncate(td, uap)
3071         struct thread *td;
3072         register struct otruncate_args /* {
3073                 char *path;
3074                 long length;
3075         } */ *uap;
3076 {
3077         struct truncate_args /* {
3078                 char *path;
3079                 int pad;
3080                 off_t length;
3081         } */ nuap;
3082
3083         nuap.path = uap->path;
3084         nuap.length = uap->length;
3085         return (truncate(td, &nuap));
3086 }
3087
3088 /*
3089  * Truncate a file given a file descriptor.
3090  */
3091 #ifndef _SYS_SYSPROTO_H_
3092 struct oftruncate_args {
3093         int     fd;
3094         long    length;
3095 };
3096 #endif
3097 int
3098 oftruncate(td, uap)
3099         struct thread *td;
3100         register struct oftruncate_args /* {
3101                 int fd;
3102                 long length;
3103         } */ *uap;
3104 {
3105         struct ftruncate_args /* {
3106                 int fd;
3107                 int pad;
3108                 off_t length;
3109         } */ nuap;
3110
3111         nuap.fd = uap->fd;
3112         nuap.length = uap->length;
3113         return (ftruncate(td, &nuap));
3114 }
3115 #endif /* COMPAT_43 */
3116
3117 /*
3118  * Sync an open file.
3119  */
3120 #ifndef _SYS_SYSPROTO_H_
3121 struct fsync_args {
3122         int     fd;
3123 };
3124 #endif
3125 int
3126 fsync(td, uap)
3127         struct thread *td;
3128         struct fsync_args /* {
3129                 int fd;
3130         } */ *uap;
3131 {
3132         struct vnode *vp;
3133         struct mount *mp;
3134         struct file *fp;
3135         int vfslocked;
3136         int error;
3137
3138         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3139                 return (error);
3140         vp = fp->f_vnode;
3141         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
3142         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3143                 goto drop;
3144         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3145         if (vp->v_object != NULL) {
3146                 VM_OBJECT_LOCK(vp->v_object);
3147                 vm_object_page_clean(vp->v_object, 0, 0, 0);
3148                 VM_OBJECT_UNLOCK(vp->v_object);
3149         }
3150         error = VOP_FSYNC(vp, MNT_WAIT, td);
3151
3152         VOP_UNLOCK(vp, 0, td);
3153         vn_finished_write(mp);
3154 drop:
3155         VFS_UNLOCK_GIANT(vfslocked);
3156         fdrop(fp, td);
3157         return (error);
3158 }
3159
3160 /*
3161  * Rename files.  Source and destination must either both be directories,
3162  * or both not be directories.  If target is a directory, it must be empty.
3163  */
3164 #ifndef _SYS_SYSPROTO_H_
3165 struct rename_args {
3166         char    *from;
3167         char    *to;
3168 };
3169 #endif
3170 int
3171 rename(td, uap)
3172         struct thread *td;
3173         register struct rename_args /* {
3174                 char *from;
3175                 char *to;
3176         } */ *uap;
3177 {
3178
3179         return (kern_rename(td, uap->from, uap->to, UIO_USERSPACE));
3180 }
3181
3182 int
3183 kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg)
3184 {
3185         struct mount *mp = NULL;
3186         struct vnode *tvp, *fvp, *tdvp;
3187         struct nameidata fromnd, tond;
3188         int tvfslocked;
3189         int fvfslocked;
3190         int error;
3191
3192         bwillwrite();
3193 #ifdef MAC
3194         NDINIT(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART | MPSAFE,
3195             pathseg, from, td);
3196 #else
3197         NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART | MPSAFE,
3198             pathseg, from, td);
3199 #endif
3200         if ((error = namei(&fromnd)) != 0)
3201                 return (error);
3202         fvfslocked = NDHASGIANT(&fromnd);
3203         tvfslocked = 0;
3204 #ifdef MAC
3205         error = mac_check_vnode_rename_from(td->td_ucred, fromnd.ni_dvp,
3206             fromnd.ni_vp, &fromnd.ni_cnd);
3207         VOP_UNLOCK(fromnd.ni_dvp, 0, td);
3208         VOP_UNLOCK(fromnd.ni_vp, 0, td);
3209 #endif
3210         fvp = fromnd.ni_vp;
3211         if (error == 0)
3212                 error = vn_start_write(fvp, &mp, V_WAIT | PCATCH);
3213         if (error != 0) {
3214                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3215                 vrele(fromnd.ni_dvp);
3216                 vrele(fvp);
3217                 goto out1;
3218         }
3219         NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART |
3220             NOOBJ | MPSAFE, pathseg, to, td);
3221         if (fromnd.ni_vp->v_type == VDIR)
3222                 tond.ni_cnd.cn_flags |= WILLBEDIR;
3223         if ((error = namei(&tond)) != 0) {
3224                 /* Translate error code for rename("dir1", "dir2/."). */
3225                 if (error == EISDIR && fvp->v_type == VDIR)
3226                         error = EINVAL;
3227                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3228                 vrele(fromnd.ni_dvp);
3229                 vrele(fvp);
3230                 goto out1;
3231         }
3232         tvfslocked = NDHASGIANT(&tond);
3233         tdvp = tond.ni_dvp;
3234         tvp = tond.ni_vp;
3235         if (tvp != NULL) {
3236                 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
3237                         error = ENOTDIR;
3238                         goto out;
3239                 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
3240                         error = EISDIR;
3241                         goto out;
3242                 }
3243         }
3244         if (fvp == tdvp)
3245                 error = EINVAL;
3246         /*
3247          * If the source is the same as the destination (that is, if they
3248          * are links to the same vnode), then there is nothing to do.
3249          */
3250         if (fvp == tvp)
3251                 error = -1;
3252 #ifdef MAC
3253         else
3254                 error = mac_check_vnode_rename_to(td->td_ucred, tdvp,
3255                     tond.ni_vp, fromnd.ni_dvp == tdvp, &tond.ni_cnd);
3256 #endif
3257 out:
3258         if (!error) {
3259                 VOP_LEASE(tdvp, td, td->td_ucred, LEASE_WRITE);
3260                 if (fromnd.ni_dvp != tdvp) {
3261                         VOP_LEASE(fromnd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3262                 }
3263                 if (tvp) {
3264                         VOP_LEASE(tvp, td, td->td_ucred, LEASE_WRITE);
3265                 }
3266                 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
3267                                    tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
3268                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3269                 NDFREE(&tond, NDF_ONLY_PNBUF);
3270         } else {
3271                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3272                 NDFREE(&tond, NDF_ONLY_PNBUF);
3273                 if (tdvp == tvp)
3274                         vrele(tdvp);
3275                 else
3276                         vput(tdvp);
3277                 if (tvp)
3278                         vput(tvp);
3279                 vrele(fromnd.ni_dvp);
3280                 vrele(fvp);
3281         }
3282         vrele(tond.ni_startdir);
3283         ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename");
3284         ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename");
3285         ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename");
3286         ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename");
3287 out1:
3288         vn_finished_write(mp);
3289         if (fromnd.ni_startdir)
3290                 vrele(fromnd.ni_startdir);
3291         VFS_UNLOCK_GIANT(fvfslocked);
3292         VFS_UNLOCK_GIANT(tvfslocked);
3293         if (error == -1)
3294                 return (0);
3295         return (error);
3296 }
3297
3298 /*
3299  * Make a directory file.
3300  */
3301 #ifndef _SYS_SYSPROTO_H_
3302 struct mkdir_args {
3303         char    *path;
3304         int     mode;
3305 };
3306 #endif
3307 int
3308 mkdir(td, uap)
3309         struct thread *td;
3310         register struct mkdir_args /* {
3311                 char *path;
3312                 int mode;
3313         } */ *uap;
3314 {
3315
3316         return (kern_mkdir(td, uap->path, UIO_USERSPACE, uap->mode));
3317 }
3318
3319 int
3320 kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode)
3321 {
3322         struct mount *mp;
3323         struct vnode *vp;
3324         struct vattr vattr;
3325         int error;
3326         struct nameidata nd;
3327         int vfslocked;
3328
3329 restart:
3330         bwillwrite();
3331         NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE, segflg, path, td);
3332         nd.ni_cnd.cn_flags |= WILLBEDIR;
3333         if ((error = namei(&nd)) != 0)
3334                 return (error);
3335         vfslocked = NDHASGIANT(&nd);
3336         vp = nd.ni_vp;
3337         if (vp != NULL) {
3338                 NDFREE(&nd, NDF_ONLY_PNBUF);
3339                 vrele(vp);
3340                 /*
3341                  * XXX namei called with LOCKPARENT but not LOCKLEAF has
3342                  * the strange behaviour of leaving the vnode unlocked
3343                  * if the target is the same vnode as the parent.
3344                  */
3345                 if (vp == nd.ni_dvp)
3346                         vrele(nd.ni_dvp);
3347                 else
3348                         vput(nd.ni_dvp);
3349                 VFS_UNLOCK_GIANT(vfslocked);
3350                 return (EEXIST);
3351         }
3352         if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3353                 NDFREE(&nd, NDF_ONLY_PNBUF);
3354                 vput(nd.ni_dvp);
3355                 VFS_UNLOCK_GIANT(vfslocked);
3356                 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3357                         return (error);
3358                 goto restart;
3359         }
3360         VATTR_NULL(&vattr);
3361         vattr.va_type = VDIR;
3362         FILEDESC_LOCK_FAST(td->td_proc->p_fd);
3363         vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask;
3364         FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
3365 #ifdef MAC
3366         error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
3367             &vattr);
3368         if (error)
3369                 goto out;
3370 #endif
3371         VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3372         error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
3373 #ifdef MAC
3374 out:
3375 #endif
3376         NDFREE(&nd, NDF_ONLY_PNBUF);
3377         vput(nd.ni_dvp);
3378         if (!error)
3379                 vput(nd.ni_vp);
3380         vn_finished_write(mp);
3381         VFS_UNLOCK_GIANT(vfslocked);
3382         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir");
3383         ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir");
3384         return (error);
3385 }
3386
3387 /*
3388  * Remove a directory file.
3389  */
3390 #ifndef _SYS_SYSPROTO_H_
3391 struct rmdir_args {
3392         char    *path;
3393 };
3394 #endif
3395 int
3396 rmdir(td, uap)
3397         struct thread *td;
3398         struct rmdir_args /* {
3399                 char *path;
3400         } */ *uap;
3401 {
3402
3403         return (kern_rmdir(td, uap->path, UIO_USERSPACE));
3404 }
3405
3406 int
3407 kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg)
3408 {
3409         struct mount *mp;
3410         struct vnode *vp;
3411         int error;
3412         struct nameidata nd;
3413         int vfslocked;
3414
3415 restart:
3416         bwillwrite();
3417         NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE, pathseg, path, td);
3418         if ((error = namei(&nd)) != 0)
3419                 return (error);
3420         vfslocked = NDHASGIANT(&nd);
3421         vp = nd.ni_vp;
3422         if (vp->v_type != VDIR) {
3423                 error = ENOTDIR;
3424                 goto out;
3425         }
3426         /*
3427          * No rmdir "." please.
3428          */
3429         if (nd.ni_dvp == vp) {
3430                 error = EINVAL;
3431                 goto out;
3432         }
3433         /*
3434          * The root of a mounted filesystem cannot be deleted.
3435          */
3436         if (vp->v_vflag & VV_ROOT) {
3437                 error = EBUSY;
3438                 goto out;
3439         }
3440 #ifdef MAC
3441         error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp,
3442             &nd.ni_cnd);
3443         if (error)
3444                 goto out;
3445 #endif
3446         if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3447                 NDFREE(&nd, NDF_ONLY_PNBUF);
3448                 if (nd.ni_dvp == vp)
3449                         vrele(nd.ni_dvp);
3450                 else
3451                         vput(nd.ni_dvp);
3452                 vput(vp);
3453                 VFS_UNLOCK_GIANT(vfslocked);
3454                 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3455                         return (error);
3456                 goto restart;
3457         }
3458         VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3459         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3460         error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
3461         vn_finished_write(mp);
3462 out:
3463         NDFREE(&nd, NDF_ONLY_PNBUF);
3464         if (nd.ni_dvp == vp)
3465                 vrele(nd.ni_dvp);
3466         else
3467                 vput(nd.ni_dvp);
3468         vput(vp);
3469         VFS_UNLOCK_GIANT(vfslocked);
3470         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir");
3471         ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir");
3472         return (error);
3473 }
3474
3475 #ifdef COMPAT_43
3476 /*
3477  * Read a block of directory entries in a filesystem independent format.
3478  */
3479 #ifndef _SYS_SYSPROTO_H_
3480 struct ogetdirentries_args {
3481         int     fd;
3482         char    *buf;
3483         u_int   count;
3484         long    *basep;
3485 };
3486 #endif
3487 int
3488 ogetdirentries(td, uap)
3489         struct thread *td;
3490         register struct ogetdirentries_args /* {
3491                 int fd;
3492                 char *buf;
3493                 u_int count;
3494                 long *basep;
3495         } */ *uap;
3496 {
3497         struct vnode *vp;
3498         struct file *fp;
3499         struct uio auio, kuio;
3500         struct iovec aiov, kiov;
3501         struct dirent *dp, *edp;
3502         caddr_t dirbuf;
3503         int error, eofflag, readcnt;
3504         long loff;
3505
3506         /* XXX arbitrary sanity limit on `count'. */
3507         if (uap->count > 64 * 1024)
3508                 return (EINVAL);
3509         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3510                 return (error);
3511         if ((fp->f_flag & FREAD) == 0) {
3512                 fdrop(fp, td);
3513                 return (EBADF);
3514         }
3515         vp = fp->f_vnode;
3516 unionread:
3517         if (vp->v_type != VDIR) {
3518                 fdrop(fp, td);
3519                 return (EINVAL);
3520         }
3521         aiov.iov_base = uap->buf;
3522         aiov.iov_len = uap->count;
3523         auio.uio_iov = &aiov;
3524         auio.uio_iovcnt = 1;
3525         auio.uio_rw = UIO_READ;
3526         auio.uio_segflg = UIO_USERSPACE;
3527         auio.uio_td = td;
3528         auio.uio_resid = uap->count;
3529         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3530         loff = auio.uio_offset = fp->f_offset;
3531 #ifdef MAC
3532         error = mac_check_vnode_readdir(td->td_ucred, vp);
3533         if (error) {
3534                 VOP_UNLOCK(vp, 0, td);
3535                 fdrop(fp, td);
3536                 return (error);
3537         }
3538 #endif
3539 #       if (BYTE_ORDER != LITTLE_ENDIAN)
3540                 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
3541                         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
3542                             NULL, NULL);
3543                         fp->f_offset = auio.uio_offset;
3544                 } else
3545 #       endif
3546         {
3547                 kuio = auio;
3548                 kuio.uio_iov = &kiov;
3549                 kuio.uio_segflg = UIO_SYSSPACE;
3550                 kiov.iov_len = uap->count;
3551                 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
3552                 kiov.iov_base = dirbuf;
3553                 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
3554                             NULL, NULL);
3555                 fp->f_offset = kuio.uio_offset;
3556                 if (error == 0) {
3557                         readcnt = uap->count - kuio.uio_resid;
3558                         edp = (struct dirent *)&dirbuf[readcnt];
3559                         for (dp = (struct dirent *)dirbuf; dp < edp; ) {
3560 #                               if (BYTE_ORDER == LITTLE_ENDIAN)
3561                                         /*
3562                                          * The expected low byte of
3563                                          * dp->d_namlen is our dp->d_type.
3564                                          * The high MBZ byte of dp->d_namlen
3565                                          * is our dp->d_namlen.
3566                                          */
3567                                         dp->d_type = dp->d_namlen;
3568                                         dp->d_namlen = 0;
3569 #                               else
3570                                         /*
3571                                          * The dp->d_type is the high byte
3572                                          * of the expected dp->d_namlen,
3573                                          * so must be zero'ed.
3574                                          */
3575                                         dp->d_type = 0;
3576 #                               endif
3577                                 if (dp->d_reclen > 0) {
3578                                         dp = (struct dirent *)
3579                                             ((char *)dp + dp->d_reclen);
3580                                 } else {
3581                                         error = EIO;
3582                                         break;
3583                                 }
3584                         }
3585                         if (dp >= edp)
3586                                 error = uiomove(dirbuf, readcnt, &auio);
3587                 }
3588                 FREE(dirbuf, M_TEMP);
3589         }
3590         VOP_UNLOCK(vp, 0, td);
3591         if (error) {
3592                 fdrop(fp, td);
3593                 return (error);
3594         }
3595         if (uap->count == auio.uio_resid) {
3596                 if (union_dircheckp) {
3597                         error = union_dircheckp(td, &vp, fp);
3598                         if (error == -1)
3599                                 goto unionread;
3600                         if (error) {
3601                                 fdrop(fp, td);
3602                                 return (error);
3603                         }
3604                 }
3605                 /*
3606                  * XXX We could delay dropping the lock above but
3607                  * union_dircheckp complicates things.
3608                  */
3609                 vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, td);
3610                 if ((vp->v_vflag & VV_ROOT) &&
3611                     (vp->v_mount->mnt_flag & MNT_UNION)) {
3612                         struct vnode *tvp = vp;
3613                         vp = vp->v_mount->mnt_vnodecovered;
3614                         VREF(vp);
3615                         fp->f_vnode = vp;
3616                         fp->f_data = vp;
3617                         fp->f_offset = 0;
3618                         vput(tvp);
3619                         goto unionread;
3620                 }
3621                 VOP_UNLOCK(vp, 0, td);
3622         }
3623         error = copyout(&loff, uap->basep, sizeof(long));
3624         fdrop(fp, td);
3625         td->td_retval[0] = uap->count - auio.uio_resid;
3626         return (error);
3627 }
3628 #endif /* COMPAT_43 */
3629
3630 /*
3631  * Read a block of directory entries in a filesystem independent format.
3632  */
3633 #ifndef _SYS_SYSPROTO_H_
3634 struct getdirentries_args {
3635         int     fd;
3636         char    *buf;
3637         u_int   count;
3638         long    *basep;
3639 };
3640 #endif
3641 int
3642 getdirentries(td, uap)
3643         struct thread *td;
3644         register struct getdirentries_args /* {
3645                 int fd;
3646                 char *buf;
3647                 u_int count;
3648                 long *basep;
3649         } */ *uap;
3650 {
3651         struct vnode *vp;
3652         struct file *fp;
3653         struct uio auio;
3654         struct iovec aiov;
3655         int vfslocked;
3656         long loff;
3657         int error, eofflag;
3658
3659         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3660                 return (error);
3661         if ((fp->f_flag & FREAD) == 0) {
3662                 fdrop(fp, td);
3663                 return (EBADF);
3664         }
3665         vp = fp->f_vnode;
3666 unionread:
3667         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
3668         if (vp->v_type != VDIR) {
3669                 error = EINVAL;
3670                 goto fail;
3671         }
3672         aiov.iov_base = uap->buf;
3673         aiov.iov_len = uap->count;
3674         auio.uio_iov = &aiov;
3675         auio.uio_iovcnt = 1;
3676         auio.uio_rw = UIO_READ;
3677         auio.uio_segflg = UIO_USERSPACE;
3678         auio.uio_td = td;
3679         auio.uio_resid = uap->count;
3680         /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */
3681         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3682         loff = auio.uio_offset = fp->f_offset;
3683 #ifdef MAC
3684         error = mac_check_vnode_readdir(td->td_ucred, vp);
3685         if (error == 0)
3686 #endif
3687                 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL,
3688                     NULL);
3689         fp->f_offset = auio.uio_offset;
3690         VOP_UNLOCK(vp, 0, td);
3691         if (error)
3692                 goto fail;
3693         if (uap->count == auio.uio_resid) {
3694                 if (union_dircheckp) {
3695                         error = union_dircheckp(td, &vp, fp);
3696                         if (error == -1) {
3697                                 VFS_UNLOCK_GIANT(vfslocked);
3698                                 goto unionread;
3699                         }
3700                         if (error)
3701                                 goto fail;
3702                 }
3703                 /*
3704                  * XXX We could delay dropping the lock above but
3705                  * union_dircheckp complicates things.
3706                  */
3707                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3708                 if ((vp->v_vflag & VV_ROOT) &&
3709                     (vp->v_mount->mnt_flag & MNT_UNION)) {
3710                         struct vnode *tvp = vp;
3711                         vp = vp->v_mount->mnt_vnodecovered;
3712                         VREF(vp);
3713                         fp->f_vnode = vp;
3714                         fp->f_data = vp;
3715                         fp->f_offset = 0;
3716                         vput(tvp);
3717                         VFS_UNLOCK_GIANT(vfslocked);
3718                         goto unionread;
3719                 }
3720                 VOP_UNLOCK(vp, 0, td);
3721         }
3722         if (uap->basep != NULL) {
3723                 error = copyout(&loff, uap->basep, sizeof(long));
3724         }
3725         td->td_retval[0] = uap->count - auio.uio_resid;
3726 fail:
3727         VFS_UNLOCK_GIANT(vfslocked);
3728         fdrop(fp, td);
3729         return (error);
3730 }
3731 #ifndef _SYS_SYSPROTO_H_
3732 struct getdents_args {
3733         int fd;
3734         char *buf;
3735         size_t count;
3736 };
3737 #endif
3738 int
3739 getdents(td, uap)
3740         struct thread *td;
3741         register struct getdents_args /* {
3742                 int fd;
3743                 char *buf;
3744                 u_int count;
3745         } */ *uap;
3746 {
3747         struct getdirentries_args ap;
3748         ap.fd = uap->fd;
3749         ap.buf = uap->buf;
3750         ap.count = uap->count;
3751         ap.basep = NULL;
3752         return (getdirentries(td, &ap));
3753 }
3754
3755 /*
3756  * Set the mode mask for creation of filesystem nodes.
3757  *
3758  * MP SAFE
3759  */
3760 #ifndef _SYS_SYSPROTO_H_
3761 struct umask_args {
3762         int     newmask;
3763 };
3764 #endif
3765 int
3766 umask(td, uap)
3767         struct thread *td;
3768         struct umask_args /* {
3769                 int newmask;
3770         } */ *uap;
3771 {
3772         register struct filedesc *fdp;
3773
3774         FILEDESC_LOCK_FAST(td->td_proc->p_fd);
3775         fdp = td->td_proc->p_fd;
3776         td->td_retval[0] = fdp->fd_cmask;
3777         fdp->fd_cmask = uap->newmask & ALLPERMS;
3778         FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
3779         return (0);
3780 }
3781
3782 /*
3783  * Void all references to file by ripping underlying filesystem
3784  * away from vnode.
3785  */
3786 #ifndef _SYS_SYSPROTO_H_
3787 struct revoke_args {
3788         char    *path;
3789 };
3790 #endif
3791 int
3792 revoke(td, uap)
3793         struct thread *td;
3794         register struct revoke_args /* {
3795                 char *path;
3796         } */ *uap;
3797 {
3798         struct vnode *vp;
3799         struct vattr vattr;
3800         int error;
3801         struct nameidata nd;
3802         int vfslocked;
3803
3804         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE, UIO_USERSPACE,
3805             uap->path, td);
3806         if ((error = namei(&nd)) != 0)
3807                 return (error);
3808         vfslocked = NDHASGIANT(&nd);
3809         vp = nd.ni_vp;
3810         NDFREE(&nd, NDF_ONLY_PNBUF);
3811         if (vp->v_type != VCHR) {
3812                 error = EINVAL;
3813                 goto out;
3814         }
3815 #ifdef MAC
3816         error = mac_check_vnode_revoke(td->td_ucred, vp);
3817         if (error)
3818                 goto out;
3819 #endif
3820         error = VOP_GETATTR(vp, &vattr, td->td_ucred, td);
3821         if (error)
3822                 goto out;
3823         if (td->td_ucred->cr_uid != vattr.va_uid) {
3824                 error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL);
3825                 if (error)
3826                         goto out;
3827         }
3828         if (vcount(vp) > 1)
3829                 VOP_REVOKE(vp, REVOKEALL);
3830 out:
3831         vput(vp);
3832         VFS_UNLOCK_GIANT(vfslocked);
3833         return (error);
3834 }
3835
3836 /*
3837  * Convert a user file descriptor to a kernel file entry.
3838  * A reference on the file entry is held upon returning.
3839  */
3840 int
3841 getvnode(fdp, fd, fpp)
3842         struct filedesc *fdp;
3843         int fd;
3844         struct file **fpp;
3845 {
3846         int error;
3847         struct file *fp;
3848
3849         fp = NULL;
3850         if (fdp == NULL)
3851                 error = EBADF;
3852         else {
3853                 FILEDESC_LOCK(fdp);
3854                 if ((u_int)fd >= fdp->fd_nfiles ||
3855                     (fp = fdp->fd_ofiles[fd]) == NULL)
3856                         error = EBADF;
3857                 else if (fp->f_vnode == NULL) {
3858                         fp = NULL;
3859                         error = EINVAL;
3860                 } else {
3861                         fhold(fp);
3862                         error = 0;
3863                 }
3864                 FILEDESC_UNLOCK(fdp);
3865         }
3866         *fpp = fp;
3867         return (error);
3868 }
3869
3870 /*
3871  * Get (NFS) file handle
3872  */
3873 #ifndef _SYS_SYSPROTO_H_
3874 struct lgetfh_args {
3875         char    *fname;
3876         fhandle_t *fhp;
3877 };
3878 #endif
3879 int
3880 lgetfh(td, uap)
3881         struct thread *td;
3882         register struct lgetfh_args *uap;
3883 {
3884         struct nameidata nd;
3885         fhandle_t fh;
3886         register struct vnode *vp;
3887         int vfslocked;
3888         int error;
3889
3890         error = suser(td);
3891         if (error)
3892                 return (error);
3893         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE,
3894             UIO_USERSPACE, uap->fname, td);
3895         error = namei(&nd);
3896         if (error)
3897                 return (error);
3898         vfslocked = NDHASGIANT(&nd);
3899         NDFREE(&nd, NDF_ONLY_PNBUF);
3900         vp = nd.ni_vp;
3901         bzero(&fh, sizeof(fh));
3902         fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
3903         error = VFS_VPTOFH(vp, &fh.fh_fid);
3904         vput(vp);
3905         VFS_UNLOCK_GIANT(vfslocked);
3906         if (error)
3907                 return (error);
3908         error = copyout(&fh, uap->fhp, sizeof (fh));
3909         return (error);
3910 }
3911
3912 #ifndef _SYS_SYSPROTO_H_
3913 struct getfh_args {
3914         char    *fname;
3915         fhandle_t *fhp;
3916 };
3917 #endif
3918 int
3919 getfh(td, uap)
3920         struct thread *td;
3921         register struct getfh_args *uap;
3922 {
3923         struct nameidata nd;
3924         fhandle_t fh;
3925         register struct vnode *vp;
3926         int vfslocked;
3927         int error;
3928
3929         error = suser(td);
3930         if (error)
3931                 return (error);
3932         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE,
3933             UIO_USERSPACE, uap->fname, td);
3934         error = namei(&nd);
3935         if (error)
3936                 return (error);
3937         vfslocked = NDHASGIANT(&nd);
3938         NDFREE(&nd, NDF_ONLY_PNBUF);
3939         vp = nd.ni_vp;
3940         bzero(&fh, sizeof(fh));
3941         fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
3942         error = VFS_VPTOFH(vp, &fh.fh_fid);
3943         vput(vp);
3944         VFS_UNLOCK_GIANT(vfslocked);
3945         if (error)
3946                 return (error);
3947         error = copyout(&fh, uap->fhp, sizeof (fh));
3948         return (error);
3949 }
3950
3951 /*
3952  * syscall for the rpc.lockd to use to translate a NFS file handle into
3953  * an open descriptor.
3954  *
3955  * warning: do not remove the suser() call or this becomes one giant
3956  * security hole.
3957  */
3958 #ifndef _SYS_SYSPROTO_H_
3959 struct fhopen_args {
3960         const struct fhandle *u_fhp;
3961         int flags;
3962 };
3963 #endif
3964 int
3965 fhopen(td, uap)
3966         struct thread *td;
3967         struct fhopen_args /* {
3968                 const struct fhandle *u_fhp;
3969                 int flags;
3970         } */ *uap;
3971 {
3972         struct proc *p = td->td_proc;
3973         struct mount *mp;
3974         struct vnode *vp;
3975         struct fhandle fhp;
3976         struct vattr vat;
3977         struct vattr *vap = &vat;
3978         struct flock lf;
3979         struct file *fp;
3980         register struct filedesc *fdp = p->p_fd;
3981         int fmode, mode, error, type;
3982         struct file *nfp;
3983         int indx;
3984
3985         error = suser(td);
3986         if (error)
3987                 return (error);
3988         fmode = FFLAGS(uap->flags);
3989         /* why not allow a non-read/write open for our lockd? */
3990         if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
3991                 return (EINVAL);
3992         error = copyin(uap->u_fhp, &fhp, sizeof(fhp));
3993         if (error)
3994                 return(error);
3995         /* find the mount point */
3996         mp = vfs_getvfs(&fhp.fh_fsid);
3997         if (mp == NULL)
3998                 return (ESTALE);
3999         /* now give me my vnode, it gets returned to me locked */
4000         error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
4001         if (error)
4002                 return (error);
4003         /*
4004          * from now on we have to make sure not
4005          * to forget about the vnode
4006          * any error that causes an abort must vput(vp)
4007          * just set error = err and 'goto bad;'.
4008          */
4009
4010         /*
4011          * from vn_open
4012          */
4013         if (vp->v_type == VLNK) {
4014                 error = EMLINK;
4015                 goto bad;
4016         }
4017         if (vp->v_type == VSOCK) {
4018                 error = EOPNOTSUPP;
4019                 goto bad;
4020         }
4021         mode = 0;
4022         if (fmode & (FWRITE | O_TRUNC)) {
4023                 if (vp->v_type == VDIR) {
4024                         error = EISDIR;
4025                         goto bad;
4026                 }
4027                 error = vn_writechk(vp);
4028                 if (error)
4029                         goto bad;
4030                 mode |= VWRITE;
4031         }
4032         if (fmode & FREAD)
4033                 mode |= VREAD;
4034         if (fmode & O_APPEND)
4035                 mode |= VAPPEND;
4036 #ifdef MAC
4037         error = mac_check_vnode_open(td->td_ucred, vp, mode);
4038         if (error)
4039                 goto bad;
4040 #endif
4041         if (mode) {
4042                 error = VOP_ACCESS(vp, mode, td->td_ucred, td);
4043                 if (error)
4044                         goto bad;
4045         }
4046         if (fmode & O_TRUNC) {
4047                 VOP_UNLOCK(vp, 0, td);                          /* XXX */
4048                 if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) {
4049                         vrele(vp);
4050                         return (error);
4051                 }
4052                 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4053                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);       /* XXX */
4054 #ifdef MAC
4055                 /*
4056                  * We don't yet have fp->f_cred, so use td->td_ucred, which
4057                  * should be right.
4058                  */
4059                 error = mac_check_vnode_write(td->td_ucred, td->td_ucred, vp);
4060                 if (error == 0) {
4061 #endif
4062                         VATTR_NULL(vap);
4063                         vap->va_size = 0;
4064                         error = VOP_SETATTR(vp, vap, td->td_ucred, td);
4065 #ifdef MAC
4066                 }
4067 #endif
4068                 vn_finished_write(mp);
4069                 if (error)
4070                         goto bad;
4071         }
4072         error = VOP_OPEN(vp, fmode, td->td_ucred, td, -1);
4073         if (error)
4074                 goto bad;
4075
4076         if (fmode & FWRITE)
4077                 vp->v_writecount++;
4078
4079         /*
4080          * end of vn_open code
4081          */
4082
4083         if ((error = falloc(td, &nfp, &indx)) != 0) {
4084                 if (fmode & FWRITE)
4085                         vp->v_writecount--;
4086                 goto bad;
4087         }
4088         /* An extra reference on `nfp' has been held for us by falloc(). */
4089         fp = nfp;
4090
4091         nfp->f_vnode = vp;
4092         nfp->f_data = vp;
4093         nfp->f_flag = fmode & FMASK;
4094         nfp->f_ops = &vnops;
4095         nfp->f_type = DTYPE_VNODE;
4096         if (fmode & (O_EXLOCK | O_SHLOCK)) {
4097                 lf.l_whence = SEEK_SET;
4098                 lf.l_start = 0;
4099                 lf.l_len = 0;
4100                 if (fmode & O_EXLOCK)
4101                         lf.l_type = F_WRLCK;
4102                 else
4103                         lf.l_type = F_RDLCK;
4104                 type = F_FLOCK;
4105                 if ((fmode & FNONBLOCK) == 0)
4106                         type |= F_WAIT;
4107                 VOP_UNLOCK(vp, 0, td);
4108                 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
4109                             type)) != 0) {
4110                         /*
4111                          * The lock request failed.  Normally close the
4112                          * descriptor but handle the case where someone might
4113                          * have dup()d or close()d it when we weren't looking.
4114                          */
4115                         fdclose(fdp, fp, indx, td);
4116
4117                         /*
4118                          * release our private reference
4119                          */
4120                         fdrop(fp, td);
4121                         return(error);
4122                 }
4123                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4124                 fp->f_flag |= FHASLOCK;
4125         }
4126
4127         VOP_UNLOCK(vp, 0, td);
4128         fdrop(fp, td);
4129         td->td_retval[0] = indx;
4130         return (0);
4131
4132 bad:
4133         vput(vp);
4134         return (error);
4135 }
4136
4137 /*
4138  * Stat an (NFS) file handle.
4139  */
4140 #ifndef _SYS_SYSPROTO_H_
4141 struct fhstat_args {
4142         struct fhandle *u_fhp;
4143         struct stat *sb;
4144 };
4145 #endif
4146 int
4147 fhstat(td, uap)
4148         struct thread *td;
4149         register struct fhstat_args /* {
4150                 struct fhandle *u_fhp;
4151                 struct stat *sb;
4152         } */ *uap;
4153 {
4154         struct stat sb;
4155         fhandle_t fh;
4156         struct mount *mp;
4157         struct vnode *vp;
4158         int error;
4159
4160         error = suser(td);
4161         if (error)
4162                 return (error);
4163         error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
4164         if (error)
4165                 return (error);
4166         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
4167                 return (ESTALE);
4168         if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
4169                 return (error);
4170         error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
4171         vput(vp);
4172         if (error)
4173                 return (error);
4174         error = copyout(&sb, uap->sb, sizeof(sb));
4175         return (error);
4176 }
4177
4178 /*
4179  * Implement fstatfs() for (NFS) file handles.
4180  */
4181 #ifndef _SYS_SYSPROTO_H_
4182 struct fhstatfs_args {
4183         struct fhandle *u_fhp;
4184         struct statfs *buf;
4185 };
4186 #endif
4187 int
4188 fhstatfs(td, uap)
4189         struct thread *td;
4190         struct fhstatfs_args /* {
4191                 struct fhandle *u_fhp;
4192                 struct statfs *buf;
4193         } */ *uap;
4194 {
4195         struct statfs sf;
4196         fhandle_t fh;
4197         int error;
4198
4199         if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
4200                 return (error);
4201         error = kern_fhstatfs(td, fh, &sf);
4202         if (error == 0)
4203                 error = copyout(&sf, uap->buf, sizeof(sf));
4204         return (error);
4205 }
4206
4207 int
4208 kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf)
4209 {
4210         struct statfs *sp;
4211         struct mount *mp;
4212         struct vnode *vp;
4213         int error;
4214
4215         error = suser(td);
4216         if (error)
4217                 return (error);
4218         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
4219                 return (ESTALE);
4220         if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
4221                 return (error);
4222         mp = vp->v_mount;
4223         sp = &mp->mnt_stat;
4224         vput(vp);
4225 #ifdef MAC
4226         error = mac_check_mount_stat(td->td_ucred, mp);
4227         if (error)
4228                 return (error);
4229 #endif
4230         /*
4231          * Set these in case the underlying filesystem fails to do so.
4232          */
4233         sp->f_version = STATFS_VERSION;
4234         sp->f_namemax = NAME_MAX;
4235         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
4236         if ((error = VFS_STATFS(mp, sp, td)) != 0)
4237                 return (error);
4238         *buf = *sp;
4239         return (0);
4240 }
4241
4242 /*
4243  * Syscall to push extended attribute configuration information into the
4244  * VFS.  Accepts a path, which it converts to a mountpoint, as well as
4245  * a command (int cmd), and attribute name and misc data.  For now, the
4246  * attribute name is left in userspace for consumption by the VFS_op.
4247  * It will probably be changed to be copied into sysspace by the
4248  * syscall in the future, once issues with various consumers of the
4249  * attribute code have raised their hands.
4250  *
4251  * Currently this is used only by UFS Extended Attributes.
4252  */
4253 int
4254 extattrctl(td, uap)
4255         struct thread *td;
4256         struct extattrctl_args /* {
4257                 const char *path;
4258                 int cmd;
4259                 const char *filename;
4260                 int attrnamespace;
4261                 const char *attrname;
4262         } */ *uap;
4263 {
4264         struct vnode *filename_vp;
4265         struct nameidata nd;
4266         struct mount *mp, *mp_writable;
4267         char attrname[EXTATTR_MAXNAMELEN];
4268         int error;
4269
4270         /*
4271          * uap->attrname is not always defined.  We check again later when we
4272          * invoke the VFS call so as to pass in NULL there if needed.
4273          */
4274         if (uap->attrname != NULL) {
4275                 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN,
4276                     NULL);
4277                 if (error)
4278                         return (error);
4279         }
4280
4281         /*
4282          * uap->filename is not always defined.  If it is, grab a vnode lock,
4283          * which VFS_EXTATTRCTL() will later release.
4284          */
4285         filename_vp = NULL;
4286         if (uap->filename != NULL) {
4287                 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
4288                     uap->filename, td);
4289                 error = namei(&nd);
4290                 if (error)
4291                         return (error);
4292                 filename_vp = nd.ni_vp;
4293                 NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK);
4294         }
4295
4296         /* uap->path is always defined. */
4297         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
4298         error = namei(&nd);
4299         if (error) {
4300                 if (filename_vp != NULL)
4301                         vput(filename_vp);
4302                 return (error);
4303         }
4304         mp = nd.ni_vp->v_mount;
4305         error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
4306         NDFREE(&nd, 0);
4307         if (error) {
4308                 if (filename_vp != NULL)
4309                         vput(filename_vp);
4310                 return (error);
4311         }
4312
4313         error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, uap->attrnamespace,
4314             uap->attrname != NULL ? attrname : NULL, td);
4315
4316         vn_finished_write(mp_writable);
4317         /*
4318          * VFS_EXTATTRCTL will have unlocked, but not de-ref'd,
4319          * filename_vp, so vrele it if it is defined.
4320          */
4321         if (filename_vp != NULL)
4322                 vrele(filename_vp);
4323         return (error);
4324 }
4325
4326 /*-
4327  * Set a named extended attribute on a file or directory
4328  *
4329  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4330  *            kernelspace string pointer "attrname", userspace buffer
4331  *            pointer "data", buffer length "nbytes", thread "td".
4332  * Returns: 0 on success, an error number otherwise
4333  * Locks: none
4334  * References: vp must be a valid reference for the duration of the call
4335  */
4336 static int
4337 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4338     void *data, size_t nbytes, struct thread *td)
4339 {
4340         struct mount *mp;
4341         struct uio auio;
4342         struct iovec aiov;
4343         ssize_t cnt;
4344         int error;
4345
4346         error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
4347         if (error)
4348                 return (error);
4349         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4350         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4351
4352         aiov.iov_base = data;
4353         aiov.iov_len = nbytes;
4354         auio.uio_iov = &aiov;
4355         auio.uio_iovcnt = 1;
4356         auio.uio_offset = 0;
4357         if (nbytes > INT_MAX) {
4358                 error = EINVAL;
4359                 goto done;
4360         }
4361         auio.uio_resid = nbytes;
4362         auio.uio_rw = UIO_WRITE;
4363         auio.uio_segflg = UIO_USERSPACE;
4364         auio.uio_td = td;
4365         cnt = nbytes;
4366
4367 #ifdef MAC
4368         error = mac_check_vnode_setextattr(td->td_ucred, vp, attrnamespace,
4369             attrname, &auio);
4370         if (error)
4371                 goto done;
4372 #endif
4373
4374         error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
4375             td->td_ucred, td);
4376         cnt -= auio.uio_resid;
4377         td->td_retval[0] = cnt;
4378
4379 done:
4380         VOP_UNLOCK(vp, 0, td);
4381         vn_finished_write(mp);
4382         return (error);
4383 }
4384
4385 int
4386 extattr_set_fd(td, uap)
4387         struct thread *td;
4388         struct extattr_set_fd_args /* {
4389                 int fd;
4390                 int attrnamespace;
4391                 const char *attrname;
4392                 void *data;
4393                 size_t nbytes;
4394         } */ *uap;
4395 {
4396         struct file *fp;
4397         char attrname[EXTATTR_MAXNAMELEN];
4398         int error;
4399
4400         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4401         if (error)
4402                 return (error);
4403
4404         error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4405         if (error)
4406                 return (error);
4407
4408         error = extattr_set_vp(fp->f_vnode, uap->attrnamespace,
4409             attrname, uap->data, uap->nbytes, td);
4410         fdrop(fp, td);
4411
4412         return (error);
4413 }
4414
4415 int
4416 extattr_set_file(td, uap)
4417         struct thread *td;
4418         struct extattr_set_file_args /* {
4419                 const char *path;
4420                 int attrnamespace;
4421                 const char *attrname;
4422                 void *data;
4423                 size_t nbytes;
4424         } */ *uap;
4425 {
4426         struct nameidata nd;
4427         char attrname[EXTATTR_MAXNAMELEN];
4428         int error;
4429
4430         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4431         if (error)
4432                 return (error);
4433
4434         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
4435         error = namei(&nd);
4436         if (error)
4437                 return (error);
4438         NDFREE(&nd, NDF_ONLY_PNBUF);
4439
4440         error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
4441             uap->data, uap->nbytes, td);
4442
4443         vrele(nd.ni_vp);
4444         return (error);
4445 }
4446
4447 int
4448 extattr_set_link(td, uap)
4449         struct thread *td;
4450         struct extattr_set_link_args /* {
4451                 const char *path;
4452                 int attrnamespace;
4453                 const char *attrname;
4454                 void *data;
4455                 size_t nbytes;
4456         } */ *uap;
4457 {
4458         struct nameidata nd;
4459         char attrname[EXTATTR_MAXNAMELEN];
4460         int error;
4461
4462         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4463         if (error)
4464                 return (error);
4465
4466         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
4467         error = namei(&nd);
4468         if (error)
4469                 return (error);
4470         NDFREE(&nd, NDF_ONLY_PNBUF);
4471
4472         error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
4473             uap->data, uap->nbytes, td);
4474
4475         vrele(nd.ni_vp);
4476         return (error);
4477 }
4478
4479 /*-
4480  * Get a named extended attribute on a file or directory
4481  *
4482  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4483  *            kernelspace string pointer "attrname", userspace buffer
4484  *            pointer "data", buffer length "nbytes", thread "td".
4485  * Returns: 0 on success, an error number otherwise
4486  * Locks: none
4487  * References: vp must be a valid reference for the duration of the call
4488  */
4489 static int
4490 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4491     void *data, size_t nbytes, struct thread *td)
4492 {
4493         struct uio auio, *auiop;
4494         struct iovec aiov;
4495         ssize_t cnt;
4496         size_t size, *sizep;
4497         int error;
4498
4499         VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
4500         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4501
4502         /*
4503          * Slightly unusual semantics: if the user provides a NULL data
4504          * pointer, they don't want to receive the data, just the
4505          * maximum read length.
4506          */
4507         auiop = NULL;
4508         sizep = NULL;
4509         cnt = 0;
4510         if (data != NULL) {
4511                 aiov.iov_base = data;
4512                 aiov.iov_len = nbytes;
4513                 auio.uio_iov = &aiov;
4514                 auio.uio_offset = 0;
4515                 if (nbytes > INT_MAX) {
4516                         error = EINVAL;
4517                         goto done;
4518                 }
4519                 auio.uio_resid = nbytes;
4520                 auio.uio_rw = UIO_READ;
4521                 auio.uio_segflg = UIO_USERSPACE;
4522                 auio.uio_td = td;
4523                 auiop = &auio;
4524                 cnt = nbytes;
4525         } else
4526                 sizep = &size;
4527
4528 #ifdef MAC
4529         error = mac_check_vnode_getextattr(td->td_ucred, vp, attrnamespace,
4530             attrname, &auio);
4531         if (error)
4532                 goto done;
4533 #endif
4534
4535         error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
4536             td->td_ucred, td);
4537
4538         if (auiop != NULL) {
4539                 cnt -= auio.uio_resid;
4540                 td->td_retval[0] = cnt;
4541         } else
4542                 td->td_retval[0] = size;
4543
4544 done:
4545         VOP_UNLOCK(vp, 0, td);
4546         return (error);
4547 }
4548
4549 int
4550 extattr_get_fd(td, uap)
4551         struct thread *td;
4552         struct extattr_get_fd_args /* {
4553                 int fd;
4554                 int attrnamespace;
4555                 const char *attrname;
4556                 void *data;
4557                 size_t nbytes;
4558         } */ *uap;
4559 {
4560         struct file *fp;
4561         char attrname[EXTATTR_MAXNAMELEN];
4562         int error;
4563
4564         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4565         if (error)
4566                 return (error);
4567
4568         error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4569         if (error)
4570                 return (error);
4571
4572         error = extattr_get_vp(fp->f_vnode, uap->attrnamespace,
4573             attrname, uap->data, uap->nbytes, td);
4574
4575         fdrop(fp, td);
4576         return (error);
4577 }
4578
4579 int
4580 extattr_get_file(td, uap)
4581         struct thread *td;
4582         struct extattr_get_file_args /* {
4583                 const char *path;
4584                 int attrnamespace;
4585                 const char *attrname;
4586                 void *data;
4587                 size_t nbytes;
4588         } */ *uap;
4589 {
4590         struct nameidata nd;
4591         char attrname[EXTATTR_MAXNAMELEN];
4592         int error;
4593
4594         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4595         if (error)
4596                 return (error);
4597
4598         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
4599         error = namei(&nd);
4600         if (error)
4601                 return (error);
4602         NDFREE(&nd, NDF_ONLY_PNBUF);
4603
4604         error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
4605             uap->data, uap->nbytes, td);
4606
4607         vrele(nd.ni_vp);
4608         return (error);
4609 }
4610
4611 int
4612 extattr_get_link(td, uap)
4613         struct thread *td;
4614         struct extattr_get_link_args /* {
4615                 const char *path;
4616                 int attrnamespace;
4617                 const char *attrname;
4618                 void *data;
4619                 size_t nbytes;
4620         } */ *uap;
4621 {
4622         struct nameidata nd;
4623         char attrname[EXTATTR_MAXNAMELEN];
4624         int error;
4625
4626         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4627         if (error)
4628                 return (error);
4629
4630         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
4631         error = namei(&nd);
4632         if (error)
4633                 return (error);
4634         NDFREE(&nd, NDF_ONLY_PNBUF);
4635
4636         error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
4637             uap->data, uap->nbytes, td);
4638
4639         vrele(nd.ni_vp);
4640         return (error);
4641 }
4642
4643 /*
4644  * extattr_delete_vp(): Delete a named extended attribute on a file or
4645  *                      directory
4646  *
4647  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4648  *            kernelspace string pointer "attrname", proc "p"
4649  * Returns: 0 on success, an error number otherwise
4650  * Locks: none
4651  * References: vp must be a valid reference for the duration of the call
4652  */
4653 static int
4654 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4655     struct thread *td)
4656 {
4657         struct mount *mp;
4658         int error;
4659
4660         error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
4661         if (error)
4662                 return (error);
4663         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4664         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4665
4666 #ifdef MAC
4667         error = mac_check_vnode_deleteextattr(td->td_ucred, vp, attrnamespace,
4668             attrname);
4669         if (error)
4670                 goto done;
4671 #endif
4672
4673         error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, td->td_ucred,
4674             td);
4675         if (error == EOPNOTSUPP)
4676                 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
4677                     td->td_ucred, td);
4678 #ifdef MAC
4679 done:
4680 #endif
4681         VOP_UNLOCK(vp, 0, td);
4682         vn_finished_write(mp);
4683         return (error);
4684 }
4685
4686 int
4687 extattr_delete_fd(td, uap)
4688         struct thread *td;
4689         struct extattr_delete_fd_args /* {
4690                 int fd;
4691                 int attrnamespace;
4692                 const char *attrname;
4693         } */ *uap;
4694 {
4695         struct file *fp;
4696         struct vnode *vp;
4697         char attrname[EXTATTR_MAXNAMELEN];
4698         int error;
4699
4700         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4701         if (error)
4702                 return (error);
4703
4704         error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4705         if (error)
4706                 return (error);
4707         vp = fp->f_vnode;
4708
4709         error = extattr_delete_vp(vp, uap->attrnamespace, attrname, td);
4710         fdrop(fp, td);
4711         return (error);
4712 }
4713
4714 int
4715 extattr_delete_file(td, uap)
4716         struct thread *td;
4717         struct extattr_delete_file_args /* {
4718                 const char *path;
4719                 int attrnamespace;
4720                 const char *attrname;
4721         } */ *uap;
4722 {
4723         struct nameidata nd;
4724         char attrname[EXTATTR_MAXNAMELEN];
4725         int error;
4726
4727         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4728         if (error)
4729                 return(error);
4730
4731         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
4732         error = namei(&nd);
4733         if (error)
4734                 return(error);
4735         NDFREE(&nd, NDF_ONLY_PNBUF);
4736
4737         error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
4738         vrele(nd.ni_vp);
4739         return(error);
4740 }
4741
4742 int
4743 extattr_delete_link(td, uap)
4744         struct thread *td;
4745         struct extattr_delete_link_args /* {
4746                 const char *path;
4747                 int attrnamespace;
4748                 const char *attrname;
4749         } */ *uap;
4750 {
4751         struct nameidata nd;
4752         char attrname[EXTATTR_MAXNAMELEN];
4753         int error;
4754
4755         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4756         if (error)
4757                 return(error);
4758
4759         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
4760         error = namei(&nd);
4761         if (error)
4762                 return(error);
4763         NDFREE(&nd, NDF_ONLY_PNBUF);
4764
4765         error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
4766         vrele(nd.ni_vp);
4767         return(error);
4768 }
4769
4770 /*-
4771  * Retrieve a list of extended attributes on a file or directory.
4772  *
4773  * Arguments: unlocked vnode "vp", attribute namespace 'attrnamespace",
4774  *            userspace buffer pointer "data", buffer length "nbytes",
4775  *            thread "td".
4776  * Returns: 0 on success, an error number otherwise
4777  * Locks: none
4778  * References: vp must be a valid reference for the duration of the call
4779  */
4780 static int
4781 extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
4782     size_t nbytes, struct thread *td)
4783 {
4784         struct uio auio, *auiop;
4785         size_t size, *sizep;
4786         struct iovec aiov;
4787         ssize_t cnt;
4788         int error;
4789
4790         VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
4791         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4792
4793         auiop = NULL;
4794         sizep = NULL;
4795         cnt = 0;
4796         if (data != NULL) {
4797                 aiov.iov_base = data;
4798                 aiov.iov_len = nbytes;
4799                 auio.uio_iov = &aiov;
4800                 auio.uio_offset = 0;
4801                 if (nbytes > INT_MAX) {
4802                         error = EINVAL;
4803                         goto done;
4804                 }
4805                 auio.uio_resid = nbytes;
4806                 auio.uio_rw = UIO_READ;
4807                 auio.uio_segflg = UIO_USERSPACE;
4808                 auio.uio_td = td;
4809                 auiop = &auio;
4810                 cnt = nbytes;
4811         } else
4812                 sizep = &size;
4813
4814 #ifdef MAC
4815         error = mac_check_vnode_listextattr(td->td_ucred, vp, attrnamespace);
4816         if (error)
4817                 goto done;
4818 #endif
4819
4820         error = VOP_LISTEXTATTR(vp, attrnamespace, auiop, sizep,
4821             td->td_ucred, td);
4822
4823         if (auiop != NULL) {
4824                 cnt -= auio.uio_resid;
4825                 td->td_retval[0] = cnt;
4826         } else
4827                 td->td_retval[0] = size;
4828
4829 done:
4830         VOP_UNLOCK(vp, 0, td);
4831         return (error);
4832 }
4833
4834
4835 int
4836 extattr_list_fd(td, uap)
4837         struct thread *td;
4838         struct extattr_list_fd_args /* {
4839                 int fd;
4840                 int attrnamespace;
4841                 void *data;
4842                 size_t nbytes;
4843         } */ *uap;
4844 {
4845         struct file *fp;
4846         int error;
4847
4848         error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4849         if (error)
4850                 return (error);
4851
4852         error = extattr_list_vp(fp->f_vnode, uap->attrnamespace, uap->data,
4853             uap->nbytes, td);
4854
4855         fdrop(fp, td);
4856         return (error);
4857 }
4858
4859 int
4860 extattr_list_file(td, uap)
4861         struct thread*td;
4862         struct extattr_list_file_args /* {
4863                 const char *path;
4864                 int attrnamespace;
4865                 void *data;
4866                 size_t nbytes;
4867         } */ *uap;
4868 {
4869         struct nameidata nd;
4870         int error;
4871
4872         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
4873         error = namei(&nd);
4874         if (error)
4875                 return (error);
4876         NDFREE(&nd, NDF_ONLY_PNBUF);
4877
4878         error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
4879             uap->nbytes, td);
4880
4881         vrele(nd.ni_vp);
4882         return (error);
4883 }
4884
4885 int
4886 extattr_list_link(td, uap)
4887         struct thread*td;
4888         struct extattr_list_link_args /* {
4889                 const char *path;
4890                 int attrnamespace;
4891                 void *data;
4892                 size_t nbytes;
4893         } */ *uap;
4894 {
4895         struct nameidata nd;
4896         int error;
4897
4898         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
4899         error = namei(&nd);
4900         if (error)
4901                 return (error);
4902         NDFREE(&nd, NDF_ONLY_PNBUF);
4903
4904         error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
4905             uap->nbytes, td);
4906
4907         vrele(nd.ni_vp);
4908         return (error);
4909 }