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