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