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