delete hardware speed, add machine byte order
[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 *
dbcf7de6 7 * @(#)vfs_syscalls.c 7.107 (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;
dbcf7de6 863 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->name, p);
dd4c01c2 864 if (error = namei(&nd))
8429d022 865 return (error);
dd4c01c2 866 vp = nd.ni_vp;
dbcf7de6
KM
867 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
868 VOP_LOCK(vp);
fc2aed1e 869 if (vp->v_type == VDIR &&
8429d022 870 (error = suser(p->p_ucred, &p->p_acflag)))
3e78e260
BJ
871 goto out;
872 /*
d4ed1dcd 873 * The root of a mounted filesystem cannot be deleted.
3e78e260 874 */
fc2aed1e
KM
875 if (vp->v_flag & VROOT) {
876 error = EBUSY;
3e78e260
BJ
877 goto out;
878 }
9db58063 879 (void) vnode_pager_uncache(vp);
3e78e260 880out:
66955caf 881 if (!error) {
dd4c01c2 882 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
dd4c01c2 883 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
66955caf 884 } else {
dd4c01c2
KM
885 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
886 if (nd.ni_dvp == vp)
887 vrele(nd.ni_dvp);
6c44e83b 888 else
dd4c01c2 889 vput(nd.ni_dvp);
66955caf
KM
890 vput(vp);
891 }
a5368812 892 CHECKREFS("unlink");
8429d022 893 return (error);
3e78e260
BJ
894}
895
9e97623a 896struct __lseek_args {
2f2b3b3d
CT
897 int fdes;
898 int pad;
899 off_t off;
900 int sbase;
901};
902
8932276d 903#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
3e78e260 904/*
d4ed1dcd 905 * Seek system call.
3e78e260 906 */
9e97623a
CT
907struct lseek_args {
908 int fdes;
909 long off;
910 int sbase;
911};
6a6a1e5f 912lseek(p, uap, retval)
be320a2b 913 struct proc *p;
9e97623a
CT
914 register struct lseek_args *uap;
915 int *retval;
be320a2b 916{
9e97623a 917 struct __lseek_args nuap;
2f2b3b3d 918 off_t qret;
be320a2b
KM
919 int error;
920
921 nuap.fdes = uap->fdes;
922 nuap.off = uap->off;
923 nuap.sbase = uap->sbase;
ae9b6dc3 924 error = __lseek(p, &nuap, &qret);
9e97623a 925 *(long *)retval = qret;
be320a2b
KM
926 return (error);
927}
8932276d 928#endif /* COMPAT_43 || COMPAT_SUNOS */
be320a2b
KM
929
930/*
931 * Seek system call.
932 */
ae9b6dc3 933__lseek(p, uap, retval)
5e00df3b 934 struct proc *p;
9e97623a
CT
935 register struct __lseek_args *uap;
936 int *retval;
6a6a1e5f 937{
8429d022 938 struct ucred *cred = p->p_ucred;
5e00df3b 939 register struct filedesc *fdp = p->p_fd;
6a6a1e5f 940 register struct file *fp;
fc2aed1e
KM
941 struct vattr vattr;
942 int error;
943
8429d022 944 if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
78eeb014 945 (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
8429d022 946 return (EBADF);
fc2aed1e 947 if (fp->f_type != DTYPE_VNODE)
8429d022 948 return (ESPIPE);
b4d1aee9
SL
949 switch (uap->sbase) {
950
951 case L_INCR:
952 fp->f_offset += uap->off;
953 break;
954
955 case L_XTND:
fc2aed1e 956 if (error = VOP_GETATTR((struct vnode *)fp->f_data,
2c69fe14 957 &vattr, cred, p))
8429d022 958 return (error);
fc2aed1e 959 fp->f_offset = uap->off + vattr.va_size;
b4d1aee9
SL
960 break;
961
962 case L_SET:
963 fp->f_offset = uap->off;
964 break;
965
966 default:
8429d022 967 return (EINVAL);
b4d1aee9 968 }
9e97623a 969 *(off_t *)retval = fp->f_offset;
8429d022 970 return (0);
3e78e260
BJ
971}
972
973/*
d4ed1dcd 974 * Check access permissions.
3e78e260 975 */
9e97623a
CT
976struct saccess_args {
977 char *fname;
978 int fmode;
979};
6a6a1e5f
KM
980/* ARGSUSED */
981saccess(p, uap, retval)
5e00df3b 982 struct proc *p;
9e97623a 983 register struct saccess_args *uap;
6a6a1e5f
KM
984 int *retval;
985{
8429d022 986 register struct ucred *cred = p->p_ucred;
fc2aed1e
KM
987 register struct vnode *vp;
988 int error, mode, svuid, svgid;
8429d022 989 struct nameidata nd;
3e78e260 990
6a6a1e5f
KM
991 svuid = cred->cr_uid;
992 svgid = cred->cr_groups[0];
8429d022
MK
993 cred->cr_uid = p->p_cred->p_ruid;
994 cred->cr_groups[0] = p->p_cred->p_rgid;
dd4c01c2
KM
995 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
996 if (error = namei(&nd))
fc2aed1e 997 goto out1;
dd4c01c2 998 vp = nd.ni_vp;
fc2aed1e
KM
999 /*
1000 * fmode == 0 means only check for exist
1001 */
1002 if (uap->fmode) {
1003 mode = 0;
1004 if (uap->fmode & R_OK)
1005 mode |= VREAD;
1006 if (uap->fmode & W_OK)
1007 mode |= VWRITE;
1008 if (uap->fmode & X_OK)
1009 mode |= VEXEC;
9230ead4 1010 if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
2c69fe14 1011 error = VOP_ACCESS(vp, mode, cred, p);
3e78e260 1012 }
fc2aed1e
KM
1013 vput(vp);
1014out1:
6a6a1e5f
KM
1015 cred->cr_uid = svuid;
1016 cred->cr_groups[0] = svgid;
8429d022 1017 return (error);
3e78e260 1018}
d67a03eb 1019
8932276d 1020#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
d67a03eb 1021/*
d4ed1dcd
KM
1022 * Stat system call.
1023 * This version follows links.
d67a03eb 1024 */
9e97623a
CT
1025struct ostat_args {
1026 char *fname;
1027 struct ostat *ub;
1028};
6a6a1e5f 1029/* ARGSUSED */
ae9b6dc3 1030ostat(p, uap, retval)
be320a2b 1031 struct proc *p;
9e97623a 1032 register struct ostat_args *uap;
be320a2b
KM
1033 int *retval;
1034{
1035 struct stat sb;
1036 struct ostat osb;
1037 int error;
1038 struct nameidata nd;
1039
1040 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
1041 if (error = namei(&nd))
1042 return (error);
1043 error = vn_stat(nd.ni_vp, &sb, p);
1044 vput(nd.ni_vp);
1045 if (error)
1046 return (error);
1047 cvtstat(&sb, &osb);
1048 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
1049 return (error);
1050}
1051
1052/*
1053 * Lstat system call.
1054 * This version does not follow links.
1055 */
9e97623a
CT
1056struct olstat_args {
1057 char *fname;
1058 struct ostat *ub;
1059};
be320a2b 1060/* ARGSUSED */
ae9b6dc3 1061olstat(p, uap, retval)
be320a2b 1062 struct proc *p;
9e97623a 1063 register struct olstat_args *uap;
be320a2b
KM
1064 int *retval;
1065{
1066 struct stat sb;
1067 struct ostat osb;
1068 int error;
1069 struct nameidata nd;
1070
1071 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
1072 if (error = namei(&nd))
1073 return (error);
1074 error = vn_stat(nd.ni_vp, &sb, p);
1075 vput(nd.ni_vp);
1076 if (error)
1077 return (error);
1078 cvtstat(&sb, &osb);
1079 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
1080 return (error);
1081}
1082
1083/*
1084 * convert from an old to a new stat structure.
1085 */
1086cvtstat(st, ost)
1087 struct stat *st;
1088 struct ostat *ost;
1089{
1090
1091 ost->st_dev = st->st_dev;
1092 ost->st_ino = st->st_ino;
1093 ost->st_mode = st->st_mode;
1094 ost->st_nlink = st->st_nlink;
1095 ost->st_uid = st->st_uid;
1096 ost->st_gid = st->st_gid;
1097 ost->st_rdev = st->st_rdev;
1098 if (st->st_size < (quad_t)1 << 32)
1099 ost->st_size = st->st_size;
1100 else
1101 ost->st_size = -2;
1102 ost->st_atime = st->st_atime;
1103 ost->st_mtime = st->st_mtime;
1104 ost->st_ctime = st->st_ctime;
1105 ost->st_blksize = st->st_blksize;
1106 ost->st_blocks = st->st_blocks;
1107 ost->st_flags = st->st_flags;
1108 ost->st_gen = st->st_gen;
1109}
8932276d 1110#endif /* COMPAT_43 || COMPAT_SUNOS */
be320a2b
KM
1111
1112/*
1113 * Stat system call.
1114 * This version follows links.
1115 */
9e97623a
CT
1116struct stat_args {
1117 char *fname;
1118 struct stat *ub;
1119};
be320a2b 1120/* ARGSUSED */
ae9b6dc3 1121stat(p, uap, retval)
5e00df3b 1122 struct proc *p;
9e97623a 1123 register struct stat_args *uap;
6a6a1e5f 1124 int *retval;
d67a03eb 1125{
6a6a1e5f
KM
1126 struct stat sb;
1127 int error;
8429d022 1128 struct nameidata nd;
d67a03eb 1129
dd4c01c2
KM
1130 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
1131 if (error = namei(&nd))
8429d022 1132 return (error);
dd4c01c2
KM
1133 error = vn_stat(nd.ni_vp, &sb, p);
1134 vput(nd.ni_vp);
6a6a1e5f 1135 if (error)
8429d022 1136 return (error);
6a6a1e5f 1137 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
8429d022 1138 return (error);
d67a03eb
BJ
1139}
1140
5485e062 1141/*
d4ed1dcd
KM
1142 * Lstat system call.
1143 * This version does not follow links.
5485e062 1144 */
9e97623a
CT
1145struct lstat_args {
1146 char *fname;
1147 struct stat *ub;
1148};
6a6a1e5f 1149/* ARGSUSED */
ae9b6dc3 1150lstat(p, uap, retval)
5e00df3b 1151 struct proc *p;
9e97623a 1152 register struct lstat_args *uap;
6a6a1e5f
KM
1153 int *retval;
1154{
fc2aed1e 1155 int error;
49f762b8
KM
1156 struct vnode *vp, *dvp;
1157 struct stat sb, sb1;
8429d022 1158 struct nameidata nd;
5485e062 1159
49f762b8
KM
1160 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
1161 uap->fname, p);
dd4c01c2 1162 if (error = namei(&nd))
8429d022 1163 return (error);
49f762b8
KM
1164 /*
1165 * For symbolic links, always return the attributes of its
1166 * containing directory, except for mode, size, and links.
1167 */
1168 vp = nd.ni_vp;
1169 dvp = nd.ni_dvp;
1170 if (vp->v_type != VLNK) {
1171 if (dvp == vp)
1172 vrele(dvp);
1173 else
1174 vput(dvp);
1175 error = vn_stat(vp, &sb, p);
1176 vput(vp);
1177 if (error)
1178 return (error);
1179 } else {
1180 error = vn_stat(dvp, &sb, p);
1181 vput(dvp);
1182 if (error) {
1183 vput(vp);
1184 return (error);
1185 }
1186 error = vn_stat(vp, &sb1, p);
1187 vput(vp);
1188 if (error)
1189 return (error);
1190 sb.st_mode &= ~S_IFDIR;
1191 sb.st_mode |= S_IFLNK;
1192 sb.st_nlink = sb1.st_nlink;
1193 sb.st_size = sb1.st_size;
1194 sb.st_blocks = sb1.st_blocks;
1195 }
fc2aed1e 1196 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
8429d022 1197 return (error);
d67a03eb
BJ
1198}
1199
1200/*
d4ed1dcd 1201 * Return target name of a symbolic link.
5485e062 1202 */
9e97623a
CT
1203struct readlink_args {
1204 char *name;
1205 char *buf;
1206 int count;
1207};
6a6a1e5f
KM
1208/* ARGSUSED */
1209readlink(p, uap, retval)
5e00df3b 1210 struct proc *p;
9e97623a 1211 register struct readlink_args *uap;
6a6a1e5f
KM
1212 int *retval;
1213{
fc2aed1e
KM
1214 register struct vnode *vp;
1215 struct iovec aiov;
1216 struct uio auio;
1217 int error;
8429d022 1218 struct nameidata nd;
5485e062 1219
a5368812 1220 CHECKPOINTREF;
dd4c01c2
KM
1221 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->name, p);
1222 if (error = namei(&nd))
8429d022 1223 return (error);
dd4c01c2 1224 vp = nd.ni_vp;
fc2aed1e
KM
1225 if (vp->v_type != VLNK) {
1226 error = EINVAL;
5485e062
BJ
1227 goto out;
1228 }
fc2aed1e
KM
1229 aiov.iov_base = uap->buf;
1230 aiov.iov_len = uap->count;
1231 auio.uio_iov = &aiov;
1232 auio.uio_iovcnt = 1;
1233 auio.uio_offset = 0;
1234 auio.uio_rw = UIO_READ;
1235 auio.uio_segflg = UIO_USERSPACE;
2c69fe14 1236 auio.uio_procp = p;
fc2aed1e 1237 auio.uio_resid = uap->count;
8429d022 1238 error = VOP_READLINK(vp, &auio, p->p_ucred);
5485e062 1239out:
fc2aed1e 1240 vput(vp);
6a6a1e5f 1241 *retval = uap->count - auio.uio_resid;
a5368812 1242 CHECKREFS("readlink");
8429d022 1243 return (error);
5485e062
BJ
1244}
1245
6995a2cb
KM
1246/*
1247 * Change flags of a file given path name.
1248 */
9e97623a
CT
1249struct chflags_args {
1250 char *fname;
1251 int flags;
1252};
6a6a1e5f
KM
1253/* ARGSUSED */
1254chflags(p, uap, retval)
5e00df3b 1255 struct proc *p;
9e97623a 1256 register struct chflags_args *uap;
6a6a1e5f
KM
1257 int *retval;
1258{
6995a2cb
KM
1259 register struct vnode *vp;
1260 struct vattr vattr;
1261 int error;
8429d022 1262 struct nameidata nd;
6995a2cb 1263
dbcf7de6 1264 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
dd4c01c2 1265 if (error = namei(&nd))
8429d022 1266 return (error);
dd4c01c2 1267 vp = nd.ni_vp;
dbcf7de6
KM
1268 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1269 VOP_LOCK(vp);
54fb9dc2 1270 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
6995a2cb
KM
1271 error = EROFS;
1272 goto out;
1273 }
3658f091
KB
1274 VATTR_NULL(&vattr);
1275 vattr.va_flags = uap->flags;
2c69fe14 1276 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
6995a2cb
KM
1277out:
1278 vput(vp);
8429d022 1279 return (error);
6995a2cb
KM
1280}
1281
1282/*
1283 * Change flags of a file given a file descriptor.
1284 */
9e97623a
CT
1285struct fchflags_args {
1286 int fd;
1287 int flags;
1288};
6a6a1e5f
KM
1289/* ARGSUSED */
1290fchflags(p, uap, retval)
5e00df3b 1291 struct proc *p;
9e97623a 1292 register struct fchflags_args *uap;
6a6a1e5f
KM
1293 int *retval;
1294{
6995a2cb
KM
1295 struct vattr vattr;
1296 struct vnode *vp;
1297 struct file *fp;
1298 int error;
1299
5e00df3b 1300 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1301 return (error);
6995a2cb 1302 vp = (struct vnode *)fp->f_data;
dbcf7de6 1303 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
6995a2cb 1304 VOP_LOCK(vp);
54fb9dc2 1305 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
6995a2cb
KM
1306 error = EROFS;
1307 goto out;
1308 }
3658f091
KB
1309 VATTR_NULL(&vattr);
1310 vattr.va_flags = uap->flags;
2c69fe14 1311 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
6995a2cb
KM
1312out:
1313 VOP_UNLOCK(vp);
8429d022 1314 return (error);
6995a2cb
KM
1315}
1316
4f083fd7
SL
1317/*
1318 * Change mode of a file given path name.
1319 */
9e97623a
CT
1320struct chmod_args {
1321 char *fname;
1322 int fmode;
1323};
6a6a1e5f
KM
1324/* ARGSUSED */
1325chmod(p, uap, retval)
5e00df3b 1326 struct proc *p;
9e97623a 1327 register struct chmod_args *uap;
6a6a1e5f
KM
1328 int *retval;
1329{
fc2aed1e
KM
1330 register struct vnode *vp;
1331 struct vattr vattr;
1332 int error;
8429d022 1333 struct nameidata nd;
5485e062 1334
dbcf7de6 1335 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
dd4c01c2 1336 if (error = namei(&nd))
8429d022 1337 return (error);
dd4c01c2 1338 vp = nd.ni_vp;
dbcf7de6
KM
1339 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1340 VOP_LOCK(vp);
54fb9dc2 1341 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
fc2aed1e
KM
1342 error = EROFS;
1343 goto out;
1344 }
3658f091
KB
1345 VATTR_NULL(&vattr);
1346 vattr.va_mode = uap->fmode & 07777;
2c69fe14 1347 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1348out:
1349 vput(vp);
8429d022 1350 return (error);
528f664c 1351}
f94ceb3b 1352
4f083fd7
SL
1353/*
1354 * Change mode of a file given a file descriptor.
1355 */
9e97623a
CT
1356struct fchmod_args {
1357 int fd;
1358 int fmode;
1359};
6a6a1e5f
KM
1360/* ARGSUSED */
1361fchmod(p, uap, retval)
5e00df3b 1362 struct proc *p;
9e97623a 1363 register struct fchmod_args *uap;
6a6a1e5f
KM
1364 int *retval;
1365{
fc2aed1e
KM
1366 struct vattr vattr;
1367 struct vnode *vp;
1368 struct file *fp;
1369 int error;
1370
5e00df3b 1371 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1372 return (error);
fc2aed1e 1373 vp = (struct vnode *)fp->f_data;
dbcf7de6 1374 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
fc2aed1e 1375 VOP_LOCK(vp);
54fb9dc2 1376 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
fc2aed1e
KM
1377 error = EROFS;
1378 goto out;
f94ceb3b 1379 }
3658f091
KB
1380 VATTR_NULL(&vattr);
1381 vattr.va_mode = uap->fmode & 07777;
2c69fe14 1382 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1383out:
1384 VOP_UNLOCK(vp);
8429d022 1385 return (error);
5485e062
BJ
1386}
1387
4f083fd7
SL
1388/*
1389 * Set ownership given a path name.
1390 */
9e97623a
CT
1391struct chown_args {
1392 char *fname;
1393 int uid;
1394 int gid;
1395};
6a6a1e5f
KM
1396/* ARGSUSED */
1397chown(p, uap, retval)
5e00df3b 1398 struct proc *p;
9e97623a 1399 register struct chown_args *uap;
6a6a1e5f
KM
1400 int *retval;
1401{
fc2aed1e
KM
1402 register struct vnode *vp;
1403 struct vattr vattr;
1404 int error;
8429d022 1405 struct nameidata nd;
d67a03eb 1406
dbcf7de6 1407 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->fname, p);
dd4c01c2 1408 if (error = namei(&nd))
8429d022 1409 return (error);
dd4c01c2 1410 vp = nd.ni_vp;
dbcf7de6
KM
1411 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1412 VOP_LOCK(vp);
54fb9dc2 1413 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
fc2aed1e
KM
1414 error = EROFS;
1415 goto out;
1416 }
3658f091
KB
1417 VATTR_NULL(&vattr);
1418 vattr.va_uid = uap->uid;
1419 vattr.va_gid = uap->gid;
2c69fe14 1420 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1421out:
1422 vput(vp);
8429d022 1423 return (error);
528f664c 1424}
f94ceb3b 1425
4f083fd7
SL
1426/*
1427 * Set ownership given a file descriptor.
1428 */
9e97623a
CT
1429struct fchown_args {
1430 int fd;
1431 int uid;
1432 int gid;
1433};
6a6a1e5f
KM
1434/* ARGSUSED */
1435fchown(p, uap, retval)
5e00df3b 1436 struct proc *p;
9e97623a 1437 register struct fchown_args *uap;
6a6a1e5f
KM
1438 int *retval;
1439{
fc2aed1e
KM
1440 struct vattr vattr;
1441 struct vnode *vp;
1442 struct file *fp;
1443 int error;
1444
5e00df3b 1445 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1446 return (error);
fc2aed1e 1447 vp = (struct vnode *)fp->f_data;
dbcf7de6 1448 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
fc2aed1e 1449 VOP_LOCK(vp);
54fb9dc2 1450 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
fc2aed1e
KM
1451 error = EROFS;
1452 goto out;
1453 }
3658f091
KB
1454 VATTR_NULL(&vattr);
1455 vattr.va_uid = uap->uid;
1456 vattr.va_gid = uap->gid;
2c69fe14 1457 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1458out:
1459 VOP_UNLOCK(vp);
8429d022 1460 return (error);
d67a03eb
BJ
1461}
1462
6a6a1e5f
KM
1463/*
1464 * Set the access and modification times of a file.
1465 */
9e97623a
CT
1466struct utimes_args {
1467 char *fname;
1468 struct timeval *tptr;
1469};
6a6a1e5f
KM
1470/* ARGSUSED */
1471utimes(p, uap, retval)
5e00df3b 1472 struct proc *p;
9e97623a 1473 register struct utimes_args *uap;
6a6a1e5f
KM
1474 int *retval;
1475{
fc2aed1e 1476 register struct vnode *vp;
bb1b75f4 1477 struct timeval tv[2];
fc2aed1e 1478 struct vattr vattr;
8e88b0cd 1479 int error;
8429d022 1480 struct nameidata nd;
bb1b75f4 1481
f8ee9a49
KB
1482 VATTR_NULL(&vattr);
1483 if (uap->tptr == NULL) {
1484 microtime(&tv[0]);
1485 tv[1] = tv[0];
fcba749b 1486 vattr.va_vaflags |= VA_UTIMES_NULL;
f8ee9a49
KB
1487 } else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
1488 return (error);
dbcf7de6 1489 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
dd4c01c2 1490 if (error = namei(&nd))
8429d022 1491 return (error);
dd4c01c2 1492 vp = nd.ni_vp;
dbcf7de6
KM
1493 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1494 VOP_LOCK(vp);
54fb9dc2 1495 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
fc2aed1e
KM
1496 error = EROFS;
1497 goto out;
bb1b75f4 1498 }
7e11a0c9
KM
1499 vattr.va_atime.ts_sec = tv[0].tv_sec;
1500 vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;
1501 vattr.va_mtime.ts_sec = tv[1].tv_sec;
1502 vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;
2c69fe14 1503 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1504out:
1505 vput(vp);
8429d022 1506 return (error);
d67a03eb 1507}
64d3a787 1508
9e97623a 1509struct __truncate_args {
2f2b3b3d
CT
1510 char *fname;
1511 int pad;
1512 off_t length;
1513};
be320a2b
KM
1514
1515/*
1516 * Truncate a file given its path name.
1517 */
1518/* ARGSUSED */
ae9b6dc3 1519__truncate(p, uap, retval)
5e00df3b 1520 struct proc *p;
9e97623a 1521 register struct __truncate_args *uap;
6a6a1e5f
KM
1522 int *retval;
1523{
fc2aed1e
KM
1524 register struct vnode *vp;
1525 struct vattr vattr;
1526 int error;
8429d022 1527 struct nameidata nd;
528f664c 1528
dbcf7de6 1529 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
dd4c01c2 1530 if (error = namei(&nd))
8429d022 1531 return (error);
dd4c01c2 1532 vp = nd.ni_vp;
dbcf7de6
KM
1533 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1534 VOP_LOCK(vp);
fc2aed1e
KM
1535 if (vp->v_type == VDIR) {
1536 error = EISDIR;
1537 goto out;
528f664c 1538 }
d7b2a16c 1539 if ((error = vn_writechk(vp)) ||
2c69fe14 1540 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)))
fc2aed1e 1541 goto out;
3658f091
KB
1542 VATTR_NULL(&vattr);
1543 vattr.va_size = uap->length;
2c69fe14 1544 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1545out:
1546 vput(vp);
8429d022 1547 return (error);
528f664c
SL
1548}
1549
9e97623a 1550struct __ftruncate_args {
2f2b3b3d
CT
1551 int fd;
1552 int pad;
1553 off_t length;
1554};
1555
4f083fd7
SL
1556/*
1557 * Truncate a file given a file descriptor.
1558 */
6a6a1e5f 1559/* ARGSUSED */
ae9b6dc3 1560__ftruncate(p, uap, retval)
5e00df3b 1561 struct proc *p;
9e97623a 1562 register struct __ftruncate_args *uap;
6a6a1e5f
KM
1563 int *retval;
1564{
fc2aed1e
KM
1565 struct vattr vattr;
1566 struct vnode *vp;
528f664c 1567 struct file *fp;
fc2aed1e
KM
1568 int error;
1569
5e00df3b 1570 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1571 return (error);
fc2aed1e 1572 if ((fp->f_flag & FWRITE) == 0)
8429d022 1573 return (EINVAL);
fc2aed1e 1574 vp = (struct vnode *)fp->f_data;
dbcf7de6 1575 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
fc2aed1e
KM
1576 VOP_LOCK(vp);
1577 if (vp->v_type == VDIR) {
1578 error = EISDIR;
1579 goto out;
528f664c 1580 }
d7b2a16c 1581 if (error = vn_writechk(vp))
fc2aed1e 1582 goto out;
3658f091
KB
1583 VATTR_NULL(&vattr);
1584 vattr.va_size = uap->length;
2c69fe14 1585 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
fc2aed1e
KM
1586out:
1587 VOP_UNLOCK(vp);
8429d022 1588 return (error);
4f083fd7
SL
1589}
1590
2f2b3b3d
CT
1591#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1592/*
1593 * Truncate a file given its path name.
1594 */
9e97623a
CT
1595struct truncate_args {
1596 char *fname;
1597 long length;
1598};
2f2b3b3d
CT
1599/* ARGSUSED */
1600truncate(p, uap, retval)
1601 struct proc *p;
9e97623a 1602 register struct truncate_args *uap;
2f2b3b3d
CT
1603 int *retval;
1604{
9e97623a 1605 struct __truncate_args nuap;
2f2b3b3d
CT
1606
1607 nuap.fname = uap->fname;
1608 nuap.length = uap->length;
1609 return (__truncate(p, &nuap, retval));
1610}
1611
1612/*
1613 * Truncate a file given a file descriptor.
1614 */
9e97623a
CT
1615struct ftruncate_args {
1616 int fd;
1617 long length;
1618};
2f2b3b3d
CT
1619/* ARGSUSED */
1620ftruncate(p, uap, retval)
1621 struct proc *p;
9e97623a 1622 register struct ftruncate_args *uap;
2f2b3b3d
CT
1623 int *retval;
1624{
d80c3f56 1625 struct __ftruncate_args nuap;
2f2b3b3d
CT
1626
1627 nuap.fd = uap->fd;
1628 nuap.length = uap->length;
1629 return (__ftruncate(p, &nuap, retval));
1630}
1631#endif /* COMPAT_43 || COMPAT_SUNOS */
1632
4f083fd7
SL
1633/*
1634 * Synch an open file.
1635 */
9e97623a
CT
1636struct fsync_args {
1637 int fd;
1638};
6a6a1e5f
KM
1639/* ARGSUSED */
1640fsync(p, uap, retval)
5e00df3b 1641 struct proc *p;
9e97623a 1642 struct fsync_args *uap;
6a6a1e5f
KM
1643 int *retval;
1644{
e79467ea 1645 register struct vnode *vp;
4f083fd7 1646 struct file *fp;
fc2aed1e 1647 int error;
4f083fd7 1648
5e00df3b 1649 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1650 return (error);
e79467ea
KM
1651 vp = (struct vnode *)fp->f_data;
1652 VOP_LOCK(vp);
09d2ef1a 1653 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
e79467ea 1654 VOP_UNLOCK(vp);
8429d022 1655 return (error);
528f664c
SL
1656}
1657
4f083fd7
SL
1658/*
1659 * Rename system call.
4f083fd7
SL
1660 *
1661 * Source and destination must either both be directories, or both
1662 * not be directories. If target is a directory, it must be empty.
1663 */
9e97623a
CT
1664struct rename_args {
1665 char *from;
1666 char *to;
1667};
6a6a1e5f
KM
1668/* ARGSUSED */
1669rename(p, uap, retval)
5e00df3b 1670 struct proc *p;
9e97623a 1671 register struct rename_args *uap;
6a6a1e5f
KM
1672 int *retval;
1673{
fc2aed1e 1674 register struct vnode *tvp, *fvp, *tdvp;
5718fad3 1675 struct nameidata fromnd, tond;
fc2aed1e 1676 int error;
4f083fd7 1677
a5368812 1678 CHECKPOINTREF;
dd4c01c2
KM
1679 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
1680 uap->from, p);
1681 if (error = namei(&fromnd))
8429d022 1682 return (error);
5718fad3 1683 fvp = fromnd.ni_vp;
dd4c01c2
KM
1684 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
1685 UIO_USERSPACE, uap->to, p);
1686 if (error = namei(&tond)) {
cfef4373 1687 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
5718fad3 1688 vrele(fromnd.ni_dvp);
66955caf
KM
1689 vrele(fvp);
1690 goto out1;
1691 }
fc2aed1e
KM
1692 tdvp = tond.ni_dvp;
1693 tvp = tond.ni_vp;
1694 if (tvp != NULL) {
1695 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
9259ee95 1696 error = ENOTDIR;
fc2aed1e
KM
1697 goto out;
1698 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
9259ee95 1699 error = EISDIR;
fc2aed1e 1700 goto out;
a5390dce 1701 }
64d3a787 1702 }
fe562f32 1703 if (fvp == tdvp)
fc2aed1e 1704 error = EINVAL;
fe562f32 1705 /*
5718fad3
KM
1706 * If source is the same as the destination (that is the
1707 * same inode number with the same name in the same directory),
fe562f32
KM
1708 * then there is nothing to do.
1709 */
5718fad3 1710 if (fvp == tvp && fromnd.ni_dvp == tdvp &&
dd4c01c2
KM
1711 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1712 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1713 fromnd.ni_cnd.cn_namelen))
fe562f32 1714 error = -1;
fc2aed1e 1715out:
66955caf 1716 if (!error) {
e62d4143
KM
1717 LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE);
1718 if (fromnd.ni_dvp != tdvp)
1719 LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1720 if (tvp)
1721 LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE);
cfef4373
JH
1722 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1723 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
66955caf 1724 } else {
cfef4373 1725 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
6c44e83b
KM
1726 if (tdvp == tvp)
1727 vrele(tdvp);
1728 else
1729 vput(tdvp);
66955caf
KM
1730 if (tvp)
1731 vput(tvp);
cfef4373 1732 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
5718fad3 1733 vrele(fromnd.ni_dvp);
66955caf 1734 vrele(fvp);
64d3a787 1735 }
c03959f9 1736 p->p_spare[1]--;
5718fad3 1737 vrele(tond.ni_startdir);
dd4c01c2 1738 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
fc2aed1e 1739out1:
c03959f9 1740 p->p_spare[1]--;
5718fad3 1741 vrele(fromnd.ni_startdir);
dd4c01c2 1742 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
a5368812 1743 CHECKREFS("rename");
fe562f32 1744 if (error == -1)
8429d022
MK
1745 return (0);
1746 return (error);
64d3a787 1747}
88a7a62a 1748
88a7a62a 1749/*
d4ed1dcd 1750 * Mkdir system call.
88a7a62a 1751 */
9e97623a
CT
1752struct mkdir_args {
1753 char *name;
1754 int dmode;
1755};
6a6a1e5f
KM
1756/* ARGSUSED */
1757mkdir(p, uap, retval)
5e00df3b 1758 struct proc *p;
9e97623a 1759 register struct mkdir_args *uap;
6a6a1e5f
KM
1760 int *retval;
1761{
fc2aed1e
KM
1762 register struct vnode *vp;
1763 struct vattr vattr;
1764 int error;
8429d022 1765 struct nameidata nd;
88a7a62a 1766
a5368812 1767 CHECKPOINTREF;
dd4c01c2
KM
1768 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->name, p);
1769 if (error = namei(&nd))
8429d022 1770 return (error);
dd4c01c2 1771 vp = nd.ni_vp;
fc2aed1e 1772 if (vp != NULL) {
dd4c01c2
KM
1773 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1774 if (nd.ni_dvp == vp)
1775 vrele(nd.ni_dvp);
6c44e83b 1776 else
dd4c01c2 1777 vput(nd.ni_dvp);
66955caf 1778 vrele(vp);
a5368812 1779 CHECKREFS("mkdir1");
8429d022 1780 return (EEXIST);
88a7a62a 1781 }
3ee1461b 1782 VATTR_NULL(&vattr);
fc2aed1e 1783 vattr.va_type = VDIR;
5e00df3b 1784 vattr.va_mode = (uap->dmode & 0777) &~ p->p_fd->fd_cmask;
dd4c01c2
KM
1785 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1786 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
5dfd04f0 1787 if (!error)
dd4c01c2 1788 vput(nd.ni_vp);
a5368812 1789 CHECKREFS("mkdir2");
8429d022 1790 return (error);
88a7a62a
SL
1791}
1792
1793/*
1794 * Rmdir system call.
1795 */
9e97623a
CT
1796struct rmdir_args {
1797 char *name;
1798};
6a6a1e5f
KM
1799/* ARGSUSED */
1800rmdir(p, uap, retval)
5e00df3b 1801 struct proc *p;
9e97623a 1802 struct rmdir_args *uap;
6a6a1e5f
KM
1803 int *retval;
1804{
fc2aed1e
KM
1805 register struct vnode *vp;
1806 int error;
8429d022 1807 struct nameidata nd;
88a7a62a 1808
a5368812 1809 CHECKPOINTREF;
dd4c01c2
KM
1810 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->name, p);
1811 if (error = namei(&nd))
8429d022 1812 return (error);
dd4c01c2 1813 vp = nd.ni_vp;
fc2aed1e
KM
1814 if (vp->v_type != VDIR) {
1815 error = ENOTDIR;
88a7a62a
SL
1816 goto out;
1817 }
1818 /*
fc2aed1e 1819 * No rmdir "." please.
88a7a62a 1820 */
dd4c01c2 1821 if (nd.ni_dvp == vp) {
fc2aed1e 1822 error = EINVAL;
88a7a62a
SL
1823 goto out;
1824 }
1825 /*
d4ed1dcd 1826 * The root of a mounted filesystem cannot be deleted.
88a7a62a 1827 */
fc2aed1e
KM
1828 if (vp->v_flag & VROOT)
1829 error = EBUSY;
88a7a62a 1830out:
66955caf 1831 if (!error) {
dd4c01c2 1832 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
e62d4143 1833 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
dd4c01c2 1834 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
66955caf 1835 } else {
dd4c01c2
KM
1836 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1837 if (nd.ni_dvp == vp)
1838 vrele(nd.ni_dvp);
6c44e83b 1839 else
dd4c01c2 1840 vput(nd.ni_dvp);
66955caf
KM
1841 vput(vp);
1842 }
a5368812 1843 CHECKREFS("rmdir");
8429d022 1844 return (error);
88a7a62a
SL
1845}
1846
3d92fa10
KM
1847#ifdef COMPAT_43
1848/*
1849 * Read a block of directory entries in a file system independent format.
1850 */
9e97623a
CT
1851struct ogetdirentries_args {
1852 int fd;
1853 char *buf;
1854 unsigned count;
1855 long *basep;
1856};
3d92fa10
KM
1857ogetdirentries(p, uap, retval)
1858 struct proc *p;
9e97623a 1859 register struct ogetdirentries_args *uap;
3d92fa10
KM
1860 int *retval;
1861{
3d92fa10
KM
1862 register struct vnode *vp;
1863 struct file *fp;
1864 struct uio auio, kuio;
1865 struct iovec aiov, kiov;
1866 struct dirent *dp, *edp;
1867 caddr_t dirbuf;
1868 int error, readcnt;
d80c3f56 1869 long loff;
3d92fa10
KM
1870
1871 if (error = getvnode(p->p_fd, uap->fd, &fp))
1872 return (error);
1873 if ((fp->f_flag & FREAD) == 0)
1874 return (EBADF);
1875 vp = (struct vnode *)fp->f_data;
1876 if (vp->v_type != VDIR)
1877 return (EINVAL);
1878 aiov.iov_base = uap->buf;
1879 aiov.iov_len = uap->count;
1880 auio.uio_iov = &aiov;
1881 auio.uio_iovcnt = 1;
1882 auio.uio_rw = UIO_READ;
1883 auio.uio_segflg = UIO_USERSPACE;
1884 auio.uio_procp = p;
1885 auio.uio_resid = uap->count;
1886 VOP_LOCK(vp);
d80c3f56 1887 loff = auio.uio_offset = fp->f_offset;
3d92fa10 1888# if (BYTE_ORDER != LITTLE_ENDIAN)
a801b5ab 1889 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
3d92fa10 1890 error = VOP_READDIR(vp, &auio, fp->f_cred);
a801b5ab
KM
1891 fp->f_offset = auio.uio_offset;
1892 } else
3d92fa10
KM
1893# endif
1894 {
1895 kuio = auio;
1896 kuio.uio_iov = &kiov;
1897 kuio.uio_segflg = UIO_SYSSPACE;
1898 kiov.iov_len = uap->count;
1899 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
1900 kiov.iov_base = dirbuf;
1901 error = VOP_READDIR(vp, &kuio, fp->f_cred);
a801b5ab 1902 fp->f_offset = kuio.uio_offset;
3d92fa10
KM
1903 if (error == 0) {
1904 readcnt = uap->count - kuio.uio_resid;
1905 edp = (struct dirent *)&dirbuf[readcnt];
1906 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
3d92fa10 1907# if (BYTE_ORDER == LITTLE_ENDIAN)
d80c3f56 1908 /*
30445fe6
KM
1909 * The expected low byte of
1910 * dp->d_namlen is our dp->d_type.
1911 * The high MBZ byte of dp->d_namlen
1912 * is our dp->d_namlen.
d80c3f56 1913 */
30445fe6
KM
1914 dp->d_type = dp->d_namlen;
1915 dp->d_namlen = 0;
1916# else
1917 /*
1918 * The dp->d_type is the high byte
1919 * of the expected dp->d_namlen,
1920 * so must be zero'ed.
1921 */
1922 dp->d_type = 0;
3d92fa10
KM
1923# endif
1924 if (dp->d_reclen > 0) {
1925 dp = (struct dirent *)
1926 ((char *)dp + dp->d_reclen);
1927 } else {
1928 error = EIO;
1929 break;
1930 }
1931 }
1932 if (dp >= edp)
1933 error = uiomove(dirbuf, readcnt, &auio);
1934 }
1935 FREE(dirbuf, M_TEMP);
1936 }
3d92fa10
KM
1937 VOP_UNLOCK(vp);
1938 if (error)
1939 return (error);
d80c3f56 1940 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
3d92fa10
KM
1941 *retval = uap->count - auio.uio_resid;
1942 return (error);
1943}
1944#endif
1945
fc2aed1e 1946/*
d4ed1dcd 1947 * Read a block of directory entries in a file system independent format.
fc2aed1e 1948 */
9e97623a
CT
1949struct getdirentries_args {
1950 int fd;
1951 char *buf;
1952 unsigned count;
1953 long *basep;
1954};
6a6a1e5f 1955getdirentries(p, uap, retval)
5e00df3b 1956 struct proc *p;
9e97623a 1957 register struct getdirentries_args *uap;
6a6a1e5f
KM
1958 int *retval;
1959{
e79467ea 1960 register struct vnode *vp;
8462a185 1961 struct file *fp;
fc2aed1e
KM
1962 struct uio auio;
1963 struct iovec aiov;
d80c3f56 1964 long loff;
09d2ef1a 1965 int error;
fc2aed1e 1966
5e00df3b 1967 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1968 return (error);
fc2aed1e 1969 if ((fp->f_flag & FREAD) == 0)
8429d022 1970 return (EBADF);
e79467ea 1971 vp = (struct vnode *)fp->f_data;
95a9cadb 1972unionread:
e79467ea 1973 if (vp->v_type != VDIR)
8429d022 1974 return (EINVAL);
fc2aed1e
KM
1975 aiov.iov_base = uap->buf;
1976 aiov.iov_len = uap->count;
1977 auio.uio_iov = &aiov;
1978 auio.uio_iovcnt = 1;
1979 auio.uio_rw = UIO_READ;
1980 auio.uio_segflg = UIO_USERSPACE;
2c69fe14 1981 auio.uio_procp = p;
fc2aed1e 1982 auio.uio_resid = uap->count;
e79467ea 1983 VOP_LOCK(vp);
d80c3f56 1984 loff = auio.uio_offset = fp->f_offset;
09d2ef1a 1985 error = VOP_READDIR(vp, &auio, fp->f_cred);
e79467ea
KM
1986 fp->f_offset = auio.uio_offset;
1987 VOP_UNLOCK(vp);
1988 if (error)
8429d022 1989 return (error);
95a9cadb
JSP
1990 if ((uap->count == auio.uio_resid) &&
1991 (vp->v_flag & VROOT) &&
1992 (vp->v_mount->mnt_flag & MNT_UNION)) {
1993 struct vnode *tvp = vp;
1994 vp = vp->v_mount->mnt_vnodecovered;
1995 VREF(vp);
1996 fp->f_data = (caddr_t) vp;
1997 fp->f_offset = 0;
1998 vrele(tvp);
1999 goto unionread;
2000 }
d80c3f56 2001 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
6a6a1e5f 2002 *retval = uap->count - auio.uio_resid;
8429d022 2003 return (error);
88a7a62a
SL
2004}
2005
2006/*
d4ed1dcd 2007 * Set the mode mask for creation of filesystem nodes.
88a7a62a 2008 */
9e97623a
CT
2009struct umask_args {
2010 int mask;
2011};
2012mode_t /* XXX */
6a6a1e5f 2013umask(p, uap, retval)
5e00df3b 2014 struct proc *p;
9e97623a 2015 struct umask_args *uap;
6a6a1e5f
KM
2016 int *retval;
2017{
5e00df3b 2018 register struct filedesc *fdp = p->p_fd;
88a7a62a 2019
5e00df3b
KM
2020 *retval = fdp->fd_cmask;
2021 fdp->fd_cmask = uap->mask & 07777;
8429d022 2022 return (0);
fc2aed1e
KM
2023}
2024
b0a98f13
MT
2025/*
2026 * Void all references to file by ripping underlying filesystem
2027 * away from vnode.
2028 */
9e97623a
CT
2029struct revoke_args {
2030 char *fname;
2031};
6a6a1e5f
KM
2032/* ARGSUSED */
2033revoke(p, uap, retval)
5e00df3b 2034 struct proc *p;
9e97623a 2035 register struct revoke_args *uap;
6a6a1e5f
KM
2036 int *retval;
2037{
b0a98f13
MT
2038 register struct vnode *vp;
2039 struct vattr vattr;
2040 int error;
8429d022 2041 struct nameidata nd;
b0a98f13 2042
dd4c01c2
KM
2043 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
2044 if (error = namei(&nd))
8429d022 2045 return (error);
dd4c01c2 2046 vp = nd.ni_vp;
b0a98f13
MT
2047 if (vp->v_type != VCHR && vp->v_type != VBLK) {
2048 error = EINVAL;
2049 goto out;
2050 }
2c69fe14 2051 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
b0a98f13 2052 goto out;
8429d022
MK
2053 if (p->p_ucred->cr_uid != vattr.va_uid &&
2054 (error = suser(p->p_ucred, &p->p_acflag)))
b0a98f13 2055 goto out;
8b81d198 2056 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
c9345cca 2057 vgoneall(vp);
b0a98f13
MT
2058out:
2059 vrele(vp);
8429d022 2060 return (error);
b0a98f13
MT
2061}
2062
d4ed1dcd
KM
2063/*
2064 * Convert a user file descriptor to a kernel file entry.
2065 */
5e00df3b
KM
2066getvnode(fdp, fdes, fpp)
2067 struct filedesc *fdp;
fc2aed1e
KM
2068 struct file **fpp;
2069 int fdes;
2070{
2071 struct file *fp;
2072
8429d022 2073 if ((unsigned)fdes >= fdp->fd_nfiles ||
78eeb014 2074 (fp = fdp->fd_ofiles[fdes]) == NULL)
fc2aed1e
KM
2075 return (EBADF);
2076 if (fp->f_type != DTYPE_VNODE)
2077 return (EINVAL);
2078 *fpp = fp;
2079 return (0);
88a7a62a 2080}