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