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