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