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