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