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