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