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