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