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