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