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