]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/kern/vfs_extattr.c
This commit was generated by cvs2svn to compensate for changes in r91586,
[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         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2033             SCARG(uap, path), td);
2034         if ((error = namei(&nd)) != 0)
2035                 return (error);
2036         error = vn_stat(nd.ni_vp, &sb, td);
2037         NDFREE(&nd, NDF_ONLY_PNBUF);
2038         vput(nd.ni_vp);
2039         if (error)
2040                 return (error);
2041         error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
2042         return (error);
2043 }
2044
2045 /*
2046  * Get file status; this version does not follow links.
2047  */
2048 #ifndef _SYS_SYSPROTO_H_
2049 struct lstat_args {
2050         char    *path;
2051         struct stat *ub;
2052 };
2053 #endif
2054 /* ARGSUSED */
2055 int
2056 lstat(td, uap)
2057         struct thread *td;
2058         register struct lstat_args /* {
2059                 syscallarg(char *) path;
2060                 syscallarg(struct stat *) ub;
2061         } */ *uap;
2062 {
2063         int error;
2064         struct vnode *vp;
2065         struct stat sb;
2066         struct nameidata nd;
2067
2068         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2069             SCARG(uap, path), td);
2070         if ((error = namei(&nd)) != 0)
2071                 return (error);
2072         vp = nd.ni_vp;
2073         error = vn_stat(vp, &sb, td);
2074         NDFREE(&nd, NDF_ONLY_PNBUF);
2075         vput(vp);
2076         if (error)
2077                 return (error);
2078         error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
2079         return (error);
2080 }
2081
2082 /*
2083  * Implementation of the NetBSD stat() function.
2084  * XXX This should probably be collapsed with the FreeBSD version,
2085  * as the differences are only due to vn_stat() clearing spares at
2086  * the end of the structures.  vn_stat could be split to avoid this,
2087  * and thus collapse the following to close to zero code.
2088  */
2089 void
2090 cvtnstat(sb, nsb)
2091         struct stat *sb;
2092         struct nstat *nsb;
2093 {
2094         nsb->st_dev = sb->st_dev;
2095         nsb->st_ino = sb->st_ino;
2096         nsb->st_mode = sb->st_mode;
2097         nsb->st_nlink = sb->st_nlink;
2098         nsb->st_uid = sb->st_uid;
2099         nsb->st_gid = sb->st_gid;
2100         nsb->st_rdev = sb->st_rdev;
2101         nsb->st_atimespec = sb->st_atimespec;
2102         nsb->st_mtimespec = sb->st_mtimespec;
2103         nsb->st_ctimespec = sb->st_ctimespec;
2104         nsb->st_size = sb->st_size;
2105         nsb->st_blocks = sb->st_blocks;
2106         nsb->st_blksize = sb->st_blksize;
2107         nsb->st_flags = sb->st_flags;
2108         nsb->st_gen = sb->st_gen;
2109         nsb->st_qspare[0] = sb->st_qspare[0];
2110         nsb->st_qspare[1] = sb->st_qspare[1];
2111 }
2112
2113 #ifndef _SYS_SYSPROTO_H_
2114 struct nstat_args {
2115         char    *path;
2116         struct nstat *ub;
2117 };
2118 #endif
2119 /* ARGSUSED */
2120 int
2121 nstat(td, uap)
2122         struct thread *td;
2123         register struct nstat_args /* {
2124                 syscallarg(char *) path;
2125                 syscallarg(struct nstat *) ub;
2126         } */ *uap;
2127 {
2128         struct stat sb;
2129         struct nstat nsb;
2130         int error;
2131         struct nameidata nd;
2132
2133         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2134             SCARG(uap, path), td);
2135         if ((error = namei(&nd)) != 0)
2136                 return (error);
2137         NDFREE(&nd, NDF_ONLY_PNBUF);
2138         error = vn_stat(nd.ni_vp, &sb, td);
2139         vput(nd.ni_vp);
2140         if (error)
2141                 return (error);
2142         cvtnstat(&sb, &nsb);
2143         error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
2144         return (error);
2145 }
2146
2147 /*
2148  * NetBSD lstat.  Get file status; this version does not follow links.
2149  */
2150 #ifndef _SYS_SYSPROTO_H_
2151 struct lstat_args {
2152         char    *path;
2153         struct stat *ub;
2154 };
2155 #endif
2156 /* ARGSUSED */
2157 int
2158 nlstat(td, uap)
2159         struct thread *td;
2160         register struct nlstat_args /* {
2161                 syscallarg(char *) path;
2162                 syscallarg(struct nstat *) ub;
2163         } */ *uap;
2164 {
2165         int error;
2166         struct vnode *vp;
2167         struct stat sb;
2168         struct nstat nsb;
2169         struct nameidata nd;
2170
2171         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2172             SCARG(uap, path), td);
2173         if ((error = namei(&nd)) != 0)
2174                 return (error);
2175         vp = nd.ni_vp;
2176         NDFREE(&nd, NDF_ONLY_PNBUF);
2177         error = vn_stat(vp, &sb, td);
2178         vput(vp);
2179         if (error)
2180                 return (error);
2181         cvtnstat(&sb, &nsb);
2182         error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
2183         return (error);
2184 }
2185
2186 /*
2187  * Get configurable pathname variables.
2188  */
2189 #ifndef _SYS_SYSPROTO_H_
2190 struct pathconf_args {
2191         char    *path;
2192         int     name;
2193 };
2194 #endif
2195 /* ARGSUSED */
2196 int
2197 pathconf(td, uap)
2198         struct thread *td;
2199         register struct pathconf_args /* {
2200                 syscallarg(char *) path;
2201                 syscallarg(int) name;
2202         } */ *uap;
2203 {
2204         int error;
2205         struct nameidata nd;
2206
2207         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2208             SCARG(uap, path), td);
2209         if ((error = namei(&nd)) != 0)
2210                 return (error);
2211         NDFREE(&nd, NDF_ONLY_PNBUF);
2212         error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), td->td_retval);
2213         vput(nd.ni_vp);
2214         return (error);
2215 }
2216
2217 /*
2218  * Return target name of a symbolic link.
2219  */
2220 #ifndef _SYS_SYSPROTO_H_
2221 struct readlink_args {
2222         char    *path;
2223         char    *buf;
2224         int     count;
2225 };
2226 #endif
2227 /* ARGSUSED */
2228 int
2229 readlink(td, uap)
2230         struct thread *td;
2231         register struct readlink_args /* {
2232                 syscallarg(char *) path;
2233                 syscallarg(char *) buf;
2234                 syscallarg(int) count;
2235         } */ *uap;
2236 {
2237         register struct vnode *vp;
2238         struct iovec aiov;
2239         struct uio auio;
2240         int error;
2241         struct nameidata nd;
2242
2243         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
2244             SCARG(uap, path), td);
2245         if ((error = namei(&nd)) != 0)
2246                 return (error);
2247         NDFREE(&nd, NDF_ONLY_PNBUF);
2248         vp = nd.ni_vp;
2249         if (vp->v_type != VLNK)
2250                 error = EINVAL;
2251         else {
2252                 aiov.iov_base = SCARG(uap, buf);
2253                 aiov.iov_len = SCARG(uap, count);
2254                 auio.uio_iov = &aiov;
2255                 auio.uio_iovcnt = 1;
2256                 auio.uio_offset = 0;
2257                 auio.uio_rw = UIO_READ;
2258                 auio.uio_segflg = UIO_USERSPACE;
2259                 auio.uio_td = td;
2260                 auio.uio_resid = SCARG(uap, count);
2261                 error = VOP_READLINK(vp, &auio, td->td_ucred);
2262         }
2263         vput(vp);
2264         td->td_retval[0] = SCARG(uap, count) - auio.uio_resid;
2265         return (error);
2266 }
2267
2268 /*
2269  * Common implementation code for chflags() and fchflags().
2270  */
2271 static int
2272 setfflags(td, vp, flags)
2273         struct thread *td;
2274         struct vnode *vp;
2275         int flags;
2276 {
2277         int error;
2278         struct mount *mp;
2279         struct vattr vattr;
2280
2281         /*
2282          * Prevent non-root users from setting flags on devices.  When
2283          * a device is reused, users can retain ownership of the device
2284          * if they are allowed to set flags and programs assume that
2285          * chown can't fail when done as root.
2286          */
2287         if (vp->v_type == VCHR || vp->v_type == VBLK) {
2288                 error = suser_xxx(td->td_ucred, td->td_proc,
2289                     PRISON_ROOT);
2290                 if (error)
2291                         return (error);
2292         }
2293
2294         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2295                 return (error);
2296         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2297         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2298         VATTR_NULL(&vattr);
2299         vattr.va_flags = flags;
2300         error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2301         VOP_UNLOCK(vp, 0, td);
2302         vn_finished_write(mp);
2303         return (error);
2304 }
2305
2306 /*
2307  * Change flags of a file given a path name.
2308  */
2309 #ifndef _SYS_SYSPROTO_H_
2310 struct chflags_args {
2311         char    *path;
2312         int     flags;
2313 };
2314 #endif
2315 /* ARGSUSED */
2316 int
2317 chflags(td, uap)
2318         struct thread *td;
2319         register struct chflags_args /* {
2320                 syscallarg(char *) path;
2321                 syscallarg(int) flags;
2322         } */ *uap;
2323 {
2324         int error;
2325         struct nameidata nd;
2326
2327         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2328         if ((error = namei(&nd)) != 0)
2329                 return (error);
2330         NDFREE(&nd, NDF_ONLY_PNBUF);
2331         error = setfflags(td, nd.ni_vp, SCARG(uap, flags));
2332         vrele(nd.ni_vp);
2333         return error;
2334 }
2335
2336 /*
2337  * Change flags of a file given a file descriptor.
2338  */
2339 #ifndef _SYS_SYSPROTO_H_
2340 struct fchflags_args {
2341         int     fd;
2342         int     flags;
2343 };
2344 #endif
2345 /* ARGSUSED */
2346 int
2347 fchflags(td, uap)
2348         struct thread *td;
2349         register struct fchflags_args /* {
2350                 syscallarg(int) fd;
2351                 syscallarg(int) flags;
2352         } */ *uap;
2353 {
2354         struct file *fp;
2355         int error;
2356
2357         if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2358                 return (error);
2359         error = setfflags(td, (struct vnode *) fp->f_data, SCARG(uap, flags));
2360         fdrop(fp, td);
2361         return (error);
2362 }
2363
2364 /*
2365  * Common implementation code for chmod(), lchmod() and fchmod().
2366  */
2367 static int
2368 setfmode(td, vp, mode)
2369         struct thread *td;
2370         struct vnode *vp;
2371         int mode;
2372 {
2373         int error;
2374         struct mount *mp;
2375         struct vattr vattr;
2376
2377         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2378                 return (error);
2379         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2380         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2381         VATTR_NULL(&vattr);
2382         vattr.va_mode = mode & ALLPERMS;
2383         error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2384         VOP_UNLOCK(vp, 0, td);
2385         vn_finished_write(mp);
2386         return error;
2387 }
2388
2389 /*
2390  * Change mode of a file given path name.
2391  */
2392 #ifndef _SYS_SYSPROTO_H_
2393 struct chmod_args {
2394         char    *path;
2395         int     mode;
2396 };
2397 #endif
2398 /* ARGSUSED */
2399 int
2400 chmod(td, uap)
2401         struct thread *td;
2402         register struct chmod_args /* {
2403                 syscallarg(char *) path;
2404                 syscallarg(int) mode;
2405         } */ *uap;
2406 {
2407         int error;
2408         struct nameidata nd;
2409
2410         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2411         if ((error = namei(&nd)) != 0)
2412                 return (error);
2413         NDFREE(&nd, NDF_ONLY_PNBUF);
2414         error = setfmode(td, nd.ni_vp, SCARG(uap, mode));
2415         vrele(nd.ni_vp);
2416         return error;
2417 }
2418
2419 /*
2420  * Change mode of a file given path name (don't follow links.)
2421  */
2422 #ifndef _SYS_SYSPROTO_H_
2423 struct lchmod_args {
2424         char    *path;
2425         int     mode;
2426 };
2427 #endif
2428 /* ARGSUSED */
2429 int
2430 lchmod(td, uap)
2431         struct thread *td;
2432         register struct lchmod_args /* {
2433                 syscallarg(char *) path;
2434                 syscallarg(int) mode;
2435         } */ *uap;
2436 {
2437         int error;
2438         struct nameidata nd;
2439
2440         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2441         if ((error = namei(&nd)) != 0)
2442                 return (error);
2443         NDFREE(&nd, NDF_ONLY_PNBUF);
2444         error = setfmode(td, nd.ni_vp, SCARG(uap, mode));
2445         vrele(nd.ni_vp);
2446         return error;
2447 }
2448
2449 /*
2450  * Change mode of a file given a file descriptor.
2451  */
2452 #ifndef _SYS_SYSPROTO_H_
2453 struct fchmod_args {
2454         int     fd;
2455         int     mode;
2456 };
2457 #endif
2458 /* ARGSUSED */
2459 int
2460 fchmod(td, uap)
2461         struct thread *td;
2462         register struct fchmod_args /* {
2463                 syscallarg(int) fd;
2464                 syscallarg(int) mode;
2465         } */ *uap;
2466 {
2467         struct file *fp;
2468         struct vnode *vp;
2469         int error;
2470
2471         if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2472                 return (error);
2473         vp = (struct vnode *)fp->f_data;
2474         error = setfmode(td, (struct vnode *)fp->f_data, SCARG(uap, mode));
2475         fdrop(fp, td);
2476         return (error);
2477 }
2478
2479 /*
2480  * Common implementation for chown(), lchown(), and fchown()
2481  */
2482 static int
2483 setfown(td, vp, uid, gid)
2484         struct thread *td;
2485         struct vnode *vp;
2486         uid_t uid;
2487         gid_t gid;
2488 {
2489         int error;
2490         struct mount *mp;
2491         struct vattr vattr;
2492
2493         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2494                 return (error);
2495         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2496         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2497         VATTR_NULL(&vattr);
2498         vattr.va_uid = uid;
2499         vattr.va_gid = gid;
2500         error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2501         VOP_UNLOCK(vp, 0, td);
2502         vn_finished_write(mp);
2503         return error;
2504 }
2505
2506 /*
2507  * Set ownership given a path name.
2508  */
2509 #ifndef _SYS_SYSPROTO_H_
2510 struct chown_args {
2511         char    *path;
2512         int     uid;
2513         int     gid;
2514 };
2515 #endif
2516 /* ARGSUSED */
2517 int
2518 chown(td, uap)
2519         struct thread *td;
2520         register struct chown_args /* {
2521                 syscallarg(char *) path;
2522                 syscallarg(int) uid;
2523                 syscallarg(int) gid;
2524         } */ *uap;
2525 {
2526         int error;
2527         struct nameidata nd;
2528
2529         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2530         if ((error = namei(&nd)) != 0)
2531                 return (error);
2532         NDFREE(&nd, NDF_ONLY_PNBUF);
2533         error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2534         vrele(nd.ni_vp);
2535         return (error);
2536 }
2537
2538 /*
2539  * Set ownership given a path name, do not cross symlinks.
2540  */
2541 #ifndef _SYS_SYSPROTO_H_
2542 struct lchown_args {
2543         char    *path;
2544         int     uid;
2545         int     gid;
2546 };
2547 #endif
2548 /* ARGSUSED */
2549 int
2550 lchown(td, uap)
2551         struct thread *td;
2552         register struct lchown_args /* {
2553                 syscallarg(char *) path;
2554                 syscallarg(int) uid;
2555                 syscallarg(int) gid;
2556         } */ *uap;
2557 {
2558         int error;
2559         struct nameidata nd;
2560
2561         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2562         if ((error = namei(&nd)) != 0)
2563                 return (error);
2564         NDFREE(&nd, NDF_ONLY_PNBUF);
2565         error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2566         vrele(nd.ni_vp);
2567         return (error);
2568 }
2569
2570 /*
2571  * Set ownership given a file descriptor.
2572  */
2573 #ifndef _SYS_SYSPROTO_H_
2574 struct fchown_args {
2575         int     fd;
2576         int     uid;
2577         int     gid;
2578 };
2579 #endif
2580 /* ARGSUSED */
2581 int
2582 fchown(td, uap)
2583         struct thread *td;
2584         register struct fchown_args /* {
2585                 syscallarg(int) fd;
2586                 syscallarg(int) uid;
2587                 syscallarg(int) gid;
2588         } */ *uap;
2589 {
2590         struct file *fp;
2591         struct vnode *vp;
2592         int error;
2593
2594         if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2595                 return (error);
2596         vp = (struct vnode *)fp->f_data;
2597         error = setfown(td, (struct vnode *)fp->f_data,
2598                 SCARG(uap, uid), SCARG(uap, gid));
2599         fdrop(fp, td);
2600         return (error);
2601 }
2602
2603 /*
2604  * Common implementation code for utimes(), lutimes(), and futimes().
2605  */
2606 static int
2607 getutimes(usrtvp, tsp)
2608         const struct timeval *usrtvp;
2609         struct timespec *tsp;
2610 {
2611         struct timeval tv[2];
2612         int error;
2613
2614         if (usrtvp == NULL) {
2615                 microtime(&tv[0]);
2616                 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2617                 tsp[1] = tsp[0];
2618         } else {
2619                 if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0)
2620                         return (error);
2621                 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2622                 TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]);
2623         }
2624         return 0;
2625 }
2626
2627 /*
2628  * Common implementation code for utimes(), lutimes(), and futimes().
2629  */
2630 static int
2631 setutimes(td, vp, ts, nullflag)
2632         struct thread *td;
2633         struct vnode *vp;
2634         const struct timespec *ts;
2635         int nullflag;
2636 {
2637         int error;
2638         struct mount *mp;
2639         struct vattr vattr;
2640
2641         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2642                 return (error);
2643         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2644         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2645         VATTR_NULL(&vattr);
2646         vattr.va_atime = ts[0];
2647         vattr.va_mtime = ts[1];
2648         if (nullflag)
2649                 vattr.va_vaflags |= VA_UTIMES_NULL;
2650         error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2651         VOP_UNLOCK(vp, 0, td);
2652         vn_finished_write(mp);
2653         return error;
2654 }
2655
2656 /*
2657  * Set the access and modification times of a file.
2658  */
2659 #ifndef _SYS_SYSPROTO_H_
2660 struct utimes_args {
2661         char    *path;
2662         struct  timeval *tptr;
2663 };
2664 #endif
2665 /* ARGSUSED */
2666 int
2667 utimes(td, uap)
2668         struct thread *td;
2669         register struct utimes_args /* {
2670                 syscallarg(char *) path;
2671                 syscallarg(struct timeval *) tptr;
2672         } */ *uap;
2673 {
2674         struct timespec ts[2];
2675         struct timeval *usrtvp;
2676         int error;
2677         struct nameidata nd;
2678
2679         usrtvp = SCARG(uap, tptr);
2680         if ((error = getutimes(usrtvp, ts)) != 0)
2681                 return (error);
2682         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2683         if ((error = namei(&nd)) != 0)
2684                 return (error);
2685         NDFREE(&nd, NDF_ONLY_PNBUF);
2686         error = setutimes(td, nd.ni_vp, ts, usrtvp == NULL);
2687         vrele(nd.ni_vp);
2688         return (error);
2689 }
2690
2691 /*
2692  * Set the access and modification times of a file.
2693  */
2694 #ifndef _SYS_SYSPROTO_H_
2695 struct lutimes_args {
2696         char    *path;
2697         struct  timeval *tptr;
2698 };
2699 #endif
2700 /* ARGSUSED */
2701 int
2702 lutimes(td, uap)
2703         struct thread *td;
2704         register struct lutimes_args /* {
2705                 syscallarg(char *) path;
2706                 syscallarg(struct timeval *) tptr;
2707         } */ *uap;
2708 {
2709         struct timespec ts[2];
2710         struct timeval *usrtvp;
2711         int error;
2712         struct nameidata nd;
2713
2714         usrtvp = SCARG(uap, tptr);
2715         if ((error = getutimes(usrtvp, ts)) != 0)
2716                 return (error);
2717         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2718         if ((error = namei(&nd)) != 0)
2719                 return (error);
2720         NDFREE(&nd, NDF_ONLY_PNBUF);
2721         error = setutimes(td, nd.ni_vp, ts, usrtvp == NULL);
2722         vrele(nd.ni_vp);
2723         return (error);
2724 }
2725
2726 /*
2727  * Set the access and modification times of a file.
2728  */
2729 #ifndef _SYS_SYSPROTO_H_
2730 struct futimes_args {
2731         int     fd;
2732         struct  timeval *tptr;
2733 };
2734 #endif
2735 /* ARGSUSED */
2736 int
2737 futimes(td, uap)
2738         struct thread *td;
2739         register struct futimes_args /* {
2740                 syscallarg(int ) fd;
2741                 syscallarg(struct timeval *) tptr;
2742         } */ *uap;
2743 {
2744         struct timespec ts[2];
2745         struct file *fp;
2746         struct timeval *usrtvp;
2747         int error;
2748
2749         usrtvp = SCARG(uap, tptr);
2750         if ((error = getutimes(usrtvp, ts)) != 0)
2751                 return (error);
2752         if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2753                 return (error);
2754         error = setutimes(td, (struct vnode *)fp->f_data, ts, usrtvp == NULL);
2755         fdrop(fp, td);
2756         return (error);
2757 }
2758
2759 /*
2760  * Truncate a file given its path name.
2761  */
2762 #ifndef _SYS_SYSPROTO_H_
2763 struct truncate_args {
2764         char    *path;
2765         int     pad;
2766         off_t   length;
2767 };
2768 #endif
2769 /* ARGSUSED */
2770 int
2771 truncate(td, uap)
2772         struct thread *td;
2773         register struct truncate_args /* {
2774                 syscallarg(char *) path;
2775                 syscallarg(int) pad;
2776                 syscallarg(off_t) length;
2777         } */ *uap;
2778 {
2779         struct mount *mp;
2780         struct vnode *vp;
2781         struct vattr vattr;
2782         int error;
2783         struct nameidata nd;
2784
2785         if (uap->length < 0)
2786                 return(EINVAL);
2787         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2788         if ((error = namei(&nd)) != 0)
2789                 return (error);
2790         vp = nd.ni_vp;
2791         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2792                 vrele(vp);
2793                 return (error);
2794         }
2795         NDFREE(&nd, NDF_ONLY_PNBUF);
2796         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2797         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2798         if (vp->v_type == VDIR)
2799                 error = EISDIR;
2800         else if ((error = vn_writechk(vp)) == 0 &&
2801             (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) {
2802                 VATTR_NULL(&vattr);
2803                 vattr.va_size = SCARG(uap, length);
2804                 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2805         }
2806         vput(vp);
2807         vn_finished_write(mp);
2808         return (error);
2809 }
2810
2811 /*
2812  * Truncate a file given a file descriptor.
2813  */
2814 #ifndef _SYS_SYSPROTO_H_
2815 struct ftruncate_args {
2816         int     fd;
2817         int     pad;
2818         off_t   length;
2819 };
2820 #endif
2821 /* ARGSUSED */
2822 int
2823 ftruncate(td, uap)
2824         struct thread *td;
2825         register struct ftruncate_args /* {
2826                 syscallarg(int) fd;
2827                 syscallarg(int) pad;
2828                 syscallarg(off_t) length;
2829         } */ *uap;
2830 {
2831         struct mount *mp;
2832         struct vattr vattr;
2833         struct vnode *vp;
2834         struct file *fp;
2835         int error;
2836
2837         if (uap->length < 0)
2838                 return(EINVAL);
2839         if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2840                 return (error);
2841         if ((fp->f_flag & FWRITE) == 0) {
2842                 fdrop(fp, td);
2843                 return (EINVAL);
2844         }
2845         vp = (struct vnode *)fp->f_data;
2846         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2847                 fdrop(fp, td);
2848                 return (error);
2849         }
2850         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2851         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2852         if (vp->v_type == VDIR)
2853                 error = EISDIR;
2854         else if ((error = vn_writechk(vp)) == 0) {
2855                 VATTR_NULL(&vattr);
2856                 vattr.va_size = SCARG(uap, length);
2857                 error = VOP_SETATTR(vp, &vattr, fp->f_cred, td);
2858         }
2859         VOP_UNLOCK(vp, 0, td);
2860         vn_finished_write(mp);
2861         fdrop(fp, td);
2862         return (error);
2863 }
2864
2865 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2866 /*
2867  * Truncate a file given its path name.
2868  */
2869 #ifndef _SYS_SYSPROTO_H_
2870 struct otruncate_args {
2871         char    *path;
2872         long    length;
2873 };
2874 #endif
2875 /* ARGSUSED */
2876 int
2877 otruncate(td, uap)
2878         struct thread *td;
2879         register struct otruncate_args /* {
2880                 syscallarg(char *) path;
2881                 syscallarg(long) length;
2882         } */ *uap;
2883 {
2884         struct truncate_args /* {
2885                 syscallarg(char *) path;
2886                 syscallarg(int) pad;
2887                 syscallarg(off_t) length;
2888         } */ nuap;
2889
2890         SCARG(&nuap, path) = SCARG(uap, path);
2891         SCARG(&nuap, length) = SCARG(uap, length);
2892         return (truncate(td, &nuap));
2893 }
2894
2895 /*
2896  * Truncate a file given a file descriptor.
2897  */
2898 #ifndef _SYS_SYSPROTO_H_
2899 struct oftruncate_args {
2900         int     fd;
2901         long    length;
2902 };
2903 #endif
2904 /* ARGSUSED */
2905 int
2906 oftruncate(td, uap)
2907         struct thread *td;
2908         register struct oftruncate_args /* {
2909                 syscallarg(int) fd;
2910                 syscallarg(long) length;
2911         } */ *uap;
2912 {
2913         struct ftruncate_args /* {
2914                 syscallarg(int) fd;
2915                 syscallarg(int) pad;
2916                 syscallarg(off_t) length;
2917         } */ nuap;
2918
2919         SCARG(&nuap, fd) = SCARG(uap, fd);
2920         SCARG(&nuap, length) = SCARG(uap, length);
2921         return (ftruncate(td, &nuap));
2922 }
2923 #endif /* COMPAT_43 || COMPAT_SUNOS */
2924
2925 /*
2926  * Sync an open file.
2927  */
2928 #ifndef _SYS_SYSPROTO_H_
2929 struct fsync_args {
2930         int     fd;
2931 };
2932 #endif
2933 /* ARGSUSED */
2934 int
2935 fsync(td, uap)
2936         struct thread *td;
2937         struct fsync_args /* {
2938                 syscallarg(int) fd;
2939         } */ *uap;
2940 {
2941         struct vnode *vp;
2942         struct mount *mp;
2943         struct file *fp;
2944         vm_object_t obj;
2945         int error;
2946
2947         GIANT_REQUIRED;
2948
2949         if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
2950                 return (error);
2951         vp = (struct vnode *)fp->f_data;
2952         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2953                 fdrop(fp, td);
2954                 return (error);
2955         }
2956         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2957         if (VOP_GETVOBJECT(vp, &obj) == 0) {
2958                 vm_object_page_clean(obj, 0, 0, 0);
2959         }
2960         error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, td);
2961 #ifdef SOFTUPDATES
2962         if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP))
2963             error = softdep_fsync(vp);
2964 #endif
2965
2966         VOP_UNLOCK(vp, 0, td);
2967         vn_finished_write(mp);
2968         fdrop(fp, td);
2969         return (error);
2970 }
2971
2972 /*
2973  * Rename files.  Source and destination must either both be directories,
2974  * or both not be directories.  If target is a directory, it must be empty.
2975  */
2976 #ifndef _SYS_SYSPROTO_H_
2977 struct rename_args {
2978         char    *from;
2979         char    *to;
2980 };
2981 #endif
2982 /* ARGSUSED */
2983 int
2984 rename(td, uap)
2985         struct thread *td;
2986         register struct rename_args /* {
2987                 syscallarg(char *) from;
2988                 syscallarg(char *) to;
2989         } */ *uap;
2990 {
2991         struct mount *mp;
2992         struct vnode *tvp, *fvp, *tdvp;
2993         struct nameidata fromnd, tond;
2994         int error;
2995
2996         bwillwrite();
2997         NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
2998             SCARG(uap, from), td);
2999         if ((error = namei(&fromnd)) != 0)
3000                 return (error);
3001         fvp = fromnd.ni_vp;
3002         if ((error = vn_start_write(fvp, &mp, V_WAIT | PCATCH)) != 0) {
3003                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3004                 vrele(fromnd.ni_dvp);
3005                 vrele(fvp);
3006                 goto out1;
3007         }
3008         NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ,
3009             UIO_USERSPACE, SCARG(uap, to), td);
3010         if (fromnd.ni_vp->v_type == VDIR)
3011                 tond.ni_cnd.cn_flags |= WILLBEDIR;
3012         if ((error = namei(&tond)) != 0) {
3013                 /* Translate error code for rename("dir1", "dir2/."). */
3014                 if (error == EISDIR && fvp->v_type == VDIR)
3015                         error = EINVAL;
3016                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3017                 vrele(fromnd.ni_dvp);
3018                 vrele(fvp);
3019                 goto out1;
3020         }
3021         tdvp = tond.ni_dvp;
3022         tvp = tond.ni_vp;
3023         if (tvp != NULL) {
3024                 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
3025                         error = ENOTDIR;
3026                         goto out;
3027                 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
3028                         error = EISDIR;
3029                         goto out;
3030                 }
3031         }
3032         if (fvp == tdvp)
3033                 error = EINVAL;
3034         /*
3035          * If source is the same as the destination (that is the
3036          * same inode number with the same name in the same directory),
3037          * then there is nothing to do.
3038          */
3039         if (fvp == tvp && fromnd.ni_dvp == tdvp &&
3040             fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
3041             !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
3042               fromnd.ni_cnd.cn_namelen))
3043                 error = -1;
3044 out:
3045         if (!error) {
3046                 VOP_LEASE(tdvp, td, td->td_ucred, LEASE_WRITE);
3047                 if (fromnd.ni_dvp != tdvp) {
3048                         VOP_LEASE(fromnd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3049                 }
3050                 if (tvp) {
3051                         VOP_LEASE(tvp, td, td->td_ucred, LEASE_WRITE);
3052                 }
3053                 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
3054                                    tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
3055                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3056                 NDFREE(&tond, NDF_ONLY_PNBUF);
3057         } else {
3058                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
3059                 NDFREE(&tond, NDF_ONLY_PNBUF);
3060                 if (tdvp == tvp)
3061                         vrele(tdvp);
3062                 else
3063                         vput(tdvp);
3064                 if (tvp)
3065                         vput(tvp);
3066                 vrele(fromnd.ni_dvp);
3067                 vrele(fvp);
3068         }
3069         vrele(tond.ni_startdir);
3070         vn_finished_write(mp);
3071         ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename");
3072         ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename");
3073         ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename");
3074         ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename");
3075 out1:
3076         if (fromnd.ni_startdir)
3077                 vrele(fromnd.ni_startdir);
3078         if (error == -1)
3079                 return (0);
3080         return (error);
3081 }
3082
3083 /*
3084  * Make a directory file.
3085  */
3086 #ifndef _SYS_SYSPROTO_H_
3087 struct mkdir_args {
3088         char    *path;
3089         int     mode;
3090 };
3091 #endif
3092 /* ARGSUSED */
3093 int
3094 mkdir(td, uap)
3095         struct thread *td;
3096         register struct mkdir_args /* {
3097                 syscallarg(char *) path;
3098                 syscallarg(int) mode;
3099         } */ *uap;
3100 {
3101
3102         return vn_mkdir(uap->path, uap->mode, UIO_USERSPACE, td);
3103 }
3104
3105 int
3106 vn_mkdir(path, mode, segflg, td)
3107         char *path;
3108         int mode;
3109         enum uio_seg segflg;
3110         struct thread *td;
3111 {
3112         struct mount *mp;
3113         struct vnode *vp;
3114         struct vattr vattr;
3115         int error;
3116         struct nameidata nd;
3117
3118 restart:
3119         bwillwrite();
3120         NDINIT(&nd, CREATE, LOCKPARENT, segflg, path, td);
3121         nd.ni_cnd.cn_flags |= WILLBEDIR;
3122         if ((error = namei(&nd)) != 0)
3123                 return (error);
3124         vp = nd.ni_vp;
3125         if (vp != NULL) {
3126                 NDFREE(&nd, NDF_ONLY_PNBUF);
3127                 vrele(vp);
3128                 vput(nd.ni_dvp);
3129                 return (EEXIST);
3130         }
3131         if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3132                 NDFREE(&nd, NDF_ONLY_PNBUF);
3133                 vput(nd.ni_dvp);
3134                 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3135                         return (error);
3136                 goto restart;
3137         }
3138         VATTR_NULL(&vattr);
3139         vattr.va_type = VDIR;
3140         FILEDESC_LOCK(td->td_proc->p_fd);
3141         vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask;
3142         FILEDESC_UNLOCK(td->td_proc->p_fd);
3143         VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3144         error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
3145         NDFREE(&nd, NDF_ONLY_PNBUF);
3146         vput(nd.ni_dvp);
3147         if (!error)
3148                 vput(nd.ni_vp);
3149         vn_finished_write(mp);
3150         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir");
3151         ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir");
3152         return (error);
3153 }
3154
3155 /*
3156  * Remove a directory file.
3157  */
3158 #ifndef _SYS_SYSPROTO_H_
3159 struct rmdir_args {
3160         char    *path;
3161 };
3162 #endif
3163 /* ARGSUSED */
3164 int
3165 rmdir(td, uap)
3166         struct thread *td;
3167         struct rmdir_args /* {
3168                 syscallarg(char *) path;
3169         } */ *uap;
3170 {
3171         struct mount *mp;
3172         struct vnode *vp;
3173         int error;
3174         struct nameidata nd;
3175
3176 restart:
3177         bwillwrite();
3178         NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
3179             SCARG(uap, path), td);
3180         if ((error = namei(&nd)) != 0)
3181                 return (error);
3182         vp = nd.ni_vp;
3183         if (vp->v_type != VDIR) {
3184                 error = ENOTDIR;
3185                 goto out;
3186         }
3187         /*
3188          * No rmdir "." please.
3189          */
3190         if (nd.ni_dvp == vp) {
3191                 error = EINVAL;
3192                 goto out;
3193         }
3194         /*
3195          * The root of a mounted filesystem cannot be deleted.
3196          */
3197         if (vp->v_flag & VROOT) {
3198                 error = EBUSY;
3199                 goto out;
3200         }
3201         if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3202                 NDFREE(&nd, NDF_ONLY_PNBUF);
3203                 if (nd.ni_dvp == vp)
3204                         vrele(nd.ni_dvp);
3205                 else
3206                         vput(nd.ni_dvp);
3207                 vput(vp);
3208                 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3209                         return (error);
3210                 goto restart;
3211         }
3212         VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3213         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3214         error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
3215         vn_finished_write(mp);
3216 out:
3217         NDFREE(&nd, NDF_ONLY_PNBUF);
3218         if (nd.ni_dvp == vp)
3219                 vrele(nd.ni_dvp);
3220         else
3221                 vput(nd.ni_dvp);
3222         vput(vp);
3223         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir");
3224         ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir");
3225         return (error);
3226 }
3227
3228 #ifdef COMPAT_43
3229 /*
3230  * Read a block of directory entries in a file system independent format.
3231  */
3232 #ifndef _SYS_SYSPROTO_H_
3233 struct ogetdirentries_args {
3234         int     fd;
3235         char    *buf;
3236         u_int   count;
3237         long    *basep;
3238 };
3239 #endif
3240 int
3241 ogetdirentries(td, uap)
3242         struct thread *td;
3243         register struct ogetdirentries_args /* {
3244                 syscallarg(int) fd;
3245                 syscallarg(char *) buf;
3246                 syscallarg(u_int) count;
3247                 syscallarg(long *) basep;
3248         } */ *uap;
3249 {
3250         struct vnode *vp;
3251         struct file *fp;
3252         struct uio auio, kuio;
3253         struct iovec aiov, kiov;
3254         struct dirent *dp, *edp;
3255         caddr_t dirbuf;
3256         int error, eofflag, readcnt;
3257         long loff;
3258
3259         /* XXX arbitrary sanity limit on `count'. */
3260         if (SCARG(uap, count) > 64 * 1024)
3261                 return (EINVAL);
3262         if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
3263                 return (error);
3264         if ((fp->f_flag & FREAD) == 0) {
3265                 fdrop(fp, td);
3266                 return (EBADF);
3267         }
3268         vp = (struct vnode *)fp->f_data;
3269 unionread:
3270         if (vp->v_type != VDIR) {
3271                 fdrop(fp, td);
3272                 return (EINVAL);
3273         }
3274         aiov.iov_base = SCARG(uap, buf);
3275         aiov.iov_len = SCARG(uap, count);
3276         auio.uio_iov = &aiov;
3277         auio.uio_iovcnt = 1;
3278         auio.uio_rw = UIO_READ;
3279         auio.uio_segflg = UIO_USERSPACE;
3280         auio.uio_td = td;
3281         auio.uio_resid = SCARG(uap, count);
3282         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3283         loff = auio.uio_offset = fp->f_offset;
3284 #       if (BYTE_ORDER != LITTLE_ENDIAN)
3285                 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
3286                         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
3287                             NULL, NULL);
3288                         fp->f_offset = auio.uio_offset;
3289                 } else
3290 #       endif
3291         {
3292                 kuio = auio;
3293                 kuio.uio_iov = &kiov;
3294                 kuio.uio_segflg = UIO_SYSSPACE;
3295                 kiov.iov_len = SCARG(uap, count);
3296                 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
3297                 kiov.iov_base = dirbuf;
3298                 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
3299                             NULL, NULL);
3300                 fp->f_offset = kuio.uio_offset;
3301                 if (error == 0) {
3302                         readcnt = SCARG(uap, count) - kuio.uio_resid;
3303                         edp = (struct dirent *)&dirbuf[readcnt];
3304                         for (dp = (struct dirent *)dirbuf; dp < edp; ) {
3305 #                               if (BYTE_ORDER == LITTLE_ENDIAN)
3306                                         /*
3307                                          * The expected low byte of
3308                                          * dp->d_namlen is our dp->d_type.
3309                                          * The high MBZ byte of dp->d_namlen
3310                                          * is our dp->d_namlen.
3311                                          */
3312                                         dp->d_type = dp->d_namlen;
3313                                         dp->d_namlen = 0;
3314 #                               else
3315                                         /*
3316                                          * The dp->d_type is the high byte
3317                                          * of the expected dp->d_namlen,
3318                                          * so must be zero'ed.
3319                                          */
3320                                         dp->d_type = 0;
3321 #                               endif
3322                                 if (dp->d_reclen > 0) {
3323                                         dp = (struct dirent *)
3324                                             ((char *)dp + dp->d_reclen);
3325                                 } else {
3326                                         error = EIO;
3327                                         break;
3328                                 }
3329                         }
3330                         if (dp >= edp)
3331                                 error = uiomove(dirbuf, readcnt, &auio);
3332                 }
3333                 FREE(dirbuf, M_TEMP);
3334         }
3335         VOP_UNLOCK(vp, 0, td);
3336         if (error) {
3337                 fdrop(fp, td);
3338                 return (error);
3339         }
3340         if (SCARG(uap, count) == auio.uio_resid) {
3341                 if (union_dircheckp) {
3342                         error = union_dircheckp(td, &vp, fp);
3343                         if (error == -1)
3344                                 goto unionread;
3345                         if (error) {
3346                                 fdrop(fp, td);
3347                                 return (error);
3348                         }
3349                 }
3350                 if ((vp->v_flag & VROOT) &&
3351                     (vp->v_mount->mnt_flag & MNT_UNION)) {
3352                         struct vnode *tvp = vp;
3353                         vp = vp->v_mount->mnt_vnodecovered;
3354                         VREF(vp);
3355                         fp->f_data = (caddr_t) vp;
3356                         fp->f_offset = 0;
3357                         vrele(tvp);
3358                         goto unionread;
3359                 }
3360         }
3361         error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
3362             sizeof(long));
3363         fdrop(fp, td);
3364         td->td_retval[0] = SCARG(uap, count) - auio.uio_resid;
3365         return (error);
3366 }
3367 #endif /* COMPAT_43 */
3368
3369 /*
3370  * Read a block of directory entries in a file system independent format.
3371  */
3372 #ifndef _SYS_SYSPROTO_H_
3373 struct getdirentries_args {
3374         int     fd;
3375         char    *buf;
3376         u_int   count;
3377         long    *basep;
3378 };
3379 #endif
3380 int
3381 getdirentries(td, uap)
3382         struct thread *td;
3383         register struct getdirentries_args /* {
3384                 syscallarg(int) fd;
3385                 syscallarg(char *) buf;
3386                 syscallarg(u_int) count;
3387                 syscallarg(long *) basep;
3388         } */ *uap;
3389 {
3390         struct vnode *vp;
3391         struct file *fp;
3392         struct uio auio;
3393         struct iovec aiov;
3394         long loff;
3395         int error, eofflag;
3396
3397         if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
3398                 return (error);
3399         if ((fp->f_flag & FREAD) == 0) {
3400                 fdrop(fp, td);
3401                 return (EBADF);
3402         }
3403         vp = (struct vnode *)fp->f_data;
3404 unionread:
3405         if (vp->v_type != VDIR) {
3406                 fdrop(fp, td);
3407                 return (EINVAL);
3408         }
3409         aiov.iov_base = SCARG(uap, buf);
3410         aiov.iov_len = SCARG(uap, count);
3411         auio.uio_iov = &aiov;
3412         auio.uio_iovcnt = 1;
3413         auio.uio_rw = UIO_READ;
3414         auio.uio_segflg = UIO_USERSPACE;
3415         auio.uio_td = td;
3416         auio.uio_resid = SCARG(uap, count);
3417         /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */
3418         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3419         loff = auio.uio_offset = fp->f_offset;
3420         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
3421         fp->f_offset = auio.uio_offset;
3422         VOP_UNLOCK(vp, 0, td);
3423         if (error) {
3424                 fdrop(fp, td);
3425                 return (error);
3426         }
3427         if (SCARG(uap, count) == auio.uio_resid) {
3428                 if (union_dircheckp) {
3429                         error = union_dircheckp(td, &vp, fp);
3430                         if (error == -1)
3431                                 goto unionread;
3432                         if (error) {
3433                                 fdrop(fp, td);
3434                                 return (error);
3435                         }
3436                 }
3437                 if ((vp->v_flag & VROOT) &&
3438                     (vp->v_mount->mnt_flag & MNT_UNION)) {
3439                         struct vnode *tvp = vp;
3440                         vp = vp->v_mount->mnt_vnodecovered;
3441                         VREF(vp);
3442                         fp->f_data = (caddr_t) vp;
3443                         fp->f_offset = 0;
3444                         vrele(tvp);
3445                         goto unionread;
3446                 }
3447         }
3448         if (SCARG(uap, basep) != NULL) {
3449                 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
3450                     sizeof(long));
3451         }
3452         td->td_retval[0] = SCARG(uap, count) - auio.uio_resid;
3453         fdrop(fp, td);
3454         return (error);
3455 }
3456 #ifndef _SYS_SYSPROTO_H_
3457 struct getdents_args {
3458         int fd;
3459         char *buf;
3460         size_t count;
3461 };
3462 #endif
3463 int
3464 getdents(td, uap)
3465         struct thread *td;
3466         register struct getdents_args /* {
3467                 syscallarg(int) fd;
3468                 syscallarg(char *) buf;
3469                 syscallarg(u_int) count;
3470         } */ *uap;
3471 {
3472         struct getdirentries_args ap;
3473         ap.fd = uap->fd;
3474         ap.buf = uap->buf;
3475         ap.count = uap->count;
3476         ap.basep = NULL;
3477         return getdirentries(td, &ap);
3478 }
3479
3480 /*
3481  * Set the mode mask for creation of filesystem nodes.
3482  *
3483  * MP SAFE
3484  */
3485 #ifndef _SYS_SYSPROTO_H_
3486 struct umask_args {
3487         int     newmask;
3488 };
3489 #endif
3490 int
3491 umask(td, uap)
3492         struct thread *td;
3493         struct umask_args /* {
3494                 syscallarg(int) newmask;
3495         } */ *uap;
3496 {
3497         register struct filedesc *fdp;
3498
3499         FILEDESC_LOCK(td->td_proc->p_fd);
3500         fdp = td->td_proc->p_fd;
3501         td->td_retval[0] = fdp->fd_cmask;
3502         fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
3503         FILEDESC_UNLOCK(td->td_proc->p_fd);
3504         return (0);
3505 }
3506
3507 /*
3508  * Void all references to file by ripping underlying filesystem
3509  * away from vnode.
3510  */
3511 #ifndef _SYS_SYSPROTO_H_
3512 struct revoke_args {
3513         char    *path;
3514 };
3515 #endif
3516 /* ARGSUSED */
3517 int
3518 revoke(td, uap)
3519         struct thread *td;
3520         register struct revoke_args /* {
3521                 syscallarg(char *) path;
3522         } */ *uap;
3523 {
3524         struct mount *mp;
3525         struct vnode *vp;
3526         struct vattr vattr;
3527         int error;
3528         struct nameidata nd;
3529
3530         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path),
3531             td);
3532         if ((error = namei(&nd)) != 0)
3533                 return (error);
3534         vp = nd.ni_vp;
3535         NDFREE(&nd, NDF_ONLY_PNBUF);
3536         if (vp->v_type != VCHR) {
3537                 vput(vp);
3538                 return (EINVAL);
3539         }
3540         error = VOP_GETATTR(vp, &vattr, td->td_ucred, td);
3541         if (error) {
3542                 vput(vp);
3543                 return (error);
3544         }
3545         VOP_UNLOCK(vp, 0, td);
3546         if (td->td_ucred->cr_uid != vattr.va_uid) {
3547                 error = suser_xxx(0, td->td_proc, PRISON_ROOT);
3548                 if (error)
3549                         goto out;
3550         }
3551         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3552                 goto out;
3553         if (vcount(vp) > 1)
3554                 VOP_REVOKE(vp, REVOKEALL);
3555         vn_finished_write(mp);
3556 out:
3557         vrele(vp);
3558         return (error);
3559 }
3560
3561 /*
3562  * Convert a user file descriptor to a kernel file entry.
3563  * The file entry is locked upon returning.
3564  */
3565 int
3566 getvnode(fdp, fd, fpp)
3567         struct filedesc *fdp;
3568         int fd;
3569         struct file **fpp;
3570 {
3571         int error;
3572         struct file *fp;
3573
3574         fp = NULL;
3575         if (fdp == NULL)
3576                 error = EBADF;
3577         else {
3578                 FILEDESC_LOCK(fdp);
3579                 if ((u_int)fd >= fdp->fd_nfiles ||
3580                     (fp = fdp->fd_ofiles[fd]) == NULL)
3581                         error = EBADF;
3582                 else if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) {
3583                         fp = NULL;
3584                         error = EINVAL;
3585                 } else {
3586                         fhold(fp);
3587                         error = 0;
3588                 }
3589                 FILEDESC_UNLOCK(fdp);
3590         }
3591         *fpp = fp;
3592         return (error);
3593 }
3594 /*
3595  * Get (NFS) file handle
3596  */
3597 #ifndef _SYS_SYSPROTO_H_
3598 struct getfh_args {
3599         char    *fname;
3600         fhandle_t *fhp;
3601 };
3602 #endif
3603 int
3604 getfh(td, uap)
3605         struct thread *td;
3606         register struct getfh_args *uap;
3607 {
3608         struct nameidata nd;
3609         fhandle_t fh;
3610         register struct vnode *vp;
3611         int error;
3612
3613         /*
3614          * Must be super user
3615          */
3616         error = suser_td(td);
3617         if (error)
3618                 return (error);
3619         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, td);
3620         error = namei(&nd);
3621         if (error)
3622                 return (error);
3623         NDFREE(&nd, NDF_ONLY_PNBUF);
3624         vp = nd.ni_vp;
3625         bzero(&fh, sizeof(fh));
3626         fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
3627         error = VFS_VPTOFH(vp, &fh.fh_fid);
3628         vput(vp);
3629         if (error)
3630                 return (error);
3631         error = copyout(&fh, uap->fhp, sizeof (fh));
3632         return (error);
3633 }
3634
3635 /*
3636  * syscall for the rpc.lockd to use to translate a NFS file handle into
3637  * an open descriptor.
3638  *
3639  * warning: do not remove the suser() call or this becomes one giant
3640  * security hole.
3641  */
3642 #ifndef _SYS_SYSPROTO_H_
3643 struct fhopen_args {
3644         const struct fhandle *u_fhp;
3645         int flags;
3646 };
3647 #endif
3648 int
3649 fhopen(td, uap)
3650         struct thread *td;
3651         struct fhopen_args /* {
3652                 syscallarg(const struct fhandle *) u_fhp;
3653                 syscallarg(int) flags;
3654         } */ *uap;
3655 {
3656         struct proc *p = td->td_proc;
3657         struct mount *mp;
3658         struct vnode *vp;
3659         struct fhandle fhp;
3660         struct vattr vat;
3661         struct vattr *vap = &vat;
3662         struct flock lf;
3663         struct file *fp;
3664         register struct filedesc *fdp = p->p_fd;
3665         int fmode, mode, error, type;
3666         struct file *nfp; 
3667         int indx;
3668
3669         /*
3670          * Must be super user
3671          */
3672         error = suser_td(td);
3673         if (error)
3674                 return (error);
3675
3676         fmode = FFLAGS(SCARG(uap, flags));
3677         /* why not allow a non-read/write open for our lockd? */
3678         if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
3679                 return (EINVAL);
3680         error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp));
3681         if (error)
3682                 return(error);
3683         /* find the mount point */
3684         mp = vfs_getvfs(&fhp.fh_fsid);
3685         if (mp == NULL)
3686                 return (ESTALE);
3687         /* now give me my vnode, it gets returned to me locked */
3688         error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
3689         if (error)
3690                 return (error);
3691         /*
3692          * from now on we have to make sure not
3693          * to forget about the vnode
3694          * any error that causes an abort must vput(vp) 
3695          * just set error = err and 'goto bad;'.
3696          */
3697
3698         /* 
3699          * from vn_open 
3700          */
3701         if (vp->v_type == VLNK) {
3702                 error = EMLINK;
3703                 goto bad;
3704         }
3705         if (vp->v_type == VSOCK) {
3706                 error = EOPNOTSUPP;
3707                 goto bad;
3708         }
3709         mode = 0;
3710         if (fmode & (FWRITE | O_TRUNC)) {
3711                 if (vp->v_type == VDIR) {
3712                         error = EISDIR;
3713                         goto bad;
3714                 }
3715                 error = vn_writechk(vp);
3716                 if (error)
3717                         goto bad;
3718                 mode |= VWRITE;
3719         }
3720         if (fmode & FREAD)
3721                 mode |= VREAD;
3722         if (mode) {
3723                 error = VOP_ACCESS(vp, mode, td->td_ucred, td);
3724                 if (error)
3725                         goto bad;
3726         }
3727         if (fmode & O_TRUNC) {
3728                 VOP_UNLOCK(vp, 0, td);                          /* XXX */
3729                 if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) {
3730                         vrele(vp);
3731                         return (error);
3732                 }
3733                 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3734                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);       /* XXX */
3735                 VATTR_NULL(vap);
3736                 vap->va_size = 0;
3737                 error = VOP_SETATTR(vp, vap, td->td_ucred, td);
3738                 vn_finished_write(mp);
3739                 if (error)
3740                         goto bad;
3741         }
3742         error = VOP_OPEN(vp, fmode, td->td_ucred, td);
3743         if (error)
3744                 goto bad;
3745         /*
3746          * Make sure that a VM object is created for VMIO support.
3747          */
3748         if (vn_canvmio(vp) == TRUE) {
3749                 if ((error = vfs_object_create(vp, td, td->td_ucred)) != 0)
3750                         goto bad;
3751         }
3752         if (fmode & FWRITE)
3753                 vp->v_writecount++;
3754
3755         /*
3756          * end of vn_open code 
3757          */
3758
3759         if ((error = falloc(td, &nfp, &indx)) != 0) {
3760                 if (fmode & FWRITE)
3761                         vp->v_writecount--;
3762                 goto bad;
3763         }
3764         fp = nfp;       
3765
3766         /*
3767          * Hold an extra reference to avoid having fp ripped out 
3768          * from under us while we block in the lock op
3769          */
3770         fhold(fp);
3771         nfp->f_data = (caddr_t)vp;
3772         nfp->f_flag = fmode & FMASK;
3773         nfp->f_ops = &vnops;
3774         nfp->f_type = DTYPE_VNODE;
3775         if (fmode & (O_EXLOCK | O_SHLOCK)) {
3776                 lf.l_whence = SEEK_SET;
3777                 lf.l_start = 0;
3778                 lf.l_len = 0;
3779                 if (fmode & O_EXLOCK)
3780                         lf.l_type = F_WRLCK;
3781                 else
3782                         lf.l_type = F_RDLCK;
3783                 type = F_FLOCK;
3784                 if ((fmode & FNONBLOCK) == 0)
3785                         type |= F_WAIT;
3786                 VOP_UNLOCK(vp, 0, td);
3787                 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
3788                         /*
3789                          * The lock request failed.  Normally close the
3790                          * descriptor but handle the case where someone might
3791                          * have dup()d or close()d it when we weren't looking.
3792                          */
3793                         FILEDESC_LOCK(fdp);
3794                         if (fdp->fd_ofiles[indx] == fp) {
3795                                 fdp->fd_ofiles[indx] = NULL;
3796                                 FILEDESC_UNLOCK(fdp);
3797                                 fdrop(fp, td);
3798                         } else
3799                                 FILEDESC_UNLOCK(fdp);
3800                         /*
3801                          * release our private reference
3802                          */
3803                         fdrop(fp, td);
3804                         return(error);
3805                 }
3806                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3807                 fp->f_flag |= FHASLOCK;
3808         }
3809         if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0))
3810                 vfs_object_create(vp, td, td->td_ucred);
3811
3812         VOP_UNLOCK(vp, 0, td);
3813         fdrop(fp, td);
3814         td->td_retval[0] = indx;
3815         return (0);
3816
3817 bad:
3818         vput(vp);
3819         return (error);
3820 }
3821
3822 /*
3823  * Stat an (NFS) file handle.
3824  */
3825 #ifndef _SYS_SYSPROTO_H_
3826 struct fhstat_args {
3827         struct fhandle *u_fhp;
3828         struct stat *sb;
3829 };
3830 #endif
3831 int
3832 fhstat(td, uap)
3833         struct thread *td;
3834         register struct fhstat_args /* {
3835                 syscallarg(struct fhandle *) u_fhp;
3836                 syscallarg(struct stat *) sb;
3837         } */ *uap;
3838 {
3839         struct stat sb;
3840         fhandle_t fh;
3841         struct mount *mp;
3842         struct vnode *vp;
3843         int error;
3844
3845         /*
3846          * Must be super user
3847          */
3848         error = suser_td(td);
3849         if (error)
3850                 return (error);
3851         
3852         error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t));
3853         if (error)
3854                 return (error);
3855
3856         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3857                 return (ESTALE);
3858         if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3859                 return (error);
3860         error = vn_stat(vp, &sb, td);
3861         vput(vp);
3862         if (error)
3863                 return (error);
3864         error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
3865         return (error);
3866 }
3867
3868 /*
3869  * Implement fstatfs() for (NFS) file handles.
3870  */
3871 #ifndef _SYS_SYSPROTO_H_
3872 struct fhstatfs_args {
3873         struct fhandle *u_fhp;
3874         struct statfs *buf;
3875 };
3876 #endif
3877 int
3878 fhstatfs(td, uap)
3879         struct thread *td;
3880         struct fhstatfs_args /* {
3881                 syscallarg(struct fhandle) *u_fhp;
3882                 syscallarg(struct statfs) *buf;
3883         } */ *uap;
3884 {
3885         struct statfs *sp;
3886         struct mount *mp;
3887         struct vnode *vp;
3888         struct statfs sb;
3889         fhandle_t fh;
3890         int error;
3891
3892         /*
3893          * Must be super user
3894          */
3895         error = suser_td(td);
3896         if (error)
3897                 return (error);
3898
3899         if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0)
3900                 return (error);
3901
3902         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3903                 return (ESTALE);
3904         if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3905                 return (error);
3906         mp = vp->v_mount;
3907         sp = &mp->mnt_stat;
3908         vput(vp);
3909         if ((error = VFS_STATFS(mp, sp, td)) != 0)
3910                 return (error);
3911         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
3912         if (suser_xxx(td->td_ucred, 0, 0)) {
3913                 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
3914                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
3915                 sp = &sb;
3916         }
3917         return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
3918 }
3919
3920 /*
3921  * Syscall to push extended attribute configuration information into the
3922  * VFS.  Accepts a path, which it converts to a mountpoint, as well as
3923  * a command (int cmd), and attribute name and misc data.  For now, the
3924  * attribute name is left in userspace for consumption by the VFS_op.
3925  * It will probably be changed to be copied into sysspace by the
3926  * syscall in the future, once issues with various consumers of the
3927  * attribute code have raised their hands.
3928  *
3929  * Currently this is used only by UFS Extended Attributes.
3930  */
3931 int
3932 extattrctl(td, uap)
3933         struct thread *td;
3934         struct extattrctl_args *uap;
3935 {
3936         struct vnode *filename_vp;
3937         struct nameidata nd;
3938         struct mount *mp, *mp_writable;
3939         char attrname[EXTATTR_MAXNAMELEN];
3940         int error;
3941
3942         /*
3943          * SCARG(uap, attrname) not always defined.  We check again later
3944          * when we invoke the VFS call so as to pass in NULL there if needed.
3945          */
3946         if (SCARG(uap, attrname) != NULL) {
3947                 error = copyinstr(SCARG(uap, attrname), attrname,
3948                     EXTATTR_MAXNAMELEN, NULL);
3949                 if (error)
3950                         return (error);
3951         }
3952
3953         /*
3954          * SCARG(uap, filename) not always defined.  If it is, grab
3955          * a vnode lock, which VFS_EXTATTRCTL() will later release.
3956          */
3957         filename_vp = NULL;
3958         if (SCARG(uap, filename) != NULL) {
3959                 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
3960                     SCARG(uap, filename), td);
3961                 if ((error = namei(&nd)) != 0)
3962                         return (error);
3963                 filename_vp = nd.ni_vp;
3964                 NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK);
3965         }
3966
3967         /* SCARG(uap, path) always defined. */
3968         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
3969         if ((error = namei(&nd)) != 0) {
3970                 if (filename_vp != NULL)
3971                         vput(filename_vp);
3972                 return (error);
3973         }
3974         mp = nd.ni_vp->v_mount;
3975         error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
3976         NDFREE(&nd, 0);
3977         if (error) {
3978                 if (filename_vp != NULL)
3979                         vput(filename_vp);
3980                 return (error);
3981         }
3982
3983         if (SCARG(uap, attrname) != NULL) {
3984                 error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), filename_vp,
3985                     SCARG(uap, attrnamespace), attrname, td);
3986         } else {
3987                 error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), filename_vp,
3988                     SCARG(uap, attrnamespace), NULL, td);
3989         }
3990
3991         vn_finished_write(mp_writable);
3992         /*
3993          * VFS_EXTATTRCTL will have unlocked, but not de-ref'd,
3994          * filename_vp, so vrele it if it is defined.
3995          */
3996         if (filename_vp != NULL)
3997                 vrele(filename_vp);
3998
3999         return (error);
4000 }
4001
4002 /*-
4003  * Set a named extended attribute on a file or directory
4004  * 
4005  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4006  *            kernelspace string pointer "attrname", userspace buffer
4007  *            pointer "data", buffer length "nbytes", thread "td".
4008  * Returns: 0 on success, an error number otherwise
4009  * Locks: none
4010  * References: vp must be a valid reference for the duration of the call
4011  */
4012 static int
4013 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4014     void *data, size_t nbytes, struct thread *td)
4015 {
4016         struct mount *mp;
4017         struct uio auio;
4018         struct iovec aiov;
4019         ssize_t cnt;
4020         int error;
4021
4022         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
4023                 return (error);
4024         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4025         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4026
4027         aiov.iov_base = data;
4028         aiov.iov_len = nbytes;
4029         auio.uio_iov = &aiov;
4030         auio.uio_iovcnt = 1;
4031         auio.uio_offset = 0;
4032         if (nbytes > INT_MAX) {
4033                 error = EINVAL;
4034                 goto done;
4035         }
4036         auio.uio_resid = nbytes;
4037         auio.uio_rw = UIO_WRITE;
4038         auio.uio_segflg = UIO_USERSPACE;
4039         auio.uio_td = td;
4040         cnt = nbytes;
4041
4042         error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
4043             td->td_ucred, td);
4044         cnt -= auio.uio_resid;
4045         td->td_retval[0] = cnt;
4046
4047 done:
4048         VOP_UNLOCK(vp, 0, td);
4049         vn_finished_write(mp);
4050         return (error);
4051 }
4052
4053 int
4054 extattr_set_file(td, uap)
4055         struct thread *td;
4056         struct extattr_set_file_args *uap;
4057 {
4058         struct nameidata nd;
4059         char attrname[EXTATTR_MAXNAMELEN];
4060         int error;
4061
4062         error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4063             NULL);
4064         if (error)
4065                 return (error);
4066
4067         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
4068         if ((error = namei(&nd)) != 0)
4069                 return (error);
4070         NDFREE(&nd, NDF_ONLY_PNBUF);
4071
4072         error = extattr_set_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
4073             SCARG(uap, data), SCARG(uap, nbytes), td);
4074
4075         vrele(nd.ni_vp);
4076         return (error);
4077 }
4078
4079 int
4080 extattr_set_fd(td, uap)
4081         struct thread *td;
4082         struct extattr_set_fd_args *uap;
4083 {
4084         struct file *fp;
4085         char attrname[EXTATTR_MAXNAMELEN];
4086         int error;
4087
4088         error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4089             NULL);
4090         if (error)
4091                 return (error);
4092
4093         if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
4094                 return (error);
4095
4096         error = extattr_set_vp((struct vnode *)fp->f_data,
4097             SCARG(uap, attrnamespace), attrname, SCARG(uap, data),
4098             SCARG(uap, nbytes), td);
4099         fdrop(fp, td);
4100
4101         return (error);
4102 }
4103
4104 /*-
4105  * Get a named extended attribute on a file or directory
4106  * 
4107  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4108  *            kernelspace string pointer "attrname", userspace buffer
4109  *            pointer "data", buffer length "nbytes", thread "td".
4110  * Returns: 0 on success, an error number otherwise
4111  * Locks: none
4112  * References: vp must be a valid reference for the duration of the call
4113  */
4114 static int
4115 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4116     void *data, size_t nbytes, struct thread *td)
4117 {
4118         struct uio auio;
4119         struct iovec aiov;
4120         ssize_t cnt;
4121         size_t size;
4122         int error;
4123
4124         VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
4125         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4126
4127         /*
4128          * Slightly unusual semantics: if the user provides a NULL data
4129          * pointer, they don't want to receive the data, just the
4130          * maximum read length.
4131          */
4132         if (data != NULL) {
4133                 aiov.iov_base = data;
4134                 aiov.iov_len = nbytes;
4135                 auio.uio_iov = &aiov;
4136                 auio.uio_offset = 0;
4137                 if (nbytes > INT_MAX) {
4138                         error = EINVAL;
4139                         goto done;
4140                 }
4141                 auio.uio_resid = nbytes;
4142                 auio.uio_rw = UIO_READ;
4143                 auio.uio_segflg = UIO_USERSPACE;
4144                 auio.uio_td = td;
4145                 cnt = nbytes;
4146                 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio,
4147                     NULL, td->td_proc->p_ucred, td);
4148                 cnt -= auio.uio_resid;
4149                 td->td_retval[0] = cnt;
4150         } else {
4151                 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, NULL,
4152                     &size, td->td_proc->p_ucred, td);
4153                 td->td_retval[0] = size;
4154         }
4155 done:
4156         VOP_UNLOCK(vp, 0, td);
4157         return (error);
4158 }
4159
4160 int
4161 extattr_get_file(td, uap)
4162         struct thread *td;
4163         struct extattr_get_file_args *uap;
4164 {
4165         struct nameidata nd;
4166         char attrname[EXTATTR_MAXNAMELEN];
4167         int error;
4168
4169         error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4170             NULL);
4171         if (error)
4172                 return (error);
4173
4174         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
4175         if ((error = namei(&nd)) != 0)
4176                 return (error);
4177         NDFREE(&nd, NDF_ONLY_PNBUF);
4178
4179         error = extattr_get_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
4180             SCARG(uap, data), SCARG(uap, nbytes), td);
4181
4182         vrele(nd.ni_vp);
4183         return (error);
4184 }
4185
4186 int
4187 extattr_get_fd(td, uap)
4188         struct thread *td;
4189         struct extattr_get_fd_args *uap;
4190 {
4191         struct file *fp;
4192         char attrname[EXTATTR_MAXNAMELEN];
4193         int error;
4194
4195         error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4196             NULL);
4197         if (error)
4198                 return (error);
4199
4200         if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
4201                 return (error);
4202
4203         error = extattr_get_vp((struct vnode *)fp->f_data,
4204             SCARG(uap, attrnamespace), attrname, SCARG(uap, data),
4205             SCARG(uap, nbytes), td);
4206
4207         fdrop(fp, td);
4208         return (error);
4209 }
4210
4211 /*
4212  * extattr_delete_vp(): Delete a named extended attribute on a file or
4213  *                      directory
4214  * 
4215  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4216  *            kernelspace string pointer "attrname", proc "p"
4217  * Returns: 0 on success, an error number otherwise
4218  * Locks: none
4219  * References: vp must be a valid reference for the duration of the call
4220  */
4221 static int
4222 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4223     struct thread *td)
4224 {
4225         struct mount *mp;
4226         int error;
4227
4228         if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
4229                 return (error);
4230         VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4231         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4232
4233         error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
4234             td->td_ucred, td);
4235
4236         VOP_UNLOCK(vp, 0, td);
4237         vn_finished_write(mp);
4238         return (error);
4239 }
4240
4241 int
4242 extattr_delete_file(td, uap)
4243         struct thread *td;
4244         struct extattr_delete_file_args *uap;
4245 {
4246         struct nameidata nd;
4247         char attrname[EXTATTR_MAXNAMELEN];
4248         int error;
4249
4250         error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4251              NULL);
4252         if (error)
4253                 return(error);
4254
4255         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
4256         if ((error = namei(&nd)) != 0)
4257                 return(error);
4258         NDFREE(&nd, NDF_ONLY_PNBUF);
4259
4260         error = extattr_delete_vp(nd.ni_vp, SCARG(uap, attrnamespace),
4261             attrname, td);
4262
4263         vrele(nd.ni_vp);
4264         return(error);
4265 }
4266
4267 int
4268 extattr_delete_fd(td, uap)
4269         struct thread *td;
4270         struct extattr_delete_fd_args *uap;
4271 {
4272         struct file *fp;
4273         struct vnode *vp;
4274         char attrname[EXTATTR_MAXNAMELEN];
4275         int error;
4276
4277         error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN,
4278             NULL);
4279         if (error)
4280                 return (error);
4281
4282         if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
4283                 return (error);
4284         vp = (struct vnode *)fp->f_data;
4285
4286         error = extattr_delete_vp((struct vnode *)fp->f_data,
4287             SCARG(uap, attrnamespace), attrname, td);
4288
4289         fdrop(fp, td);
4290         return (error);
4291 }