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