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