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