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