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