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