Annotation of sys/isofs/cd9660/cd9660_vfsops.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: cd9660_vfsops.c,v 1.46 2007/06/08 05:35:32 deraadt Exp $ */
2: /* $NetBSD: cd9660_vfsops.c,v 1.26 1997/06/13 15:38:58 pk Exp $ */
3:
4: /*-
5: * Copyright (c) 1994
6: * The Regents of the University of California. All rights reserved.
7: *
8: * This code is derived from software contributed to Berkeley
9: * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
10: * Support code is derived from software contributed to Berkeley
11: * by Atsushi Murai (amurai@spec.co.jp).
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. Neither the name of the University nor the names of its contributors
22: * may be used to endorse or promote products derived from this software
23: * without specific prior written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35: * SUCH DAMAGE.
36: *
37: * @(#)cd9660_vfsops.c 8.9 (Berkeley) 12/5/94
38: */
39:
40: #include <sys/param.h>
41: #include <sys/systm.h>
42: #include <sys/namei.h>
43: #include <sys/proc.h>
44: #include <sys/kernel.h>
45: #include <sys/vnode.h>
46: #include <miscfs/specfs/specdev.h>
47: #include <sys/mount.h>
48: #include <sys/buf.h>
49: #include <sys/file.h>
50: #include <sys/disklabel.h>
51: #include <sys/ioctl.h>
52: #include <sys/cdio.h>
53: #include <sys/conf.h>
54: #include <sys/errno.h>
55: #include <sys/malloc.h>
56: #include <sys/stat.h>
57:
58: #include <isofs/cd9660/iso.h>
59: #include <isofs/cd9660/cd9660_extern.h>
60: #include <isofs/cd9660/iso_rrip.h>
61: #include <isofs/cd9660/cd9660_node.h>
62:
63: const struct vfsops cd9660_vfsops = {
64: cd9660_mount,
65: cd9660_start,
66: cd9660_unmount,
67: cd9660_root,
68: cd9660_quotactl,
69: cd9660_statfs,
70: cd9660_sync,
71: cd9660_vget,
72: cd9660_fhtovp,
73: cd9660_vptofh,
74: cd9660_init,
75: cd9660_sysctl,
76: cd9660_check_export
77: };
78:
79: /*
80: * Called by vfs_mountroot when iso is going to be mounted as root.
81: */
82:
83: static int iso_mountfs(struct vnode *devvp, struct mount *mp,
84: struct proc *p, struct iso_args *argp);
85: int iso_disklabelspoof(dev_t dev, void (*strat)(struct buf *),
86: struct disklabel *lp);
87:
88: int
89: cd9660_mountroot()
90: {
91: struct mount *mp;
92: extern struct vnode *rootvp;
93: struct proc *p = curproc; /* XXX */
94: int error;
95: struct iso_args args;
96:
97: /*
98: * Get vnodes for swapdev and rootdev.
99: */
100: if ((error = bdevvp(swapdev, &swapdev_vp)) ||
101: (error = bdevvp(rootdev, &rootvp))) {
102: printf("cd9660_mountroot: can't setup bdevvp's");
103: return (error);
104: }
105:
106: if ((error = vfs_rootmountalloc("cd9660", "root_device", &mp)) != 0)
107: return (error);
108: args.flags = ISOFSMNT_ROOT;
109: if ((error = iso_mountfs(rootvp, mp, p, &args)) != 0) {
110: mp->mnt_vfc->vfc_refcount--;
111: vfs_unbusy(mp);
112: free(mp, M_MOUNT);
113: return (error);
114: }
115:
116: CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
117: (void)cd9660_statfs(mp, &mp->mnt_stat, p);
118: vfs_unbusy(mp);
119: inittodr(0);
120:
121: return (0);
122: }
123:
124: /*
125: * VFS Operations.
126: *
127: * mount system call
128: */
129: int
130: cd9660_mount(mp, path, data, ndp, p)
131: register struct mount *mp;
132: const char *path;
133: void *data;
134: struct nameidata *ndp;
135: struct proc *p;
136: {
137: struct vnode *devvp;
138: struct iso_args args;
139: size_t size;
140: int error;
141: struct iso_mnt *imp = NULL;
142:
143: error = copyin(data, &args, sizeof (struct iso_args));
144: if (error)
145: return (error);
146:
147: if ((mp->mnt_flag & MNT_RDONLY) == 0)
148: return (EROFS);
149:
150: /*
151: * If updating, check whether changing from read-only to
152: * read/write; if there is no device name, that's all we do.
153: */
154: if (mp->mnt_flag & MNT_UPDATE) {
155: imp = VFSTOISOFS(mp);
156: if (args.fspec == 0)
157: return (vfs_export(mp, &imp->im_export,
158: &args.export_info));
159: }
160: /*
161: * Not an update, or updating the name: look up the name
162: * and verify that it refers to a sensible block device.
163: */
164: NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
165: if ((error = namei(ndp)) != 0)
166: return (error);
167: devvp = ndp->ni_vp;
168:
169: if (devvp->v_type != VBLK) {
170: vrele(devvp);
171: return (ENOTBLK);
172: }
173: if (major(devvp->v_rdev) >= nblkdev) {
174: vrele(devvp);
175: return (ENXIO);
176: }
177: /*
178: * If mount by non-root, then verify that user has necessary
179: * permissions on the device.
180: */
181: if (p->p_ucred->cr_uid != 0) {
182: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
183: error = VOP_ACCESS(devvp, VREAD, p->p_ucred, p);
184: if (error) {
185: vput(devvp);
186: return (error);
187: }
188: VOP_UNLOCK(devvp, 0, p);
189: }
190: if ((mp->mnt_flag & MNT_UPDATE) == 0)
191: error = iso_mountfs(devvp, mp, p, &args);
192: else {
193: if (devvp != imp->im_devvp)
194: error = EINVAL; /* needs translation */
195: else
196: vrele(devvp);
197: }
198: if (error) {
199: vrele(devvp);
200: return (error);
201: }
202: imp = VFSTOISOFS(mp);
203: (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
204: bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
205: (void)copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
206: &size);
207: bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
208: bcopy(&args, &mp->mnt_stat.mount_info.iso_args, sizeof(args));
209: (void)cd9660_statfs(mp, &mp->mnt_stat, p);
210: return (0);
211: }
212:
213: /*
214: * Common code for mount and mountroot
215: */
216: static int
217: iso_mountfs(devvp, mp, p, argp)
218: register struct vnode *devvp;
219: struct mount *mp;
220: struct proc *p;
221: struct iso_args *argp;
222: {
223: register struct iso_mnt *isomp = (struct iso_mnt *)0;
224: struct buf *bp = NULL;
225: struct buf *pribp = NULL, *supbp = NULL;
226: dev_t dev = devvp->v_rdev;
227: int error = EINVAL;
228: int needclose = 0;
229: int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
230: extern struct vnode *rootvp;
231: int iso_bsize;
232: int iso_blknum;
233: int joliet_level;
234: struct iso_volume_descriptor *vdp;
235: struct iso_primary_descriptor *pri = NULL;
236: struct iso_supplementary_descriptor *sup = NULL;
237: struct iso_directory_record *rootp;
238: int logical_block_size;
239: int sess;
240:
241: if (!ronly)
242: return (EROFS);
243:
244: /*
245: * Disallow multiple mounts of the same device.
246: * Disallow mounting of a device that is currently in use
247: * (except for root, which might share swap device for miniroot).
248: * Flush out any old buffers remaining from a previous use.
249: */
250: if ((error = vfs_mountedon(devvp)) != 0)
251: return (error);
252: if (vcount(devvp) > 1 && devvp != rootvp)
253: return (EBUSY);
254: if ((error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
255: return (error);
256:
257: error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
258: if (error)
259: return (error);
260: needclose = 1;
261:
262: /*
263: * This is the "logical sector size". The standard says this
264: * should be 2048 or the physical sector size on the device,
265: * whichever is greater. For now, we'll just use a constant.
266: */
267: iso_bsize = ISO_DEFAULT_BLOCK_SIZE;
268:
269: if (argp->flags & ISOFSMNT_SESS) {
270: sess = argp->sess;
271: if (sess < 0)
272: sess = 0;
273: } else {
274: sess = 0;
275: error = VOP_IOCTL(devvp, CDIOREADMSADDR, (caddr_t)&sess, 0,
276: FSCRED, p);
277: if (error)
278: sess = 0;
279: }
280:
281: joliet_level = 0;
282: for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
283: if ((error = bread(devvp,
284: (iso_blknum + sess) * btodb(iso_bsize),
285: iso_bsize, NOCRED, &bp)) != 0)
286: goto out;
287:
288: vdp = (struct iso_volume_descriptor *)bp->b_data;
289: if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0) {
290: error = EINVAL;
291: goto out;
292: }
293:
294: switch (isonum_711 (vdp->type)){
295: case ISO_VD_PRIMARY:
296: if (pribp == NULL) {
297: pribp = bp;
298: bp = NULL;
299: pri = (struct iso_primary_descriptor *)vdp;
300: }
301: break;
302: case ISO_VD_SUPPLEMENTARY:
303: if (supbp == NULL) {
304: supbp = bp;
305: bp = NULL;
306: sup = (struct iso_supplementary_descriptor *)vdp;
307:
308: if (!(argp->flags & ISOFSMNT_NOJOLIET)) {
309: if (bcmp(sup->escape, "%/@", 3) == 0)
310: joliet_level = 1;
311: if (bcmp(sup->escape, "%/C", 3) == 0)
312: joliet_level = 2;
313: if (bcmp(sup->escape, "%/E", 3) == 0)
314: joliet_level = 3;
315:
316: if (isonum_711 (sup->flags) & 1)
317: joliet_level = 0;
318: }
319: }
320: break;
321:
322: case ISO_VD_END:
323: goto vd_end;
324:
325: default:
326: break;
327: }
328: if (bp) {
329: brelse(bp);
330: bp = NULL;
331: }
332: }
333: vd_end:
334: if (bp) {
335: brelse(bp);
336: bp = NULL;
337: }
338:
339: if (pri == NULL) {
340: error = EINVAL;
341: goto out;
342: }
343:
344: logical_block_size = isonum_723 (pri->logical_block_size);
345:
346: if (logical_block_size < DEV_BSIZE || logical_block_size > MAXBSIZE
347: || (logical_block_size & (logical_block_size - 1)) != 0) {
348: error = EINVAL;
349: goto out;
350: }
351:
352: rootp = (struct iso_directory_record *)pri->root_directory_record;
353:
354: isomp = malloc(sizeof *isomp, M_ISOFSMNT, M_WAITOK);
355: bzero((caddr_t)isomp, sizeof *isomp);
356: isomp->logical_block_size = logical_block_size;
357: isomp->volume_space_size = isonum_733 (pri->volume_space_size);
358: bcopy (rootp, isomp->root, sizeof isomp->root);
359: isomp->root_extent = isonum_733 (rootp->extent);
360: isomp->root_size = isonum_733 (rootp->size);
361: isomp->joliet_level = 0;
362: /*
363: * Since an ISO9660 multi-session CD can also access previous sessions,
364: * we have to include them into the space considerations.
365: */
366: isomp->volume_space_size += sess;
367: isomp->im_bmask = logical_block_size - 1;
368: isomp->im_bshift = ffs(logical_block_size) - 1;
369:
370: pribp->b_flags |= B_AGE;
371: brelse(pribp);
372: pribp = NULL;
373:
374: mp->mnt_data = (qaddr_t)isomp;
375: mp->mnt_stat.f_fsid.val[0] = (long)dev;
376: mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
377: mp->mnt_maxsymlinklen = 0;
378: mp->mnt_flag |= MNT_LOCAL;
379: isomp->im_mountp = mp;
380: isomp->im_dev = dev;
381: isomp->im_devvp = devvp;
382:
383: /* Check the Rock Ridge Extension support */
384: if (!(argp->flags & ISOFSMNT_NORRIP)) {
385: if ((error = bread(isomp->im_devvp, (isomp->root_extent +
386: isonum_711(rootp->ext_attr_length)) <<
387: (isomp->im_bshift - DEV_BSHIFT),
388: isomp->logical_block_size, NOCRED, &bp)) != 0)
389: goto out;
390:
391: rootp = (struct iso_directory_record *)bp->b_data;
392:
393: if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) {
394: argp->flags |= ISOFSMNT_NORRIP;
395: } else {
396: argp->flags &= ~ISOFSMNT_GENS;
397: }
398:
399: /*
400: * The contents are valid,
401: * but they will get reread as part of another vnode, so...
402: */
403: bp->b_flags |= B_AGE;
404: brelse(bp);
405: bp = NULL;
406: }
407: isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS |
408: ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET);
409: switch (isomp->im_flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS)) {
410: default:
411: isomp->iso_ftype = ISO_FTYPE_DEFAULT;
412: break;
413: case ISOFSMNT_GENS|ISOFSMNT_NORRIP:
414: isomp->iso_ftype = ISO_FTYPE_9660;
415: break;
416: case 0:
417: isomp->iso_ftype = ISO_FTYPE_RRIP;
418: break;
419: }
420:
421: /* Decide whether to use the Joliet descriptor */
422:
423: if (isomp->iso_ftype != ISO_FTYPE_RRIP && joliet_level) {
424: rootp = (struct iso_directory_record *)
425: sup->root_directory_record;
426: bcopy(rootp, isomp->root, sizeof isomp->root);
427: isomp->root_extent = isonum_733(rootp->extent);
428: isomp->root_size = isonum_733(rootp->size);
429: isomp->joliet_level = joliet_level;
430: supbp->b_flags |= B_AGE;
431: }
432:
433: if (supbp) {
434: brelse(supbp);
435: supbp = NULL;
436: }
437:
438: devvp->v_specmountpoint = mp;
439:
440: return (0);
441: out:
442: if (bp)
443: brelse(bp);
444: if (supbp)
445: brelse(supbp);
446: if (needclose)
447: (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED,
448: p);
449: if (isomp) {
450: free((caddr_t)isomp, M_ISOFSMNT);
451: mp->mnt_data = (qaddr_t)0;
452: }
453: return (error);
454: }
455:
456: /*
457: * Test to see if the device is an ISOFS filesystem.
458: */
459: int
460: iso_disklabelspoof(dev, strat, lp)
461: dev_t dev;
462: void (*strat)(struct buf *);
463: register struct disklabel *lp;
464: {
465: struct buf *bp = NULL;
466: struct iso_volume_descriptor *vdp;
467: struct iso_primary_descriptor *pri;
468: int logical_block_size;
469: int error = EINVAL;
470: int iso_blknum;
471: int i;
472:
473: bp = geteblk(ISO_DEFAULT_BLOCK_SIZE);
474: bp->b_dev = dev;
475:
476: for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
477: bp->b_blkno = iso_blknum * btodb(ISO_DEFAULT_BLOCK_SIZE);
478: bp->b_bcount = ISO_DEFAULT_BLOCK_SIZE;
479: bp->b_flags = B_BUSY | B_READ;
480: bp->b_cylinder = bp->b_blkno / lp->d_secpercyl;
481:
482: /*printf("d_secsize %d iso_blknum %d b_blkno %d bcount %d\n",
483: lp->d_secsize, iso_blknum, bp->b_blkno, bp->b_bcount);*/
484:
485: (*strat)(bp);
486:
487: if (biowait(bp))
488: goto out;
489:
490: vdp = (struct iso_volume_descriptor *)bp->b_data;
491: /*printf("%2x%2x%2x type %2x\n", vdp->id[0], vdp->id[1],
492: vdp->id[2], isonum_711(vdp->type));*/
493: if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0 ||
494: isonum_711 (vdp->type) == ISO_VD_END)
495: goto out;
496:
497: if (isonum_711 (vdp->type) == ISO_VD_PRIMARY)
498: break;
499: }
500:
501: if (isonum_711 (vdp->type) != ISO_VD_PRIMARY)
502: goto out;
503:
504: pri = (struct iso_primary_descriptor *)vdp;
505: logical_block_size = isonum_723 (pri->logical_block_size);
506: if (logical_block_size < DEV_BSIZE || logical_block_size > MAXBSIZE ||
507: (logical_block_size & (logical_block_size - 1)) != 0)
508: goto out;
509:
510: /*
511: * build a disklabel for the CD
512: */
513: strncpy(lp->d_typename, pri->volume_id, sizeof lp->d_typename);
514: strncpy(lp->d_packname, pri->volume_id+16, sizeof lp->d_packname);
515: for (i = 0; i < MAXPARTITIONS; i++) {
516: DL_SETPSIZE(&lp->d_partitions[i], 0);
517: DL_SETPOFFSET(&lp->d_partitions[i], 0);
518: }
519: DL_SETPOFFSET(&lp->d_partitions[0], 0);
520: DL_SETPSIZE(&lp->d_partitions[0], DL_GETDSIZE(lp));
521: lp->d_partitions[0].p_fstype = FS_ISO9660;
522: DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
523: DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp));
524: lp->d_partitions[RAW_PART].p_fstype = FS_ISO9660;
525: lp->d_npartitions = RAW_PART + 1;
526: lp->d_bbsize = 8192; /* fake */
527: lp->d_sbsize = 64*1024; /* fake */
528: lp->d_version = 1;
529:
530: lp->d_magic = DISKMAGIC;
531: lp->d_magic2 = DISKMAGIC;
532: lp->d_checksum = dkcksum(lp);
533: error = 0;
534: out:
535: bp->b_flags |= B_INVAL;
536: brelse(bp);
537: return (error);
538: }
539:
540: /*
541: * Make a filesystem operational.
542: * Nothing to do at the moment.
543: */
544: /* ARGSUSED */
545: int
546: cd9660_start(mp, flags, p)
547: struct mount *mp;
548: int flags;
549: struct proc *p;
550: {
551: return (0);
552: }
553:
554: /*
555: * unmount system call
556: */
557: int
558: cd9660_unmount(mp, mntflags, p)
559: struct mount *mp;
560: int mntflags;
561: struct proc *p;
562: {
563: register struct iso_mnt *isomp;
564: int error, flags = 0;
565:
566: if (mntflags & MNT_FORCE)
567: flags |= FORCECLOSE;
568: #if 0
569: mntflushbuf(mp, 0);
570: if (mntinvalbuf(mp))
571: return (EBUSY);
572: #endif
573: if ((error = vflush(mp, NULLVP, flags)) != 0)
574: return (error);
575:
576: isomp = VFSTOISOFS(mp);
577:
578: #ifdef ISODEVMAP
579: if (isomp->iso_ftype == ISO_FTYPE_RRIP)
580: iso_dunmap(isomp->im_dev);
581: #endif
582:
583: isomp->im_devvp->v_specmountpoint = NULL;
584: error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, p);
585: vrele(isomp->im_devvp);
586: free((caddr_t)isomp, M_ISOFSMNT);
587: mp->mnt_data = (qaddr_t)0;
588: mp->mnt_flag &= ~MNT_LOCAL;
589: return (error);
590: }
591:
592: /*
593: * Return root of a filesystem
594: */
595: int
596: cd9660_root(mp, vpp)
597: struct mount *mp;
598: struct vnode **vpp;
599: {
600: struct iso_mnt *imp = VFSTOISOFS(mp);
601: struct iso_directory_record *dp =
602: (struct iso_directory_record *)imp->root;
603: ino_t ino = isodirino(dp, imp);
604:
605: /*
606: * With RRIP we must use the `.' entry of the root directory.
607: * Simply tell vget, that it's a relocated directory.
608: */
609: return (cd9660_vget_internal(mp, ino, vpp,
610: imp->iso_ftype == ISO_FTYPE_RRIP, dp));
611: }
612:
613: /*
614: * Do operations associated with quotas, not supported
615: */
616: /* ARGSUSED */
617: int
618: cd9660_quotactl(mp, cmd, uid, arg, p)
619: struct mount *mp;
620: int cmd;
621: uid_t uid;
622: caddr_t arg;
623: struct proc *p;
624: {
625:
626: return (EOPNOTSUPP);
627: }
628:
629: /*
630: * Get file system statistics.
631: */
632: int
633: cd9660_statfs(mp, sbp, p)
634: struct mount *mp;
635: register struct statfs *sbp;
636: struct proc *p;
637: {
638: register struct iso_mnt *isomp;
639:
640: isomp = VFSTOISOFS(mp);
641:
642: sbp->f_bsize = isomp->logical_block_size;
643: sbp->f_iosize = sbp->f_bsize; /* XXX */
644: sbp->f_blocks = isomp->volume_space_size;
645: sbp->f_bfree = 0; /* total free blocks */
646: sbp->f_bavail = 0; /* blocks free for non superuser */
647: sbp->f_files = 0; /* total files */
648: sbp->f_ffree = 0; /* free file nodes */
649: if (sbp != &mp->mnt_stat) {
650: bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
651: bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname,
652: MNAMELEN);
653: bcopy(&mp->mnt_stat.mount_info.iso_args,
654: &sbp->mount_info.iso_args, sizeof(struct iso_args));
655: }
656: /* Use the first spare for flags: */
657: sbp->f_spare[0] = isomp->im_flags;
658: return (0);
659: }
660:
661: /* ARGSUSED */
662: int
663: cd9660_sync(mp, waitfor, cred, p)
664: struct mount *mp;
665: int waitfor;
666: struct ucred *cred;
667: struct proc *p;
668: {
669: return (0);
670: }
671:
672: /*
673: * File handle to vnode
674: *
675: * Have to be really careful about stale file handles:
676: * - check that the inode number is in range
677: * - call iget() to get the locked inode
678: * - check for an unallocated inode (i_mode == 0)
679: * - check that the generation number matches
680: */
681:
682: struct ifid {
683: ushort ifid_len;
684: ushort ifid_pad;
685: int ifid_ino;
686: long ifid_start;
687: };
688:
689: /* ARGSUSED */
690: int
691: cd9660_fhtovp(mp, fhp, vpp)
692: register struct mount *mp;
693: struct fid *fhp;
694: struct vnode **vpp;
695: {
696: struct ifid *ifhp = (struct ifid *)fhp;
697: register struct iso_node *ip;
698: struct vnode *nvp;
699: int error;
700:
701: #ifdef ISOFS_DBG
702: printf("fhtovp: ino %d, start %ld\n", ifhp->ifid_ino,
703: ifhp->ifid_start);
704: #endif
705:
706: if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) {
707: *vpp = NULLVP;
708: return (error);
709: }
710: ip = VTOI(nvp);
711: if (ip->inode.iso_mode == 0) {
712: vput(nvp);
713: *vpp = NULLVP;
714: return (ESTALE);
715: }
716: *vpp = nvp;
717: return (0);
718: }
719:
720: int
721: cd9660_vget(mp, ino, vpp)
722: struct mount *mp;
723: ino_t ino;
724: struct vnode **vpp;
725: {
726:
727: /*
728: * XXXX
729: * It would be nice if we didn't always set the `relocated' flag
730: * and force the extra read, but I don't want to think about fixing
731: * that right now.
732: */
733: return (cd9660_vget_internal(mp, ino, vpp,
734: #if 0
735: VFSTOISOFS(mp)->iso_ftype == ISO_FTYPE_RRIP,
736: #else
737: 0,
738: #endif
739: NULL));
740: }
741:
742: int
743: cd9660_vget_internal(mp, ino, vpp, relocated, isodir)
744: struct mount *mp;
745: ino_t ino;
746: struct vnode **vpp;
747: int relocated;
748: struct iso_directory_record *isodir;
749: {
750: register struct iso_mnt *imp;
751: struct iso_node *ip;
752: struct buf *bp;
753: struct vnode *vp, *nvp;
754: dev_t dev;
755: int error;
756:
757: retry:
758: imp = VFSTOISOFS(mp);
759: dev = imp->im_dev;
760: if ((*vpp = cd9660_ihashget(dev, ino)) != NULLVP)
761: return (0);
762:
763: /* Allocate a new vnode/iso_node. */
764: if ((error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp)) != 0) {
765: *vpp = NULLVP;
766: return (error);
767: }
768: MALLOC(ip, struct iso_node *, sizeof(struct iso_node), M_ISOFSNODE,
769: M_WAITOK);
770: bzero((caddr_t)ip, sizeof(struct iso_node));
771: lockinit(&ip->i_lock, PINOD, "isoinode", 0, 0);
772: vp->v_data = ip;
773: ip->i_vnode = vp;
774: ip->i_dev = dev;
775: ip->i_number = ino;
776:
777: /*
778: * Put it onto its hash chain and lock it so that other requests for
779: * this inode will block if they arrive while we are sleeping waiting
780: * for old data structures to be purged or for the contents of the
781: * disk portion of this inode to be read.
782: */
783: error = cd9660_ihashins(ip);
784:
785: if (error) {
786: vrele(vp);
787:
788: if (error == EEXIST)
789: goto retry;
790:
791: return (error);
792: }
793:
794: if (isodir == 0) {
795: int lbn, off;
796:
797: lbn = lblkno(imp, ino);
798: if (lbn >= imp->volume_space_size) {
799: vput(vp);
800: printf("fhtovp: lbn exceed volume space %d\n", lbn);
801: return (ESTALE);
802: }
803:
804: off = blkoff(imp, ino);
805: if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size)
806: {
807: vput(vp);
808: printf("fhtovp: crosses block boundary %d\n",
809: off + ISO_DIRECTORY_RECORD_SIZE);
810: return (ESTALE);
811: }
812:
813: error = bread(imp->im_devvp,
814: lbn << (imp->im_bshift - DEV_BSHIFT),
815: imp->logical_block_size, NOCRED, &bp);
816: if (error) {
817: vput(vp);
818: brelse(bp);
819: printf("fhtovp: bread error %d\n",error);
820: return (error);
821: }
822: isodir = (struct iso_directory_record *)(bp->b_data + off);
823:
824: if (off + isonum_711(isodir->length) >
825: imp->logical_block_size) {
826: vput(vp);
827: if (bp != 0)
828: brelse(bp);
829: printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
830: off +isonum_711(isodir->length), off,
831: isonum_711(isodir->length));
832: return (ESTALE);
833: }
834:
835: #if 0
836: if (isonum_733(isodir->extent) +
837: isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {
838: if (bp != 0)
839: brelse(bp);
840: printf("fhtovp: file start miss %d vs %d\n",
841: isonum_733(isodir->extent) +
842: isonum_711(isodir->ext_attr_length),
843: ifhp->ifid_start);
844: return (ESTALE);
845: }
846: #endif
847: } else
848: bp = 0;
849:
850: ip->i_mnt = imp;
851: ip->i_devvp = imp->im_devvp;
852: VREF(ip->i_devvp);
853:
854: if (relocated) {
855: /*
856: * On relocated directories we must
857: * read the `.' entry out of a dir.
858: */
859: ip->iso_start = ino >> imp->im_bshift;
860: if (bp != 0)
861: brelse(bp);
862: if ((error = cd9660_bufatoff(ip, (off_t)0, NULL, &bp)) != 0) {
863: vput(vp);
864: return (error);
865: }
866: isodir = (struct iso_directory_record *)bp->b_data;
867: }
868:
869: ip->iso_extent = isonum_733(isodir->extent);
870: ip->i_size = (u_int32_t) isonum_733(isodir->size);
871: ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
872:
873: /*
874: * Setup time stamp, attribute
875: */
876: vp->v_type = VNON;
877: switch (imp->iso_ftype) {
878: default: /* ISO_FTYPE_9660 */
879: {
880: struct buf *bp2;
881: int off;
882: if ((imp->im_flags & ISOFSMNT_EXTATT) &&
883: (off = isonum_711(isodir->ext_attr_length)))
884: cd9660_bufatoff(ip, (off_t)-(off << imp->im_bshift),
885: NULL, &bp2);
886: else
887: bp2 = NULL;
888: cd9660_defattr(isodir, ip, bp2);
889: cd9660_deftstamp(isodir, ip, bp2);
890: if (bp2)
891: brelse(bp2);
892: break;
893: }
894: case ISO_FTYPE_RRIP:
895: cd9660_rrip_analyze(isodir, ip, imp);
896: break;
897: }
898:
899: if (bp != 0)
900: brelse(bp);
901:
902: /*
903: * Initialize the associated vnode
904: */
905: switch (vp->v_type = IFTOVT(ip->inode.iso_mode)) {
906: case VFIFO:
907: #ifdef FIFO
908: vp->v_op = cd9660_fifoop_p;
909: break;
910: #else
911: vput(vp);
912: return (EOPNOTSUPP);
913: #endif /* FIFO */
914: case VCHR:
915: case VBLK:
916: /*
917: * if device, look at device number table for translation
918: */
919: #ifdef ISODEVMAP
920: if (dp = iso_dmap(dev, ino, 0))
921: ip->inode.iso_rdev = dp->d_dev;
922: #endif
923: vp->v_op = cd9660_specop_p;
924: if ((nvp = checkalias(vp, ip->inode.iso_rdev, mp)) != NULL) {
925: /*
926: * Discard unneeded vnode, but save its iso_node.
927: * Note that the lock is carried over in the iso_node
928: */
929: nvp->v_data = vp->v_data;
930: vp->v_data = NULL;
931: vp->v_op = spec_vnodeop_p;
932: vrele(vp);
933: vgone(vp);
934: /*
935: * Reinitialize aliased inode.
936: */
937: vp = nvp;
938: ip->i_vnode = vp;
939: }
940: break;
941: case VLNK:
942: case VNON:
943: case VSOCK:
944: case VDIR:
945: case VBAD:
946: break;
947: case VREG:
948: uvm_vnp_setsize(vp, ip->i_size);
949: break;
950: }
951:
952: if (ip->iso_extent == imp->root_extent)
953: vp->v_flag |= VROOT;
954:
955: /*
956: * XXX need generation number?
957: */
958:
959: *vpp = vp;
960: return (0);
961: }
962:
963: /*
964: * Vnode pointer to File handle
965: */
966: /* ARGSUSED */
967: int
968: cd9660_vptofh(vp, fhp)
969: struct vnode *vp;
970: struct fid *fhp;
971: {
972: register struct iso_node *ip = VTOI(vp);
973: register struct ifid *ifhp;
974:
975: ifhp = (struct ifid *)fhp;
976: ifhp->ifid_len = sizeof(struct ifid);
977:
978: ifhp->ifid_ino = ip->i_number;
979: ifhp->ifid_start = ip->iso_start;
980:
981: #ifdef ISOFS_DBG
982: printf("vptofh: ino %d, start %ld\n",
983: ifhp->ifid_ino,ifhp->ifid_start);
984: #endif
985: return (0);
986: }
987:
988: /*
989: * Verify a remote client has export rights and return these rights via
990: * exflagsp and credanonp.
991: */
992: int
993: cd9660_check_export(mp, nam, exflagsp, credanonp)
994: register struct mount *mp;
995: struct mbuf *nam;
996: int *exflagsp;
997: struct ucred **credanonp;
998: {
999: register struct netcred *np;
1000: register struct iso_mnt *imp = VFSTOISOFS(mp);
1001:
1002: /*
1003: * Get the export permission structure for this <mp, client> tuple.
1004: */
1005: np = vfs_export_lookup(mp, &imp->im_export, nam);
1006: if (np == NULL)
1007: return (EACCES);
1008:
1009: *exflagsp = np->netc_exflags;
1010: *credanonp = &np->netc_anon;
1011: return (0);
1012: }
CVSweb