lseek (long form) is used too much to make it COMPAT_43
[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 *
64deb204 7 * @(#)vfs_syscalls.c 7.109 (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
9e97623a 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 */
ae9b6dc3 908__lseek(p, uap, retval)
5e00df3b 909 struct proc *p;
9e97623a
CT
910 register struct __lseek_args *uap;
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
64deb204
KM
948/*
949 * Old lseek system call.
950 *
951 * XXX should be COMPAT_43, but too much breaks.
952 */
953struct lseek_args {
954 int fdes;
955 long off;
956 int sbase;
957};
958lseek(p, uap, retval)
959 struct proc *p;
960 register struct lseek_args *uap;
961 int *retval;
962{
963 struct __lseek_args nuap;
964 off_t qret;
965 int error;
966
967 nuap.fdes = uap->fdes;
968 nuap.off = uap->off;
969 nuap.sbase = uap->sbase;
970 error = __lseek(p, &nuap, &qret);
971 *(long *)retval = qret;
972 return (error);
973}
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
1202/*
d4ed1dcd 1203 * Return target name of a symbolic link.
5485e062 1204 */
9e97623a
CT
1205struct readlink_args {
1206 char *name;
1207 char *buf;
1208 int count;
1209};
6a6a1e5f
KM
1210/* ARGSUSED */
1211readlink(p, uap, retval)
5e00df3b 1212 struct proc *p;
9e97623a 1213 register struct readlink_args *uap;
6a6a1e5f
KM
1214 int *retval;
1215{
fc2aed1e
KM
1216 register struct vnode *vp;
1217 struct iovec aiov;
1218 struct uio auio;
1219 int error;
8429d022 1220 struct nameidata nd;
5485e062 1221
a5368812 1222 CHECKPOINTREF;
dd4c01c2
KM
1223 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->name, p);
1224 if (error = namei(&nd))
8429d022 1225 return (error);
dd4c01c2 1226 vp = nd.ni_vp;
fc2aed1e
KM
1227 if (vp->v_type != VLNK) {
1228 error = EINVAL;
5485e062
BJ
1229 goto out;
1230 }
fc2aed1e
KM
1231 aiov.iov_base = uap->buf;
1232 aiov.iov_len = uap->count;
1233 auio.uio_iov = &aiov;
1234 auio.uio_iovcnt = 1;
1235 auio.uio_offset = 0;
1236 auio.uio_rw = UIO_READ;
1237 auio.uio_segflg = UIO_USERSPACE;
2c69fe14 1238 auio.uio_procp = p;
fc2aed1e 1239 auio.uio_resid = uap->count;
8429d022 1240 error = VOP_READLINK(vp, &auio, p->p_ucred);
5485e062 1241out:
fc2aed1e 1242 vput(vp);
6a6a1e5f 1243 *retval = uap->count - auio.uio_resid;
a5368812 1244 CHECKREFS("readlink");
8429d022 1245 return (error);
5485e062
BJ
1246}
1247
6995a2cb
KM
1248/*
1249 * Change flags of a file given path name.
1250 */
9e97623a
CT
1251struct chflags_args {
1252 char *fname;
1253 int flags;
1254};
6a6a1e5f
KM
1255/* ARGSUSED */
1256chflags(p, uap, retval)
5e00df3b 1257 struct proc *p;
9e97623a 1258 register struct chflags_args *uap;
6a6a1e5f
KM
1259 int *retval;
1260{
6995a2cb
KM
1261 register struct vnode *vp;
1262 struct vattr vattr;
1263 int error;
8429d022 1264 struct nameidata nd;
6995a2cb 1265
dbcf7de6 1266 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
dd4c01c2 1267 if (error = namei(&nd))
8429d022 1268 return (error);
dd4c01c2 1269 vp = nd.ni_vp;
dbcf7de6
KM
1270 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1271 VOP_LOCK(vp);
54fb9dc2 1272 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
6995a2cb
KM
1273 error = EROFS;
1274 goto out;
1275 }
3658f091
KB
1276 VATTR_NULL(&vattr);
1277 vattr.va_flags = uap->flags;
2c69fe14 1278 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
6995a2cb
KM
1279out:
1280 vput(vp);
8429d022 1281 return (error);
6995a2cb
KM
1282}
1283
1284/*
1285 * Change flags of a file given a file descriptor.
1286 */
9e97623a
CT
1287struct fchflags_args {
1288 int fd;
1289 int flags;
1290};
6a6a1e5f
KM
1291/* ARGSUSED */
1292fchflags(p, uap, retval)
5e00df3b 1293 struct proc *p;
9e97623a 1294 register struct fchflags_args *uap;
6a6a1e5f
KM
1295 int *retval;
1296{
6995a2cb
KM
1297 struct vattr vattr;
1298 struct vnode *vp;
1299 struct file *fp;
1300 int error;
1301
5e00df3b 1302 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1303 return (error);
6995a2cb 1304 vp = (struct vnode *)fp->f_data;
dbcf7de6 1305 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
6995a2cb 1306 VOP_LOCK(vp);
54fb9dc2 1307 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
6995a2cb
KM
1308 error = EROFS;
1309 goto out;
1310 }
3658f091
KB
1311 VATTR_NULL(&vattr);
1312 vattr.va_flags = uap->flags;
2c69fe14 1313 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
6995a2cb
KM
1314out:
1315 VOP_UNLOCK(vp);
8429d022 1316 return (error);
6995a2cb
KM
1317}
1318
4f083fd7
SL
1319/*
1320 * Change mode of a file given path name.
1321 */
9e97623a
CT
1322struct chmod_args {
1323 char *fname;
1324 int fmode;
1325};
6a6a1e5f
KM
1326/* ARGSUSED */
1327chmod(p, uap, retval)
5e00df3b 1328 struct proc *p;
9e97623a 1329 register struct chmod_args *uap;
6a6a1e5f
KM
1330 int *retval;
1331{
fc2aed1e
KM
1332 register struct vnode *vp;
1333 struct vattr vattr;
1334 int error;
8429d022 1335 struct nameidata nd;
5485e062 1336
dbcf7de6 1337 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
dd4c01c2 1338 if (error = namei(&nd))
8429d022 1339 return (error);
dd4c01c2 1340 vp = nd.ni_vp;
dbcf7de6
KM
1341 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1342 VOP_LOCK(vp);
54fb9dc2 1343 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
fc2aed1e
KM
1344 error = EROFS;
1345 goto out;
1346 }
3658f091
KB
1347 VATTR_NULL(&vattr);
1348 vattr.va_mode = uap->fmode & 07777;
2c69fe14 1349 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1350out:
1351 vput(vp);
8429d022 1352 return (error);
528f664c 1353}
f94ceb3b 1354
4f083fd7
SL
1355/*
1356 * Change mode of a file given a file descriptor.
1357 */
9e97623a
CT
1358struct fchmod_args {
1359 int fd;
1360 int fmode;
1361};
6a6a1e5f
KM
1362/* ARGSUSED */
1363fchmod(p, uap, retval)
5e00df3b 1364 struct proc *p;
9e97623a 1365 register struct fchmod_args *uap;
6a6a1e5f
KM
1366 int *retval;
1367{
fc2aed1e
KM
1368 struct vattr vattr;
1369 struct vnode *vp;
1370 struct file *fp;
1371 int error;
1372
5e00df3b 1373 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1374 return (error);
fc2aed1e 1375 vp = (struct vnode *)fp->f_data;
dbcf7de6 1376 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
fc2aed1e 1377 VOP_LOCK(vp);
54fb9dc2 1378 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
fc2aed1e
KM
1379 error = EROFS;
1380 goto out;
f94ceb3b 1381 }
3658f091
KB
1382 VATTR_NULL(&vattr);
1383 vattr.va_mode = uap->fmode & 07777;
2c69fe14 1384 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1385out:
1386 VOP_UNLOCK(vp);
8429d022 1387 return (error);
5485e062
BJ
1388}
1389
4f083fd7
SL
1390/*
1391 * Set ownership given a path name.
1392 */
9e97623a
CT
1393struct chown_args {
1394 char *fname;
1395 int uid;
1396 int gid;
1397};
6a6a1e5f
KM
1398/* ARGSUSED */
1399chown(p, uap, retval)
5e00df3b 1400 struct proc *p;
9e97623a 1401 register struct chown_args *uap;
6a6a1e5f
KM
1402 int *retval;
1403{
fc2aed1e
KM
1404 register struct vnode *vp;
1405 struct vattr vattr;
1406 int error;
8429d022 1407 struct nameidata nd;
d67a03eb 1408
dbcf7de6 1409 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->fname, p);
dd4c01c2 1410 if (error = namei(&nd))
8429d022 1411 return (error);
dd4c01c2 1412 vp = nd.ni_vp;
dbcf7de6
KM
1413 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1414 VOP_LOCK(vp);
54fb9dc2 1415 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
fc2aed1e
KM
1416 error = EROFS;
1417 goto out;
1418 }
3658f091
KB
1419 VATTR_NULL(&vattr);
1420 vattr.va_uid = uap->uid;
1421 vattr.va_gid = uap->gid;
2c69fe14 1422 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1423out:
1424 vput(vp);
8429d022 1425 return (error);
528f664c 1426}
f94ceb3b 1427
4f083fd7
SL
1428/*
1429 * Set ownership given a file descriptor.
1430 */
9e97623a
CT
1431struct fchown_args {
1432 int fd;
1433 int uid;
1434 int gid;
1435};
6a6a1e5f
KM
1436/* ARGSUSED */
1437fchown(p, uap, retval)
5e00df3b 1438 struct proc *p;
9e97623a 1439 register struct fchown_args *uap;
6a6a1e5f
KM
1440 int *retval;
1441{
fc2aed1e
KM
1442 struct vattr vattr;
1443 struct vnode *vp;
1444 struct file *fp;
1445 int error;
1446
5e00df3b 1447 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1448 return (error);
fc2aed1e 1449 vp = (struct vnode *)fp->f_data;
dbcf7de6 1450 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
fc2aed1e 1451 VOP_LOCK(vp);
54fb9dc2 1452 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
fc2aed1e
KM
1453 error = EROFS;
1454 goto out;
1455 }
3658f091
KB
1456 VATTR_NULL(&vattr);
1457 vattr.va_uid = uap->uid;
1458 vattr.va_gid = uap->gid;
2c69fe14 1459 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1460out:
1461 VOP_UNLOCK(vp);
8429d022 1462 return (error);
d67a03eb
BJ
1463}
1464
6a6a1e5f
KM
1465/*
1466 * Set the access and modification times of a file.
1467 */
9e97623a
CT
1468struct utimes_args {
1469 char *fname;
1470 struct timeval *tptr;
1471};
6a6a1e5f
KM
1472/* ARGSUSED */
1473utimes(p, uap, retval)
5e00df3b 1474 struct proc *p;
9e97623a 1475 register struct utimes_args *uap;
6a6a1e5f
KM
1476 int *retval;
1477{
fc2aed1e 1478 register struct vnode *vp;
bb1b75f4 1479 struct timeval tv[2];
fc2aed1e 1480 struct vattr vattr;
8e88b0cd 1481 int error;
8429d022 1482 struct nameidata nd;
bb1b75f4 1483
f8ee9a49
KB
1484 VATTR_NULL(&vattr);
1485 if (uap->tptr == NULL) {
1486 microtime(&tv[0]);
1487 tv[1] = tv[0];
fcba749b 1488 vattr.va_vaflags |= VA_UTIMES_NULL;
f8ee9a49
KB
1489 } else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
1490 return (error);
dbcf7de6 1491 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
dd4c01c2 1492 if (error = namei(&nd))
8429d022 1493 return (error);
dd4c01c2 1494 vp = nd.ni_vp;
dbcf7de6
KM
1495 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1496 VOP_LOCK(vp);
54fb9dc2 1497 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
fc2aed1e
KM
1498 error = EROFS;
1499 goto out;
bb1b75f4 1500 }
7e11a0c9
KM
1501 vattr.va_atime.ts_sec = tv[0].tv_sec;
1502 vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;
1503 vattr.va_mtime.ts_sec = tv[1].tv_sec;
1504 vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;
2c69fe14 1505 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1506out:
1507 vput(vp);
8429d022 1508 return (error);
d67a03eb 1509}
64d3a787 1510
9e97623a 1511struct __truncate_args {
2f2b3b3d
CT
1512 char *fname;
1513 int pad;
1514 off_t length;
1515};
be320a2b
KM
1516
1517/*
1518 * Truncate a file given its path name.
1519 */
1520/* ARGSUSED */
ae9b6dc3 1521__truncate(p, uap, retval)
5e00df3b 1522 struct proc *p;
9e97623a 1523 register struct __truncate_args *uap;
6a6a1e5f
KM
1524 int *retval;
1525{
fc2aed1e
KM
1526 register struct vnode *vp;
1527 struct vattr vattr;
1528 int error;
8429d022 1529 struct nameidata nd;
528f664c 1530
dbcf7de6 1531 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
dd4c01c2 1532 if (error = namei(&nd))
8429d022 1533 return (error);
dd4c01c2 1534 vp = nd.ni_vp;
dbcf7de6
KM
1535 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1536 VOP_LOCK(vp);
fc2aed1e
KM
1537 if (vp->v_type == VDIR) {
1538 error = EISDIR;
1539 goto out;
528f664c 1540 }
d7b2a16c 1541 if ((error = vn_writechk(vp)) ||
2c69fe14 1542 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)))
fc2aed1e 1543 goto out;
3658f091
KB
1544 VATTR_NULL(&vattr);
1545 vattr.va_size = uap->length;
2c69fe14 1546 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
fc2aed1e
KM
1547out:
1548 vput(vp);
8429d022 1549 return (error);
528f664c
SL
1550}
1551
9e97623a 1552struct __ftruncate_args {
2f2b3b3d
CT
1553 int fd;
1554 int pad;
1555 off_t length;
1556};
1557
4f083fd7
SL
1558/*
1559 * Truncate a file given a file descriptor.
1560 */
6a6a1e5f 1561/* ARGSUSED */
ae9b6dc3 1562__ftruncate(p, uap, retval)
5e00df3b 1563 struct proc *p;
9e97623a 1564 register struct __ftruncate_args *uap;
6a6a1e5f
KM
1565 int *retval;
1566{
fc2aed1e
KM
1567 struct vattr vattr;
1568 struct vnode *vp;
528f664c 1569 struct file *fp;
fc2aed1e
KM
1570 int error;
1571
5e00df3b 1572 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1573 return (error);
fc2aed1e 1574 if ((fp->f_flag & FWRITE) == 0)
8429d022 1575 return (EINVAL);
fc2aed1e 1576 vp = (struct vnode *)fp->f_data;
dbcf7de6 1577 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
fc2aed1e
KM
1578 VOP_LOCK(vp);
1579 if (vp->v_type == VDIR) {
1580 error = EISDIR;
1581 goto out;
528f664c 1582 }
d7b2a16c 1583 if (error = vn_writechk(vp))
fc2aed1e 1584 goto out;
3658f091
KB
1585 VATTR_NULL(&vattr);
1586 vattr.va_size = uap->length;
2c69fe14 1587 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
fc2aed1e
KM
1588out:
1589 VOP_UNLOCK(vp);
8429d022 1590 return (error);
4f083fd7
SL
1591}
1592
2f2b3b3d
CT
1593#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1594/*
1595 * Truncate a file given its path name.
1596 */
9e97623a
CT
1597struct truncate_args {
1598 char *fname;
1599 long length;
1600};
2f2b3b3d
CT
1601/* ARGSUSED */
1602truncate(p, uap, retval)
1603 struct proc *p;
9e97623a 1604 register struct truncate_args *uap;
2f2b3b3d
CT
1605 int *retval;
1606{
9e97623a 1607 struct __truncate_args nuap;
2f2b3b3d
CT
1608
1609 nuap.fname = uap->fname;
1610 nuap.length = uap->length;
1611 return (__truncate(p, &nuap, retval));
1612}
1613
1614/*
1615 * Truncate a file given a file descriptor.
1616 */
9e97623a
CT
1617struct ftruncate_args {
1618 int fd;
1619 long length;
1620};
2f2b3b3d
CT
1621/* ARGSUSED */
1622ftruncate(p, uap, retval)
1623 struct proc *p;
9e97623a 1624 register struct ftruncate_args *uap;
2f2b3b3d
CT
1625 int *retval;
1626{
d80c3f56 1627 struct __ftruncate_args nuap;
2f2b3b3d
CT
1628
1629 nuap.fd = uap->fd;
1630 nuap.length = uap->length;
1631 return (__ftruncate(p, &nuap, retval));
1632}
1633#endif /* COMPAT_43 || COMPAT_SUNOS */
1634
4f083fd7
SL
1635/*
1636 * Synch an open file.
1637 */
9e97623a
CT
1638struct fsync_args {
1639 int fd;
1640};
6a6a1e5f
KM
1641/* ARGSUSED */
1642fsync(p, uap, retval)
5e00df3b 1643 struct proc *p;
9e97623a 1644 struct fsync_args *uap;
6a6a1e5f
KM
1645 int *retval;
1646{
e79467ea 1647 register struct vnode *vp;
4f083fd7 1648 struct file *fp;
fc2aed1e 1649 int error;
4f083fd7 1650
5e00df3b 1651 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1652 return (error);
e79467ea
KM
1653 vp = (struct vnode *)fp->f_data;
1654 VOP_LOCK(vp);
09d2ef1a 1655 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
e79467ea 1656 VOP_UNLOCK(vp);
8429d022 1657 return (error);
528f664c
SL
1658}
1659
4f083fd7
SL
1660/*
1661 * Rename system call.
4f083fd7
SL
1662 *
1663 * Source and destination must either both be directories, or both
1664 * not be directories. If target is a directory, it must be empty.
1665 */
9e97623a
CT
1666struct rename_args {
1667 char *from;
1668 char *to;
1669};
6a6a1e5f
KM
1670/* ARGSUSED */
1671rename(p, uap, retval)
5e00df3b 1672 struct proc *p;
9e97623a 1673 register struct rename_args *uap;
6a6a1e5f
KM
1674 int *retval;
1675{
fc2aed1e 1676 register struct vnode *tvp, *fvp, *tdvp;
5718fad3 1677 struct nameidata fromnd, tond;
fc2aed1e 1678 int error;
4f083fd7 1679
a5368812 1680 CHECKPOINTREF;
dd4c01c2
KM
1681 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
1682 uap->from, p);
1683 if (error = namei(&fromnd))
8429d022 1684 return (error);
5718fad3 1685 fvp = fromnd.ni_vp;
dd4c01c2
KM
1686 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
1687 UIO_USERSPACE, uap->to, p);
1688 if (error = namei(&tond)) {
cfef4373 1689 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
5718fad3 1690 vrele(fromnd.ni_dvp);
66955caf
KM
1691 vrele(fvp);
1692 goto out1;
1693 }
fc2aed1e
KM
1694 tdvp = tond.ni_dvp;
1695 tvp = tond.ni_vp;
1696 if (tvp != NULL) {
1697 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
9259ee95 1698 error = ENOTDIR;
fc2aed1e
KM
1699 goto out;
1700 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
9259ee95 1701 error = EISDIR;
fc2aed1e 1702 goto out;
a5390dce 1703 }
64d3a787 1704 }
fe562f32 1705 if (fvp == tdvp)
fc2aed1e 1706 error = EINVAL;
fe562f32 1707 /*
5718fad3
KM
1708 * If source is the same as the destination (that is the
1709 * same inode number with the same name in the same directory),
fe562f32
KM
1710 * then there is nothing to do.
1711 */
5718fad3 1712 if (fvp == tvp && fromnd.ni_dvp == tdvp &&
dd4c01c2
KM
1713 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1714 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1715 fromnd.ni_cnd.cn_namelen))
fe562f32 1716 error = -1;
fc2aed1e 1717out:
66955caf 1718 if (!error) {
e62d4143
KM
1719 LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE);
1720 if (fromnd.ni_dvp != tdvp)
1721 LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1722 if (tvp)
1723 LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE);
cfef4373
JH
1724 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1725 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
66955caf 1726 } else {
cfef4373 1727 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
6c44e83b
KM
1728 if (tdvp == tvp)
1729 vrele(tdvp);
1730 else
1731 vput(tdvp);
66955caf
KM
1732 if (tvp)
1733 vput(tvp);
cfef4373 1734 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
5718fad3 1735 vrele(fromnd.ni_dvp);
66955caf 1736 vrele(fvp);
64d3a787 1737 }
c03959f9 1738 p->p_spare[1]--;
5718fad3 1739 vrele(tond.ni_startdir);
dd4c01c2 1740 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
fc2aed1e 1741out1:
c03959f9 1742 p->p_spare[1]--;
5718fad3 1743 vrele(fromnd.ni_startdir);
dd4c01c2 1744 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
a5368812 1745 CHECKREFS("rename");
fe562f32 1746 if (error == -1)
8429d022
MK
1747 return (0);
1748 return (error);
64d3a787 1749}
88a7a62a 1750
88a7a62a 1751/*
d4ed1dcd 1752 * Mkdir system call.
88a7a62a 1753 */
9e97623a
CT
1754struct mkdir_args {
1755 char *name;
1756 int dmode;
1757};
6a6a1e5f
KM
1758/* ARGSUSED */
1759mkdir(p, uap, retval)
5e00df3b 1760 struct proc *p;
9e97623a 1761 register struct mkdir_args *uap;
6a6a1e5f
KM
1762 int *retval;
1763{
fc2aed1e
KM
1764 register struct vnode *vp;
1765 struct vattr vattr;
1766 int error;
8429d022 1767 struct nameidata nd;
88a7a62a 1768
a5368812 1769 CHECKPOINTREF;
dd4c01c2
KM
1770 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->name, p);
1771 if (error = namei(&nd))
8429d022 1772 return (error);
dd4c01c2 1773 vp = nd.ni_vp;
fc2aed1e 1774 if (vp != NULL) {
dd4c01c2
KM
1775 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1776 if (nd.ni_dvp == vp)
1777 vrele(nd.ni_dvp);
6c44e83b 1778 else
dd4c01c2 1779 vput(nd.ni_dvp);
66955caf 1780 vrele(vp);
a5368812 1781 CHECKREFS("mkdir1");
8429d022 1782 return (EEXIST);
88a7a62a 1783 }
3ee1461b 1784 VATTR_NULL(&vattr);
fc2aed1e 1785 vattr.va_type = VDIR;
5e00df3b 1786 vattr.va_mode = (uap->dmode & 0777) &~ p->p_fd->fd_cmask;
dd4c01c2
KM
1787 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1788 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
5dfd04f0 1789 if (!error)
dd4c01c2 1790 vput(nd.ni_vp);
a5368812 1791 CHECKREFS("mkdir2");
8429d022 1792 return (error);
88a7a62a
SL
1793}
1794
1795/*
1796 * Rmdir system call.
1797 */
9e97623a
CT
1798struct rmdir_args {
1799 char *name;
1800};
6a6a1e5f
KM
1801/* ARGSUSED */
1802rmdir(p, uap, retval)
5e00df3b 1803 struct proc *p;
9e97623a 1804 struct rmdir_args *uap;
6a6a1e5f
KM
1805 int *retval;
1806{
fc2aed1e
KM
1807 register struct vnode *vp;
1808 int error;
8429d022 1809 struct nameidata nd;
88a7a62a 1810
a5368812 1811 CHECKPOINTREF;
dd4c01c2
KM
1812 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->name, p);
1813 if (error = namei(&nd))
8429d022 1814 return (error);
dd4c01c2 1815 vp = nd.ni_vp;
fc2aed1e
KM
1816 if (vp->v_type != VDIR) {
1817 error = ENOTDIR;
88a7a62a
SL
1818 goto out;
1819 }
1820 /*
fc2aed1e 1821 * No rmdir "." please.
88a7a62a 1822 */
dd4c01c2 1823 if (nd.ni_dvp == vp) {
fc2aed1e 1824 error = EINVAL;
88a7a62a
SL
1825 goto out;
1826 }
1827 /*
d4ed1dcd 1828 * The root of a mounted filesystem cannot be deleted.
88a7a62a 1829 */
fc2aed1e
KM
1830 if (vp->v_flag & VROOT)
1831 error = EBUSY;
88a7a62a 1832out:
66955caf 1833 if (!error) {
dd4c01c2 1834 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
e62d4143 1835 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
dd4c01c2 1836 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
66955caf 1837 } else {
dd4c01c2
KM
1838 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1839 if (nd.ni_dvp == vp)
1840 vrele(nd.ni_dvp);
6c44e83b 1841 else
dd4c01c2 1842 vput(nd.ni_dvp);
66955caf
KM
1843 vput(vp);
1844 }
a5368812 1845 CHECKREFS("rmdir");
8429d022 1846 return (error);
88a7a62a
SL
1847}
1848
3d92fa10
KM
1849#ifdef COMPAT_43
1850/*
1851 * Read a block of directory entries in a file system independent format.
1852 */
9e97623a
CT
1853struct ogetdirentries_args {
1854 int fd;
1855 char *buf;
1856 unsigned count;
1857 long *basep;
1858};
3d92fa10
KM
1859ogetdirentries(p, uap, retval)
1860 struct proc *p;
9e97623a 1861 register struct ogetdirentries_args *uap;
3d92fa10
KM
1862 int *retval;
1863{
3d92fa10
KM
1864 register struct vnode *vp;
1865 struct file *fp;
1866 struct uio auio, kuio;
1867 struct iovec aiov, kiov;
1868 struct dirent *dp, *edp;
1869 caddr_t dirbuf;
1870 int error, readcnt;
d80c3f56 1871 long loff;
3d92fa10
KM
1872
1873 if (error = getvnode(p->p_fd, uap->fd, &fp))
1874 return (error);
1875 if ((fp->f_flag & FREAD) == 0)
1876 return (EBADF);
1877 vp = (struct vnode *)fp->f_data;
1878 if (vp->v_type != VDIR)
1879 return (EINVAL);
1880 aiov.iov_base = uap->buf;
1881 aiov.iov_len = uap->count;
1882 auio.uio_iov = &aiov;
1883 auio.uio_iovcnt = 1;
1884 auio.uio_rw = UIO_READ;
1885 auio.uio_segflg = UIO_USERSPACE;
1886 auio.uio_procp = p;
1887 auio.uio_resid = uap->count;
1888 VOP_LOCK(vp);
d80c3f56 1889 loff = auio.uio_offset = fp->f_offset;
3d92fa10 1890# if (BYTE_ORDER != LITTLE_ENDIAN)
a801b5ab 1891 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
3d92fa10 1892 error = VOP_READDIR(vp, &auio, fp->f_cred);
a801b5ab
KM
1893 fp->f_offset = auio.uio_offset;
1894 } else
3d92fa10
KM
1895# endif
1896 {
1897 kuio = auio;
1898 kuio.uio_iov = &kiov;
1899 kuio.uio_segflg = UIO_SYSSPACE;
1900 kiov.iov_len = uap->count;
1901 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
1902 kiov.iov_base = dirbuf;
1903 error = VOP_READDIR(vp, &kuio, fp->f_cred);
a801b5ab 1904 fp->f_offset = kuio.uio_offset;
3d92fa10
KM
1905 if (error == 0) {
1906 readcnt = uap->count - kuio.uio_resid;
1907 edp = (struct dirent *)&dirbuf[readcnt];
1908 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
3d92fa10 1909# if (BYTE_ORDER == LITTLE_ENDIAN)
d80c3f56 1910 /*
30445fe6
KM
1911 * The expected low byte of
1912 * dp->d_namlen is our dp->d_type.
1913 * The high MBZ byte of dp->d_namlen
1914 * is our dp->d_namlen.
d80c3f56 1915 */
30445fe6
KM
1916 dp->d_type = dp->d_namlen;
1917 dp->d_namlen = 0;
1918# else
1919 /*
1920 * The dp->d_type is the high byte
1921 * of the expected dp->d_namlen,
1922 * so must be zero'ed.
1923 */
1924 dp->d_type = 0;
3d92fa10
KM
1925# endif
1926 if (dp->d_reclen > 0) {
1927 dp = (struct dirent *)
1928 ((char *)dp + dp->d_reclen);
1929 } else {
1930 error = EIO;
1931 break;
1932 }
1933 }
1934 if (dp >= edp)
1935 error = uiomove(dirbuf, readcnt, &auio);
1936 }
1937 FREE(dirbuf, M_TEMP);
1938 }
3d92fa10
KM
1939 VOP_UNLOCK(vp);
1940 if (error)
1941 return (error);
d80c3f56 1942 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
3d92fa10
KM
1943 *retval = uap->count - auio.uio_resid;
1944 return (error);
1945}
1946#endif
1947
fc2aed1e 1948/*
d4ed1dcd 1949 * Read a block of directory entries in a file system independent format.
fc2aed1e 1950 */
9e97623a
CT
1951struct getdirentries_args {
1952 int fd;
1953 char *buf;
1954 unsigned count;
1955 long *basep;
1956};
6a6a1e5f 1957getdirentries(p, uap, retval)
5e00df3b 1958 struct proc *p;
9e97623a 1959 register struct getdirentries_args *uap;
6a6a1e5f
KM
1960 int *retval;
1961{
e79467ea 1962 register struct vnode *vp;
8462a185 1963 struct file *fp;
fc2aed1e
KM
1964 struct uio auio;
1965 struct iovec aiov;
d80c3f56 1966 long loff;
09d2ef1a 1967 int error;
fc2aed1e 1968
5e00df3b 1969 if (error = getvnode(p->p_fd, uap->fd, &fp))
8429d022 1970 return (error);
fc2aed1e 1971 if ((fp->f_flag & FREAD) == 0)
8429d022 1972 return (EBADF);
e79467ea 1973 vp = (struct vnode *)fp->f_data;
95a9cadb 1974unionread:
e79467ea 1975 if (vp->v_type != VDIR)
8429d022 1976 return (EINVAL);
fc2aed1e
KM
1977 aiov.iov_base = uap->buf;
1978 aiov.iov_len = uap->count;
1979 auio.uio_iov = &aiov;
1980 auio.uio_iovcnt = 1;
1981 auio.uio_rw = UIO_READ;
1982 auio.uio_segflg = UIO_USERSPACE;
2c69fe14 1983 auio.uio_procp = p;
fc2aed1e 1984 auio.uio_resid = uap->count;
e79467ea 1985 VOP_LOCK(vp);
d80c3f56 1986 loff = auio.uio_offset = fp->f_offset;
09d2ef1a 1987 error = VOP_READDIR(vp, &auio, fp->f_cred);
e79467ea
KM
1988 fp->f_offset = auio.uio_offset;
1989 VOP_UNLOCK(vp);
1990 if (error)
8429d022 1991 return (error);
95a9cadb
JSP
1992 if ((uap->count == auio.uio_resid) &&
1993 (vp->v_flag & VROOT) &&
1994 (vp->v_mount->mnt_flag & MNT_UNION)) {
1995 struct vnode *tvp = vp;
1996 vp = vp->v_mount->mnt_vnodecovered;
1997 VREF(vp);
1998 fp->f_data = (caddr_t) vp;
1999 fp->f_offset = 0;
2000 vrele(tvp);
2001 goto unionread;
2002 }
d80c3f56 2003 error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
6a6a1e5f 2004 *retval = uap->count - auio.uio_resid;
8429d022 2005 return (error);
88a7a62a
SL
2006}
2007
2008/*
d4ed1dcd 2009 * Set the mode mask for creation of filesystem nodes.
88a7a62a 2010 */
9e97623a
CT
2011struct umask_args {
2012 int mask;
2013};
2014mode_t /* XXX */
6a6a1e5f 2015umask(p, uap, retval)
5e00df3b 2016 struct proc *p;
9e97623a 2017 struct umask_args *uap;
6a6a1e5f
KM
2018 int *retval;
2019{
5e00df3b 2020 register struct filedesc *fdp = p->p_fd;
88a7a62a 2021
5e00df3b
KM
2022 *retval = fdp->fd_cmask;
2023 fdp->fd_cmask = uap->mask & 07777;
8429d022 2024 return (0);
fc2aed1e
KM
2025}
2026
b0a98f13
MT
2027/*
2028 * Void all references to file by ripping underlying filesystem
2029 * away from vnode.
2030 */
9e97623a
CT
2031struct revoke_args {
2032 char *fname;
2033};
6a6a1e5f
KM
2034/* ARGSUSED */
2035revoke(p, uap, retval)
5e00df3b 2036 struct proc *p;
9e97623a 2037 register struct revoke_args *uap;
6a6a1e5f
KM
2038 int *retval;
2039{
b0a98f13
MT
2040 register struct vnode *vp;
2041 struct vattr vattr;
2042 int error;
8429d022 2043 struct nameidata nd;
b0a98f13 2044
dd4c01c2
KM
2045 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
2046 if (error = namei(&nd))
8429d022 2047 return (error);
dd4c01c2 2048 vp = nd.ni_vp;
b0a98f13
MT
2049 if (vp->v_type != VCHR && vp->v_type != VBLK) {
2050 error = EINVAL;
2051 goto out;
2052 }
2c69fe14 2053 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
b0a98f13 2054 goto out;
8429d022
MK
2055 if (p->p_ucred->cr_uid != vattr.va_uid &&
2056 (error = suser(p->p_ucred, &p->p_acflag)))
b0a98f13 2057 goto out;
8b81d198 2058 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
c9345cca 2059 vgoneall(vp);
b0a98f13
MT
2060out:
2061 vrele(vp);
8429d022 2062 return (error);
b0a98f13
MT
2063}
2064
d4ed1dcd
KM
2065/*
2066 * Convert a user file descriptor to a kernel file entry.
2067 */
5e00df3b
KM
2068getvnode(fdp, fdes, fpp)
2069 struct filedesc *fdp;
fc2aed1e
KM
2070 struct file **fpp;
2071 int fdes;
2072{
2073 struct file *fp;
2074
8429d022 2075 if ((unsigned)fdes >= fdp->fd_nfiles ||
78eeb014 2076 (fp = fdp->fd_ofiles[fdes]) == NULL)
fc2aed1e
KM
2077 return (EBADF);
2078 if (fp->f_type != DTYPE_VNODE)
2079 return (EINVAL);
2080 *fpp = fp;
2081 return (0);
88a7a62a 2082}