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