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