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