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