generalize the buffer pool so that NFS can become a client
[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 *
fc2aed1e
KM
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 *
601de38e 17 * @(#)vfs_syscalls.c 7.14 (Berkeley) %G%
da7c5cc6 18 */
6459ebe0 19
94368568
JB
20#include "param.h"
21#include "systm.h"
fc2aed1e 22#include "syscontext.h"
94368568
JB
23#include "kernel.h"
24#include "file.h"
25#include "stat.h"
fc2aed1e
KM
26#include "vnode.h"
27#include "../ufs/inode.h"
28#include "mount.h"
94368568 29#include "proc.h"
94368568 30#include "uio.h"
fc2aed1e 31#include "malloc.h"
88a7a62a 32
fc2aed1e
KM
33/*
34 * Virtual File System System Calls
35 */
3e78e260 36
4f083fd7 37/*
fc2aed1e 38 * mount system call
4f083fd7 39 */
601de38e
KM
40mount(scp)
41 register struct syscontext *scp;
3e78e260 42{
fc2aed1e
KM
43 register struct a {
44 int type;
45 char *dir;
46 int flags;
47 caddr_t data;
601de38e
KM
48 } *uap = (struct a *)scp->sc_ap;
49 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e
KM
50 struct vnode *vp;
51 struct mount *mp;
52 int error;
3e78e260 53
fc2aed1e
KM
54 /*
55 * Must be super user
56 */
601de38e 57 if (error = suser(scp->sc_cred, &scp->sc_acflag))
fc2aed1e
KM
58 RETURN (error);
59 /*
60 * Get vnode to be covered
61 */
62 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
63 ndp->ni_segflg = UIO_USERSPACE;
64 ndp->ni_dirp = uap->dir;
65 if (error = namei(ndp))
66 RETURN (error);
67 vp = ndp->ni_vp;
68 if (vp->v_count != 1) {
69 vput(vp);
70 RETURN (EBUSY);
71 }
72 if (vp->v_type != VDIR) {
73 vput(vp);
74 RETURN (ENOTDIR);
75 }
76 if (uap->type > MOUNT_MAXTYPE ||
77 vfssw[uap->type] == (struct vfsops *)0) {
78 vput(vp);
79 RETURN (ENODEV);
80 }
81
82 /*
83 * Mount the filesystem.
84 */
85 mp = (struct mount *)malloc((u_long)sizeof(struct mount),
86 M_MOUNT, M_WAITOK);
87 mp->m_op = vfssw[uap->type];
88 mp->m_flag = 0;
89 mp->m_exroot = 0;
90 error = vfs_add(vp, mp, uap->flags);
91 if (!error)
92 error = VFS_MOUNT(mp, uap->dir, uap->data, ndp);
93 cache_purge(vp);
94 VOP_UNLOCK(vp);
95 if (!error) {
96 vfs_unlock(mp);
97 } else {
98 vfs_remove(mp);
99 free((caddr_t)mp, M_MOUNT);
100 vrele(vp);
101 }
102 RETURN (error);
3e78e260
BJ
103}
104
4f083fd7 105/*
fc2aed1e
KM
106 * Unmount system call.
107 *
108 * Note: unmount takes a path to the vnode mounted on as argument,
109 * not special file (as before).
4f083fd7 110 */
601de38e
KM
111unmount(scp)
112 register struct syscontext *scp;
fc2aed1e
KM
113{
114 struct a {
115 char *pathp;
116 int flags;
601de38e 117 } *uap = (struct a *)scp->sc_ap;
fc2aed1e
KM
118 register struct vnode *vp;
119 register struct mount *mp;
601de38e 120 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e
KM
121 struct vnode *coveredvp;
122 int error;
123
124 /*
125 * Must be super user
126 */
601de38e 127 if (error = suser(scp->sc_cred, &scp->sc_acflag))
fc2aed1e
KM
128 RETURN (error);
129
130 ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
131 ndp->ni_segflg = UIO_USERSPACE;
132 ndp->ni_dirp = uap->pathp;
133 if (error = namei(ndp))
134 RETURN (error);
135 vp = ndp->ni_vp;
136 /*
137 * Must be the root of the filesystem
138 */
139 if ((vp->v_flag & VROOT) == 0) {
140 vput(vp);
141 RETURN (EINVAL);
142 }
143 mp = vp->v_mount;
144 vput(vp);
145 /*
146 * Do the unmount.
147 */
148 coveredvp = mp->m_vnodecovered;
149 if (error = vfs_lock(mp))
150 RETURN (error);
151
152 xumount(mp); /* remove unused sticky files from text table */
153 cache_purgevfs(mp); /* remove cache entries for this file sys */
154 VFS_SYNC(mp, MNT_WAIT);
155
156 error = VFS_UNMOUNT(mp, uap->flags);
157 if (error) {
158 vfs_unlock(mp);
159 } else {
160 vrele(coveredvp);
161 vfs_remove(mp);
162 free((caddr_t)mp, M_MOUNT);
163 }
164 RETURN (error);
165}
166
167/*
168 * Sync system call.
169 * Sync each mounted filesystem.
170 */
601de38e
KM
171sync(scp)
172 register struct syscontext *scp;
3e78e260 173{
fc2aed1e
KM
174 register struct mount *mp;
175
176 mp = rootfs;
177 do {
178 if ((mp->m_flag & M_RDONLY) == 0)
179 VFS_SYNC(mp, MNT_NOWAIT);
180 mp = mp->m_next;
181 } while (mp != rootfs);
182}
183
184/*
185 * get filesystem statistics
186 */
601de38e
KM
187statfs(scp)
188 register struct syscontext *scp;
fc2aed1e
KM
189{
190 struct a {
191 char *path;
192 struct statfs *buf;
601de38e 193 } *uap = (struct a *)scp->sc_ap;
fc2aed1e 194 register struct vnode *vp;
601de38e 195 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e
KM
196 struct statfs sb;
197 int error;
3e78e260 198
fc2aed1e
KM
199 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
200 ndp->ni_segflg = UIO_USERSPACE;
201 ndp->ni_dirp = uap->path;
202 if (error = namei(ndp))
203 RETURN (error);
204 vp = ndp->ni_vp;
205 if (error = VFS_STATFS(vp->v_mount, &sb))
206 goto out;
207 error = copyout((caddr_t)&sb, (caddr_t)uap->buf, sizeof(sb));
208out:
209 vput(vp);
210 RETURN (error);
211}
212
601de38e
KM
213fstatfs(scp)
214 register struct syscontext *scp;
fc2aed1e
KM
215{
216 struct a {
217 int fd;
218 struct statfs *buf;
601de38e 219 } *uap = (struct a *)scp->sc_ap;
fc2aed1e
KM
220 struct file *fp;
221 struct statfs sb;
222 int error;
223
601de38e 224 if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
fc2aed1e
KM
225 RETURN (error);
226 if (error = VFS_STATFS(((struct vnode *)fp->f_data)->v_mount, &sb))
227 RETURN (error);
228 RETURN (copyout((caddr_t)&sb, (caddr_t)uap->buf, sizeof(sb)));
3e78e260
BJ
229}
230
bfcdbfbf
KM
231/*
232 * get statistics on all filesystems
233 */
601de38e
KM
234getfsstat(scp)
235 register struct syscontext *scp;
bfcdbfbf
KM
236{
237 struct a {
238 struct statfs *buf;
239 long bufsize;
601de38e 240 } *uap = (struct a *)scp->sc_ap;
bfcdbfbf
KM
241 register struct mount *mp;
242 register struct statfs *sfsp;
243 long count, maxcount, error;
244
245 maxcount = uap->bufsize / sizeof(struct statfs);
246 sfsp = uap->buf;
247 mp = rootfs;
248 count = 0;
249 do {
250 count++;
251 if (sfsp && count <= maxcount) {
252 if (error = VFS_STATFS(mp, sfsp))
253 RETURN (error);
254 sfsp++;
255 }
256 mp = mp->m_prev;
257 } while (mp != rootfs);
258 if (sfsp && count > maxcount)
601de38e 259 scp->sc_retval1 = maxcount;
bfcdbfbf 260 else
601de38e 261 scp->sc_retval1 = count;
bfcdbfbf
KM
262 RETURN (0);
263}
264
6995a2cb
KM
265/*
266 * Change current working directory to a given file descriptor.
267 */
601de38e
KM
268fchdir(scp)
269 register struct syscontext *scp;
6995a2cb
KM
270{
271 struct a {
272 int fd;
601de38e 273 } *uap = (struct a *)scp->sc_ap;
6995a2cb
KM
274 register struct vnode *vp;
275 struct file *fp;
276 int error;
277
601de38e 278 if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
6995a2cb
KM
279 RETURN (error);
280 vp = (struct vnode *)fp->f_data;
281 VOP_LOCK(vp);
282 if (vp->v_type != VDIR)
283 error = ENOTDIR;
284 else
601de38e 285 error = VOP_ACCESS(vp, VEXEC, scp->sc_cred);
6995a2cb 286 VOP_UNLOCK(vp);
601de38e
KM
287 vrele(scp->sc_cdir);
288 scp->sc_cdir = vp;
6995a2cb
KM
289 RETURN (error);
290}
291
4f083fd7 292/*
fc2aed1e 293 * Change current working directory (``.'').
4f083fd7 294 */
601de38e
KM
295chdir(scp)
296 register struct syscontext *scp;
3e78e260 297{
3e78e260
BJ
298 struct a {
299 char *fname;
601de38e
KM
300 } *uap = (struct a *)scp->sc_ap;
301 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e 302 int error;
3e78e260 303
fc2aed1e 304 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
715baff1
KM
305 ndp->ni_segflg = UIO_USERSPACE;
306 ndp->ni_dirp = uap->fname;
fc2aed1e
KM
307 if (error = chdirec(ndp))
308 RETURN (error);
601de38e
KM
309 vrele(scp->sc_cdir);
310 scp->sc_cdir = ndp->ni_vp;
fc2aed1e
KM
311 RETURN (0);
312}
313
314/*
315 * Change notion of root (``/'') directory.
316 */
601de38e
KM
317chroot(scp)
318 register struct syscontext *scp;
fc2aed1e
KM
319{
320 struct a {
321 char *fname;
601de38e
KM
322 } *uap = (struct a *)scp->sc_ap;
323 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e
KM
324 int error;
325
601de38e 326 if (error = suser(scp->sc_cred, &scp->sc_acflag))
fc2aed1e
KM
327 RETURN (error);
328 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
329 ndp->ni_segflg = UIO_USERSPACE;
330 ndp->ni_dirp = uap->fname;
331 if (error = chdirec(ndp))
332 RETURN (error);
601de38e
KM
333 vrele(scp->sc_rdir);
334 scp->sc_rdir = ndp->ni_vp;
fc2aed1e
KM
335 RETURN (0);
336}
337
338/*
339 * Common routine for chroot and chdir.
340 */
341chdirec(ndp)
342 register struct nameidata *ndp;
343{
344 struct vnode *vp;
345 int error;
346
347 if (error = namei(ndp))
348 return (error);
349 vp = ndp->ni_vp;
350 if (vp->v_type != VDIR)
351 error = ENOTDIR;
352 else
d7b2a16c 353 error = VOP_ACCESS(vp, VEXEC, ndp->ni_cred);
fc2aed1e
KM
354 VOP_UNLOCK(vp);
355 if (error)
356 vrele(vp);
357 return (error);
3e78e260
BJ
358}
359
360/*
361 * Open system call.
362 */
601de38e
KM
363open(scp)
364 register struct syscontext *scp;
3e78e260 365{
88a7a62a 366 struct a {
3e78e260 367 char *fname;
528f664c 368 int mode;
88a7a62a 369 int crtmode;
601de38e
KM
370 } *uap = (struct a *) scp->sc_ap;
371 struct nameidata *ndp = &scp->sc_nd;
3e78e260 372
fc2aed1e
KM
373 ndp->ni_segflg = UIO_USERSPACE;
374 ndp->ni_dirp = uap->fname;
601de38e
KM
375 RETURN (copen(scp, uap->mode-FOPEN, uap->crtmode &~ scp->sc_cmask, ndp,
376 &scp->sc_retval1));
3e78e260
BJ
377}
378
379/*
380 * Creat system call.
381 */
601de38e
KM
382creat(scp)
383 register struct syscontext *scp;
3e78e260 384{
88a7a62a 385 struct a {
3e78e260
BJ
386 char *fname;
387 int fmode;
601de38e
KM
388 } *uap = (struct a *)scp->sc_ap;
389 struct nameidata *ndp = &scp->sc_nd;
3e78e260 390
fc2aed1e
KM
391 ndp->ni_segflg = UIO_USERSPACE;
392 ndp->ni_dirp = uap->fname;
601de38e
KM
393 RETURN (copen(scp, FWRITE|FCREAT|FTRUNC, uap->fmode &~ scp->sc_cmask,
394 ndp, &scp->sc_retval1));
3e78e260
BJ
395}
396
397/*
398 * Common code for open and creat.
88a7a62a
SL
399 * Check permissions, allocate an open file structure,
400 * and call the device open routine if any.
3e78e260 401 */
601de38e
KM
402copen(scp, fmode, cmode, ndp, resultfd)
403 register struct syscontext *scp;
fc2aed1e
KM
404 int fmode, cmode;
405 struct nameidata *ndp;
406 int *resultfd;
3e78e260
BJ
407{
408 register struct file *fp;
fc2aed1e
KM
409 struct file *nfp;
410 int indx, error;
411 extern struct fileops vnops;
412
413 if (error = falloc(&nfp, &indx))
414 return (error);
415 fp = nfp;
601de38e 416 scp->sc_retval1 = indx; /* XXX for fdopen() */
fc2aed1e 417 if (error = vn_open(ndp, fmode, (cmode & 07777) &~ ISVTX)) {
601de38e 418 scp->sc_ofile[indx] = NULL;
fc2aed1e
KM
419 crfree(fp->f_cred);
420 fp->f_count--;
421 return (error);
528f664c 422 }
fc2aed1e
KM
423 fp->f_flag = fmode & FMASK;
424 fp->f_type = DTYPE_VNODE;
425 fp->f_ops = &vnops;
426 fp->f_data = (caddr_t)ndp->ni_vp;
427 if (resultfd)
428 *resultfd = indx;
429 return (0);
3e78e260
BJ
430}
431
432/*
433 * Mknod system call
434 */
601de38e
KM
435mknod(scp)
436 register struct syscontext *scp;
3e78e260 437{
3e78e260
BJ
438 register struct a {
439 char *fname;
440 int fmode;
441 int dev;
601de38e
KM
442 } *uap = (struct a *)scp->sc_ap;
443 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e
KM
444 register struct vnode *vp;
445 struct vattr vattr;
446 int error;
3e78e260 447
601de38e 448 if (error = suser(scp->sc_cred, &scp->sc_acflag))
fc2aed1e
KM
449 RETURN (error);
450 ndp->ni_nameiop = CREATE | LOCKPARENT;
715baff1
KM
451 ndp->ni_segflg = UIO_USERSPACE;
452 ndp->ni_dirp = uap->fname;
fc2aed1e
KM
453 if (error = namei(ndp))
454 RETURN (error);
455 vp = ndp->ni_vp;
456 if (vp != NULL) {
457 error = EEXIST;
88a7a62a 458 goto out;
3e78e260 459 }
fc2aed1e
KM
460 vattr_null(&vattr);
461 switch (uap->fmode & IFMT) {
88a7a62a 462
7bfaea72 463 case IFMT: /* used by badsect to flag bad sectors */
fc2aed1e
KM
464 vattr.va_type = VBAD;
465 break;
88a7a62a 466 case IFCHR:
fc2aed1e
KM
467 vattr.va_type = VCHR;
468 break;
88a7a62a 469 case IFBLK:
fc2aed1e
KM
470 vattr.va_type = VBLK;
471 break;
472 default:
473 error = EINVAL;
474 goto out;
3e78e260 475 }
601de38e 476 vattr.va_mode = (uap->fmode & 07777) &~ scp->sc_cmask;
fc2aed1e 477 vattr.va_rdev = uap->dev;
3e78e260 478out:
fc2aed1e
KM
479 if (error)
480 VOP_ABORTOP(ndp);
481 else
482 error = VOP_MKNOD(ndp, &vattr, ndp->ni_cred);
483 RETURN (error);
3e78e260
BJ
484}
485
486/*
487 * link system call
488 */
601de38e
KM
489link(scp)
490 register struct syscontext *scp;
3e78e260 491{
3e78e260
BJ
492 register struct a {
493 char *target;
494 char *linkname;
601de38e
KM
495 } *uap = (struct a *)scp->sc_ap;
496 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e
KM
497 register struct vnode *vp, *xp;
498 int error;
3e78e260 499
715baff1
KM
500 ndp->ni_nameiop = LOOKUP | FOLLOW;
501 ndp->ni_segflg = UIO_USERSPACE;
502 ndp->ni_dirp = uap->target;
fc2aed1e
KM
503 if (error = namei(ndp))
504 RETURN (error);
505 vp = ndp->ni_vp;
506 if (vp->v_type == VDIR &&
601de38e 507 (error = suser(scp->sc_cred, &scp->sc_acflag)))
fc2aed1e
KM
508 goto out1;
509 ndp->ni_nameiop = CREATE | LOCKPARENT;
715baff1 510 ndp->ni_dirp = (caddr_t)uap->linkname;
fc2aed1e
KM
511 if (error = namei(ndp))
512 goto out1;
513 xp = ndp->ni_vp;
3e78e260 514 if (xp != NULL) {
fc2aed1e 515 error = EEXIST;
3e78e260
BJ
516 goto out;
517 }
fc2aed1e
KM
518 xp = ndp->ni_dvp;
519 if (vp->v_mount != xp->v_mount)
520 error = EXDEV;
3e78e260 521out:
fc2aed1e
KM
522 if (error)
523 VOP_ABORTOP(ndp);
524 else
525 error = VOP_LINK(vp, ndp);
526out1:
527 vrele(vp);
528 RETURN (error);
3e78e260
BJ
529}
530
531/*
532 * symlink -- make a symbolic link
533 */
601de38e
KM
534symlink(scp)
535 register struct syscontext *scp;
3e78e260 536{
fc2aed1e 537 struct a {
3e78e260
BJ
538 char *target;
539 char *linkname;
601de38e
KM
540 } *uap = (struct a *)scp->sc_ap;
541 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e
KM
542 register struct vnode *vp;
543 struct vattr vattr;
544 char *target;
545 int error;
3e78e260 546
715baff1
KM
547 ndp->ni_segflg = UIO_USERSPACE;
548 ndp->ni_dirp = uap->linkname;
fc2aed1e
KM
549 MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
550 if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0))
551 goto out1;
552 ndp->ni_nameiop = CREATE | LOCKPARENT;
553 if (error = namei(ndp))
554 goto out1;
555 vp = ndp->ni_vp;
556 if (vp) {
557 error = EEXIST;
558 goto out;
3e78e260 559 }
fc2aed1e
KM
560 vp = ndp->ni_dvp;
561 vattr_null(&vattr);
601de38e 562 vattr.va_mode = 0777 &~ scp->sc_cmask;
fc2aed1e
KM
563out:
564 if (error)
565 VOP_ABORTOP(ndp);
566 else
567 error = VOP_SYMLINK(ndp, &vattr, target);
568out1:
569 FREE(target, M_NAMEI);
570 RETURN (error);
3e78e260
BJ
571}
572
573/*
574 * Unlink system call.
575 * Hard to avoid races here, especially
576 * in unlinking directories.
577 */
601de38e
KM
578unlink(scp)
579 register struct syscontext *scp;
3e78e260 580{
3e78e260
BJ
581 struct a {
582 char *fname;
601de38e
KM
583 } *uap = (struct a *)scp->sc_ap;
584 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e
KM
585 register struct vnode *vp;
586 int error;
3e78e260 587
fc2aed1e 588 ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
715baff1
KM
589 ndp->ni_segflg = UIO_USERSPACE;
590 ndp->ni_dirp = uap->fname;
fc2aed1e
KM
591 if (error = namei(ndp))
592 RETURN (error);
593 vp = ndp->ni_vp;
594 if (vp->v_type == VDIR &&
601de38e 595 (error = suser(scp->sc_cred, &scp->sc_acflag)))
3e78e260
BJ
596 goto out;
597 /*
598 * Don't unlink a mounted file.
599 */
fc2aed1e
KM
600 if (vp->v_flag & VROOT) {
601 error = EBUSY;
3e78e260
BJ
602 goto out;
603 }
fc2aed1e
KM
604 if (vp->v_flag & VTEXT)
605 xrele(vp); /* try once to free text */
3e78e260 606out:
fc2aed1e
KM
607 if (error)
608 VOP_ABORTOP(ndp);
8eee8525 609 else
fc2aed1e
KM
610 error = VOP_REMOVE(ndp);
611 RETURN (error);
3e78e260
BJ
612}
613
614/*
615 * Seek system call
616 */
601de38e
KM
617lseek(scp)
618 register struct syscontext *scp;
3e78e260
BJ
619{
620 register struct file *fp;
621 register struct a {
fc2aed1e 622 int fdes;
3e78e260
BJ
623 off_t off;
624 int sbase;
601de38e 625 } *uap = (struct a *)scp->sc_ap;
fc2aed1e
KM
626 struct vattr vattr;
627 int error;
628
629 if ((unsigned)uap->fdes >= NOFILE ||
601de38e 630 (fp = scp->sc_ofile[uap->fdes]) == NULL)
fc2aed1e
KM
631 RETURN (EBADF);
632 if (fp->f_type != DTYPE_VNODE)
633 RETURN (ESPIPE);
b4d1aee9
SL
634 switch (uap->sbase) {
635
636 case L_INCR:
637 fp->f_offset += uap->off;
638 break;
639
640 case L_XTND:
fc2aed1e 641 if (error = VOP_GETATTR((struct vnode *)fp->f_data,
601de38e 642 &vattr, scp->sc_cred))
fc2aed1e
KM
643 RETURN (error);
644 fp->f_offset = uap->off + vattr.va_size;
b4d1aee9
SL
645 break;
646
647 case L_SET:
648 fp->f_offset = uap->off;
649 break;
650
651 default:
fc2aed1e 652 RETURN (EINVAL);
b4d1aee9 653 }
601de38e 654 scp->sc_offset = fp->f_offset;
fc2aed1e 655 RETURN (0);
3e78e260
BJ
656}
657
658/*
659 * Access system call
660 */
601de38e
KM
661saccess(scp)
662 register struct syscontext *scp;
3e78e260 663{
3e78e260
BJ
664 register struct a {
665 char *fname;
666 int fmode;
601de38e
KM
667 } *uap = (struct a *)scp->sc_ap;
668 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e
KM
669 register struct vnode *vp;
670 int error, mode, svuid, svgid;
3e78e260 671
601de38e
KM
672 svuid = scp->sc_uid;
673 svgid = scp->sc_gid;
674 scp->sc_uid = scp->sc_ruid;
675 scp->sc_gid = scp->sc_rgid;
fc2aed1e 676 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
715baff1
KM
677 ndp->ni_segflg = UIO_USERSPACE;
678 ndp->ni_dirp = uap->fname;
fc2aed1e
KM
679 if (error = namei(ndp))
680 goto out1;
681 vp = ndp->ni_vp;
682 /*
683 * fmode == 0 means only check for exist
684 */
685 if (uap->fmode) {
686 mode = 0;
687 if (uap->fmode & R_OK)
688 mode |= VREAD;
689 if (uap->fmode & W_OK)
690 mode |= VWRITE;
691 if (uap->fmode & X_OK)
692 mode |= VEXEC;
d7b2a16c
KM
693 if ((error = vn_writechk(vp)) == 0)
694 error = VOP_ACCESS(vp, mode, ndp->ni_cred);
3e78e260 695 }
fc2aed1e
KM
696 vput(vp);
697out1:
601de38e
KM
698 scp->sc_uid = svuid;
699 scp->sc_gid = svgid;
fc2aed1e 700 RETURN (error);
3e78e260 701}
d67a03eb 702
d67a03eb 703/*
6459ebe0 704 * Stat system call. This version follows links.
d67a03eb 705 */
601de38e
KM
706stat(scp)
707 struct syscontext *scp;
d67a03eb 708{
d67a03eb 709
601de38e 710 stat1(scp, FOLLOW);
d67a03eb
BJ
711}
712
5485e062 713/*
6459ebe0 714 * Lstat system call. This version does not follow links.
5485e062 715 */
601de38e
KM
716lstat(scp)
717 struct syscontext *scp;
88a7a62a
SL
718{
719
601de38e 720 stat1(scp, NOFOLLOW);
88a7a62a
SL
721}
722
601de38e
KM
723stat1(scp, follow)
724 register struct syscontext *scp;
88a7a62a 725 int follow;
5485e062 726{
5485e062
BJ
727 register struct a {
728 char *fname;
88a7a62a 729 struct stat *ub;
601de38e
KM
730 } *uap = (struct a *)scp->sc_ap;
731 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e
KM
732 struct stat sb;
733 int error;
5485e062 734
fc2aed1e 735 ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow;
715baff1
KM
736 ndp->ni_segflg = UIO_USERSPACE;
737 ndp->ni_dirp = uap->fname;
fc2aed1e
KM
738 if (error = namei(ndp))
739 RETURN (error);
740 error = vn_stat(ndp->ni_vp, &sb);
741 vput(ndp->ni_vp);
742 if (error)
743 RETURN (error);
744 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
745 RETURN (error);
d67a03eb
BJ
746}
747
748/*
5485e062
BJ
749 * Return target name of a symbolic link
750 */
601de38e
KM
751readlink(scp)
752 register struct syscontext *scp;
5485e062 753{
5485e062
BJ
754 register struct a {
755 char *name;
756 char *buf;
757 int count;
601de38e
KM
758 } *uap = (struct a *)scp->sc_ap;
759 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e
KM
760 register struct vnode *vp;
761 struct iovec aiov;
762 struct uio auio;
763 int error;
5485e062 764
fc2aed1e 765 ndp->ni_nameiop = LOOKUP | LOCKLEAF;
715baff1
KM
766 ndp->ni_segflg = UIO_USERSPACE;
767 ndp->ni_dirp = uap->name;
fc2aed1e
KM
768 if (error = namei(ndp))
769 RETURN (error);
770 vp = ndp->ni_vp;
771 if (vp->v_type != VLNK) {
772 error = EINVAL;
5485e062
BJ
773 goto out;
774 }
fc2aed1e
KM
775 aiov.iov_base = uap->buf;
776 aiov.iov_len = uap->count;
777 auio.uio_iov = &aiov;
778 auio.uio_iovcnt = 1;
779 auio.uio_offset = 0;
780 auio.uio_rw = UIO_READ;
781 auio.uio_segflg = UIO_USERSPACE;
782 auio.uio_resid = uap->count;
783 error = VOP_READLINK(vp, &auio, ndp->ni_cred);
5485e062 784out:
fc2aed1e 785 vput(vp);
601de38e 786 scp->sc_retval1 = uap->count - auio.uio_resid;
fc2aed1e 787 RETURN (error);
5485e062
BJ
788}
789
6995a2cb
KM
790/*
791 * Change flags of a file given path name.
792 */
601de38e
KM
793chflags(scp)
794 register struct syscontext *scp;
6995a2cb
KM
795{
796 struct a {
797 char *fname;
798 int flags;
601de38e
KM
799 } *uap = (struct a *)scp->sc_ap;
800 register struct nameidata *ndp = &scp->sc_nd;
6995a2cb
KM
801 register struct vnode *vp;
802 struct vattr vattr;
803 int error;
804
805 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
806 ndp->ni_segflg = UIO_USERSPACE;
807 ndp->ni_dirp = uap->fname;
808 vattr_null(&vattr);
809 vattr.va_flags = uap->flags;
810 if (error = namei(ndp))
811 RETURN (error);
812 vp = ndp->ni_vp;
813 if (vp->v_mount->m_flag & M_RDONLY) {
814 error = EROFS;
815 goto out;
816 }
817 error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
818out:
819 vput(vp);
820 RETURN (error);
821}
822
823/*
824 * Change flags of a file given a file descriptor.
825 */
601de38e
KM
826fchflags(scp)
827 register struct syscontext *scp;
6995a2cb
KM
828{
829 struct a {
830 int fd;
831 int flags;
601de38e 832 } *uap = (struct a *)scp->sc_ap;
6995a2cb
KM
833 struct vattr vattr;
834 struct vnode *vp;
835 struct file *fp;
836 int error;
837
601de38e 838 if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
6995a2cb
KM
839 RETURN (error);
840 vattr_null(&vattr);
841 vattr.va_flags = uap->flags;
842 vp = (struct vnode *)fp->f_data;
843 VOP_LOCK(vp);
844 if (vp->v_mount->m_flag & M_RDONLY) {
845 error = EROFS;
846 goto out;
847 }
848 error = VOP_SETATTR(vp, &vattr, fp->f_cred);
849out:
850 VOP_UNLOCK(vp);
851 RETURN (error);
852}
853
4f083fd7
SL
854/*
855 * Change mode of a file given path name.
856 */
601de38e
KM
857chmod(scp)
858 register struct syscontext *scp;
5485e062 859{
528f664c 860 struct a {
3e78e260
BJ
861 char *fname;
862 int fmode;
601de38e
KM
863 } *uap = (struct a *)scp->sc_ap;
864 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e
KM
865 register struct vnode *vp;
866 struct vattr vattr;
867 int error;
5485e062 868
fc2aed1e
KM
869 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
870 ndp->ni_segflg = UIO_USERSPACE;
871 ndp->ni_dirp = uap->fname;
872 vattr_null(&vattr);
873 vattr.va_mode = uap->fmode & 07777;
874 if (error = namei(ndp))
875 RETURN (error);
876 vp = ndp->ni_vp;
877 if (vp->v_mount->m_flag & M_RDONLY) {
878 error = EROFS;
879 goto out;
880 }
881 error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
882out:
883 vput(vp);
884 RETURN (error);
528f664c 885}
f94ceb3b 886
4f083fd7
SL
887/*
888 * Change mode of a file given a file descriptor.
889 */
601de38e
KM
890fchmod(scp)
891 register struct syscontext *scp;
528f664c
SL
892{
893 struct a {
894 int fd;
895 int fmode;
601de38e 896 } *uap = (struct a *)scp->sc_ap;
fc2aed1e
KM
897 struct vattr vattr;
898 struct vnode *vp;
899 struct file *fp;
900 int error;
901
601de38e 902 if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
fc2aed1e
KM
903 RETURN (error);
904 vattr_null(&vattr);
905 vattr.va_mode = uap->fmode & 07777;
906 vp = (struct vnode *)fp->f_data;
907 VOP_LOCK(vp);
908 if (vp->v_mount->m_flag & M_RDONLY) {
909 error = EROFS;
910 goto out;
f94ceb3b 911 }
fc2aed1e
KM
912 error = VOP_SETATTR(vp, &vattr, fp->f_cred);
913out:
914 VOP_UNLOCK(vp);
915 RETURN (error);
5485e062
BJ
916}
917
4f083fd7
SL
918/*
919 * Set ownership given a path name.
920 */
601de38e
KM
921chown(scp)
922 register struct syscontext *scp;
d67a03eb 923{
528f664c 924 struct a {
3e78e260
BJ
925 char *fname;
926 int uid;
927 int gid;
601de38e
KM
928 } *uap = (struct a *)scp->sc_ap;
929 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e
KM
930 register struct vnode *vp;
931 struct vattr vattr;
932 int error;
d67a03eb 933
fc2aed1e 934 ndp->ni_nameiop = LOOKUP | NOFOLLOW | LOCKLEAF;
18b0bce6
KB
935 ndp->ni_segflg = UIO_USERSPACE;
936 ndp->ni_dirp = uap->fname;
fc2aed1e
KM
937 vattr_null(&vattr);
938 vattr.va_uid = uap->uid;
939 vattr.va_gid = uap->gid;
940 if (error = namei(ndp))
941 RETURN (error);
942 vp = ndp->ni_vp;
943 if (vp->v_mount->m_flag & M_RDONLY) {
944 error = EROFS;
945 goto out;
946 }
947 error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
948out:
949 vput(vp);
950 RETURN (error);
528f664c 951}
f94ceb3b 952
4f083fd7
SL
953/*
954 * Set ownership given a file descriptor.
955 */
601de38e
KM
956fchown(scp)
957 register struct syscontext *scp;
528f664c
SL
958{
959 struct a {
960 int fd;
961 int uid;
962 int gid;
601de38e 963 } *uap = (struct a *)scp->sc_ap;
fc2aed1e
KM
964 struct vattr vattr;
965 struct vnode *vp;
966 struct file *fp;
967 int error;
968
601de38e 969 if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
fc2aed1e
KM
970 RETURN (error);
971 vattr_null(&vattr);
972 vattr.va_uid = uap->uid;
973 vattr.va_gid = uap->gid;
974 vp = (struct vnode *)fp->f_data;
975 VOP_LOCK(vp);
976 if (vp->v_mount->m_flag & M_RDONLY) {
977 error = EROFS;
978 goto out;
979 }
980 error = VOP_SETATTR(vp, &vattr, fp->f_cred);
981out:
982 VOP_UNLOCK(vp);
983 RETURN (error);
d67a03eb
BJ
984}
985
601de38e
KM
986utimes(scp)
987 register struct syscontext *scp;
bb1b75f4
SL
988{
989 register struct a {
990 char *fname;
991 struct timeval *tptr;
601de38e
KM
992 } *uap = (struct a *)scp->sc_ap;
993 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e 994 register struct vnode *vp;
bb1b75f4 995 struct timeval tv[2];
fc2aed1e
KM
996 struct vattr vattr;
997 int error;
bb1b75f4 998
fc2aed1e
KM
999 if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
1000 RETURN (error);
1001 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1002 ndp->ni_segflg = UIO_USERSPACE;
1003 ndp->ni_dirp = uap->fname;
1004 vattr_null(&vattr);
1005 vattr.va_atime = tv[0];
1006 vattr.va_mtime = tv[1];
1007 if (error = namei(ndp))
1008 RETURN (error);
1009 vp = ndp->ni_vp;
1010 if (vp->v_mount->m_flag & M_RDONLY) {
1011 error = EROFS;
1012 goto out;
bb1b75f4 1013 }
fc2aed1e
KM
1014 error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1015out:
1016 vput(vp);
1017 RETURN (error);
d67a03eb 1018}
64d3a787 1019
4f083fd7
SL
1020/*
1021 * Truncate a file given its path name.
1022 */
601de38e
KM
1023truncate(scp)
1024 register struct syscontext *scp;
528f664c
SL
1025{
1026 struct a {
1027 char *fname;
c979c6ce 1028 off_t length;
601de38e
KM
1029 } *uap = (struct a *)scp->sc_ap;
1030 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e
KM
1031 register struct vnode *vp;
1032 struct vattr vattr;
1033 int error;
528f664c 1034
fc2aed1e 1035 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
715baff1
KM
1036 ndp->ni_segflg = UIO_USERSPACE;
1037 ndp->ni_dirp = uap->fname;
fc2aed1e
KM
1038 vattr_null(&vattr);
1039 vattr.va_size = uap->length;
1040 if (error = namei(ndp))
1041 RETURN (error);
1042 vp = ndp->ni_vp;
1043 if (vp->v_type == VDIR) {
1044 error = EISDIR;
1045 goto out;
528f664c 1046 }
d7b2a16c
KM
1047 if ((error = vn_writechk(vp)) ||
1048 (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred)))
fc2aed1e
KM
1049 goto out;
1050 error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1051out:
1052 vput(vp);
1053 RETURN (error);
528f664c
SL
1054}
1055
4f083fd7
SL
1056/*
1057 * Truncate a file given a file descriptor.
1058 */
601de38e
KM
1059ftruncate(scp)
1060 register struct syscontext *scp;
528f664c
SL
1061{
1062 struct a {
1063 int fd;
c979c6ce 1064 off_t length;
601de38e 1065 } *uap = (struct a *)scp->sc_ap;
fc2aed1e
KM
1066 struct vattr vattr;
1067 struct vnode *vp;
528f664c 1068 struct file *fp;
fc2aed1e
KM
1069 int error;
1070
601de38e 1071 if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
fc2aed1e
KM
1072 RETURN (error);
1073 if ((fp->f_flag & FWRITE) == 0)
1074 RETURN (EINVAL);
1075 vattr_null(&vattr);
1076 vattr.va_size = uap->length;
1077 vp = (struct vnode *)fp->f_data;
1078 VOP_LOCK(vp);
1079 if (vp->v_type == VDIR) {
1080 error = EISDIR;
1081 goto out;
528f664c 1082 }
d7b2a16c 1083 if (error = vn_writechk(vp))
fc2aed1e
KM
1084 goto out;
1085 error = VOP_SETATTR(vp, &vattr, fp->f_cred);
1086out:
1087 VOP_UNLOCK(vp);
1088 RETURN (error);
4f083fd7
SL
1089}
1090
1091/*
1092 * Synch an open file.
1093 */
601de38e
KM
1094fsync(scp)
1095 register struct syscontext *scp;
4f083fd7
SL
1096{
1097 struct a {
1098 int fd;
601de38e 1099 } *uap = (struct a *)scp->sc_ap;
4f083fd7 1100 struct file *fp;
fc2aed1e 1101 int error;
4f083fd7 1102
601de38e 1103 if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
fc2aed1e
KM
1104 RETURN (error);
1105 error = VOP_FSYNC((struct vnode *)fp->f_data, fp->f_flag, fp->f_cred);
1106 RETURN (error);
528f664c
SL
1107}
1108
4f083fd7
SL
1109/*
1110 * Rename system call.
4f083fd7
SL
1111 *
1112 * Source and destination must either both be directories, or both
1113 * not be directories. If target is a directory, it must be empty.
1114 */
601de38e
KM
1115rename(scp)
1116 register struct syscontext *scp;
528f664c
SL
1117{
1118 struct a {
1119 char *from;
1120 char *to;
601de38e 1121 } *uap = (struct a *)scp->sc_ap;
fc2aed1e 1122 register struct vnode *tvp, *fvp, *tdvp;
601de38e 1123 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e
KM
1124 struct nameidata tond;
1125 int error;
4f083fd7 1126
fc2aed1e 1127 ndp->ni_nameiop = DELETE | WANTPARENT;
715baff1
KM
1128 ndp->ni_segflg = UIO_USERSPACE;
1129 ndp->ni_dirp = uap->from;
fc2aed1e
KM
1130 if (error = namei(ndp))
1131 RETURN (error);
1132 fvp = ndp->ni_vp;
41eb2f3d 1133 nddup(ndp, &tond);
fc2aed1e
KM
1134 tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
1135 tond.ni_segflg = UIO_USERSPACE;
1136 tond.ni_dirp = uap->to;
fc2aed1e
KM
1137 error = namei(&tond);
1138 tdvp = tond.ni_dvp;
1139 tvp = tond.ni_vp;
1140 if (tvp != NULL) {
1141 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
a5390dce 1142 error = EISDIR;
fc2aed1e
KM
1143 goto out;
1144 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1145 error = ENOTDIR;
1146 goto out;
a5390dce 1147 }
4f083fd7 1148 }
fc2aed1e
KM
1149 if (error) {
1150 VOP_ABORTOP(ndp);
1151 goto out1;
4f083fd7 1152 }
fc2aed1e
KM
1153 if (fvp->v_mount != tdvp->v_mount) {
1154 error = EXDEV;
1155 goto out;
64d3a787 1156 }
fc2aed1e
KM
1157 if (fvp == tdvp || fvp == tvp)
1158 error = EINVAL;
1159out:
1160 if (error) {
1161 VOP_ABORTOP(&tond);
1162 VOP_ABORTOP(ndp);
1163 } else {
1164 error = VOP_RENAME(ndp, &tond);
64d3a787 1165 }
fc2aed1e 1166out1:
41eb2f3d 1167 ndrele(&tond);
fc2aed1e 1168 RETURN (error);
64d3a787 1169}
88a7a62a 1170
88a7a62a
SL
1171/*
1172 * Mkdir system call
1173 */
601de38e
KM
1174mkdir(scp)
1175 register struct syscontext *scp;
88a7a62a
SL
1176{
1177 struct a {
1178 char *name;
1179 int dmode;
601de38e
KM
1180 } *uap = (struct a *)scp->sc_ap;
1181 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e
KM
1182 register struct vnode *vp;
1183 struct vattr vattr;
1184 int error;
88a7a62a 1185
fc2aed1e 1186 ndp->ni_nameiop = CREATE | LOCKPARENT;
715baff1
KM
1187 ndp->ni_segflg = UIO_USERSPACE;
1188 ndp->ni_dirp = uap->name;
fc2aed1e
KM
1189 if (error = namei(ndp))
1190 RETURN (error);
1191 vp = ndp->ni_vp;
1192 if (vp != NULL) {
1193 VOP_ABORTOP(ndp);
1194 RETURN (EEXIST);
88a7a62a 1195 }
fc2aed1e
KM
1196 vattr_null(&vattr);
1197 vattr.va_type = VDIR;
601de38e 1198 vattr.va_mode = (uap->dmode & 0777) &~ scp->sc_cmask;
fc2aed1e 1199 error = VOP_MKDIR(ndp, &vattr);
5dfd04f0
KM
1200 if (!error)
1201 vput(ndp->ni_vp);
fc2aed1e 1202 RETURN (error);
88a7a62a
SL
1203}
1204
1205/*
1206 * Rmdir system call.
1207 */
601de38e
KM
1208rmdir(scp)
1209 register struct syscontext *scp;
88a7a62a
SL
1210{
1211 struct a {
1212 char *name;
601de38e
KM
1213 } *uap = (struct a *)scp->sc_ap;
1214 register struct nameidata *ndp = &scp->sc_nd;
fc2aed1e
KM
1215 register struct vnode *vp;
1216 int error;
88a7a62a 1217
fc2aed1e 1218 ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
715baff1
KM
1219 ndp->ni_segflg = UIO_USERSPACE;
1220 ndp->ni_dirp = uap->name;
fc2aed1e
KM
1221 if (error = namei(ndp))
1222 RETURN (error);
1223 vp = ndp->ni_vp;
1224 if (vp->v_type != VDIR) {
1225 error = ENOTDIR;
88a7a62a
SL
1226 goto out;
1227 }
1228 /*
fc2aed1e 1229 * No rmdir "." please.
88a7a62a 1230 */
fc2aed1e
KM
1231 if (ndp->ni_dvp == vp) {
1232 error = EINVAL;
88a7a62a
SL
1233 goto out;
1234 }
1235 /*
fc2aed1e 1236 * Don't unlink a mounted file.
88a7a62a 1237 */
fc2aed1e
KM
1238 if (vp->v_flag & VROOT)
1239 error = EBUSY;
88a7a62a 1240out:
fc2aed1e
KM
1241 if (error)
1242 VOP_ABORTOP(ndp);
1243 else
1244 error = VOP_RMDIR(ndp);
1245 RETURN (error);
88a7a62a
SL
1246}
1247
fc2aed1e
KM
1248/*
1249 * Read a block of directory entries in a file system independent format
1250 */
601de38e
KM
1251getdirentries(scp)
1252 register struct syscontext *scp;
88a7a62a 1253{
fc2aed1e
KM
1254 register struct a {
1255 int fd;
1256 char *buf;
1257 unsigned count;
1258 long *basep;
601de38e 1259 } *uap = (struct a *)scp->sc_ap;
8462a185 1260 struct file *fp;
fc2aed1e
KM
1261 struct uio auio;
1262 struct iovec aiov;
58030ad2 1263 off_t off;
fc2aed1e
KM
1264 int error;
1265
601de38e 1266 if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
fc2aed1e
KM
1267 RETURN (error);
1268 if ((fp->f_flag & FREAD) == 0)
1269 RETURN (EBADF);
1270 aiov.iov_base = uap->buf;
1271 aiov.iov_len = uap->count;
1272 auio.uio_iov = &aiov;
1273 auio.uio_iovcnt = 1;
1274 auio.uio_rw = UIO_READ;
1275 auio.uio_segflg = UIO_USERSPACE;
1276 auio.uio_resid = uap->count;
58030ad2 1277 off = fp->f_offset;
fc2aed1e
KM
1278 if (error = VOP_READDIR((struct vnode *)fp->f_data, &auio,
1279 &(fp->f_offset), fp->f_cred))
1280 RETURN (error);
58030ad2 1281 error = copyout((caddr_t)&off, (caddr_t)uap->basep,
fc2aed1e 1282 sizeof(long));
601de38e 1283 scp->sc_retval1 = uap->count - auio.uio_resid;
fc2aed1e 1284 RETURN (error);
88a7a62a
SL
1285}
1286
1287/*
1288 * mode mask for creation of files
1289 */
601de38e
KM
1290umask(scp)
1291 register struct syscontext *scp;
88a7a62a
SL
1292{
1293 register struct a {
1294 int mask;
601de38e 1295 } *uap = (struct a *)scp->sc_ap;
88a7a62a 1296
601de38e
KM
1297 scp->sc_retval1 = scp->sc_cmask;
1298 scp->sc_cmask = uap->mask & 07777;
fc2aed1e
KM
1299 RETURN (0);
1300}
1301
601de38e
KM
1302getvnode(ofile, fdes, fpp)
1303 struct file *ofile[];
fc2aed1e
KM
1304 struct file **fpp;
1305 int fdes;
1306{
1307 struct file *fp;
1308
601de38e 1309 if ((unsigned)fdes >= NOFILE || (fp = ofile[fdes]) == NULL)
fc2aed1e
KM
1310 return (EBADF);
1311 if (fp->f_type != DTYPE_VNODE)
1312 return (EINVAL);
1313 *fpp = fp;
1314 return (0);
88a7a62a 1315}