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