fixes for fp context switching
[unix-history] / usr / src / sys / kern / vfs_syscalls.c
CommitLineData
da7c5cc6 1/*
fc2aed1e
KM
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
da7c5cc6 4 *
dbf0c423 5 * %sccs.include.redist.c%
fc2aed1e 6 *
6aaf085a 7 * @(#)vfs_syscalls.c 7.74 (Berkeley) %G%
da7c5cc6 8 */
6459ebe0 9
94368568
JB
10#include "param.h"
11#include "systm.h"
8429d022 12#include "namei.h"
5e00df3b 13#include "filedesc.h"
94368568
JB
14#include "kernel.h"
15#include "file.h"
16#include "stat.h"
fc2aed1e 17#include "vnode.h"
fc2aed1e 18#include "mount.h"
94368568 19#include "proc.h"
94368568 20#include "uio.h"
fc2aed1e 21#include "malloc.h"
88a7a62a 22
fc2aed1e
KM
23/*
24 * Virtual File System System Calls
25 */
3e78e260 26
4f083fd7 27/*
d4ed1dcd 28 * Mount system call.
4f083fd7 29 */
6a6a1e5f
KM
30/* ARGSUSED */
31mount(p, uap, retval)
5e00df3b 32 struct proc *p;
6a6a1e5f 33 register struct args {
fc2aed1e
KM
34 int type;
35 char *dir;
36 int flags;
37 caddr_t data;
6a6a1e5f
KM
38 } *uap;
39 int *retval;
40{
8429d022 41 register struct nameidata *ndp;
d48157d5
KM
42 register struct vnode *vp;
43 register struct mount *mp;
47971887 44 int error, flag;
8429d022 45 struct nameidata nd;
3e78e260 46
fc2aed1e
KM
47 /*
48 * Must be super user
49 */
8429d022
MK
50 if (error = suser(p->p_ucred, &p->p_acflag))
51 return (error);
fc2aed1e
KM
52 /*
53 * Get vnode to be covered
54 */
8429d022 55 ndp = &nd;
fc2aed1e
KM
56 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
57 ndp->ni_segflg = UIO_USERSPACE;
58 ndp->ni_dirp = uap->dir;
8429d022
MK
59 if (error = namei(ndp, p))
60 return (error);
fc2aed1e 61 vp = ndp->ni_vp;
54fb9dc2 62 if (uap->flags & MNT_UPDATE) {
d48157d5
KM
63 if ((vp->v_flag & VROOT) == 0) {
64 vput(vp);
8429d022 65 return (EINVAL);
d48157d5
KM
66 }
67 mp = vp->v_mount;
68 /*
69 * We allow going from read-only to read-write,
70 * but not from read-write to read-only.
71 */
54fb9dc2
KM
72 if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
73 (uap->flags & MNT_RDONLY) != 0) {
d48157d5 74 vput(vp);
8429d022 75 return (EOPNOTSUPP); /* Needs translation */
d48157d5 76 }
54fb9dc2
KM
77 flag = mp->mnt_flag;
78 mp->mnt_flag |= MNT_UPDATE;
d48157d5
KM
79 VOP_UNLOCK(vp);
80 goto update;
81 }
89cdb378 82 vinvalbuf(vp, 1);
8b81d198 83 if (vp->v_usecount != 1) {
fc2aed1e 84 vput(vp);
8429d022 85 return (EBUSY);
fc2aed1e
KM
86 }
87 if (vp->v_type != VDIR) {
88 vput(vp);
8429d022 89 return (ENOTDIR);
fc2aed1e 90 }
62d239e5 91 if ((unsigned long)uap->type > MOUNT_MAXTYPE ||
fc2aed1e
KM
92 vfssw[uap->type] == (struct vfsops *)0) {
93 vput(vp);
8429d022 94 return (ENODEV);
fc2aed1e
KM
95 }
96
97 /*
d48157d5 98 * Allocate and initialize the file system.
fc2aed1e
KM
99 */
100 mp = (struct mount *)malloc((u_long)sizeof(struct mount),
101 M_MOUNT, M_WAITOK);
54fb9dc2
KM
102 mp->mnt_op = vfssw[uap->type];
103 mp->mnt_flag = 0;
104 mp->mnt_exroot = 0;
105 mp->mnt_mounth = NULLVP;
d48157d5
KM
106 if (error = vfs_lock(mp)) {
107 free((caddr_t)mp, M_MOUNT);
108 vput(vp);
8429d022 109 return (error);
d48157d5
KM
110 }
111 if (vp->v_mountedhere != (struct mount *)0) {
112 vfs_unlock(mp);
113 free((caddr_t)mp, M_MOUNT);
114 vput(vp);
8429d022 115 return (EBUSY);
d48157d5 116 }
d48157d5 117 vp->v_mountedhere = mp;
54fb9dc2 118 mp->mnt_vnodecovered = vp;
d48157d5
KM
119update:
120 /*
121 * Set the mount level flags.
122 */
54fb9dc2
KM
123 if (uap->flags & MNT_RDONLY)
124 mp->mnt_flag |= MNT_RDONLY;
d48157d5 125 else
54fb9dc2
KM
126 mp->mnt_flag &= ~MNT_RDONLY;
127 if (uap->flags & MNT_NOSUID)
128 mp->mnt_flag |= MNT_NOSUID;
d48157d5 129 else
54fb9dc2
KM
130 mp->mnt_flag &= ~MNT_NOSUID;
131 if (uap->flags & MNT_NOEXEC)
132 mp->mnt_flag |= MNT_NOEXEC;
d48157d5 133 else
54fb9dc2
KM
134 mp->mnt_flag &= ~MNT_NOEXEC;
135 if (uap->flags & MNT_NODEV)
136 mp->mnt_flag |= MNT_NODEV;
d48157d5 137 else
54fb9dc2
KM
138 mp->mnt_flag &= ~MNT_NODEV;
139 if (uap->flags & MNT_SYNCHRONOUS)
140 mp->mnt_flag |= MNT_SYNCHRONOUS;
d48157d5 141 else
54fb9dc2 142 mp->mnt_flag &= ~MNT_SYNCHRONOUS;
d48157d5
KM
143 /*
144 * Mount the filesystem.
145 */
2c69fe14 146 error = VFS_MOUNT(mp, uap->dir, uap->data, ndp, p);
54fb9dc2
KM
147 if (mp->mnt_flag & MNT_UPDATE) {
148 mp->mnt_flag &= ~MNT_UPDATE;
d48157d5 149 vrele(vp);
47971887 150 if (error)
54fb9dc2 151 mp->mnt_flag = flag;
8429d022 152 return (error);
d48157d5 153 }
92d0de98
KM
154 /*
155 * Put the new filesystem on the mount list after root.
156 */
54fb9dc2
KM
157 mp->mnt_next = rootfs->mnt_next;
158 mp->mnt_prev = rootfs;
159 rootfs->mnt_next = mp;
160 mp->mnt_next->mnt_prev = mp;
fc2aed1e 161 cache_purge(vp);
fc2aed1e 162 if (!error) {
d48157d5 163 VOP_UNLOCK(vp);
fc2aed1e 164 vfs_unlock(mp);
2c69fe14 165 error = VFS_START(mp, 0, p);
fc2aed1e
KM
166 } else {
167 vfs_remove(mp);
168 free((caddr_t)mp, M_MOUNT);
d48157d5 169 vput(vp);
fc2aed1e 170 }
8429d022 171 return (error);
3e78e260
BJ
172}
173
4f083fd7 174/*
fc2aed1e
KM
175 * Unmount system call.
176 *
177 * Note: unmount takes a path to the vnode mounted on as argument,
178 * not special file (as before).
4f083fd7 179 */
6a6a1e5f
KM
180/* ARGSUSED */
181unmount(p, uap, retval)
5e00df3b 182 struct proc *p;
6a6a1e5f 183 register struct args {
fc2aed1e
KM
184 char *pathp;
185 int flags;
6a6a1e5f
KM
186 } *uap;
187 int *retval;
188{
fc2aed1e 189 register struct vnode *vp;
8429d022 190 register struct nameidata *ndp;
9151110e 191 struct mount *mp;
fc2aed1e 192 int error;
8429d022 193 struct nameidata nd;
fc2aed1e
KM
194
195 /*
196 * Must be super user
197 */
8429d022
MK
198 if (error = suser(p->p_ucred, &p->p_acflag))
199 return (error);
fc2aed1e 200
8429d022 201 ndp = &nd;
fc2aed1e
KM
202 ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
203 ndp->ni_segflg = UIO_USERSPACE;
204 ndp->ni_dirp = uap->pathp;
8429d022
MK
205 if (error = namei(ndp, p))
206 return (error);
fc2aed1e
KM
207 vp = ndp->ni_vp;
208 /*
209 * Must be the root of the filesystem
210 */
211 if ((vp->v_flag & VROOT) == 0) {
212 vput(vp);
8429d022 213 return (EINVAL);
fc2aed1e
KM
214 }
215 mp = vp->v_mount;
216 vput(vp);
2c69fe14 217 return (dounmount(mp, uap->flags, p));
9151110e
KM
218}
219
220/*
221 * Do an unmount.
222 */
2c69fe14 223dounmount(mp, flags, p)
9151110e
KM
224 register struct mount *mp;
225 int flags;
2c69fe14 226 struct proc *p;
9151110e
KM
227{
228 struct vnode *coveredvp;
229 int error;
230
54fb9dc2 231 coveredvp = mp->mnt_vnodecovered;
c001b1c3
KM
232 if (vfs_busy(mp))
233 return (EBUSY);
54fb9dc2 234 mp->mnt_flag |= MNT_UNMOUNT;
fc2aed1e 235 if (error = vfs_lock(mp))
9151110e 236 return (error);
fc2aed1e 237
9db58063 238 vnode_pager_umount(mp); /* release cached vnodes */
fc2aed1e 239 cache_purgevfs(mp); /* remove cache entries for this file sys */
a99a44da 240 if ((error = VFS_SYNC(mp, MNT_WAIT)) == 0 || (flags & MNT_FORCE))
2c69fe14 241 error = VFS_UNMOUNT(mp, flags, p);
54fb9dc2 242 mp->mnt_flag &= ~MNT_UNMOUNT;
c001b1c3 243 vfs_unbusy(mp);
fc2aed1e
KM
244 if (error) {
245 vfs_unlock(mp);
246 } else {
247 vrele(coveredvp);
248 vfs_remove(mp);
249 free((caddr_t)mp, M_MOUNT);
250 }
9151110e 251 return (error);
fc2aed1e
KM
252}
253
254/*
255 * Sync system call.
256 * Sync each mounted filesystem.
257 */
ff4fb102 258/* ARGSUSED */
6a6a1e5f 259sync(p, uap, retval)
5e00df3b 260 struct proc *p;
8429d022 261 void *uap;
6a6a1e5f 262 int *retval;
3e78e260 263{
fc2aed1e 264 register struct mount *mp;
c001b1c3 265 struct mount *omp;
fc2aed1e
KM
266
267 mp = rootfs;
268 do {
62e35d50
KM
269 /*
270 * The lock check below is to avoid races with mount
271 * and unmount.
272 */
54fb9dc2 273 if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 &&
c001b1c3 274 !vfs_busy(mp)) {
fc2aed1e 275 VFS_SYNC(mp, MNT_NOWAIT);
c001b1c3 276 omp = mp;
54fb9dc2 277 mp = mp->mnt_next;
c001b1c3
KM
278 vfs_unbusy(omp);
279 } else
54fb9dc2 280 mp = mp->mnt_next;
fc2aed1e 281 } while (mp != rootfs);
78eeb014 282 return (0);
fc2aed1e
KM
283}
284
c001b1c3 285/*
d4ed1dcd 286 * Operate on filesystem quotas.
c001b1c3 287 */
6a6a1e5f
KM
288/* ARGSUSED */
289quotactl(p, uap, retval)
5e00df3b 290 struct proc *p;
6a6a1e5f 291 register struct args {
c001b1c3
KM
292 char *path;
293 int cmd;
294 int uid;
295 caddr_t arg;
6a6a1e5f
KM
296 } *uap;
297 int *retval;
298{
c001b1c3 299 register struct mount *mp;
8429d022 300 register struct nameidata *ndp;
c001b1c3 301 int error;
8429d022 302 struct nameidata nd;
c001b1c3 303
8429d022 304 ndp = &nd;
c001b1c3
KM
305 ndp->ni_nameiop = LOOKUP | FOLLOW;
306 ndp->ni_segflg = UIO_USERSPACE;
307 ndp->ni_dirp = uap->path;
8429d022
MK
308 if (error = namei(ndp, p))
309 return (error);
c001b1c3
KM
310 mp = ndp->ni_vp->v_mount;
311 vrele(ndp->ni_vp);
2c69fe14 312 return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p));
c001b1c3
KM
313}
314
fc2aed1e 315/*
d4ed1dcd 316 * Get filesystem statistics.
fc2aed1e 317 */
6a6a1e5f
KM
318/* ARGSUSED */
319statfs(p, uap, retval)
5e00df3b 320 struct proc *p;
6a6a1e5f 321 register struct args {
fc2aed1e
KM
322 char *path;
323 struct statfs *buf;
6a6a1e5f
KM
324 } *uap;
325 int *retval;
326{
3f705640 327 register struct mount *mp;
8429d022 328 register struct nameidata *ndp;
62e35d50 329 register struct statfs *sp;
fc2aed1e 330 int error;
8429d022 331 struct nameidata nd;
3e78e260 332
8429d022 333 ndp = &nd;
e114af99 334 ndp->ni_nameiop = LOOKUP | FOLLOW;
fc2aed1e
KM
335 ndp->ni_segflg = UIO_USERSPACE;
336 ndp->ni_dirp = uap->path;
8429d022
MK
337 if (error = namei(ndp, p))
338 return (error);
e114af99 339 mp = ndp->ni_vp->v_mount;
54fb9dc2 340 sp = &mp->mnt_stat;
e114af99 341 vrele(ndp->ni_vp);
2c69fe14 342 if (error = VFS_STATFS(mp, sp, p))
8429d022 343 return (error);
54fb9dc2 344 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
8429d022 345 return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
fc2aed1e
KM
346}
347
6a6a1e5f 348/*
d4ed1dcd 349 * Get filesystem statistics.
6a6a1e5f
KM
350 */
351/* ARGSUSED */
352fstatfs(p, uap, retval)
5e00df3b 353 struct proc *p;
6a6a1e5f 354 register struct args {
fc2aed1e
KM
355 int fd;
356 struct statfs *buf;
6a6a1e5f
KM
357 } *uap;
358 int *retval;
359{
fc2aed1e 360 struct file *fp;
3f705640 361 struct mount *mp;
62e35d50 362 register struct statfs *sp;
fc2aed1e
KM
363 int error;
364
5e00df3b 365 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 366 return (error);
3f705640 367 mp = ((struct vnode *)fp->f_data)->v_mount;
54fb9dc2 368 sp = &mp->mnt_stat;
2c69fe14 369 if (error = VFS_STATFS(mp, sp, p))
8429d022 370 return (error);
54fb9dc2 371 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
8429d022 372 return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
3e78e260
BJ
373}
374
bfcdbfbf 375/*
d4ed1dcd 376 * Get statistics on all filesystems.
bfcdbfbf 377 */
6a6a1e5f 378getfsstat(p, uap, retval)
5e00df3b 379 struct proc *p;
6a6a1e5f 380 register struct args {
bfcdbfbf
KM
381 struct statfs *buf;
382 long bufsize;
62e35d50 383 int flags;
6a6a1e5f
KM
384 } *uap;
385 int *retval;
386{
bfcdbfbf 387 register struct mount *mp;
62e35d50 388 register struct statfs *sp;
f62fad9a 389 caddr_t sfsp;
bfcdbfbf
KM
390 long count, maxcount, error;
391
392 maxcount = uap->bufsize / sizeof(struct statfs);
f62fad9a 393 sfsp = (caddr_t)uap->buf;
bfcdbfbf
KM
394 mp = rootfs;
395 count = 0;
396 do {
54fb9dc2
KM
397 if (sfsp && count < maxcount &&
398 ((mp->mnt_flag & MNT_MLOCK) == 0)) {
399 sp = &mp->mnt_stat;
62e35d50
KM
400 /*
401 * If MNT_NOWAIT is specified, do not refresh the
402 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
403 */
404 if (((uap->flags & MNT_NOWAIT) == 0 ||
405 (uap->flags & MNT_WAIT)) &&
2c69fe14 406 (error = VFS_STATFS(mp, sp, p))) {
54fb9dc2 407 mp = mp->mnt_prev;
fd8516be
KM
408 continue;
409 }
54fb9dc2 410 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
62e35d50 411 if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp)))
8429d022 412 return (error);
62e35d50 413 sfsp += sizeof(*sp);
bfcdbfbf 414 }
f62fad9a 415 count++;
54fb9dc2 416 mp = mp->mnt_prev;
bfcdbfbf
KM
417 } while (mp != rootfs);
418 if (sfsp && count > maxcount)
6a6a1e5f 419 *retval = maxcount;
bfcdbfbf 420 else
6a6a1e5f 421 *retval = count;
8429d022 422 return (0);
bfcdbfbf
KM
423}
424
6995a2cb
KM
425/*
426 * Change current working directory to a given file descriptor.
427 */
6a6a1e5f
KM
428/* ARGSUSED */
429fchdir(p, uap, retval)
5e00df3b 430 struct proc *p;
6a6a1e5f 431 struct args {
6995a2cb 432 int fd;
6a6a1e5f
KM
433 } *uap;
434 int *retval;
435{
5e00df3b 436 register struct filedesc *fdp = p->p_fd;
6995a2cb
KM
437 register struct vnode *vp;
438 struct file *fp;
439 int error;
440
5e00df3b 441 if (error = getvnode(fdp, uap->fd, &fp))
8429d022 442 return (error);
6995a2cb
KM
443 vp = (struct vnode *)fp->f_data;
444 VOP_LOCK(vp);
445 if (vp->v_type != VDIR)
446 error = ENOTDIR;
447 else
2c69fe14 448 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
6995a2cb 449 VOP_UNLOCK(vp);
ab214c34 450 if (error)
8429d022 451 return (error);
ab214c34 452 VREF(vp);
5e00df3b
KM
453 vrele(fdp->fd_cdir);
454 fdp->fd_cdir = vp;
8429d022 455 return (0);
6995a2cb
KM
456}
457
4f083fd7 458/*
fc2aed1e 459 * Change current working directory (``.'').
4f083fd7 460 */
6a6a1e5f
KM
461/* ARGSUSED */
462chdir(p, uap, retval)
5e00df3b 463 struct proc *p;
6a6a1e5f 464 struct args {
3e78e260 465 char *fname;
6a6a1e5f
KM
466 } *uap;
467 int *retval;
468{
8429d022 469 register struct nameidata *ndp;
5e00df3b 470 register struct filedesc *fdp = p->p_fd;
fc2aed1e 471 int error;
8429d022 472 struct nameidata nd;
3e78e260 473
8429d022 474 ndp = &nd;
fc2aed1e 475 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
715baff1
KM
476 ndp->ni_segflg = UIO_USERSPACE;
477 ndp->ni_dirp = uap->fname;
8429d022
MK
478 if (error = chdirec(ndp, p))
479 return (error);
5e00df3b
KM
480 vrele(fdp->fd_cdir);
481 fdp->fd_cdir = ndp->ni_vp;
8429d022 482 return (0);
fc2aed1e
KM
483}
484
485/*
486 * Change notion of root (``/'') directory.
487 */
6a6a1e5f
KM
488/* ARGSUSED */
489chroot(p, uap, retval)
5e00df3b 490 struct proc *p;
6a6a1e5f 491 struct args {
fc2aed1e 492 char *fname;
6a6a1e5f
KM
493 } *uap;
494 int *retval;
495{
8429d022 496 register struct nameidata *ndp;
5e00df3b 497 register struct filedesc *fdp = p->p_fd;
fc2aed1e 498 int error;
8429d022 499 struct nameidata nd;
fc2aed1e 500
8429d022
MK
501 if (error = suser(p->p_ucred, &p->p_acflag))
502 return (error);
503 ndp = &nd;
fc2aed1e
KM
504 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
505 ndp->ni_segflg = UIO_USERSPACE;
506 ndp->ni_dirp = uap->fname;
8429d022
MK
507 if (error = chdirec(ndp, p))
508 return (error);
5e00df3b
KM
509 if (fdp->fd_rdir != NULL)
510 vrele(fdp->fd_rdir);
511 fdp->fd_rdir = ndp->ni_vp;
8429d022 512 return (0);
fc2aed1e
KM
513}
514
515/*
516 * Common routine for chroot and chdir.
517 */
8429d022
MK
518chdirec(ndp, p)
519 struct nameidata *ndp;
520 struct proc *p;
fc2aed1e
KM
521{
522 struct vnode *vp;
523 int error;
524
8429d022 525 if (error = namei(ndp, p))
fc2aed1e
KM
526 return (error);
527 vp = ndp->ni_vp;
528 if (vp->v_type != VDIR)
529 error = ENOTDIR;
530 else
2c69fe14 531 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
fc2aed1e
KM
532 VOP_UNLOCK(vp);
533 if (error)
534 vrele(vp);
535 return (error);
3e78e260
BJ
536}
537
538/*
539 * Open system call.
6a6a1e5f
KM
540 * Check permissions, allocate an open file structure,
541 * and call the device open routine if any.
3e78e260 542 */
6a6a1e5f 543open(p, uap, retval)
5e00df3b 544 struct proc *p;
6a6a1e5f 545 register struct args {
3e78e260 546 char *fname;
528f664c 547 int mode;
88a7a62a 548 int crtmode;
6a6a1e5f
KM
549 } *uap;
550 int *retval;
3e78e260 551{
8429d022 552 struct nameidata *ndp;
5e00df3b 553 register struct filedesc *fdp = p->p_fd;
3e78e260 554 register struct file *fp;
6aaf085a 555 register struct vnode *vp;
6a6a1e5f 556 int fmode, cmode;
fc2aed1e 557 struct file *nfp;
ff8d1617
KM
558 int type, indx, error;
559 struct flock lf;
8429d022 560 struct nameidata nd;
fc2aed1e
KM
561 extern struct fileops vnops;
562
5e00df3b 563 if (error = falloc(p, &nfp, &indx))
8429d022 564 return (error);
fc2aed1e 565 fp = nfp;
13b8b20b 566 fmode = FFLAGS(uap->mode);
5e00df3b 567 cmode = ((uap->crtmode &~ fdp->fd_cmask) & 07777) &~ S_ISVTX;
8429d022 568 ndp = &nd;
6a6a1e5f
KM
569 ndp->ni_segflg = UIO_USERSPACE;
570 ndp->ni_dirp = uap->fname;
03951846 571 p->p_dupfd = -indx - 1; /* XXX check for fdopen */
8429d022 572 if (error = vn_open(ndp, p, fmode, cmode)) {
336f999d 573 ffree(fp);
198ba51a 574 if (error == ENODEV && /* XXX from fdopen */
03951846 575 p->p_dupfd >= 0 &&
5e00df3b 576 (error = dupfdopen(fdp, indx, p->p_dupfd, fmode)) == 0) {
6a6a1e5f 577 *retval = indx;
8429d022 578 return (0);
6a6a1e5f 579 }
b10521d6
KM
580 if (error == ERESTART)
581 error = EINTR;
78eeb014 582 fdp->fd_ofiles[indx] = NULL;
8429d022 583 return (error);
528f664c 584 }
6aaf085a 585 vp = ndp->ni_vp;
b40ecf6f 586 fp->f_flag = fmode & FMASK;
ff8d1617
KM
587 if (fmode & (O_EXLOCK | O_SHLOCK)) {
588 lf.l_whence = SEEK_SET;
589 lf.l_start = 0;
590 lf.l_len = 0;
591 if (fmode & O_EXLOCK)
592 lf.l_type = F_WRLCK;
593 else
594 lf.l_type = F_RDLCK;
595 type = F_FLOCK;
596 if ((fmode & FNONBLOCK) == 0)
597 type |= F_WAIT;
6aaf085a
KM
598 if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
599 VOP_UNLOCK(vp);
600 (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
336f999d 601 ffree(fp);
ff8d1617
KM
602 fdp->fd_ofiles[indx] = NULL;
603 return (error);
604 }
b40ecf6f 605 fp->f_flag |= FHASLOCK;
ff8d1617 606 }
6aaf085a 607 VOP_UNLOCK(vp);
fc2aed1e
KM
608 fp->f_type = DTYPE_VNODE;
609 fp->f_ops = &vnops;
6aaf085a 610 fp->f_data = (caddr_t)vp;
6a6a1e5f 611 *retval = indx;
8429d022 612 return (0);
3e78e260
BJ
613}
614
4fde03dc 615#ifdef COMPAT_43
3e78e260 616/*
6a6a1e5f 617 * Creat system call.
3e78e260 618 */
4fde03dc 619ocreat(p, uap, retval)
6a6a1e5f
KM
620 struct proc *p;
621 register struct args {
622 char *fname;
623 int fmode;
624 } *uap;
625 int *retval;
3e78e260 626{
6a6a1e5f
KM
627 struct args {
628 char *fname;
629 int mode;
630 int crtmode;
631 } openuap;
632
633 openuap.fname = uap->fname;
634 openuap.crtmode = uap->fmode;
635 openuap.mode = O_WRONLY | O_CREAT | O_TRUNC;
8429d022 636 return (open(p, &openuap, retval));
6a6a1e5f 637}
4fde03dc 638#endif /* COMPAT_43 */
6a6a1e5f
KM
639
640/*
d4ed1dcd 641 * Mknod system call.
6a6a1e5f
KM
642 */
643/* ARGSUSED */
644mknod(p, uap, retval)
5e00df3b 645 struct proc *p;
6a6a1e5f 646 register struct args {
3e78e260
BJ
647 char *fname;
648 int fmode;
649 int dev;
6a6a1e5f
KM
650 } *uap;
651 int *retval;
652{
8429d022 653 register struct nameidata *ndp;
fc2aed1e
KM
654 register struct vnode *vp;
655 struct vattr vattr;
656 int error;
8429d022 657 struct nameidata nd;
3e78e260 658
8429d022
MK
659 if (error = suser(p->p_ucred, &p->p_acflag))
660 return (error);
661 ndp = &nd;
fc2aed1e 662 ndp->ni_nameiop = CREATE | LOCKPARENT;
715baff1
KM
663 ndp->ni_segflg = UIO_USERSPACE;
664 ndp->ni_dirp = uap->fname;
8429d022
MK
665 if (error = namei(ndp, p))
666 return (error);
fc2aed1e
KM
667 vp = ndp->ni_vp;
668 if (vp != NULL) {
669 error = EEXIST;
88a7a62a 670 goto out;
3e78e260 671 }
3ee1461b 672 VATTR_NULL(&vattr);
ab389897 673 switch (uap->fmode & S_IFMT) {
88a7a62a 674
ab389897 675 case S_IFMT: /* used by badsect to flag bad sectors */
fc2aed1e
KM
676 vattr.va_type = VBAD;
677 break;
ab389897 678 case S_IFCHR:
fc2aed1e
KM
679 vattr.va_type = VCHR;
680 break;
ab389897 681 case S_IFBLK:
fc2aed1e
KM
682 vattr.va_type = VBLK;
683 break;
684 default:
685 error = EINVAL;
686 goto out;
3e78e260 687 }
5e00df3b 688 vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask;
fc2aed1e 689 vattr.va_rdev = uap->dev;
3e78e260 690out:
66955caf 691 if (!error) {
2c69fe14 692 error = VOP_MKNOD(ndp, &vattr, p->p_ucred, p);
66955caf
KM
693 } else {
694 VOP_ABORTOP(ndp);
6c44e83b
KM
695 if (ndp->ni_dvp == vp)
696 vrele(ndp->ni_dvp);
697 else
698 vput(ndp->ni_dvp);
66955caf
KM
699 if (vp)
700 vrele(vp);
701 }
8429d022 702 return (error);
3e78e260
BJ
703}
704
4751dd21 705/*
d4ed1dcd 706 * Mkfifo system call.
4751dd21 707 */
6a6a1e5f
KM
708/* ARGSUSED */
709mkfifo(p, uap, retval)
5e00df3b 710 struct proc *p;
6a6a1e5f 711 register struct args {
4751dd21
KM
712 char *fname;
713 int fmode;
6a6a1e5f
KM
714 } *uap;
715 int *retval;
716{
8429d022 717 register struct nameidata *ndp;
4751dd21
KM
718 struct vattr vattr;
719 int error;
8429d022 720 struct nameidata nd;
4751dd21
KM
721
722#ifndef FIFO
8429d022 723 return (EOPNOTSUPP);
4751dd21 724#else
8429d022 725 ndp = &nd;
4751dd21
KM
726 ndp->ni_nameiop = CREATE | LOCKPARENT;
727 ndp->ni_segflg = UIO_USERSPACE;
728 ndp->ni_dirp = uap->fname;
8429d022
MK
729 if (error = namei(ndp, p))
730 return (error);
4751dd21
KM
731 if (ndp->ni_vp != NULL) {
732 VOP_ABORTOP(ndp);
6c44e83b
KM
733 if (ndp->ni_dvp == ndp->ni_vp)
734 vrele(ndp->ni_dvp);
735 else
736 vput(ndp->ni_dvp);
66955caf 737 vrele(ndp->ni_vp);
8429d022 738 return (EEXIST);
4751dd21 739 }
3658f091
KB
740 VATTR_NULL(&vattr);
741 vattr.va_type = VFIFO;
5e00df3b 742 vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask;
2c69fe14 743 return (VOP_MKNOD(ndp, &vattr, p->p_ucred, p));
4751dd21
KM
744#endif /* FIFO */
745}
746
3e78e260 747/*
d4ed1dcd 748 * Link system call.
3e78e260 749 */
6a6a1e5f
KM
750/* ARGSUSED */
751link(p, uap, retval)
5e00df3b 752 struct proc *p;
6a6a1e5f 753 register struct args {
3e78e260
BJ
754 char *target;
755 char *linkname;
6a6a1e5f
KM
756 } *uap;
757 int *retval;
758{
8429d022 759 register struct nameidata *ndp;
fc2aed1e
KM
760 register struct vnode *vp, *xp;
761 int error;
8429d022 762 struct nameidata nd;
3e78e260 763
8429d022 764 ndp = &nd;
715baff1
KM
765 ndp->ni_nameiop = LOOKUP | FOLLOW;
766 ndp->ni_segflg = UIO_USERSPACE;
767 ndp->ni_dirp = uap->target;
8429d022
MK
768 if (error = namei(ndp, p))
769 return (error);
fc2aed1e
KM
770 vp = ndp->ni_vp;
771 if (vp->v_type == VDIR &&
8429d022 772 (error = suser(p->p_ucred, &p->p_acflag)))
fc2aed1e
KM
773 goto out1;
774 ndp->ni_nameiop = CREATE | LOCKPARENT;
715baff1 775 ndp->ni_dirp = (caddr_t)uap->linkname;
8429d022 776 if (error = namei(ndp, p))
fc2aed1e
KM
777 goto out1;
778 xp = ndp->ni_vp;
3e78e260 779 if (xp != NULL) {
fc2aed1e 780 error = EEXIST;
3e78e260
BJ
781 goto out;
782 }
fc2aed1e
KM
783 xp = ndp->ni_dvp;
784 if (vp->v_mount != xp->v_mount)
785 error = EXDEV;
3e78e260 786out:
66955caf 787 if (!error) {
2c69fe14 788 error = VOP_LINK(vp, ndp, p);
66955caf
KM
789 } else {
790 VOP_ABORTOP(ndp);
6c44e83b
KM
791 if (ndp->ni_dvp == ndp->ni_vp)
792 vrele(ndp->ni_dvp);
793 else
794 vput(ndp->ni_dvp);
66955caf
KM
795 if (ndp->ni_vp)
796 vrele(ndp->ni_vp);
797 }
fc2aed1e
KM
798out1:
799 vrele(vp);
8429d022 800 return (error);
3e78e260
BJ
801}
802
803/*
d4ed1dcd 804 * Make a symbolic link.
3e78e260 805 */
6a6a1e5f
KM
806/* ARGSUSED */
807symlink(p, uap, retval)
5e00df3b 808 struct proc *p;
6a6a1e5f 809 register struct args {
3e78e260
BJ
810 char *target;
811 char *linkname;
6a6a1e5f
KM
812 } *uap;
813 int *retval;
814{
8429d022 815 register struct nameidata *ndp;
fc2aed1e
KM
816 struct vattr vattr;
817 char *target;
818 int error;
8429d022 819 struct nameidata nd;
3e78e260 820
8429d022 821 ndp = &nd;
715baff1
KM
822 ndp->ni_segflg = UIO_USERSPACE;
823 ndp->ni_dirp = uap->linkname;
fc2aed1e
KM
824 MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
825 if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0))
66955caf 826 goto out;
fc2aed1e 827 ndp->ni_nameiop = CREATE | LOCKPARENT;
8429d022 828 if (error = namei(ndp, p))
66955caf
KM
829 goto out;
830 if (ndp->ni_vp) {
831 VOP_ABORTOP(ndp);
6c44e83b
KM
832 if (ndp->ni_dvp == ndp->ni_vp)
833 vrele(ndp->ni_dvp);
834 else
835 vput(ndp->ni_dvp);
66955caf 836 vrele(ndp->ni_vp);
fc2aed1e
KM
837 error = EEXIST;
838 goto out;
3e78e260 839 }
3ee1461b 840 VATTR_NULL(&vattr);
5e00df3b 841 vattr.va_mode = 0777 &~ p->p_fd->fd_cmask;
2c69fe14 842 error = VOP_SYMLINK(ndp, &vattr, target, p);
fc2aed1e 843out:
fc2aed1e 844 FREE(target, M_NAMEI);
8429d022 845 return (error);
3e78e260
BJ
846}
847
848/*
d4ed1dcd 849 * Delete a name from the filesystem.
3e78e260 850 */
6a6a1e5f
KM
851/* ARGSUSED */
852unlink(p, uap, retval)
5e00df3b 853 struct proc *p;
6a6a1e5f 854 struct args {
3e78e260 855 char *fname;
6a6a1e5f
KM
856 } *uap;
857 int *retval;
858{
8429d022 859 register struct nameidata *ndp;
fc2aed1e
KM
860 register struct vnode *vp;
861 int error;
8429d022 862 struct nameidata nd;
3e78e260 863
8429d022 864 ndp = &nd;
fc2aed1e 865 ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
715baff1
KM
866 ndp->ni_segflg = UIO_USERSPACE;
867 ndp->ni_dirp = uap->fname;
8429d022
MK
868 if (error = namei(ndp, p))
869 return (error);
fc2aed1e
KM
870 vp = ndp->ni_vp;
871 if (vp->v_type == VDIR &&
8429d022 872 (error = suser(p->p_ucred, &p->p_acflag)))
3e78e260
BJ
873 goto out;
874 /*
d4ed1dcd 875 * The root of a mounted filesystem cannot be deleted.
3e78e260 876 */
fc2aed1e
KM
877 if (vp->v_flag & VROOT) {
878 error = EBUSY;
3e78e260
BJ
879 goto out;
880 }
9db58063 881 (void) vnode_pager_uncache(vp);
3e78e260 882out:
66955caf 883 if (!error) {
2c69fe14 884 error = VOP_REMOVE(ndp, p);
66955caf
KM
885 } else {
886 VOP_ABORTOP(ndp);
6c44e83b
KM
887 if (ndp->ni_dvp == vp)
888 vrele(ndp->ni_dvp);
889 else
890 vput(ndp->ni_dvp);
66955caf
KM
891 vput(vp);
892 }
8429d022 893 return (error);
3e78e260
BJ
894}
895
896/*
d4ed1dcd 897 * Seek system call.
3e78e260 898 */
6a6a1e5f 899lseek(p, uap, retval)
5e00df3b 900 struct proc *p;
6a6a1e5f 901 register struct args {
fc2aed1e 902 int fdes;
3e78e260
BJ
903 off_t off;
904 int sbase;
6a6a1e5f
KM
905 } *uap;
906 off_t *retval;
907{
8429d022 908 struct ucred *cred = p->p_ucred;
5e00df3b 909 register struct filedesc *fdp = p->p_fd;
6a6a1e5f 910 register struct file *fp;
fc2aed1e
KM
911 struct vattr vattr;
912 int error;
913
8429d022 914 if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
78eeb014 915 (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
8429d022 916 return (EBADF);
fc2aed1e 917 if (fp->f_type != DTYPE_VNODE)
8429d022 918 return (ESPIPE);
b4d1aee9
SL
919 switch (uap->sbase) {
920
921 case L_INCR:
922 fp->f_offset += uap->off;
923 break;
924
925 case L_XTND:
fc2aed1e 926 if (error = VOP_GETATTR((struct vnode *)fp->f_data,
2c69fe14 927 &vattr, cred, p))
8429d022 928 return (error);
fc2aed1e 929 fp->f_offset = uap->off + vattr.va_size;
b4d1aee9
SL
930 break;
931
932 case L_SET:
933 fp->f_offset = uap->off;
934 break;
935
936 default:
8429d022 937 return (EINVAL);
b4d1aee9 938 }
6a6a1e5f 939 *retval = fp->f_offset;
8429d022 940 return (0);
3e78e260
BJ
941}
942
943/*
d4ed1dcd 944 * Check access permissions.
3e78e260 945 */
6a6a1e5f
KM
946/* ARGSUSED */
947saccess(p, uap, retval)
5e00df3b 948 struct proc *p;
6a6a1e5f 949 register struct args {
3e78e260
BJ
950 char *fname;
951 int fmode;
6a6a1e5f
KM
952 } *uap;
953 int *retval;
954{
8429d022
MK
955 register struct nameidata *ndp;
956 register struct ucred *cred = p->p_ucred;
fc2aed1e
KM
957 register struct vnode *vp;
958 int error, mode, svuid, svgid;
8429d022 959 struct nameidata nd;
3e78e260 960
8429d022 961 ndp = &nd;
6a6a1e5f
KM
962 svuid = cred->cr_uid;
963 svgid = cred->cr_groups[0];
8429d022
MK
964 cred->cr_uid = p->p_cred->p_ruid;
965 cred->cr_groups[0] = p->p_cred->p_rgid;
fc2aed1e 966 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
715baff1
KM
967 ndp->ni_segflg = UIO_USERSPACE;
968 ndp->ni_dirp = uap->fname;
8429d022 969 if (error = namei(ndp, p))
fc2aed1e
KM
970 goto out1;
971 vp = ndp->ni_vp;
972 /*
973 * fmode == 0 means only check for exist
974 */
975 if (uap->fmode) {
976 mode = 0;
977 if (uap->fmode & R_OK)
978 mode |= VREAD;
979 if (uap->fmode & W_OK)
980 mode |= VWRITE;
981 if (uap->fmode & X_OK)
982 mode |= VEXEC;
9230ead4 983 if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
2c69fe14 984 error = VOP_ACCESS(vp, mode, cred, p);
3e78e260 985 }
fc2aed1e
KM
986 vput(vp);
987out1:
6a6a1e5f
KM
988 cred->cr_uid = svuid;
989 cred->cr_groups[0] = svgid;
8429d022 990 return (error);
3e78e260 991}
d67a03eb 992
d67a03eb 993/*
d4ed1dcd
KM
994 * Stat system call.
995 * This version follows links.
d67a03eb 996 */
6a6a1e5f
KM
997/* ARGSUSED */
998stat(p, uap, retval)
5e00df3b 999 struct proc *p;
6a6a1e5f
KM
1000 register struct args {
1001 char *fname;
1002 struct stat *ub;
1003 } *uap;
1004 int *retval;
d67a03eb 1005{
8429d022 1006 register struct nameidata *ndp;
6a6a1e5f
KM
1007 struct stat sb;
1008 int error;
8429d022 1009 struct nameidata nd;
d67a03eb 1010
8429d022 1011 ndp = &nd;
6a6a1e5f
KM
1012 ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
1013 ndp->ni_segflg = UIO_USERSPACE;
1014 ndp->ni_dirp = uap->fname;
8429d022
MK
1015 if (error = namei(ndp, p))
1016 return (error);
2c69fe14 1017 error = vn_stat(ndp->ni_vp, &sb, p);
6a6a1e5f
KM
1018 vput(ndp->ni_vp);
1019 if (error)
8429d022 1020 return (error);
6a6a1e5f 1021 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
8429d022 1022 return (error);
d67a03eb
BJ
1023}
1024
5485e062 1025/*
d4ed1dcd
KM
1026 * Lstat system call.
1027 * This version does not follow links.
5485e062 1028 */
6a6a1e5f
KM
1029/* ARGSUSED */
1030lstat(p, uap, retval)
5e00df3b 1031 struct proc *p;
6a6a1e5f 1032 register struct args {
5485e062 1033 char *fname;
88a7a62a 1034 struct stat *ub;
6a6a1e5f
KM
1035 } *uap;
1036 int *retval;
1037{
8429d022 1038 register struct nameidata *ndp;
fc2aed1e
KM
1039 struct stat sb;
1040 int error;
8429d022 1041 struct nameidata nd;
5485e062 1042
8429d022 1043 ndp = &nd;
6a6a1e5f 1044 ndp->ni_nameiop = LOOKUP | LOCKLEAF | NOFOLLOW;
715baff1
KM
1045 ndp->ni_segflg = UIO_USERSPACE;
1046 ndp->ni_dirp = uap->fname;
8429d022
MK
1047 if (error = namei(ndp, p))
1048 return (error);
2c69fe14 1049 error = vn_stat(ndp->ni_vp, &sb, p);
fc2aed1e
KM
1050 vput(ndp->ni_vp);
1051 if (error)
8429d022 1052 return (error);
fc2aed1e 1053 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
8429d022 1054 return (error);
d67a03eb
BJ
1055}
1056
1057/*
d4ed1dcd 1058 * Return target name of a symbolic link.
5485e062 1059 */
6a6a1e5f
KM
1060/* ARGSUSED */
1061readlink(p, uap, retval)
5e00df3b 1062 struct proc *p;
6a6a1e5f 1063 register struct args {
5485e062
BJ
1064 char *name;
1065 char *buf;
1066 int count;
6a6a1e5f
KM
1067 } *uap;
1068 int *retval;
1069{
8429d022 1070 register struct nameidata *ndp;
fc2aed1e
KM
1071 register struct vnode *vp;
1072 struct iovec aiov;
1073 struct uio auio;
1074 int error;
8429d022 1075 struct nameidata nd;
5485e062 1076
8429d022 1077 ndp = &nd;
fc2aed1e 1078 ndp->ni_nameiop = LOOKUP | LOCKLEAF;
715baff1
KM
1079 ndp->ni_segflg = UIO_USERSPACE;
1080 ndp->ni_dirp = uap->name;
8429d022
MK
1081 if (error = namei(ndp, p))
1082 return (error);
fc2aed1e
KM
1083 vp = ndp->ni_vp;
1084 if (vp->v_type != VLNK) {
1085 error = EINVAL;
5485e062
BJ
1086 goto out;
1087 }
fc2aed1e
KM
1088 aiov.iov_base = uap->buf;
1089 aiov.iov_len = uap->count;
1090 auio.uio_iov = &aiov;
1091 auio.uio_iovcnt = 1;
1092 auio.uio_offset = 0;
1093 auio.uio_rw = UIO_READ;
1094 auio.uio_segflg = UIO_USERSPACE;
2c69fe14 1095 auio.uio_procp = p;
fc2aed1e 1096 auio.uio_resid = uap->count;
8429d022 1097 error = VOP_READLINK(vp, &auio, p->p_ucred);
5485e062 1098out:
fc2aed1e 1099 vput(vp);
6a6a1e5f 1100 *retval = uap->count - auio.uio_resid;
8429d022 1101 return (error);
5485e062
BJ
1102}
1103
6995a2cb
KM
1104/*
1105 * Change flags of a file given path name.
1106 */
6a6a1e5f
KM
1107/* ARGSUSED */
1108chflags(p, uap, retval)
5e00df3b 1109 struct proc *p;
6a6a1e5f 1110 register struct args {
6995a2cb
KM
1111 char *fname;
1112 int flags;
6a6a1e5f
KM
1113 } *uap;
1114 int *retval;
1115{
8429d022 1116 register struct nameidata *ndp;
6995a2cb
KM
1117 register struct vnode *vp;
1118 struct vattr vattr;
1119 int error;
8429d022 1120 struct nameidata nd;
6995a2cb 1121
8429d022 1122 ndp = &nd;
6995a2cb
KM
1123 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1124 ndp->ni_segflg = UIO_USERSPACE;
1125 ndp->ni_dirp = uap->fname;
8429d022
MK
1126 if (error = namei(ndp, p))
1127 return (error);
6995a2cb 1128 vp = ndp->ni_vp;
54fb9dc2 1129 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
6995a2cb
KM
1130 error = EROFS;
1131 goto out;
1132 }
3658f091
KB
1133 VATTR_NULL(&vattr);
1134 vattr.va_flags = uap->flags;
2c69fe14 1135 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
6995a2cb
KM
1136out:
1137 vput(vp);
8429d022 1138 return (error);
6995a2cb
KM
1139}
1140
1141/*
1142 * Change flags of a file given a file descriptor.
1143 */
6a6a1e5f
KM
1144/* ARGSUSED */
1145fchflags(p, uap, retval)
5e00df3b 1146 struct proc *p;
6a6a1e5f 1147 register struct args {
6995a2cb
KM
1148 int fd;
1149 int flags;
6a6a1e5f
KM
1150 } *uap;
1151 int *retval;
1152{
6995a2cb
KM
1153 struct vattr vattr;
1154 struct vnode *vp;
1155 struct file *fp;
1156 int error;
1157
5e00df3b 1158 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1159 return (error);
6995a2cb
KM
1160 vp = (struct vnode *)fp->f_data;
1161 VOP_LOCK(vp);
54fb9dc2 1162 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
6995a2cb
KM
1163 error = EROFS;
1164 goto out;
1165 }
3658f091
KB
1166 VATTR_NULL(&vattr);
1167 vattr.va_flags = uap->flags;
2c69fe14 1168 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
6995a2cb
KM
1169out:
1170 VOP_UNLOCK(vp);
8429d022 1171 return (error);
6995a2cb
KM
1172}
1173
4f083fd7
SL
1174/*
1175 * Change mode of a file given path name.
1176 */
6a6a1e5f
KM
1177/* ARGSUSED */
1178chmod(p, uap, retval)
5e00df3b 1179 struct proc *p;
6a6a1e5f 1180 register struct args {
3e78e260
BJ
1181 char *fname;
1182 int fmode;
6a6a1e5f
KM
1183 } *uap;
1184 int *retval;
1185{
8429d022 1186 register struct nameidata *ndp;
fc2aed1e
KM
1187 register struct vnode *vp;
1188 struct vattr vattr;
1189 int error;
8429d022 1190 struct nameidata nd;
5485e062 1191
8429d022 1192 ndp = &nd;
fc2aed1e
KM
1193 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1194 ndp->ni_segflg = UIO_USERSPACE;
1195 ndp->ni_dirp = uap->fname;
8429d022
MK
1196 if (error = namei(ndp, p))
1197 return (error);
fc2aed1e 1198 vp = ndp->ni_vp;
54fb9dc2 1199 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
fc2aed1e
KM
1200 error = EROFS;
1201 goto out;
1202 }
3658f091
KB
1203 VATTR_NULL(&vattr);
1204 vattr.va_mode = uap->fmode & 07777;
2c69fe14 1205 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1206out:
1207 vput(vp);
8429d022 1208 return (error);
528f664c 1209}
f94ceb3b 1210
4f083fd7
SL
1211/*
1212 * Change mode of a file given a file descriptor.
1213 */
6a6a1e5f
KM
1214/* ARGSUSED */
1215fchmod(p, uap, retval)
5e00df3b 1216 struct proc *p;
6a6a1e5f 1217 register struct args {
528f664c
SL
1218 int fd;
1219 int fmode;
6a6a1e5f
KM
1220 } *uap;
1221 int *retval;
1222{
fc2aed1e
KM
1223 struct vattr vattr;
1224 struct vnode *vp;
1225 struct file *fp;
1226 int error;
1227
5e00df3b 1228 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1229 return (error);
fc2aed1e
KM
1230 vp = (struct vnode *)fp->f_data;
1231 VOP_LOCK(vp);
54fb9dc2 1232 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
fc2aed1e
KM
1233 error = EROFS;
1234 goto out;
f94ceb3b 1235 }
3658f091
KB
1236 VATTR_NULL(&vattr);
1237 vattr.va_mode = uap->fmode & 07777;
2c69fe14 1238 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1239out:
1240 VOP_UNLOCK(vp);
8429d022 1241 return (error);
5485e062
BJ
1242}
1243
4f083fd7
SL
1244/*
1245 * Set ownership given a path name.
1246 */
6a6a1e5f
KM
1247/* ARGSUSED */
1248chown(p, uap, retval)
5e00df3b 1249 struct proc *p;
6a6a1e5f 1250 register struct args {
3e78e260
BJ
1251 char *fname;
1252 int uid;
1253 int gid;
6a6a1e5f
KM
1254 } *uap;
1255 int *retval;
1256{
8429d022 1257 register struct nameidata *ndp;
fc2aed1e
KM
1258 register struct vnode *vp;
1259 struct vattr vattr;
1260 int error;
8429d022 1261 struct nameidata nd;
d67a03eb 1262
8429d022 1263 ndp = &nd;
fc2aed1e 1264 ndp->ni_nameiop = LOOKUP | NOFOLLOW | LOCKLEAF;
18b0bce6
KB
1265 ndp->ni_segflg = UIO_USERSPACE;
1266 ndp->ni_dirp = uap->fname;
8429d022
MK
1267 if (error = namei(ndp, p))
1268 return (error);
fc2aed1e 1269 vp = ndp->ni_vp;
54fb9dc2 1270 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
fc2aed1e
KM
1271 error = EROFS;
1272 goto out;
1273 }
3658f091
KB
1274 VATTR_NULL(&vattr);
1275 vattr.va_uid = uap->uid;
1276 vattr.va_gid = uap->gid;
2c69fe14 1277 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1278out:
1279 vput(vp);
8429d022 1280 return (error);
528f664c 1281}
f94ceb3b 1282
4f083fd7
SL
1283/*
1284 * Set ownership given a file descriptor.
1285 */
6a6a1e5f
KM
1286/* ARGSUSED */
1287fchown(p, uap, retval)
5e00df3b 1288 struct proc *p;
6a6a1e5f 1289 register struct args {
528f664c
SL
1290 int fd;
1291 int uid;
1292 int gid;
6a6a1e5f
KM
1293 } *uap;
1294 int *retval;
1295{
fc2aed1e
KM
1296 struct vattr vattr;
1297 struct vnode *vp;
1298 struct file *fp;
1299 int error;
1300
5e00df3b 1301 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1302 return (error);
fc2aed1e
KM
1303 vp = (struct vnode *)fp->f_data;
1304 VOP_LOCK(vp);
54fb9dc2 1305 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
fc2aed1e
KM
1306 error = EROFS;
1307 goto out;
1308 }
3658f091
KB
1309 VATTR_NULL(&vattr);
1310 vattr.va_uid = uap->uid;
1311 vattr.va_gid = uap->gid;
2c69fe14 1312 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1313out:
1314 VOP_UNLOCK(vp);
8429d022 1315 return (error);
d67a03eb
BJ
1316}
1317
6a6a1e5f
KM
1318/*
1319 * Set the access and modification times of a file.
1320 */
1321/* ARGSUSED */
1322utimes(p, uap, retval)
5e00df3b 1323 struct proc *p;
6a6a1e5f 1324 register struct args {
bb1b75f4
SL
1325 char *fname;
1326 struct timeval *tptr;
6a6a1e5f
KM
1327 } *uap;
1328 int *retval;
1329{
8429d022 1330 register struct nameidata *ndp;
fc2aed1e 1331 register struct vnode *vp;
bb1b75f4 1332 struct timeval tv[2];
fc2aed1e
KM
1333 struct vattr vattr;
1334 int error;
8429d022 1335 struct nameidata nd;
bb1b75f4 1336
fc2aed1e 1337 if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
8429d022
MK
1338 return (error);
1339 ndp = &nd;
fc2aed1e
KM
1340 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1341 ndp->ni_segflg = UIO_USERSPACE;
1342 ndp->ni_dirp = uap->fname;
8429d022
MK
1343 if (error = namei(ndp, p))
1344 return (error);
fc2aed1e 1345 vp = ndp->ni_vp;
54fb9dc2 1346 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
fc2aed1e
KM
1347 error = EROFS;
1348 goto out;
bb1b75f4 1349 }
3658f091
KB
1350 VATTR_NULL(&vattr);
1351 vattr.va_atime = tv[0];
1352 vattr.va_mtime = tv[1];
2c69fe14 1353 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1354out:
1355 vput(vp);
8429d022 1356 return (error);
d67a03eb 1357}
64d3a787 1358
4f083fd7
SL
1359/*
1360 * Truncate a file given its path name.
1361 */
6a6a1e5f
KM
1362/* ARGSUSED */
1363truncate(p, uap, retval)
5e00df3b 1364 struct proc *p;
6a6a1e5f 1365 register struct args {
528f664c 1366 char *fname;
c979c6ce 1367 off_t length;
6a6a1e5f
KM
1368 } *uap;
1369 int *retval;
1370{
8429d022 1371 register struct nameidata *ndp;
fc2aed1e
KM
1372 register struct vnode *vp;
1373 struct vattr vattr;
1374 int error;
8429d022 1375 struct nameidata nd;
528f664c 1376
8429d022 1377 ndp = &nd;
fc2aed1e 1378 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
715baff1
KM
1379 ndp->ni_segflg = UIO_USERSPACE;
1380 ndp->ni_dirp = uap->fname;
8429d022
MK
1381 if (error = namei(ndp, p))
1382 return (error);
fc2aed1e
KM
1383 vp = ndp->ni_vp;
1384 if (vp->v_type == VDIR) {
1385 error = EISDIR;
1386 goto out;
528f664c 1387 }
d7b2a16c 1388 if ((error = vn_writechk(vp)) ||
2c69fe14 1389 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)))
fc2aed1e 1390 goto out;
3658f091
KB
1391 VATTR_NULL(&vattr);
1392 vattr.va_size = uap->length;
2c69fe14 1393 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1394out:
1395 vput(vp);
8429d022 1396 return (error);
528f664c
SL
1397}
1398
4f083fd7
SL
1399/*
1400 * Truncate a file given a file descriptor.
1401 */
6a6a1e5f
KM
1402/* ARGSUSED */
1403ftruncate(p, uap, retval)
5e00df3b 1404 struct proc *p;
6a6a1e5f 1405 register struct args {
528f664c 1406 int fd;
c979c6ce 1407 off_t length;
6a6a1e5f
KM
1408 } *uap;
1409 int *retval;
1410{
fc2aed1e
KM
1411 struct vattr vattr;
1412 struct vnode *vp;
528f664c 1413 struct file *fp;
fc2aed1e
KM
1414 int error;
1415
5e00df3b 1416 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1417 return (error);
fc2aed1e 1418 if ((fp->f_flag & FWRITE) == 0)
8429d022 1419 return (EINVAL);
fc2aed1e
KM
1420 vp = (struct vnode *)fp->f_data;
1421 VOP_LOCK(vp);
1422 if (vp->v_type == VDIR) {
1423 error = EISDIR;
1424 goto out;
528f664c 1425 }
d7b2a16c 1426 if (error = vn_writechk(vp))
fc2aed1e 1427 goto out;
3658f091
KB
1428 VATTR_NULL(&vattr);
1429 vattr.va_size = uap->length;
2c69fe14 1430 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
fc2aed1e
KM
1431out:
1432 VOP_UNLOCK(vp);
8429d022 1433 return (error);
4f083fd7
SL
1434}
1435
1436/*
1437 * Synch an open file.
1438 */
6a6a1e5f
KM
1439/* ARGSUSED */
1440fsync(p, uap, retval)
5e00df3b 1441 struct proc *p;
6a6a1e5f 1442 struct args {
4f083fd7 1443 int fd;
6a6a1e5f
KM
1444 } *uap;
1445 int *retval;
1446{
e79467ea 1447 register struct vnode *vp;
4f083fd7 1448 struct file *fp;
fc2aed1e 1449 int error;
4f083fd7 1450
5e00df3b 1451 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1452 return (error);
e79467ea
KM
1453 vp = (struct vnode *)fp->f_data;
1454 VOP_LOCK(vp);
2c69fe14 1455 error = VOP_FSYNC(vp, fp->f_flag, fp->f_cred, MNT_WAIT, p);
e79467ea 1456 VOP_UNLOCK(vp);
8429d022 1457 return (error);
528f664c
SL
1458}
1459
4f083fd7
SL
1460/*
1461 * Rename system call.
4f083fd7
SL
1462 *
1463 * Source and destination must either both be directories, or both
1464 * not be directories. If target is a directory, it must be empty.
1465 */
6a6a1e5f
KM
1466/* ARGSUSED */
1467rename(p, uap, retval)
5e00df3b 1468 struct proc *p;
6a6a1e5f 1469 register struct args {
528f664c
SL
1470 char *from;
1471 char *to;
6a6a1e5f
KM
1472 } *uap;
1473 int *retval;
1474{
fc2aed1e 1475 register struct vnode *tvp, *fvp, *tdvp;
5718fad3 1476 struct nameidata fromnd, tond;
fc2aed1e 1477 int error;
4f083fd7 1478
5718fad3
KM
1479 fromnd.ni_nameiop = DELETE | WANTPARENT | SAVESTART;
1480 fromnd.ni_segflg = UIO_USERSPACE;
1481 fromnd.ni_dirp = uap->from;
1482 if (error = namei(&fromnd, p))
8429d022 1483 return (error);
5718fad3
KM
1484 fvp = fromnd.ni_vp;
1485 tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
fc2aed1e
KM
1486 tond.ni_segflg = UIO_USERSPACE;
1487 tond.ni_dirp = uap->to;
8429d022 1488 if (error = namei(&tond, p)) {
5718fad3
KM
1489 VOP_ABORTOP(&fromnd);
1490 vrele(fromnd.ni_dvp);
66955caf
KM
1491 vrele(fvp);
1492 goto out1;
1493 }
fc2aed1e
KM
1494 tdvp = tond.ni_dvp;
1495 tvp = tond.ni_vp;
1496 if (tvp != NULL) {
1497 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
9259ee95 1498 error = ENOTDIR;
fc2aed1e
KM
1499 goto out;
1500 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
9259ee95 1501 error = EISDIR;
fc2aed1e 1502 goto out;
a5390dce 1503 }
73f5d967
KM
1504 if (fvp->v_mount != tvp->v_mount) {
1505 error = EXDEV;
1506 goto out;
1507 }
4f083fd7 1508 }
fc2aed1e
KM
1509 if (fvp->v_mount != tdvp->v_mount) {
1510 error = EXDEV;
1511 goto out;
64d3a787 1512 }
fe562f32 1513 if (fvp == tdvp)
fc2aed1e 1514 error = EINVAL;
fe562f32 1515 /*
5718fad3
KM
1516 * If source is the same as the destination (that is the
1517 * same inode number with the same name in the same directory),
fe562f32
KM
1518 * then there is nothing to do.
1519 */
5718fad3
KM
1520 if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1521 fromnd.ni_namelen == tond.ni_namelen &&
1522 !bcmp(fromnd.ni_ptr, tond.ni_ptr, fromnd.ni_namelen))
fe562f32 1523 error = -1;
fc2aed1e 1524out:
66955caf 1525 if (!error) {
5718fad3 1526 error = VOP_RENAME(&fromnd, &tond, p);
66955caf 1527 } else {
fc2aed1e 1528 VOP_ABORTOP(&tond);
6c44e83b
KM
1529 if (tdvp == tvp)
1530 vrele(tdvp);
1531 else
1532 vput(tdvp);
66955caf
KM
1533 if (tvp)
1534 vput(tvp);
5718fad3
KM
1535 VOP_ABORTOP(&fromnd);
1536 vrele(fromnd.ni_dvp);
66955caf 1537 vrele(fvp);
64d3a787 1538 }
c03959f9 1539 p->p_spare[1]--;
5718fad3
KM
1540 vrele(tond.ni_startdir);
1541 FREE(tond.ni_pnbuf, M_NAMEI);
fc2aed1e 1542out1:
c03959f9 1543 p->p_spare[1]--;
5718fad3
KM
1544 vrele(fromnd.ni_startdir);
1545 FREE(fromnd.ni_pnbuf, M_NAMEI);
fe562f32 1546 if (error == -1)
8429d022
MK
1547 return (0);
1548 return (error);
64d3a787 1549}
88a7a62a 1550
88a7a62a 1551/*
d4ed1dcd 1552 * Mkdir system call.
88a7a62a 1553 */
6a6a1e5f
KM
1554/* ARGSUSED */
1555mkdir(p, uap, retval)
5e00df3b 1556 struct proc *p;
6a6a1e5f 1557 register struct args {
88a7a62a
SL
1558 char *name;
1559 int dmode;
6a6a1e5f
KM
1560 } *uap;
1561 int *retval;
1562{
8429d022 1563 register struct nameidata *ndp;
fc2aed1e
KM
1564 register struct vnode *vp;
1565 struct vattr vattr;
1566 int error;
8429d022 1567 struct nameidata nd;
88a7a62a 1568
8429d022 1569 ndp = &nd;
fc2aed1e 1570 ndp->ni_nameiop = CREATE | LOCKPARENT;
715baff1
KM
1571 ndp->ni_segflg = UIO_USERSPACE;
1572 ndp->ni_dirp = uap->name;
8429d022
MK
1573 if (error = namei(ndp, p))
1574 return (error);
fc2aed1e
KM
1575 vp = ndp->ni_vp;
1576 if (vp != NULL) {
1577 VOP_ABORTOP(ndp);
6c44e83b
KM
1578 if (ndp->ni_dvp == vp)
1579 vrele(ndp->ni_dvp);
1580 else
1581 vput(ndp->ni_dvp);
66955caf 1582 vrele(vp);
8429d022 1583 return (EEXIST);
88a7a62a 1584 }
3ee1461b 1585 VATTR_NULL(&vattr);
fc2aed1e 1586 vattr.va_type = VDIR;
5e00df3b 1587 vattr.va_mode = (uap->dmode & 0777) &~ p->p_fd->fd_cmask;
2c69fe14 1588 error = VOP_MKDIR(ndp, &vattr, p);
5dfd04f0
KM
1589 if (!error)
1590 vput(ndp->ni_vp);
8429d022 1591 return (error);
88a7a62a
SL
1592}
1593
1594/*
1595 * Rmdir system call.
1596 */
6a6a1e5f
KM
1597/* ARGSUSED */
1598rmdir(p, uap, retval)
5e00df3b 1599 struct proc *p;
6a6a1e5f 1600 struct args {
88a7a62a 1601 char *name;
6a6a1e5f
KM
1602 } *uap;
1603 int *retval;
1604{
8429d022 1605 register struct nameidata *ndp;
fc2aed1e
KM
1606 register struct vnode *vp;
1607 int error;
8429d022 1608 struct nameidata nd;
88a7a62a 1609
8429d022 1610 ndp = &nd;
fc2aed1e 1611 ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
715baff1
KM
1612 ndp->ni_segflg = UIO_USERSPACE;
1613 ndp->ni_dirp = uap->name;
8429d022
MK
1614 if (error = namei(ndp, p))
1615 return (error);
fc2aed1e
KM
1616 vp = ndp->ni_vp;
1617 if (vp->v_type != VDIR) {
1618 error = ENOTDIR;
88a7a62a
SL
1619 goto out;
1620 }
1621 /*
fc2aed1e 1622 * No rmdir "." please.
88a7a62a 1623 */
fc2aed1e
KM
1624 if (ndp->ni_dvp == vp) {
1625 error = EINVAL;
88a7a62a
SL
1626 goto out;
1627 }
1628 /*
d4ed1dcd 1629 * The root of a mounted filesystem cannot be deleted.
88a7a62a 1630 */
fc2aed1e
KM
1631 if (vp->v_flag & VROOT)
1632 error = EBUSY;
88a7a62a 1633out:
66955caf 1634 if (!error) {
2c69fe14 1635 error = VOP_RMDIR(ndp, p);
66955caf
KM
1636 } else {
1637 VOP_ABORTOP(ndp);
6c44e83b
KM
1638 if (ndp->ni_dvp == vp)
1639 vrele(ndp->ni_dvp);
1640 else
1641 vput(ndp->ni_dvp);
66955caf
KM
1642 vput(vp);
1643 }
8429d022 1644 return (error);
88a7a62a
SL
1645}
1646
fc2aed1e 1647/*
d4ed1dcd 1648 * Read a block of directory entries in a file system independent format.
fc2aed1e 1649 */
6a6a1e5f 1650getdirentries(p, uap, retval)
5e00df3b 1651 struct proc *p;
6a6a1e5f 1652 register struct args {
fc2aed1e
KM
1653 int fd;
1654 char *buf;
1655 unsigned count;
1656 long *basep;
6a6a1e5f
KM
1657 } *uap;
1658 int *retval;
1659{
e79467ea 1660 register struct vnode *vp;
8462a185 1661 struct file *fp;
fc2aed1e
KM
1662 struct uio auio;
1663 struct iovec aiov;
58030ad2 1664 off_t off;
c242ace6 1665 int error, eofflag;
fc2aed1e 1666
5e00df3b 1667 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1668 return (error);
fc2aed1e 1669 if ((fp->f_flag & FREAD) == 0)
8429d022 1670 return (EBADF);
e79467ea
KM
1671 vp = (struct vnode *)fp->f_data;
1672 if (vp->v_type != VDIR)
8429d022 1673 return (EINVAL);
fc2aed1e
KM
1674 aiov.iov_base = uap->buf;
1675 aiov.iov_len = uap->count;
1676 auio.uio_iov = &aiov;
1677 auio.uio_iovcnt = 1;
1678 auio.uio_rw = UIO_READ;
1679 auio.uio_segflg = UIO_USERSPACE;
2c69fe14 1680 auio.uio_procp = p;
fc2aed1e 1681 auio.uio_resid = uap->count;
e79467ea
KM
1682 VOP_LOCK(vp);
1683 auio.uio_offset = off = fp->f_offset;
c242ace6 1684 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag);
e79467ea
KM
1685 fp->f_offset = auio.uio_offset;
1686 VOP_UNLOCK(vp);
1687 if (error)
8429d022 1688 return (error);
e79467ea 1689 error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long));
6a6a1e5f 1690 *retval = uap->count - auio.uio_resid;
8429d022 1691 return (error);
88a7a62a
SL
1692}
1693
1694/*
d4ed1dcd 1695 * Set the mode mask for creation of filesystem nodes.
88a7a62a 1696 */
6a6a1e5f
KM
1697mode_t
1698umask(p, uap, retval)
5e00df3b 1699 struct proc *p;
6a6a1e5f 1700 struct args {
88a7a62a 1701 int mask;
6a6a1e5f
KM
1702 } *uap;
1703 int *retval;
1704{
5e00df3b 1705 register struct filedesc *fdp = p->p_fd;
88a7a62a 1706
5e00df3b
KM
1707 *retval = fdp->fd_cmask;
1708 fdp->fd_cmask = uap->mask & 07777;
8429d022 1709 return (0);
fc2aed1e
KM
1710}
1711
b0a98f13
MT
1712/*
1713 * Void all references to file by ripping underlying filesystem
1714 * away from vnode.
1715 */
6a6a1e5f
KM
1716/* ARGSUSED */
1717revoke(p, uap, retval)
5e00df3b 1718 struct proc *p;
6a6a1e5f 1719 register struct args {
b0a98f13 1720 char *fname;
6a6a1e5f
KM
1721 } *uap;
1722 int *retval;
1723{
8429d022 1724 register struct nameidata *ndp;
b0a98f13
MT
1725 register struct vnode *vp;
1726 struct vattr vattr;
1727 int error;
8429d022 1728 struct nameidata nd;
b0a98f13 1729
8429d022 1730 ndp = &nd;
b0a98f13
MT
1731 ndp->ni_nameiop = LOOKUP | FOLLOW;
1732 ndp->ni_segflg = UIO_USERSPACE;
1733 ndp->ni_dirp = uap->fname;
8429d022
MK
1734 if (error = namei(ndp, p))
1735 return (error);
b0a98f13
MT
1736 vp = ndp->ni_vp;
1737 if (vp->v_type != VCHR && vp->v_type != VBLK) {
1738 error = EINVAL;
1739 goto out;
1740 }
2c69fe14 1741 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
b0a98f13 1742 goto out;
8429d022
MK
1743 if (p->p_ucred->cr_uid != vattr.va_uid &&
1744 (error = suser(p->p_ucred, &p->p_acflag)))
b0a98f13 1745 goto out;
8b81d198 1746 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
c9345cca 1747 vgoneall(vp);
b0a98f13
MT
1748out:
1749 vrele(vp);
8429d022 1750 return (error);
b0a98f13
MT
1751}
1752
d4ed1dcd
KM
1753/*
1754 * Convert a user file descriptor to a kernel file entry.
1755 */
5e00df3b
KM
1756getvnode(fdp, fdes, fpp)
1757 struct filedesc *fdp;
fc2aed1e
KM
1758 struct file **fpp;
1759 int fdes;
1760{
1761 struct file *fp;
1762
8429d022 1763 if ((unsigned)fdes >= fdp->fd_nfiles ||
78eeb014 1764 (fp = fdp->fd_ofiles[fdes]) == NULL)
fc2aed1e
KM
1765 return (EBADF);
1766 if (fp->f_type != DTYPE_VNODE)
1767 return (EINVAL);
1768 *fpp = fp;
1769 return (0);
88a7a62a 1770}