ec59fb2fbbcc201b8787a7574983e01a930d4083
[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  * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.5 2003/06/25 05:22:32 dillon Exp $
41  */
42
43 /* For 4.3 integer FS ID compatibility */
44 #include "opt_compat.h"
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/buf.h>
49 #include <sys/sysent.h>
50 #include <sys/malloc.h>
51 #include <sys/mount.h>
52 #include <sys/sysproto.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/namei.h>
63 #include <sys/dirent.h>
64 #include <sys/extattr.h>
65
66 #include <machine/limits.h>
67 #include <miscfs/union/union.h>
68 #include <sys/sysctl.h>
69 #include <vm/vm.h>
70 #include <vm/vm_object.h>
71 #include <vm/vm_zone.h>
72 #include <vm/vm_page.h>
73
74 #include <sys/file2.h>
75
76 static int change_dir __P((struct nameidata *ndp, struct thread *td));
77 static void checkdirs __P((struct vnode *olddp));
78 static int chroot_refuse_vdir_fds __P((struct filedesc *fdp));
79 static int getutimes __P((const struct timeval *, struct timespec *));
80 static int setfown __P((struct vnode *, uid_t, gid_t));
81 static int setfmode __P((struct vnode *, int));
82 static int setfflags __P((struct vnode *, int));
83 static int setutimes __P((struct vnode *, const struct timespec *, int));
84 static int      usermount = 0;  /* if 1, non-root can mount fs. */
85
86 int (*union_dircheckp) __P((struct thread *, struct vnode **, struct file *));
87
88 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, "");
89
90 /*
91  * Virtual File System System Calls
92  */
93
94 /*
95  * Mount a file system.
96  */
97 #ifndef _SYS_SYSPROTO_H_
98 struct mount_args {
99         char    *type;
100         char    *path;
101         int     flags;
102         caddr_t data;
103 };
104 #endif
105 /*
106  * mount_args(char *type, char *path, int flags, caddr_t data)
107  */
108 /* ARGSUSED */
109 int
110 mount(struct mount_args *uap)
111 {
112         struct thread *td = curthread;
113         struct proc *p = td->td_proc;
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(td)))
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(td);
132                 if (error)
133                         return (error);
134         }
135         /*
136          * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users
137          */
138         if (suser(td)) 
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), td);
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(td))) {
172                         vput(vp);
173                         return (error);
174                 }
175                 if (vfs_busy(mp, LK_NOWAIT, 0, td)) {
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, td);
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, td);
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, td)) ||
199             (va.va_uid != p->p_ucred->cr_uid &&
200              (error = suser(td)))) {
201                 vput(vp);
202                 return (error);
203         }
204         if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, td, 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(td)) != 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, td);
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, td);
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, td);
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, td);
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, td);
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, td);
355                 if ((mp->mnt_flag & MNT_RDONLY) == 0)
356                         error = vfs_allocate_syncvnode(mp);
357                 vfs_unbusy(mp, td);
358                 if ((error = VFS_START(mp, 0, td)) != 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, td);
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(struct vnode *olddp)
379 {
380         struct filedesc *fdp;
381         struct vnode *newdp;
382         struct proc *p;
383
384         if (olddp->v_usecount == 1)
385                 return;
386         if (VFS_ROOT(olddp->v_mountedhere, &newdp))
387                 panic("mount: lost mount");
388         LIST_FOREACH(p, &allproc, p_list) {
389                 fdp = p->p_fd;
390                 if (fdp->fd_cdir == olddp) {
391                         vrele(fdp->fd_cdir);
392                         VREF(newdp);
393                         fdp->fd_cdir = newdp;
394                 }
395                 if (fdp->fd_rdir == olddp) {
396                         vrele(fdp->fd_rdir);
397                         VREF(newdp);
398                         fdp->fd_rdir = newdp;
399                 }
400         }
401         if (rootvnode == olddp) {
402                 vrele(rootvnode);
403                 VREF(newdp);
404                 rootvnode = newdp;
405         }
406         vput(newdp);
407 }
408
409 /*
410  * Unmount a file system.
411  *
412  * Note: unmount takes a path to the vnode mounted on as argument,
413  * not special file (as before).
414  */
415 #ifndef _SYS_SYSPROTO_H_
416 struct unmount_args {
417         char    *path;
418         int     flags;
419 };
420 #endif
421 /*
422  * umount_args(char *path, int flags)
423  */
424 /* ARGSUSED */
425 int
426 unmount(struct unmount_args *uap)
427 {
428         struct thread *td = curthread;
429         struct proc *p = td->td_proc;
430         struct vnode *vp;
431         struct mount *mp;
432         int error;
433         struct nameidata nd;
434
435         KKASSERT(p);
436         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
437             SCARG(uap, path), td);
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(td))) {
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), td));
471 }
472
473 /*
474  * Do the actual file system unmount.
475  */
476 int
477 dounmount(struct mount *mp, int flags, struct thread *td)
478 {
479         struct vnode *coveredvp;
480         int error;
481         int async_flag;
482         struct proc *p = td->td_proc;
483
484         KKASSERT(p);
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, td);
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, td)) == 0) ||
515             (flags & MNT_FORCE))
516                 error = VFS_UNMOUNT(mp, flags, td);
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, td);
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, td);
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(struct sync_args *uap)
561 {
562         struct thread *td = curthread;
563         struct proc *p = td->td_proc;
564         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, td)) {
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), td);
579                         mp->mnt_flag |= asyncflag;
580                 }
581                 simple_lock(&mountlist_slock);
582                 nmp = TAILQ_NEXT(mp, mnt_list);
583                 vfs_unbusy(mp, td);
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  *  quotactl_args(char *path, int fcmd, int uid, caddr_t arg)
607  *
608  * Change filesystem quotas.
609  */
610 /* ARGSUSED */
611 int
612 quotactl(struct quotactl_args *uap)
613 {
614         struct thread *td = curthread;
615         struct proc *p = td->td_proc;
616         struct mount *mp;
617         int error;
618         struct nameidata nd;
619
620         KKASSERT(p);
621         if (p->p_ucred->cr_prison && !prison_quotas)
622                 return (EPERM);
623         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
624         if ((error = namei(&nd)) != 0)
625                 return (error);
626         mp = nd.ni_vp->v_mount;
627         NDFREE(&nd, NDF_ONLY_PNBUF);
628         vrele(nd.ni_vp);
629         return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
630             SCARG(uap, arg), td));
631 }
632
633 /*
634  * statfs_args(char *path, struct statfs *buf)
635  *
636  * Get filesystem statistics.
637  */
638 /* ARGSUSED */
639 int
640 statfs(struct statfs_args *uap)
641 {
642         struct thread *td = curthread;
643         struct mount *mp;
644         struct statfs *sp;
645         int error;
646         struct nameidata nd;
647         struct statfs sb;
648
649         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
650         if ((error = namei(&nd)) != 0)
651                 return (error);
652         mp = nd.ni_vp->v_mount;
653         sp = &mp->mnt_stat;
654         NDFREE(&nd, NDF_ONLY_PNBUF);
655         vrele(nd.ni_vp);
656         error = VFS_STATFS(mp, sp, td);
657         if (error)
658                 return (error);
659         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
660         if (suser(td)) {
661                 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
662                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
663                 sp = &sb;
664         }
665         return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
666 }
667
668 /*
669  * fstatfs_args(int fd, struct statfs *buf)
670  *
671  * Get filesystem statistics.
672  */
673 /* ARGSUSED */
674 int
675 fstatfs(struct fstatfs_args *uap)
676 {
677         struct thread *td = curthread;
678         struct proc *p = td->td_proc;
679         struct file *fp;
680         struct mount *mp;
681         register struct statfs *sp;
682         int error;
683         struct statfs sb;
684
685         KKASSERT(p);
686         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
687                 return (error);
688         mp = ((struct vnode *)fp->f_data)->v_mount;
689         if (mp == NULL)
690                 return (EBADF);
691         sp = &mp->mnt_stat;
692         error = VFS_STATFS(mp, sp, td);
693         if (error)
694                 return (error);
695         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
696         if (suser(td)) {
697                 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
698                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
699                 sp = &sb;
700         }
701         return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
702 }
703
704 /*
705  * getfsstat_args(struct statfs *buf, long bufsize, int flags)
706  *
707  * Get statistics on all filesystems.
708  */
709 /* ARGSUSED */
710 int
711 getfsstat(struct getfsstat_args *uap)
712 {
713         struct thread *td = curthread;
714         struct proc *p = td->td_proc;
715         struct mount *mp, *nmp;
716         struct statfs *sp;
717         caddr_t sfsp;
718         long count, maxcount, error;
719
720         maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
721         sfsp = (caddr_t)SCARG(uap, buf);
722         count = 0;
723         simple_lock(&mountlist_slock);
724         for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
725                 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, td)) {
726                         nmp = TAILQ_NEXT(mp, mnt_list);
727                         continue;
728                 }
729                 if (sfsp && count < maxcount) {
730                         sp = &mp->mnt_stat;
731                         /*
732                          * If MNT_NOWAIT or MNT_LAZY is specified, do not
733                          * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
734                          * overrides MNT_WAIT.
735                          */
736                         if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
737                             (SCARG(uap, flags) & MNT_WAIT)) &&
738                             (error = VFS_STATFS(mp, sp, td))) {
739                                 simple_lock(&mountlist_slock);
740                                 nmp = TAILQ_NEXT(mp, mnt_list);
741                                 vfs_unbusy(mp, td);
742                                 continue;
743                         }
744                         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
745                         error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
746                         if (error) {
747                                 vfs_unbusy(mp, td);
748                                 return (error);
749                         }
750                         sfsp += sizeof(*sp);
751                 }
752                 count++;
753                 simple_lock(&mountlist_slock);
754                 nmp = TAILQ_NEXT(mp, mnt_list);
755                 vfs_unbusy(mp, td);
756         }
757         simple_unlock(&mountlist_slock);
758         if (sfsp && count > maxcount)
759                 p->p_retval[0] = maxcount;
760         else
761                 p->p_retval[0] = count;
762         return (0);
763 }
764
765 /*
766  * fchdir_args(int fd)
767  *
768  * Change current working directory to a given file descriptor.
769  */
770 /* ARGSUSED */
771 int
772 fchdir(struct fchdir_args *uap)
773 {
774         struct thread *td = curthread;
775         struct proc *p = td->td_proc;
776         struct filedesc *fdp = p->p_fd;
777         struct vnode *vp, *tdp;
778         struct mount *mp;
779         struct file *fp;
780         int error;
781
782         if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
783                 return (error);
784         vp = (struct vnode *)fp->f_data;
785         VREF(vp);
786         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
787         if (vp->v_type != VDIR)
788                 error = ENOTDIR;
789         else
790                 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, td);
791         while (!error && (mp = vp->v_mountedhere) != NULL) {
792                 if (vfs_busy(mp, 0, 0, td))
793                         continue;
794                 error = VFS_ROOT(mp, &tdp);
795                 vfs_unbusy(mp, td);
796                 if (error)
797                         break;
798                 vput(vp);
799                 vp = tdp;
800         }
801         if (error) {
802                 vput(vp);
803                 return (error);
804         }
805         VOP_UNLOCK(vp, 0, td);
806         vrele(fdp->fd_cdir);
807         fdp->fd_cdir = vp;
808         return (0);
809 }
810
811 /*
812  * chdir_args(char *path)
813  *
814  * Change current working directory (``.'').
815  */
816 /* ARGSUSED */
817 int
818 chdir(struct chdir_args *uap)
819 {
820         struct thread *td = curthread;
821         struct proc *p = td->td_proc;
822         struct filedesc *fdp = p->p_fd;
823         int error;
824         struct nameidata nd;
825
826         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
827             SCARG(uap, path), td);
828         if ((error = change_dir(&nd, td)) != 0)
829                 return (error);
830         NDFREE(&nd, NDF_ONLY_PNBUF);
831         vrele(fdp->fd_cdir);
832         fdp->fd_cdir = nd.ni_vp;
833         return (0);
834 }
835
836 /*
837  * Helper function for raised chroot(2) security function:  Refuse if
838  * any filedescriptors are open directories.
839  */
840 static int
841 chroot_refuse_vdir_fds(fdp)
842         struct filedesc *fdp;
843 {
844         struct vnode *vp;
845         struct file *fp;
846         int error;
847         int fd;
848
849         for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
850                 error = getvnode(fdp, fd, &fp);
851                 if (error)
852                         continue;
853                 vp = (struct vnode *)fp->f_data;
854                 if (vp->v_type != VDIR)
855                         continue;
856                 return(EPERM);
857         }
858         return (0);
859 }
860
861 /*
862  * This sysctl determines if we will allow a process to chroot(2) if it
863  * has a directory open:
864  *      0: disallowed for all processes.
865  *      1: allowed for processes that were not already chroot(2)'ed.
866  *      2: allowed for all processes.
867  */
868
869 static int chroot_allow_open_directories = 1;
870
871 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
872      &chroot_allow_open_directories, 0, "");
873
874 /*
875  * chroot_args(char *path)
876  *
877  * Change notion of root (``/'') directory.
878  */
879 /* ARGSUSED */
880 int
881 chroot(struct chroot_args *uap)
882 {
883         struct thread *td = curthread;
884         struct proc *p = td->td_proc;
885         struct filedesc *fdp = p->p_fd;
886         int error;
887         struct nameidata nd;
888
889         KKASSERT(p);
890         error = suser_cred(p->p_ucred, PRISON_ROOT);
891         if (error)
892                 return (error);
893         if (chroot_allow_open_directories == 0 ||
894             (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode))
895                 error = chroot_refuse_vdir_fds(fdp);
896         if (error)
897                 return (error);
898         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
899             SCARG(uap, path), td);
900         if ((error = change_dir(&nd, td)) != 0)
901                 return (error);
902         NDFREE(&nd, NDF_ONLY_PNBUF);
903         vrele(fdp->fd_rdir);
904         fdp->fd_rdir = nd.ni_vp;
905         if (!fdp->fd_jdir) {
906                 fdp->fd_jdir = nd.ni_vp;
907                 VREF(fdp->fd_jdir);
908         }
909         return (0);
910 }
911
912 /*
913  * Common routine for chroot and chdir.
914  */
915 static int
916 change_dir(struct nameidata *ndp, struct thread *td)
917 {
918         struct vnode *vp;
919         int error;
920
921         error = namei(ndp);
922         if (error)
923                 return (error);
924         vp = ndp->ni_vp;
925         if (vp->v_type != VDIR)
926                 error = ENOTDIR;
927         else
928                 error = VOP_ACCESS(vp, VEXEC, ndp->ni_cnd.cn_cred, td);
929         if (error)
930                 vput(vp);
931         else
932                 VOP_UNLOCK(vp, 0, td);
933         return (error);
934 }
935
936 /*
937  * open_args(char *path, int flags, int mode)
938  *
939  * Check permissions, allocate an open file structure,
940  * and call the device open routine if any.
941  */
942 int
943 open(struct open_args *uap)
944 {
945         struct thread *td = curthread;
946         struct proc *p = td->td_proc;
947         struct filedesc *fdp = p->p_fd;
948         struct file *fp;
949         struct vnode *vp;
950         int cmode, flags, oflags;
951         struct file *nfp;
952         int type, indx, error;
953         struct flock lf;
954         struct nameidata nd;
955
956         oflags = SCARG(uap, flags);
957         if ((oflags & O_ACCMODE) == O_ACCMODE)
958                 return (EINVAL);
959         flags = FFLAGS(oflags);
960         error = falloc(p, &nfp, &indx);
961         if (error)
962                 return (error);
963         fp = nfp;
964         cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
965         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
966         p->p_dupfd = -indx - 1;                 /* XXX check for fdopen */
967         /*
968          * Bump the ref count to prevent another process from closing
969          * the descriptor while we are blocked in vn_open()
970          */
971         fhold(fp);
972         error = vn_open(&nd, flags, cmode);
973         if (error) {
974                 /*
975                  * release our own reference
976                  */
977                 fdrop(fp, td);
978
979                 /*
980                  * handle special fdopen() case.  bleh.  dupfdopen() is
981                  * responsible for dropping the old contents of ofiles[indx]
982                  * if it succeeds.
983                  */
984                 if ((error == ENODEV || error == ENXIO) &&
985                     p->p_dupfd >= 0 &&                  /* XXX from fdopen */
986                     (error =
987                         dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
988                         p->p_retval[0] = indx;
989                         return (0);
990                 }
991                 /*
992                  * Clean up the descriptor, but only if another thread hadn't
993                  * replaced or closed it.
994                  */
995                 if (fdp->fd_ofiles[indx] == fp) {
996                         fdp->fd_ofiles[indx] = NULL;
997                         fdrop(fp, td);
998                 }
999
1000                 if (error == ERESTART)
1001                         error = EINTR;
1002                 return (error);
1003         }
1004         p->p_dupfd = 0;
1005         NDFREE(&nd, NDF_ONLY_PNBUF);
1006         vp = nd.ni_vp;
1007
1008         /*
1009          * There should be 2 references on the file, one from the descriptor
1010          * table, and one for us.
1011          *
1012          * Handle the case where someone closed the file (via its file
1013          * descriptor) while we were blocked.  The end result should look
1014          * like opening the file succeeded but it was immediately closed.
1015          */
1016         if (fp->f_count == 1) {
1017                 KASSERT(fdp->fd_ofiles[indx] != fp,
1018                     ("Open file descriptor lost all refs"));
1019                 VOP_UNLOCK(vp, 0, td);
1020                 vn_close(vp, flags & FMASK, fp->f_cred, td);
1021                 fdrop(fp, td);
1022                 p->p_retval[0] = indx;
1023                 return 0;
1024         }
1025
1026         fp->f_data = (caddr_t)vp;
1027         fp->f_flag = flags & FMASK;
1028         fp->f_ops = &vnops;
1029         fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
1030         if (flags & (O_EXLOCK | O_SHLOCK)) {
1031                 lf.l_whence = SEEK_SET;
1032                 lf.l_start = 0;
1033                 lf.l_len = 0;
1034                 if (flags & O_EXLOCK)
1035                         lf.l_type = F_WRLCK;
1036                 else
1037                         lf.l_type = F_RDLCK;
1038                 type = F_FLOCK;
1039                 if ((flags & FNONBLOCK) == 0)
1040                         type |= F_WAIT;
1041                 VOP_UNLOCK(vp, 0, td);
1042                 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
1043                         /*
1044                          * lock request failed.  Normally close the descriptor
1045                          * but handle the case where someone might have dup()d
1046                          * it when we weren't looking.  One reference is
1047                          * owned by the descriptor array, the other by us.
1048                          */
1049                         if (fdp->fd_ofiles[indx] == fp) {
1050                                 fdp->fd_ofiles[indx] = NULL;
1051                                 fdrop(fp, td);
1052                         }
1053                         fdrop(fp, td);
1054                         return (error);
1055                 }
1056                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1057                 fp->f_flag |= FHASLOCK;
1058         }
1059         /* assert that vn_open created a backing object if one is needed */
1060         KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0,
1061                 ("open: vmio vnode has no backing object after vn_open"));
1062         VOP_UNLOCK(vp, 0, td);
1063
1064         /*
1065          * release our private reference, leaving the one associated with the
1066          * descriptor table intact.
1067          */
1068         fdrop(fp, td);
1069         p->p_retval[0] = indx;
1070         return (0);
1071 }
1072
1073 #ifdef COMPAT_43
1074 /*
1075  * ocreat(char *path, int mode)
1076  *
1077  * Create a file.
1078  */
1079 int
1080 ocreat(struct ocreat_args *uap)
1081 {
1082         struct open_args /* {
1083                 syscallarg(char *) path;
1084                 syscallarg(int) flags;
1085                 syscallarg(int) mode;
1086         } */ nuap;
1087
1088         SCARG(&nuap, path) = SCARG(uap, path);
1089         SCARG(&nuap, mode) = SCARG(uap, mode);
1090         SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
1091         return (open(&nuap));
1092 }
1093 #endif /* COMPAT_43 */
1094
1095 /*
1096  * mknod_args(char *path, int mode, int dev)
1097  *
1098  * Create a special file.
1099  */
1100 /* ARGSUSED */
1101 int
1102 mknod(struct mknod_args *uap)
1103 {
1104         struct thread *td = curthread;
1105         struct proc *p = td->td_proc;
1106         struct vnode *vp;
1107         struct vattr vattr;
1108         int error;
1109         int whiteout = 0;
1110         struct nameidata nd;
1111
1112         KKASSERT(p);
1113
1114         switch (SCARG(uap, mode) & S_IFMT) {
1115         case S_IFCHR:
1116         case S_IFBLK:
1117                 error = suser(td);
1118                 break;
1119         default:
1120                 error = suser_cred(p->p_ucred, PRISON_ROOT);
1121                 break;
1122         }
1123         if (error)
1124                 return (error);
1125         bwillwrite();
1126         NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td);
1127         if ((error = namei(&nd)) != 0)
1128                 return (error);
1129         vp = nd.ni_vp;
1130         if (vp != NULL)
1131                 error = EEXIST;
1132         else {
1133                 VATTR_NULL(&vattr);
1134                 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1135                 vattr.va_rdev = SCARG(uap, dev);
1136                 whiteout = 0;
1137
1138                 switch (SCARG(uap, mode) & S_IFMT) {
1139                 case S_IFMT:    /* used by badsect to flag bad sectors */
1140                         vattr.va_type = VBAD;
1141                         break;
1142                 case S_IFCHR:
1143                         vattr.va_type = VCHR;
1144                         break;
1145                 case S_IFBLK:
1146                         vattr.va_type = VBLK;
1147                         break;
1148                 case S_IFWHT:
1149                         whiteout = 1;
1150                         break;
1151                 default:
1152                         error = EINVAL;
1153                         break;
1154                 }
1155         }
1156         if (!error) {
1157                 VOP_LEASE(nd.ni_dvp, td, p->p_ucred, LEASE_WRITE);
1158                 if (whiteout)
1159                         error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
1160                 else {
1161                         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1162                                                 &nd.ni_cnd, &vattr);
1163                         if (error == 0)
1164                                 vput(nd.ni_vp);
1165                 }
1166                 NDFREE(&nd, NDF_ONLY_PNBUF);
1167                 vput(nd.ni_dvp);
1168         } else {
1169                 NDFREE(&nd, NDF_ONLY_PNBUF);
1170                 if (nd.ni_dvp == vp)
1171                         vrele(nd.ni_dvp);
1172                 else
1173                         vput(nd.ni_dvp);
1174                 if (vp)
1175                         vrele(vp);
1176         }
1177         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod");
1178         ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod");
1179         return (error);
1180 }
1181
1182 /*
1183  * mkfifo_args(char *path, int mode)
1184  *
1185  * Create a named pipe.
1186  */
1187 /* ARGSUSED */
1188 int
1189 mkfifo(struct mkfifo_args *uap)
1190 {
1191         struct thread *td = curthread;
1192         struct proc *p = td->td_proc;
1193         struct vattr vattr;
1194         int error;
1195         struct nameidata nd;
1196
1197         bwillwrite();
1198         NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td);
1199         if ((error = namei(&nd)) != 0)
1200                 return (error);
1201         if (nd.ni_vp != NULL) {
1202                 NDFREE(&nd, NDF_ONLY_PNBUF);
1203                 if (nd.ni_dvp == nd.ni_vp)
1204                         vrele(nd.ni_dvp);
1205                 else
1206                         vput(nd.ni_dvp);
1207                 vrele(nd.ni_vp);
1208                 return (EEXIST);
1209         }
1210         VATTR_NULL(&vattr);
1211         vattr.va_type = VFIFO;
1212         vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1213         VOP_LEASE(nd.ni_dvp, td, p->p_ucred, LEASE_WRITE);
1214         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1215         if (error == 0)
1216                 vput(nd.ni_vp);
1217         NDFREE(&nd, NDF_ONLY_PNBUF);
1218         vput(nd.ni_dvp);
1219         return (error);
1220 }
1221
1222 /*
1223  * link_args(char *path, char *link)
1224  *
1225  * Make a hard file link.
1226  */
1227 /* ARGSUSED */
1228 int
1229 link(struct link_args *uap)
1230 {
1231         struct thread *td = curthread;
1232         struct proc *p = td->td_proc;
1233         struct vnode *vp;
1234         struct nameidata nd;
1235         int error;
1236
1237         bwillwrite();
1238         NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), td);
1239         if ((error = namei(&nd)) != 0)
1240                 return (error);
1241         NDFREE(&nd, NDF_ONLY_PNBUF);
1242         vp = nd.ni_vp;
1243         if (vp->v_type == VDIR)
1244                 error = EPERM;          /* POSIX */
1245         else {
1246                 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), td);
1247                 error = namei(&nd);
1248                 if (!error) {
1249                         if (nd.ni_vp != NULL) {
1250                                 if (nd.ni_vp)
1251                                         vrele(nd.ni_vp);
1252                                 error = EEXIST;
1253                         } else {
1254                                 VOP_LEASE(nd.ni_dvp, td, p->p_ucred,
1255                                     LEASE_WRITE);
1256                                 VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
1257                                 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1258                         }
1259                         NDFREE(&nd, NDF_ONLY_PNBUF);
1260                         if (nd.ni_dvp == nd.ni_vp)
1261                                 vrele(nd.ni_dvp);
1262                         else
1263                                 vput(nd.ni_dvp);
1264                 }
1265         }
1266         vrele(vp);
1267         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link");
1268         ASSERT_VOP_UNLOCKED(nd.ni_vp, "link");
1269         return (error);
1270 }
1271
1272 /*
1273  * symlink(char *path, char *link)
1274  *
1275  * Make a symbolic link.
1276  */
1277 /* ARGSUSED */
1278 int
1279 symlink(struct symlink_args *uap)
1280 {
1281         struct thread *td = curthread;
1282         struct proc *p = td->td_proc;
1283         struct vattr vattr;
1284         char *path;
1285         int error;
1286         struct nameidata nd;
1287
1288         path = zalloc(namei_zone);
1289         if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0)
1290                 goto out;
1291         bwillwrite();
1292         NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), td);
1293         if ((error = namei(&nd)) != 0)
1294                 goto out;
1295         if (nd.ni_vp) {
1296                 NDFREE(&nd, NDF_ONLY_PNBUF);
1297                 if (nd.ni_dvp == nd.ni_vp)
1298                         vrele(nd.ni_dvp);
1299                 else
1300                         vput(nd.ni_dvp);
1301                 vrele(nd.ni_vp);
1302                 error = EEXIST;
1303                 goto out;
1304         }
1305         VATTR_NULL(&vattr);
1306         vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
1307         VOP_LEASE(nd.ni_dvp, td, p->p_ucred, LEASE_WRITE);
1308         error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
1309         NDFREE(&nd, NDF_ONLY_PNBUF);
1310         if (error == 0)
1311                 vput(nd.ni_vp);
1312         vput(nd.ni_dvp);
1313         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink");
1314         ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink");
1315 out:
1316         zfree(namei_zone, path);
1317         return (error);
1318 }
1319
1320 /*
1321  * undelete_args(char *path)
1322  *
1323  * Delete a whiteout from the filesystem.
1324  */
1325 /* ARGSUSED */
1326 int
1327 undelete(struct undelete_args *uap)
1328 {
1329         struct thread *td = curthread;
1330         struct proc *p = td->td_proc;
1331         int error;
1332         struct nameidata nd;
1333
1334         bwillwrite();
1335         NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
1336             SCARG(uap, path), td);
1337         error = namei(&nd);
1338         if (error)
1339                 return (error);
1340
1341         if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1342                 NDFREE(&nd, NDF_ONLY_PNBUF);
1343                 if (nd.ni_dvp == nd.ni_vp)
1344                         vrele(nd.ni_dvp);
1345                 else
1346                         vput(nd.ni_dvp);
1347                 if (nd.ni_vp)
1348                         vrele(nd.ni_vp);
1349                 return (EEXIST);
1350         }
1351
1352         VOP_LEASE(nd.ni_dvp, td, p->p_ucred, LEASE_WRITE);
1353         error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
1354         NDFREE(&nd, NDF_ONLY_PNBUF);
1355         vput(nd.ni_dvp);
1356         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete");
1357         ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete");
1358         return (error);
1359 }
1360
1361 /*
1362  * unlink_args(char *path)
1363  *
1364  * Delete a name from the filesystem.
1365  */
1366 int
1367 unlink(struct unlink_args *uap)
1368 {
1369         struct thread *td = curthread;
1370         struct proc *p = td->td_proc;
1371         struct vnode *vp;
1372         int error;
1373         struct nameidata nd;
1374
1375         bwillwrite();
1376         NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td);
1377         if ((error = namei(&nd)) != 0)
1378                 return (error);
1379         vp = nd.ni_vp;
1380         VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
1381         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1382
1383         if (vp->v_type == VDIR)
1384                 error = EPERM;          /* POSIX */
1385         else {
1386                 /*
1387                  * The root of a mounted filesystem cannot be deleted.
1388                  *
1389                  * XXX: can this only be a VDIR case?
1390                  */
1391                 if (vp->v_flag & VROOT)
1392                         error = EBUSY;
1393         }
1394
1395         if (!error) {
1396                 VOP_LEASE(nd.ni_dvp, td, p->p_ucred, LEASE_WRITE);
1397                 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
1398         }
1399         NDFREE(&nd, NDF_ONLY_PNBUF);
1400         if (nd.ni_dvp == vp)
1401                 vrele(nd.ni_dvp);
1402         else
1403                 vput(nd.ni_dvp);
1404         if (vp != NULLVP)
1405                 vput(vp);
1406         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
1407         ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
1408         return (error);
1409 }
1410
1411 /*
1412  * lseek_args(int fd, int pad, off_t offset, int whence)
1413  *
1414  * Reposition read/write file offset.
1415  */
1416 int
1417 lseek(struct lseek_args *uap)
1418 {
1419         struct thread *td = curthread;
1420         struct proc *p = td->td_proc;
1421         struct ucred *cred = p->p_ucred;
1422         struct filedesc *fdp = p->p_fd;
1423         struct file *fp;
1424         struct vattr vattr;
1425         int error;
1426
1427         if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
1428             (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
1429                 return (EBADF);
1430         if (fp->f_type != DTYPE_VNODE)
1431                 return (ESPIPE);
1432         switch (SCARG(uap, whence)) {
1433         case L_INCR:
1434                 fp->f_offset += SCARG(uap, offset);
1435                 break;
1436         case L_XTND:
1437                 error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, td);
1438                 if (error)
1439                         return (error);
1440                 fp->f_offset = SCARG(uap, offset) + vattr.va_size;
1441                 break;
1442         case L_SET:
1443                 fp->f_offset = SCARG(uap, offset);
1444                 break;
1445         default:
1446                 return (EINVAL);
1447         }
1448         *(off_t *)(p->p_retval) = fp->f_offset;
1449         return (0);
1450 }
1451
1452 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1453 /*
1454  * Reposition read/write file offset.
1455  *
1456  * olseek_args(int fd, long offset, int whence)
1457  */
1458 int
1459 olseek(struct olseek_args *uap)
1460 {
1461         struct lseek_args /* {
1462                 syscallarg(int) fd;
1463                 syscallarg(int) pad;
1464                 syscallarg(off_t) offset;
1465                 syscallarg(int) whence;
1466         } */ nuap;
1467         int error;
1468
1469         SCARG(&nuap, fd) = SCARG(uap, fd);
1470         SCARG(&nuap, offset) = SCARG(uap, offset);
1471         SCARG(&nuap, whence) = SCARG(uap, whence);
1472         error = lseek(&nuap);
1473         return (error);
1474 }
1475 #endif /* COMPAT_43 */
1476
1477 /*
1478  * access_args(char *path, int flags)
1479  *
1480  * Check access permissions.
1481  */
1482 int
1483 access(struct access_args *uap)
1484 {
1485         struct thread *td = curthread;
1486         struct proc *p = td->td_proc;
1487         struct ucred *cred, *tmpcred;
1488         struct vnode *vp;
1489         int error, flags;
1490         struct nameidata nd;
1491
1492         cred = p->p_ucred;
1493         /*
1494          * Create and modify a temporary credential instead of one that
1495          * is potentially shared.  This could also mess up socket
1496          * buffer accounting which can run in an interrupt context.
1497          */
1498         tmpcred = crdup(cred);
1499         tmpcred->cr_uid = p->p_ucred->cr_ruid;
1500         tmpcred->cr_groups[0] = p->p_ucred->cr_rgid;
1501         p->p_ucred = tmpcred;
1502         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1503             SCARG(uap, path), td);
1504         if ((error = namei(&nd)) != 0)
1505                 goto out1;
1506         vp = nd.ni_vp;
1507
1508         /* Flags == 0 means only check for existence. */
1509         if (SCARG(uap, flags)) {
1510                 flags = 0;
1511                 if (SCARG(uap, flags) & R_OK)
1512                         flags |= VREAD;
1513                 if (SCARG(uap, flags) & W_OK)
1514                         flags |= VWRITE;
1515                 if (SCARG(uap, flags) & X_OK)
1516                         flags |= VEXEC;
1517                 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1518                         error = VOP_ACCESS(vp, flags, tmpcred, td);
1519         }
1520         NDFREE(&nd, NDF_ONLY_PNBUF);
1521         vput(vp);
1522 out1:
1523         p->p_ucred = cred;
1524         crfree(tmpcred);
1525         return (error);
1526 }
1527
1528 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1529 /*
1530  * ostat_args(char *path, struct ostat *ub)
1531  *
1532  * Get file status; this version follows links.
1533  */
1534 /* ARGSUSED */
1535 int
1536 ostat(struct ostat_args *uap)
1537 {
1538         struct thread *td = curthread;
1539         struct stat sb;
1540         struct ostat osb;
1541         int error;
1542         struct nameidata nd;
1543
1544         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1545             SCARG(uap, path), td);
1546         if ((error = namei(&nd)) != 0)
1547                 return (error);
1548         NDFREE(&nd, NDF_ONLY_PNBUF);
1549         error = vn_stat(nd.ni_vp, &sb, td);
1550         vput(nd.ni_vp);
1551         if (error)
1552                 return (error);
1553         cvtstat(&sb, &osb);
1554         error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1555         return (error);
1556 }
1557
1558 /*
1559  * olstat_args(char *path, struct ostat *ub)
1560  *
1561  * Get file status; this version does not follow links.
1562  */
1563 /* ARGSUSED */
1564 int
1565 olstat(struct olstat_args *uap)
1566 {
1567         struct thread *td = curthread;
1568         struct vnode *vp;
1569         struct stat sb;
1570         struct ostat osb;
1571         int error;
1572         struct nameidata nd;
1573
1574         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1575             SCARG(uap, path), td);
1576         if ((error = namei(&nd)) != 0)
1577                 return (error);
1578         vp = nd.ni_vp;
1579         error = vn_stat(vp, &sb, td);
1580         NDFREE(&nd, NDF_ONLY_PNBUF);
1581         vput(vp);
1582         if (error)
1583                 return (error);
1584         cvtstat(&sb, &osb);
1585         error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1586         return (error);
1587 }
1588
1589 /*
1590  * Convert from an old to a new stat structure.
1591  */
1592 void
1593 cvtstat(st, ost)
1594         struct stat *st;
1595         struct ostat *ost;
1596 {
1597         ost->st_dev = st->st_dev;
1598         ost->st_ino = st->st_ino;
1599         ost->st_mode = st->st_mode;
1600         ost->st_nlink = st->st_nlink;
1601         ost->st_uid = st->st_uid;
1602         ost->st_gid = st->st_gid;
1603         ost->st_rdev = st->st_rdev;
1604         if (st->st_size < (quad_t)1 << 32)
1605                 ost->st_size = st->st_size;
1606         else
1607                 ost->st_size = -2;
1608         ost->st_atime = st->st_atime;
1609         ost->st_mtime = st->st_mtime;
1610         ost->st_ctime = st->st_ctime;
1611         ost->st_blksize = st->st_blksize;
1612         ost->st_blocks = st->st_blocks;
1613         ost->st_flags = st->st_flags;
1614         ost->st_gen = st->st_gen;
1615 }
1616 #endif /* COMPAT_43 || COMPAT_SUNOS */
1617
1618 /*
1619  * stat_args(char *path, struct stat *ub)
1620  *
1621  * Get file status; this version follows links.
1622  */
1623 /* ARGSUSED */
1624 int
1625 stat(struct stat_args *uap)
1626 {
1627         struct thread *td = curthread;
1628         struct stat sb;
1629         int error;
1630         struct nameidata nd;
1631
1632         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1633             SCARG(uap, path), td);
1634         if ((error = namei(&nd)) != 0)
1635                 return (error);
1636         error = vn_stat(nd.ni_vp, &sb, td);
1637         NDFREE(&nd, NDF_ONLY_PNBUF);
1638         vput(nd.ni_vp);
1639         if (error)
1640                 return (error);
1641         error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1642         return (error);
1643 }
1644
1645 /*
1646  * lstat_args(char *path, struct stat *ub)
1647  *
1648  * Get file status; this version does not follow links.
1649  */
1650 /* ARGSUSED */
1651 int
1652 lstat(struct lstat_args *uap)
1653 {
1654         struct thread *td = curthread;
1655         int error;
1656         struct vnode *vp;
1657         struct stat sb;
1658         struct nameidata nd;
1659
1660         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1661             SCARG(uap, path), td);
1662         if ((error = namei(&nd)) != 0)
1663                 return (error);
1664         vp = nd.ni_vp;
1665         error = vn_stat(vp, &sb, td);
1666         NDFREE(&nd, NDF_ONLY_PNBUF);
1667         vput(vp);
1668         if (error)
1669                 return (error);
1670         error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1671         return (error);
1672 }
1673
1674 void
1675 cvtnstat(sb, nsb)
1676         struct stat *sb;
1677         struct nstat *nsb;
1678 {
1679         nsb->st_dev = sb->st_dev;
1680         nsb->st_ino = sb->st_ino;
1681         nsb->st_mode = sb->st_mode;
1682         nsb->st_nlink = sb->st_nlink;
1683         nsb->st_uid = sb->st_uid;
1684         nsb->st_gid = sb->st_gid;
1685         nsb->st_rdev = sb->st_rdev;
1686         nsb->st_atimespec = sb->st_atimespec;
1687         nsb->st_mtimespec = sb->st_mtimespec;
1688         nsb->st_ctimespec = sb->st_ctimespec;
1689         nsb->st_size = sb->st_size;
1690         nsb->st_blocks = sb->st_blocks;
1691         nsb->st_blksize = sb->st_blksize;
1692         nsb->st_flags = sb->st_flags;
1693         nsb->st_gen = sb->st_gen;
1694         nsb->st_qspare[0] = sb->st_qspare[0];
1695         nsb->st_qspare[1] = sb->st_qspare[1];
1696 }
1697
1698 /*
1699  * nstat_args(char *path, struct nstat *ub)
1700  */
1701 /* ARGSUSED */
1702 int
1703 nstat(struct nstat_args *uap)
1704 {
1705         struct thread *td = curthread;
1706         struct stat sb;
1707         struct nstat nsb;
1708         int error;
1709         struct nameidata nd;
1710
1711         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1712             SCARG(uap, path), td);
1713         if ((error = namei(&nd)) != 0)
1714                 return (error);
1715         NDFREE(&nd, NDF_ONLY_PNBUF);
1716         error = vn_stat(nd.ni_vp, &sb, td);
1717         vput(nd.ni_vp);
1718         if (error)
1719                 return (error);
1720         cvtnstat(&sb, &nsb);
1721         error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
1722         return (error);
1723 }
1724
1725 /*
1726  * lstat_args(char *path, struct stat *ub)
1727  *
1728  * Get file status; this version does not follow links.
1729  */
1730 /* ARGSUSED */
1731 int
1732 nlstat(struct nlstat_args *uap)
1733 {
1734         struct thread *td = curthread;
1735         int error;
1736         struct vnode *vp;
1737         struct stat sb;
1738         struct nstat nsb;
1739         struct nameidata nd;
1740
1741         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1742             SCARG(uap, path), td);
1743         if ((error = namei(&nd)) != 0)
1744                 return (error);
1745         vp = nd.ni_vp;
1746         NDFREE(&nd, NDF_ONLY_PNBUF);
1747         error = vn_stat(vp, &sb, td);
1748         vput(vp);
1749         if (error)
1750                 return (error);
1751         cvtnstat(&sb, &nsb);
1752         error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
1753         return (error);
1754 }
1755
1756 /*
1757  * pathconf_Args(char *path, int name)
1758  *
1759  * Get configurable pathname variables.
1760  */
1761 /* ARGSUSED */
1762 int
1763 pathconf(struct pathconf_args *uap)
1764 {
1765         struct thread *td = curthread;
1766         struct proc *p = td->td_proc;
1767         int error;
1768         struct nameidata nd;
1769
1770         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1771             SCARG(uap, path), td);
1772         if ((error = namei(&nd)) != 0)
1773                 return (error);
1774         NDFREE(&nd, NDF_ONLY_PNBUF);
1775         error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), p->p_retval);
1776         vput(nd.ni_vp);
1777         return (error);
1778 }
1779
1780 /*
1781  * readlink_args(char *path, char *buf, int count)
1782  *
1783  * Return target name of a symbolic link.
1784  */
1785 /* ARGSUSED */
1786 int
1787 readlink(struct readlink_args *uap)
1788 {
1789         struct thread *td = curthread;
1790         struct proc *p = td->td_proc;
1791         struct vnode *vp;
1792         struct iovec aiov;
1793         struct uio auio;
1794         int error;
1795         struct nameidata nd;
1796
1797         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1798             SCARG(uap, path), td);
1799         if ((error = namei(&nd)) != 0)
1800                 return (error);
1801         NDFREE(&nd, NDF_ONLY_PNBUF);
1802         vp = nd.ni_vp;
1803         if (vp->v_type != VLNK)
1804                 error = EINVAL;
1805         else {
1806                 aiov.iov_base = SCARG(uap, buf);
1807                 aiov.iov_len = SCARG(uap, count);
1808                 auio.uio_iov = &aiov;
1809                 auio.uio_iovcnt = 1;
1810                 auio.uio_offset = 0;
1811                 auio.uio_rw = UIO_READ;
1812                 auio.uio_segflg = UIO_USERSPACE;
1813                 auio.uio_td = td;
1814                 auio.uio_resid = SCARG(uap, count);
1815                 error = VOP_READLINK(vp, &auio, p->p_ucred);
1816         }
1817         vput(vp);
1818         p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
1819         return (error);
1820 }
1821
1822 static int
1823 setfflags(struct vnode *vp, int flags)
1824 {
1825         struct thread *td = curthread;
1826         struct proc *p = td->td_proc;
1827         int error;
1828         struct vattr vattr;
1829
1830         /*
1831          * Prevent non-root users from setting flags on devices.  When
1832          * a device is reused, users can retain ownership of the device
1833          * if they are allowed to set flags and programs assume that
1834          * chown can't fail when done as root.
1835          */
1836         if ((vp->v_type == VCHR || vp->v_type == VBLK) && 
1837             ((error = suser_cred(p->p_ucred, PRISON_ROOT)) != 0))
1838                 return (error);
1839
1840         VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
1841         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1842         VATTR_NULL(&vattr);
1843         vattr.va_flags = flags;
1844         error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
1845         VOP_UNLOCK(vp, 0, td);
1846         return (error);
1847 }
1848
1849 /*
1850  * chflags(char *path, int flags)
1851  *
1852  * Change flags of a file given a path name.
1853  */
1854 /* ARGSUSED */
1855 int
1856 chflags(struct chflags_args *uap)
1857 {
1858         struct thread *td = curthread;
1859         int error;
1860         struct nameidata nd;
1861
1862         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
1863         if ((error = namei(&nd)) != 0)
1864                 return (error);
1865         NDFREE(&nd, NDF_ONLY_PNBUF);
1866         error = setfflags(nd.ni_vp, SCARG(uap, flags));
1867         vrele(nd.ni_vp);
1868         return error;
1869 }
1870
1871 /*
1872  * fchflags_args(int fd, int flags)
1873  *
1874  * Change flags of a file given a file descriptor.
1875  */
1876 /* ARGSUSED */
1877 int
1878 fchflags(struct fchflags_args *uap)
1879 {
1880         struct thread *td = curthread;
1881         struct proc *p = td->td_proc;
1882         struct file *fp;
1883         int error;
1884
1885         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1886                 return (error);
1887         return setfflags((struct vnode *) fp->f_data, SCARG(uap, flags));
1888 }
1889
1890 static int
1891 setfmode(struct vnode *vp, int mode)
1892 {
1893         struct thread *td = curthread;
1894         struct proc *p = td->td_proc;
1895         int error;
1896         struct vattr vattr;
1897
1898         VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
1899         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1900         VATTR_NULL(&vattr);
1901         vattr.va_mode = mode & ALLPERMS;
1902         error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
1903         VOP_UNLOCK(vp, 0, td);
1904         return error;
1905 }
1906
1907 /*
1908  * chmod_args(char *path, int mode)
1909  *
1910  * Change mode of a file given path name.
1911  */
1912 /* ARGSUSED */
1913 int
1914 chmod(struct chmod_args *uap)
1915 {
1916         struct thread *td = curthread;
1917         int error;
1918         struct nameidata nd;
1919
1920         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
1921         if ((error = namei(&nd)) != 0)
1922                 return (error);
1923         NDFREE(&nd, NDF_ONLY_PNBUF);
1924         error = setfmode(nd.ni_vp, SCARG(uap, mode));
1925         vrele(nd.ni_vp);
1926         return error;
1927 }
1928
1929 /*
1930  * lchmod_args(char *path, int mode)
1931  *
1932  * Change mode of a file given path name (don't follow links.)
1933  */
1934 /* ARGSUSED */
1935 int
1936 lchmod(struct lchmod_args *uap)
1937 {
1938         struct thread *td = curthread;
1939         int error;
1940         struct nameidata nd;
1941
1942         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
1943         if ((error = namei(&nd)) != 0)
1944                 return (error);
1945         NDFREE(&nd, NDF_ONLY_PNBUF);
1946         error = setfmode(nd.ni_vp, SCARG(uap, mode));
1947         vrele(nd.ni_vp);
1948         return error;
1949 }
1950
1951 /*
1952  * fchmod_args(int fd, int mode)
1953  *
1954  * Change mode of a file given a file descriptor.
1955  */
1956 /* ARGSUSED */
1957 int
1958 fchmod(struct fchmod_args *uap)
1959 {
1960         struct thread *td = curthread;
1961         struct proc *p = td->td_proc;
1962         struct file *fp;
1963         int error;
1964
1965         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1966                 return (error);
1967         return setfmode((struct vnode *)fp->f_data, SCARG(uap, mode));
1968 }
1969
1970 static int
1971 setfown(struct vnode *vp, uid_t uid, gid_t gid)
1972 {
1973         struct thread *td = curthread;
1974         struct proc *p = td->td_proc;
1975         int error;
1976         struct vattr vattr;
1977
1978         VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
1979         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1980         VATTR_NULL(&vattr);
1981         vattr.va_uid = uid;
1982         vattr.va_gid = gid;
1983         error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
1984         VOP_UNLOCK(vp, 0, td);
1985         return error;
1986 }
1987
1988 /*
1989  * chown(char *path, int uid, int gid)
1990  *
1991  * Set ownership given a path name.
1992  */
1993 /* ARGSUSED */
1994 int
1995 chown(struct chown_args *uap)
1996 {
1997         struct thread *td = curthread;
1998         int error;
1999         struct nameidata nd;
2000
2001         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2002         if ((error = namei(&nd)) != 0)
2003                 return (error);
2004         NDFREE(&nd, NDF_ONLY_PNBUF);
2005         error = setfown(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2006         vrele(nd.ni_vp);
2007         return (error);
2008 }
2009
2010 /*
2011  * lchown_args(char *path, int uid, int gid)
2012  *
2013  * Set ownership given a path name, do not cross symlinks.
2014  */
2015 /* ARGSUSED */
2016 int
2017 lchown(struct lchown_args *uap)
2018 {
2019         struct thread *td = curthread;
2020         int error;
2021         struct nameidata nd;
2022
2023         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2024         if ((error = namei(&nd)) != 0)
2025                 return (error);
2026         NDFREE(&nd, NDF_ONLY_PNBUF);
2027         error = setfown(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2028         vrele(nd.ni_vp);
2029         return (error);
2030 }
2031
2032 /*
2033  * fchown_args(int fd, int uid, int gid)
2034  *
2035  * Set ownership given a file descriptor.
2036  */
2037 /* ARGSUSED */
2038 int
2039 fchown(struct fchown_args *uap)
2040 {
2041         struct thread *td = curthread;
2042         struct proc *p = td->td_proc;
2043         struct file *fp;
2044         int error;
2045
2046         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2047                 return (error);
2048         return setfown((struct vnode *)fp->f_data,
2049                 SCARG(uap, uid), SCARG(uap, gid));
2050 }
2051
2052 static int
2053 getutimes(const struct timeval *usrtvp, struct timespec *tsp)
2054 {
2055         struct timeval tv[2];
2056         int error;
2057
2058         if (usrtvp == NULL) {
2059                 microtime(&tv[0]);
2060                 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2061                 tsp[1] = tsp[0];
2062         } else {
2063                 if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0)
2064                         return (error);
2065                 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2066                 TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]);
2067         }
2068         return 0;
2069 }
2070
2071 static int
2072 setutimes(struct vnode *vp, const struct timespec *ts, int nullflag)
2073 {
2074         struct thread *td = curthread;
2075         struct proc *p = td->td_proc;
2076         int error;
2077         struct vattr vattr;
2078
2079         VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
2080         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2081         VATTR_NULL(&vattr);
2082         vattr.va_atime = ts[0];
2083         vattr.va_mtime = ts[1];
2084         if (nullflag)
2085                 vattr.va_vaflags |= VA_UTIMES_NULL;
2086         error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
2087         VOP_UNLOCK(vp, 0, td);
2088         return error;
2089 }
2090
2091 /*
2092  * utimes_args(char *path, struct timeval *tptr)
2093  *
2094  * Set the access and modification times of a file.
2095  */
2096 /* ARGSUSED */
2097 int
2098 utimes(struct utimes_args *uap)
2099 {
2100         struct thread *td = curthread;
2101         struct timespec ts[2];
2102         struct timeval *usrtvp;
2103         int error;
2104         struct nameidata nd;
2105
2106         usrtvp = SCARG(uap, tptr);
2107         if ((error = getutimes(usrtvp, ts)) != 0)
2108                 return (error);
2109         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2110         if ((error = namei(&nd)) != 0)
2111                 return (error);
2112         NDFREE(&nd, NDF_ONLY_PNBUF);
2113         error = setutimes(nd.ni_vp, ts, usrtvp == NULL);
2114         vrele(nd.ni_vp);
2115         return (error);
2116 }
2117
2118 /*
2119  * lutimes_args(char *path, struct timeval *tptr)
2120  *
2121  * Set the access and modification times of a file.
2122  */
2123 /* ARGSUSED */
2124 int
2125 lutimes(struct lutimes_args *uap)
2126 {
2127         struct thread *td = curthread;
2128         struct timespec ts[2];
2129         struct timeval *usrtvp;
2130         int error;
2131         struct nameidata nd;
2132
2133         usrtvp = SCARG(uap, tptr);
2134         if ((error = getutimes(usrtvp, ts)) != 0)
2135                 return (error);
2136         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2137         if ((error = namei(&nd)) != 0)
2138                 return (error);
2139         NDFREE(&nd, NDF_ONLY_PNBUF);
2140         error = setutimes(nd.ni_vp, ts, usrtvp == NULL);
2141         vrele(nd.ni_vp);
2142         return (error);
2143 }
2144
2145 /*
2146  * futimes_args(int fd, struct timeval *tptr)
2147  *
2148  * Set the access and modification times of a file.
2149  */
2150 /* ARGSUSED */
2151 int
2152 futimes(struct futimes_args *uap)
2153 {
2154         struct thread *td = curthread;
2155         struct proc *p = td->td_proc;
2156         struct timespec ts[2];
2157         struct file *fp;
2158         struct timeval *usrtvp;
2159         int error;
2160
2161         usrtvp = SCARG(uap, tptr);
2162         if ((error = getutimes(usrtvp, ts)) != 0)
2163                 return (error);
2164         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2165                 return (error);
2166         return setutimes((struct vnode *)fp->f_data, ts, usrtvp == NULL);
2167 }
2168
2169 /*
2170  * truncate(char *path, int pad, off_t length)
2171  *
2172  * Truncate a file given its path name.
2173  */
2174 /* ARGSUSED */
2175 int
2176 truncate(struct truncate_args *uap)
2177 {
2178         struct thread *td = curthread;
2179         struct proc *p = td->td_proc;
2180         struct vnode *vp;
2181         struct vattr vattr;
2182         int error;
2183         struct nameidata nd;
2184
2185         if (uap->length < 0)
2186                 return(EINVAL);
2187         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2188         if ((error = namei(&nd)) != 0)
2189                 return (error);
2190         vp = nd.ni_vp;
2191         NDFREE(&nd, NDF_ONLY_PNBUF);
2192         VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
2193         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2194         if (vp->v_type == VDIR)
2195                 error = EISDIR;
2196         else if ((error = vn_writechk(vp)) == 0 &&
2197             (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, td)) == 0) {
2198                 VATTR_NULL(&vattr);
2199                 vattr.va_size = SCARG(uap, length);
2200                 error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
2201         }
2202         vput(vp);
2203         return (error);
2204 }
2205
2206 /*
2207  * ftruncate_args(int fd, int pad, off_t length)
2208  *
2209  * Truncate a file given a file descriptor.
2210  */
2211 /* ARGSUSED */
2212 int
2213 ftruncate(struct ftruncate_args *uap)
2214 {
2215         struct thread *td = curthread;
2216         struct proc *p = td->td_proc;
2217         struct vattr vattr;
2218         struct vnode *vp;
2219         struct file *fp;
2220         int error;
2221
2222         if (uap->length < 0)
2223                 return(EINVAL);
2224         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2225                 return (error);
2226         if ((fp->f_flag & FWRITE) == 0)
2227                 return (EINVAL);
2228         vp = (struct vnode *)fp->f_data;
2229         VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
2230         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2231         if (vp->v_type == VDIR)
2232                 error = EISDIR;
2233         else if ((error = vn_writechk(vp)) == 0) {
2234                 VATTR_NULL(&vattr);
2235                 vattr.va_size = SCARG(uap, length);
2236                 error = VOP_SETATTR(vp, &vattr, fp->f_cred, td);
2237         }
2238         VOP_UNLOCK(vp, 0, td);
2239         return (error);
2240 }
2241
2242 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2243 /*
2244  * otruncate_args(char *path, long length)
2245  *
2246  * Truncate a file given its path name.
2247  */
2248 /* ARGSUSED */
2249 int
2250 otruncate(struct otruncate_args *uap)
2251 {
2252         struct truncate_args /* {
2253                 syscallarg(char *) path;
2254                 syscallarg(int) pad;
2255                 syscallarg(off_t) length;
2256         } */ nuap;
2257
2258         SCARG(&nuap, path) = SCARG(uap, path);
2259         SCARG(&nuap, length) = SCARG(uap, length);
2260         return (truncate(&nuap));
2261 }
2262
2263 /*
2264  * oftruncate_args(int fd, long length)
2265  *
2266  * Truncate a file given a file descriptor.
2267  */
2268 /* ARGSUSED */
2269 int
2270 oftruncate(struct oftruncate_args *uap)
2271 {
2272         struct ftruncate_args /* {
2273                 syscallarg(int) fd;
2274                 syscallarg(int) pad;
2275                 syscallarg(off_t) length;
2276         } */ nuap;
2277
2278         SCARG(&nuap, fd) = SCARG(uap, fd);
2279         SCARG(&nuap, length) = SCARG(uap, length);
2280         return (ftruncate(&nuap));
2281 }
2282 #endif /* COMPAT_43 || COMPAT_SUNOS */
2283
2284 /*
2285  * fsync(int fd)
2286  *
2287  * Sync an open file.
2288  */
2289 /* ARGSUSED */
2290 int
2291 fsync(struct fsync_args *uap)
2292 {
2293         struct thread *td = curthread;
2294         struct proc *p = td->td_proc;
2295         struct vnode *vp;
2296         struct file *fp;
2297         vm_object_t obj;
2298         int error;
2299
2300         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2301                 return (error);
2302         vp = (struct vnode *)fp->f_data;
2303         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2304         if (VOP_GETVOBJECT(vp, &obj) == 0)
2305                 vm_object_page_clean(obj, 0, 0, 0);
2306         if ((error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, td)) == 0 &&
2307             vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP) &&
2308             bioops.io_fsync)
2309                 error = (*bioops.io_fsync)(vp);
2310         VOP_UNLOCK(vp, 0, td);
2311         return (error);
2312 }
2313
2314 /*
2315  * rename_args(char *from, char *to)
2316  *
2317  * Rename files.  Source and destination must either both be directories,
2318  * or both not be directories.  If target is a directory, it must be empty.
2319  */
2320 /* ARGSUSED */
2321 int
2322 rename(struct rename_args *uap)
2323 {
2324         struct thread *td = curthread;
2325         struct proc *p = td->td_proc;
2326         struct vnode *tvp, *fvp, *tdvp;
2327         struct nameidata fromnd, tond;
2328         int error;
2329
2330         bwillwrite();
2331         NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
2332             SCARG(uap, from), td);
2333         if ((error = namei(&fromnd)) != 0)
2334                 return (error);
2335         fvp = fromnd.ni_vp;
2336         NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ,
2337             UIO_USERSPACE, SCARG(uap, to), td);
2338         if (fromnd.ni_vp->v_type == VDIR)
2339                 tond.ni_cnd.cn_flags |= WILLBEDIR;
2340         if ((error = namei(&tond)) != 0) {
2341                 /* Translate error code for rename("dir1", "dir2/."). */
2342                 if (error == EISDIR && fvp->v_type == VDIR)
2343                         error = EINVAL;
2344                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
2345                 vrele(fromnd.ni_dvp);
2346                 vrele(fvp);
2347                 goto out1;
2348         }
2349         tdvp = tond.ni_dvp;
2350         tvp = tond.ni_vp;
2351         if (tvp != NULL) {
2352                 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2353                         error = ENOTDIR;
2354                         goto out;
2355                 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2356                         error = EISDIR;
2357                         goto out;
2358                 }
2359         }
2360         if (fvp == tdvp)
2361                 error = EINVAL;
2362         /*
2363          * If the source is the same as the destination (that is, if they
2364          * are links to the same vnode), then there is nothing to do.
2365          */
2366         if (fvp == tvp)
2367                 error = -1;
2368 out:
2369         if (!error) {
2370                 VOP_LEASE(tdvp, td, p->p_ucred, LEASE_WRITE);
2371                 if (fromnd.ni_dvp != tdvp) {
2372                         VOP_LEASE(fromnd.ni_dvp, td, p->p_ucred, LEASE_WRITE);
2373                 }
2374                 if (tvp) {
2375                         VOP_LEASE(tvp, td, p->p_ucred, LEASE_WRITE);
2376                 }
2377                 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2378                                    tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2379                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
2380                 NDFREE(&tond, NDF_ONLY_PNBUF);
2381         } else {
2382                 NDFREE(&fromnd, NDF_ONLY_PNBUF);
2383                 NDFREE(&tond, NDF_ONLY_PNBUF);
2384                 if (tdvp == tvp)
2385                         vrele(tdvp);
2386                 else
2387                         vput(tdvp);
2388                 if (tvp)
2389                         vput(tvp);
2390                 vrele(fromnd.ni_dvp);
2391                 vrele(fvp);
2392         }
2393         vrele(tond.ni_startdir);
2394         ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename");
2395         ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename");
2396         ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename");
2397         ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename");
2398 out1:
2399         if (fromnd.ni_startdir)
2400                 vrele(fromnd.ni_startdir);
2401         if (error == -1)
2402                 return (0);
2403         return (error);
2404 }
2405
2406 /*
2407  * mkdir_args(char *path, int mode)
2408  *
2409  * Make a directory file.
2410  */
2411 /* ARGSUSED */
2412 int
2413 mkdir(struct mkdir_args *uap)
2414 {
2415         struct thread *td = curthread;
2416         struct proc *p = td->td_proc;
2417         struct vnode *vp;
2418         struct vattr vattr;
2419         int error;
2420         struct nameidata nd;
2421
2422         bwillwrite();
2423         NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td);
2424         nd.ni_cnd.cn_flags |= WILLBEDIR;
2425         if ((error = namei(&nd)) != 0)
2426                 return (error);
2427         vp = nd.ni_vp;
2428         if (vp != NULL) {
2429                 NDFREE(&nd, NDF_ONLY_PNBUF);
2430                 if (nd.ni_dvp == vp)
2431                         vrele(nd.ni_dvp);
2432                 else
2433                         vput(nd.ni_dvp);
2434                 vrele(vp);
2435                 return (EEXIST);
2436         }
2437         VATTR_NULL(&vattr);
2438         vattr.va_type = VDIR;
2439         vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
2440         VOP_LEASE(nd.ni_dvp, td, p->p_ucred, LEASE_WRITE);
2441         error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
2442         NDFREE(&nd, NDF_ONLY_PNBUF);
2443         vput(nd.ni_dvp);
2444         if (!error)
2445                 vput(nd.ni_vp);
2446         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir");
2447         ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir");
2448         return (error);
2449 }
2450
2451 /*
2452  * rmdir_args(char *path)
2453  *
2454  * Remove a directory file.
2455  */
2456 /* ARGSUSED */
2457 int
2458 rmdir(struct rmdir_args *uap)
2459 {
2460         struct thread *td = curthread;
2461         struct proc *p = td->td_proc;
2462         struct vnode *vp;
2463         int error;
2464         struct nameidata nd;
2465
2466         bwillwrite();
2467         NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
2468             SCARG(uap, path), td);
2469         if ((error = namei(&nd)) != 0)
2470                 return (error);
2471         vp = nd.ni_vp;
2472         if (vp->v_type != VDIR) {
2473                 error = ENOTDIR;
2474                 goto out;
2475         }
2476         /*
2477          * No rmdir "." please.
2478          */
2479         if (nd.ni_dvp == vp) {
2480                 error = EINVAL;
2481                 goto out;
2482         }
2483         /*
2484          * The root of a mounted filesystem cannot be deleted.
2485          */
2486         if (vp->v_flag & VROOT)
2487                 error = EBUSY;
2488         else {
2489                 VOP_LEASE(nd.ni_dvp, td, p->p_ucred, LEASE_WRITE);
2490                 VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
2491                 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2492         }
2493 out:
2494         NDFREE(&nd, NDF_ONLY_PNBUF);
2495         if (nd.ni_dvp == vp)
2496                 vrele(nd.ni_dvp);
2497         else
2498                 vput(nd.ni_dvp);
2499         if (vp != NULLVP)
2500                 vput(vp);
2501         ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir");
2502         ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir");
2503         return (error);
2504 }
2505
2506 #ifdef COMPAT_43
2507 /*
2508  * ogetdirentries_args(int fd, char *buf, u_int count, long *basep)
2509  *
2510  * Read a block of directory entries in a file system independent format.
2511  */
2512 int
2513 ogetdirentries(struct ogetdirentries_args *uap)
2514 {
2515         struct thread *td = curthread;
2516         struct proc *p = td->td_proc;
2517         struct vnode *vp;
2518         struct file *fp;
2519         struct uio auio, kuio;
2520         struct iovec aiov, kiov;
2521         struct dirent *dp, *edp;
2522         caddr_t dirbuf;
2523         int error, eofflag, readcnt;
2524         long loff;
2525
2526         /* XXX arbitrary sanity limit on `count'. */
2527         if (SCARG(uap, count) > 64 * 1024)
2528                 return (EINVAL);
2529         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2530                 return (error);
2531         if ((fp->f_flag & FREAD) == 0)
2532                 return (EBADF);
2533         vp = (struct vnode *)fp->f_data;
2534 unionread:
2535         if (vp->v_type != VDIR)
2536                 return (EINVAL);
2537         aiov.iov_base = SCARG(uap, buf);
2538         aiov.iov_len = SCARG(uap, count);
2539         auio.uio_iov = &aiov;
2540         auio.uio_iovcnt = 1;
2541         auio.uio_rw = UIO_READ;
2542         auio.uio_segflg = UIO_USERSPACE;
2543         auio.uio_td = td;
2544         auio.uio_resid = SCARG(uap, count);
2545         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2546         loff = auio.uio_offset = fp->f_offset;
2547 #       if (BYTE_ORDER != LITTLE_ENDIAN)
2548                 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
2549                         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
2550                             NULL, NULL);
2551                         fp->f_offset = auio.uio_offset;
2552                 } else
2553 #       endif
2554         {
2555                 kuio = auio;
2556                 kuio.uio_iov = &kiov;
2557                 kuio.uio_segflg = UIO_SYSSPACE;
2558                 kiov.iov_len = SCARG(uap, count);
2559                 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
2560                 kiov.iov_base = dirbuf;
2561                 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
2562                             NULL, NULL);
2563                 fp->f_offset = kuio.uio_offset;
2564                 if (error == 0) {
2565                         readcnt = SCARG(uap, count) - kuio.uio_resid;
2566                         edp = (struct dirent *)&dirbuf[readcnt];
2567                         for (dp = (struct dirent *)dirbuf; dp < edp; ) {
2568 #                               if (BYTE_ORDER == LITTLE_ENDIAN)
2569                                         /*
2570                                          * The expected low byte of
2571                                          * dp->d_namlen is our dp->d_type.
2572                                          * The high MBZ byte of dp->d_namlen
2573                                          * is our dp->d_namlen.
2574                                          */
2575                                         dp->d_type = dp->d_namlen;
2576                                         dp->d_namlen = 0;
2577 #                               else
2578                                         /*
2579                                          * The dp->d_type is the high byte
2580                                          * of the expected dp->d_namlen,
2581                                          * so must be zero'ed.
2582                                          */
2583                                         dp->d_type = 0;
2584 #                               endif
2585                                 if (dp->d_reclen > 0) {
2586                                         dp = (struct dirent *)
2587                                             ((char *)dp + dp->d_reclen);
2588                                 } else {
2589                                         error = EIO;
2590                                         break;
2591                                 }
2592                         }
2593                         if (dp >= edp)
2594                                 error = uiomove(dirbuf, readcnt, &auio);
2595                 }
2596                 FREE(dirbuf, M_TEMP);
2597         }
2598         VOP_UNLOCK(vp, 0, td);
2599         if (error)
2600                 return (error);
2601         if (SCARG(uap, count) == auio.uio_resid) {
2602                 if (union_dircheckp) {
2603                         error = union_dircheckp(td, &vp, fp);
2604                         if (error == -1)
2605                                 goto unionread;
2606                         if (error)
2607                                 return (error);
2608                 }
2609                 if ((vp->v_flag & VROOT) &&
2610                     (vp->v_mount->mnt_flag & MNT_UNION)) {
2611                         struct vnode *tvp = vp;
2612                         vp = vp->v_mount->mnt_vnodecovered;
2613                         VREF(vp);
2614                         fp->f_data = (caddr_t) vp;
2615                         fp->f_offset = 0;
2616                         vrele(tvp);
2617                         goto unionread;
2618                 }
2619         }
2620         error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2621             sizeof(long));
2622         p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
2623         return (error);
2624 }
2625 #endif /* COMPAT_43 */
2626
2627 /*
2628  * getdirentries_args(int fd, char *buf, u_int conut, long *basep)
2629  *
2630  * Read a block of directory entries in a file system independent format.
2631  */
2632 int
2633 getdirentries(struct getdirentries_args *uap)
2634 {
2635         struct thread *td = curthread;
2636         struct proc *p = td->td_proc;
2637         struct vnode *vp;
2638         struct file *fp;
2639         struct uio auio;
2640         struct iovec aiov;
2641         long loff;
2642         int error, eofflag;
2643
2644         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2645                 return (error);
2646         if ((fp->f_flag & FREAD) == 0)
2647                 return (EBADF);
2648         vp = (struct vnode *)fp->f_data;
2649 unionread:
2650         if (vp->v_type != VDIR)
2651                 return (EINVAL);
2652         aiov.iov_base = SCARG(uap, buf);
2653         aiov.iov_len = SCARG(uap, count);
2654         auio.uio_iov = &aiov;
2655         auio.uio_iovcnt = 1;
2656         auio.uio_rw = UIO_READ;
2657         auio.uio_segflg = UIO_USERSPACE;
2658         auio.uio_td = td;
2659         auio.uio_resid = SCARG(uap, count);
2660         /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */
2661         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2662         loff = auio.uio_offset = fp->f_offset;
2663         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
2664         fp->f_offset = auio.uio_offset;
2665         VOP_UNLOCK(vp, 0, td);
2666         if (error)
2667                 return (error);
2668         if (SCARG(uap, count) == auio.uio_resid) {
2669                 if (union_dircheckp) {
2670                         error = union_dircheckp(td, &vp, fp);
2671                         if (error == -1)
2672                                 goto unionread;
2673                         if (error)
2674                                 return (error);
2675                 }
2676                 if ((vp->v_flag & VROOT) &&
2677                     (vp->v_mount->mnt_flag & MNT_UNION)) {
2678                         struct vnode *tvp = vp;
2679                         vp = vp->v_mount->mnt_vnodecovered;
2680                         VREF(vp);
2681                         fp->f_data = (caddr_t) vp;
2682                         fp->f_offset = 0;
2683                         vrele(tvp);
2684                         goto unionread;
2685                 }
2686         }
2687         if (SCARG(uap, basep) != NULL) {
2688                 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2689                     sizeof(long));
2690         }
2691         p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
2692         return (error);
2693 }
2694
2695 /*
2696  * getdents_args(int fd, char *buf, size_t count)
2697  */
2698 int
2699 getdents(struct getdents_args *uap)
2700 {
2701         struct getdirentries_args ap;
2702
2703         ap.fd = uap->fd;
2704         ap.buf = uap->buf;
2705         ap.count = uap->count;
2706         ap.basep = NULL;
2707         return getdirentries(&ap);
2708 }
2709
2710 /*
2711  * umask(int newmask)
2712  *
2713  * Set the mode mask for creation of filesystem nodes.
2714  *
2715  * MP SAFE
2716  */
2717 int
2718 umask(struct umask_args *uap)
2719 {
2720         struct thread *td = curthread;
2721         struct proc *p = td->td_proc;
2722         struct filedesc *fdp;
2723
2724         fdp = p->p_fd;
2725         p->p_retval[0] = fdp->fd_cmask;
2726         fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
2727         return (0);
2728 }
2729
2730 /*
2731  * revoke(char *path)
2732  *
2733  * Void all references to file by ripping underlying filesystem
2734  * away from vnode.
2735  */
2736 /* ARGSUSED */
2737 int
2738 revoke(struct revoke_args *uap)
2739 {
2740         struct thread *td = curthread;
2741         struct proc *p = td->td_proc;
2742         struct vnode *vp;
2743         struct vattr vattr;
2744         int error;
2745         struct nameidata nd;
2746
2747         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
2748         if ((error = namei(&nd)) != 0)
2749                 return (error);
2750         vp = nd.ni_vp;
2751         NDFREE(&nd, NDF_ONLY_PNBUF);
2752         if (vp->v_type != VCHR && vp->v_type != VBLK) {
2753                 error = EINVAL;
2754                 goto out;
2755         }
2756         if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, td)) != 0)
2757                 goto out;
2758         if (p->p_ucred->cr_uid != vattr.va_uid &&
2759             (error = suser_cred(p->p_ucred, PRISON_ROOT)))
2760                 goto out;
2761         if (vcount(vp) > 1)
2762                 VOP_REVOKE(vp, REVOKEALL);
2763 out:
2764         vrele(vp);
2765         return (error);
2766 }
2767
2768 /*
2769  * Convert a user file descriptor to a kernel file entry.
2770  */
2771 int
2772 getvnode(struct filedesc *fdp, int fd, struct file **fpp)
2773 {
2774         struct file *fp;
2775
2776         if ((u_int)fd >= fdp->fd_nfiles ||
2777             (fp = fdp->fd_ofiles[fd]) == NULL)
2778                 return (EBADF);
2779         if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO)
2780                 return (EINVAL);
2781         *fpp = fp;
2782         return (0);
2783 }
2784 /*
2785  * getfh_args(char *fname, fhandle_t *fhp)
2786  *
2787  * Get (NFS) file handle
2788  */
2789 int
2790 getfh(struct getfh_args *uap)
2791 {
2792         struct thread *td = curthread;
2793         struct nameidata nd;
2794         fhandle_t fh;
2795         struct vnode *vp;
2796         int error;
2797
2798         /*
2799          * Must be super user
2800          */
2801         error = suser(td);
2802         if (error)
2803                 return (error);
2804         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, td);
2805         error = namei(&nd);
2806         if (error)
2807                 return (error);
2808         NDFREE(&nd, NDF_ONLY_PNBUF);
2809         vp = nd.ni_vp;
2810         bzero(&fh, sizeof(fh));
2811         fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
2812         error = VFS_VPTOFH(vp, &fh.fh_fid);
2813         vput(vp);
2814         if (error)
2815                 return (error);
2816         error = copyout(&fh, uap->fhp, sizeof (fh));
2817         return (error);
2818 }
2819
2820 /*
2821  * fhopen_args(const struct fhandle *u_fhp, int flags)
2822  *
2823  * syscall for the rpc.lockd to use to translate a NFS file handle into
2824  * an open descriptor.
2825  *
2826  * warning: do not remove the suser() call or this becomes one giant
2827  * security hole.
2828  */
2829 int
2830 fhopen(struct fhopen_args *uap)
2831 {
2832         struct thread *td = curthread;
2833         struct proc *p = td->td_proc;
2834         struct mount *mp;
2835         struct vnode *vp;
2836         struct fhandle fhp;
2837         struct vattr vat;
2838         struct vattr *vap = &vat;
2839         struct flock lf;
2840         struct file *fp;
2841         struct filedesc *fdp = p->p_fd;
2842         int fmode, mode, error, type;
2843         struct file *nfp; 
2844         int indx;
2845
2846         /*
2847          * Must be super user
2848          */
2849         error = suser(td);
2850         if (error)
2851                 return (error);
2852
2853         fmode = FFLAGS(SCARG(uap, flags));
2854         /* why not allow a non-read/write open for our lockd? */
2855         if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
2856                 return (EINVAL);
2857         error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp));
2858         if (error)
2859                 return(error);
2860         /* find the mount point */
2861         mp = vfs_getvfs(&fhp.fh_fsid);
2862         if (mp == NULL)
2863                 return (ESTALE);
2864         /* now give me my vnode, it gets returned to me locked */
2865         error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
2866         if (error)
2867                 return (error);
2868         /*
2869          * from now on we have to make sure not
2870          * to forget about the vnode
2871          * any error that causes an abort must vput(vp) 
2872          * just set error = err and 'goto bad;'.
2873          */
2874
2875         /* 
2876          * from vn_open 
2877          */
2878         if (vp->v_type == VLNK) {
2879                 error = EMLINK;
2880                 goto bad;
2881         }
2882         if (vp->v_type == VSOCK) {
2883                 error = EOPNOTSUPP;
2884                 goto bad;
2885         }
2886         mode = 0;
2887         if (fmode & (FWRITE | O_TRUNC)) {
2888                 if (vp->v_type == VDIR) {
2889                         error = EISDIR;
2890                         goto bad;
2891                 }
2892                 error = vn_writechk(vp);
2893                 if (error)
2894                         goto bad;
2895                 mode |= VWRITE;
2896         }
2897         if (fmode & FREAD)
2898                 mode |= VREAD;
2899         if (mode) {
2900                 error = VOP_ACCESS(vp, mode, p->p_ucred, td);
2901                 if (error)
2902                         goto bad;
2903         }
2904         if (fmode & O_TRUNC) {
2905                 VOP_UNLOCK(vp, 0, td);                          /* XXX */
2906                 VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
2907                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);       /* XXX */
2908                 VATTR_NULL(vap);
2909                 vap->va_size = 0;
2910                 error = VOP_SETATTR(vp, vap, p->p_ucred, td);
2911                 if (error)
2912                         goto bad;
2913         }
2914         error = VOP_OPEN(vp, fmode, p->p_ucred, td);
2915         if (error)
2916                 goto bad;
2917         /*
2918          * Make sure that a VM object is created for VMIO support.
2919          */
2920         if (vn_canvmio(vp) == TRUE) {
2921                 if ((error = vfs_object_create(vp, td, p->p_ucred)) != 0)
2922                         goto bad;
2923         }
2924         if (fmode & FWRITE)
2925                 vp->v_writecount++;
2926
2927         /*
2928          * end of vn_open code 
2929          */
2930
2931         if ((error = falloc(p, &nfp, &indx)) != 0) {
2932                 if (fmode & FWRITE)
2933                         vp->v_writecount--;
2934                 goto bad;
2935         }
2936         fp = nfp;       
2937
2938         /*
2939          * hold an extra reference to avoid having fp ripped out
2940          * from under us while we block in the lock op.
2941          */
2942         fhold(fp);
2943         nfp->f_data = (caddr_t)vp;
2944         nfp->f_flag = fmode & FMASK;
2945         nfp->f_ops = &vnops;
2946         nfp->f_type = DTYPE_VNODE;
2947         if (fmode & (O_EXLOCK | O_SHLOCK)) {
2948                 lf.l_whence = SEEK_SET;
2949                 lf.l_start = 0;
2950                 lf.l_len = 0;
2951                 if (fmode & O_EXLOCK)
2952                         lf.l_type = F_WRLCK;
2953                 else
2954                         lf.l_type = F_RDLCK;
2955                 type = F_FLOCK;
2956                 if ((fmode & FNONBLOCK) == 0)
2957                         type |= F_WAIT;
2958                 VOP_UNLOCK(vp, 0, td);
2959                 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
2960                         /*
2961                          * lock request failed.  Normally close the descriptor
2962                          * but handle the case where someone might have dup()d
2963                          * or close()d it when we weren't looking.
2964                          */
2965                         if (fdp->fd_ofiles[indx] == fp) {
2966                                 fdp->fd_ofiles[indx] = NULL;
2967                                 fdrop(fp, td);
2968                         }
2969
2970                         /*
2971                          * release our private reference.
2972                          */
2973                         fdrop(fp, td);
2974                         return (error);
2975                 }
2976                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2977                 fp->f_flag |= FHASLOCK;
2978         }
2979         if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0))
2980                 vfs_object_create(vp, td, p->p_ucred);
2981
2982         VOP_UNLOCK(vp, 0, td);
2983         fdrop(fp, td);
2984         p->p_retval[0] = indx;
2985         return (0);
2986
2987 bad:
2988         vput(vp);
2989         return (error);
2990 }
2991
2992 /*
2993  * fhstat_args(struct fhandle *u_fhp, struct stat *sb)
2994  */
2995 int
2996 fhstat(struct fhstat_args *uap)
2997 {
2998         struct thread *td = curthread;
2999         struct stat sb;
3000         fhandle_t fh;
3001         struct mount *mp;
3002         struct vnode *vp;
3003         int error;
3004
3005         /*
3006          * Must be super user
3007          */
3008         error = suser(td);
3009         if (error)
3010                 return (error);
3011         
3012         error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t));
3013         if (error)
3014                 return (error);
3015
3016         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3017                 return (ESTALE);
3018         if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3019                 return (error);
3020         error = vn_stat(vp, &sb, td);
3021         vput(vp);
3022         if (error)
3023                 return (error);
3024         error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
3025         return (error);
3026 }
3027
3028 /*
3029  * fhstatfs_args(struct fhandle *u_fhp, struct statfs *buf)
3030  */
3031 int
3032 fhstatfs(struct fhstatfs_args *uap)
3033 {
3034         struct thread *td = curthread;
3035         struct statfs *sp;
3036         struct mount *mp;
3037         struct vnode *vp;
3038         struct statfs sb;
3039         fhandle_t fh;
3040         int error;
3041
3042         /*
3043          * Must be super user
3044          */
3045         if ((error = suser(td)))
3046                 return (error);
3047
3048         if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0)
3049                 return (error);
3050
3051         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3052                 return (ESTALE);
3053         if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3054                 return (error);
3055         mp = vp->v_mount;
3056         sp = &mp->mnt_stat;
3057         vput(vp);
3058         if ((error = VFS_STATFS(mp, sp, td)) != 0)
3059                 return (error);
3060         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
3061         if (suser(td)) {
3062                 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
3063                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
3064                 sp = &sb;
3065         }
3066         return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
3067 }
3068
3069 /*
3070  * Syscall to push extended attribute configuration information into the
3071  * VFS.  Accepts a path, which it converts to a mountpoint, as well as
3072  * a command (int cmd), and attribute name and misc data.  For now, the
3073  * attribute name is left in userspace for consumption by the VFS_op.
3074  * It will probably be changed to be copied into sysspace by the
3075  * syscall in the future, once issues with various consumers of the
3076  * attribute code have raised their hands.
3077  *
3078  * Currently this is used only by UFS Extended Attributes.
3079  */
3080 int
3081 extattrctl(struct extattrctl_args *uap)
3082 {
3083         struct thread *td = curthread;
3084         struct nameidata nd;
3085         struct mount *mp;
3086         int error;
3087
3088         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
3089         if ((error = namei(&nd)) != 0)
3090                 return (error);
3091         mp = nd.ni_vp->v_mount;
3092         NDFREE(&nd, 0);
3093         return (VFS_EXTATTRCTL(mp, SCARG(uap, cmd), SCARG(uap, attrname),
3094             SCARG(uap, arg), td));
3095 }
3096
3097 /*
3098  * Syscall to set a named extended attribute on a file or directory.
3099  * Accepts attribute name, and a uio structure pointing to the data to set.
3100  * The uio is consumed in the style of writev().  The real work happens
3101  * in VOP_SETEXTATTR().
3102  */
3103 int
3104 extattr_set_file(struct extattr_set_file_args *uap)
3105 {
3106         struct thread *td = curthread;
3107         struct proc *p = td->td_proc;
3108         struct nameidata nd;
3109         struct uio auio;
3110         struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV];
3111         char attrname[EXTATTR_MAXNAMELEN];
3112         u_int iovlen, cnt;
3113         int error, i;
3114
3115         error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
3116         if (error)
3117                 return (error);
3118         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
3119             SCARG(uap, path), td);
3120         if ((error = namei(&nd)) != 0)
3121                 return(error);
3122         iovlen = uap->iovcnt * sizeof(struct iovec);
3123         if (uap->iovcnt > UIO_SMALLIOV) {
3124                 if (uap->iovcnt > UIO_MAXIOV) {
3125                         error = EINVAL;
3126                         goto done;
3127                 }
3128                 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
3129                 needfree = iov;
3130         } else
3131                 iov = aiov;
3132         auio.uio_iov = iov;
3133         auio.uio_iovcnt = uap->iovcnt;
3134         auio.uio_rw = UIO_WRITE;
3135         auio.uio_segflg = UIO_USERSPACE;
3136         auio.uio_td = td;
3137         auio.uio_offset = 0;
3138         if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
3139                 goto done;
3140         auio.uio_resid = 0;
3141         for (i = 0; i < uap->iovcnt; i++) {
3142                 if (iov->iov_len > INT_MAX - auio.uio_resid) {
3143                         error = EINVAL;
3144                         goto done;
3145                 }
3146                 auio.uio_resid += iov->iov_len;
3147                 iov++;
3148         }
3149         cnt = auio.uio_resid;
3150         error = VOP_SETEXTATTR(nd.ni_vp, attrname, &auio, p->p_ucred, td);
3151         cnt -= auio.uio_resid;
3152         p->p_retval[0] = cnt;
3153 done:
3154         if (needfree)
3155                 FREE(needfree, M_IOV);
3156         NDFREE(&nd, 0);
3157         return (error);
3158 }
3159
3160 /*
3161  * Syscall to get a named extended attribute on a file or directory.
3162  * Accepts attribute name, and a uio structure pointing to a buffer for the
3163  * data.  The uio is consumed in the style of readv().  The real work
3164  * happens in VOP_GETEXTATTR();
3165  */
3166 int
3167 extattr_get_file(struct extattr_get_file_args *uap)
3168 {
3169         struct thread *td = curthread;
3170         struct proc *p = td->td_proc;
3171         struct nameidata nd;
3172         struct uio auio;
3173         struct iovec *iov, *needfree, aiov[UIO_SMALLIOV];
3174         char attrname[EXTATTR_MAXNAMELEN];
3175         u_int iovlen, cnt;
3176         int error, i;
3177
3178         error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
3179         if (error)
3180                 return (error);
3181         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
3182             SCARG(uap, path), td);
3183         if ((error = namei(&nd)) != 0)
3184                 return (error);
3185         iovlen = uap->iovcnt * sizeof (struct iovec);
3186         if (uap->iovcnt > UIO_SMALLIOV) {
3187                 if (uap->iovcnt > UIO_MAXIOV) {
3188                         NDFREE(&nd, 0);
3189                         return (EINVAL);
3190                 }
3191                 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
3192                 needfree = iov;
3193         } else {
3194                 iov = aiov;
3195                 needfree = NULL;
3196         }
3197         auio.uio_iov = iov;
3198         auio.uio_iovcnt = uap->iovcnt;
3199         auio.uio_rw = UIO_READ;
3200         auio.uio_segflg = UIO_USERSPACE;
3201         auio.uio_td = td;
3202         auio.uio_offset = 0;
3203         if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
3204                 goto done;
3205         auio.uio_resid = 0;
3206         for (i = 0; i < uap->iovcnt; i++) {
3207                 if (iov->iov_len > INT_MAX - auio.uio_resid) {
3208                         error = EINVAL;
3209                         goto done;
3210                 }
3211                 auio.uio_resid += iov->iov_len;
3212                 iov++;
3213         }
3214         cnt = auio.uio_resid;
3215         error = VOP_GETEXTATTR(nd.ni_vp, attrname, &auio, p->p_ucred, td);
3216         cnt -= auio.uio_resid;
3217         p->p_retval[0] = cnt;
3218 done:
3219         if (needfree)
3220                 FREE(needfree, M_IOV);
3221         NDFREE(&nd, 0);
3222         return(error);
3223 }
3224
3225 /*
3226  * Syscall to delete a named extended attribute from a file or directory.
3227  * Accepts attribute name.  The real work happens in VOP_SETEXTATTR().
3228  */
3229 int
3230 extattr_delete_file(struct extattr_delete_file_args *uap)
3231 {
3232         struct thread *td = curthread;
3233         struct proc *p = td->td_proc;
3234         struct nameidata nd;
3235         char attrname[EXTATTR_MAXNAMELEN];
3236         int     error;
3237
3238         error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
3239         if (error)
3240                 return(error);
3241         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
3242             SCARG(uap, path), td);
3243         if ((error = namei(&nd)) != 0)
3244                 return(error);
3245         error = VOP_SETEXTATTR(nd.ni_vp, attrname, NULL, p->p_ucred, td);
3246         NDFREE(&nd, 0);
3247         return(error);
3248 }