|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* $NetBSD: cd9660_vfsops.c,v 1.18 1995/03/09 12:05:36 mycroft Exp $ */
26:
27: /*-
28: * Copyright (c) 1994
29: * The Regents of the University of California. All rights reserved.
30: *
31: * This code is derived from software contributed to Berkeley
32: * by Pace Willisson ([email protected]). The Rock Ridge Extension
33: * Support code is derived from software contributed to Berkeley
34: * by Atsushi Murai ([email protected]).
35: *
36: * Redistribution and use in source and binary forms, with or without
37: * modification, are permitted provided that the following conditions
38: * are met:
39: * 1. Redistributions of source code must retain the above copyright
40: * notice, this list of conditions and the following disclaimer.
41: * 2. Redistributions in binary form must reproduce the above copyright
42: * notice, this list of conditions and the following disclaimer in the
43: * documentation and/or other materials provided with the distribution.
44: * 3. All advertising materials mentioning features or use of this software
45: * must display the following acknowledgement:
46: * This product includes software developed by the University of
47: * California, Berkeley and its contributors.
48: * 4. Neither the name of the University nor the names of its contributors
49: * may be used to endorse or promote products derived from this software
50: * without specific prior written permission.
51: *
52: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62: * SUCH DAMAGE.
63: *
64: * @(#)cd9660_vfsops.c 8.9 (Berkeley) 12/5/94
65: */
66:
67: #include <sys/param.h>
68: #include <sys/systm.h>
69: #include <sys/namei.h>
70: #include <sys/proc.h>
71: #include <sys/kernel.h>
72: #include <sys/vnode.h>
73: #include <miscfs/specfs/specdev.h>
74: #include <sys/mount.h>
75: #include <sys/buf.h>
76: #include <sys/file.h>
77: #include <sys/disklabel.h>
78: #include <sys/ioctl.h>
79: #include <sys/errno.h>
80: #include <sys/malloc.h>
81: #include <sys/stat.h>
82:
83: #include <isofs/cd9660/iso.h>
84: #include <isofs/cd9660/iso_rrip.h>
85: #include <isofs/cd9660/cd9660_node.h>
86: #include <isofs/cd9660/cd9660_mount.h>
87:
88: extern int enodev ();
89:
90: struct vfsops cd9660_vfsops = {
91: cd9660_mount,
92: cd9660_start,
93: cd9660_unmount,
94: cd9660_root,
95: cd9660_quotactl,
96: cd9660_statfs,
97: cd9660_sync,
98: cd9660_vget,
99: cd9660_fhtovp,
100: cd9660_vptofh,
101: cd9660_init,
102: cd9660_sysctl
103: };
104:
105: /*
106: * Called by vfs_mountroot when iso is going to be mounted as root.
107: *
108: * Name is updated by mount(8) after booting.
109: */
110: #define ROOTNAME "root_device"
111:
112: static int iso_mountfs __P((struct vnode *devvp, struct mount *mp,
113: struct proc *p, struct iso_args *argp));
114: static void DRGetTypeCreatorAndFlags( struct iso_mnt * theMountPointPtr,
115: struct iso_directory_record * theDirRecPtr,
116: u_int32_t * theTypePtr,
117: u_int32_t * theCreatorPtr,
118: u_int16_t * theFlagsPtr );
119:
120: int cd9660_vget_internal( struct mount *mp,
121: ino_t ino,
122: struct vnode **vpp,
123: int relocated,
124: struct iso_directory_record *isodir,
125: struct proc *p );
126:
127:
128: int
129: cd9660_mountroot()
130: {
131: register struct mount *mp;
132: extern struct vnode *rootvp;
133: struct proc *p = current_proc(); /* XXX */
134: struct iso_mnt *imp;
135: size_t size;
136: int error;
137: struct iso_args args;
138:
139:
140: /*
141: * Get vnodes for swapdev and rootdev.
142: */
143: #if 0
144: if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp))
145: panic("cd9660_mountroot: can't setup bdevvp's");
146: #else
147: if ( bdevvp(rootdev, &rootvp))
148: panic("cd9660_mountroot: can't setup bdevvp's");
149:
150: #endif
151:
152: MALLOC_ZONE(mp, struct mount *,
153: sizeof(struct mount), M_MOUNT, M_WAITOK);
154: bzero((char *)mp, (u_long)sizeof(struct mount));
155: mp->mnt_op = &cd9660_vfsops;
156: mp->mnt_flag = MNT_RDONLY;
157: LIST_INIT(&mp->mnt_vnodelist);
158: args.flags = ISOFSMNT_ROOT;
159: if ((error = iso_mountfs(rootvp, mp, p, &args))) {
160: FREE_ZONE(mp, sizeof (struct mount), M_MOUNT);
161: return (error);
162: }
163: simple_lock(&mountlist_slock);
164: #if 0
165: if (error = VFS_LOCK(mp)) {
166: (void)cd9660_unmount(mp, 0, p);
167: FREE_ZONE(mp, sizeof (struct mount), M_MOUNT);
168: return (error);
169: }
170: #endif
171: CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
172: simple_unlock(&mountlist_slock);
173: mp->mnt_vnodecovered = NULLVP;
174: imp = VFSTOISOFS(mp);
175: (void) copystr("/", mp->mnt_stat.f_mntonname, MNAMELEN - 1,
176: &size);
177: bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
178: (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
179: &size);
180: bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
181: (void)cd9660_statfs(mp, &mp->mnt_stat, p);
182: // VFS_UNLOCK(mp);
183: return (0);
184: }
185:
186: /*
187: * VFS Operations.
188: *
189: * mount system call
190: */
191: int
192: cd9660_mount(mp, path, data, ndp, p)
193: register struct mount *mp;
194: char *path;
195: caddr_t data;
196: struct nameidata *ndp;
197: struct proc *p;
198: {
199: struct vnode *devvp;
200: struct iso_args args;
201: size_t size;
202: int error;
203: struct iso_mnt *imp;
204:
205: if ( (error = copyin(data, (caddr_t)&args, sizeof (struct iso_args))) )
206: return (error);
207:
208: if ((mp->mnt_flag & MNT_RDONLY) == 0)
209: return (EROFS);
210:
211: imp = VFSTOISOFS(mp); /* set up imp before use. */
212:
213: /*
214: * If updating, check whether changing from read-only to
215: * read/write; if there is no device name, that's all we do.
216: */
217: if (mp->mnt_flag & MNT_UPDATE) {
218: if (args.fspec == 0)
219: return (vfs_export(mp, &imp->im_export, &args.export));
220: }
221: /*
222: * Not an update, or updating the name: look up the name
223: * and verify that it refers to a sensible block device.
224: */
225: NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
226: if ( (error = namei(ndp)) )
227: return (error);
228: devvp = ndp->ni_vp;
229:
230: if (devvp->v_type != VBLK) {
231: vrele(devvp);
232: return ENOTBLK;
233: }
234: if (major(devvp->v_rdev) >= nblkdev) {
235: vrele(devvp);
236: return ENXIO;
237: }
238: if ((mp->mnt_flag & MNT_UPDATE) == 0)
239: error = iso_mountfs(devvp, mp, p, &args);
240: else {
241: if (devvp != imp->im_devvp)
242: error = EINVAL; /* needs translation */
243: else
244: vrele(devvp);
245: }
246: if (error) {
247: vrele(devvp);
248: return error;
249: }
250:
251: /* Set the mount flag to indicate that we support volfs */
252: mp->mnt_flag |= MNT_DOVOLFS;
253:
254: (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
255: bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
256: (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
257: &size);
258: bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
259: return 0;
260: }
261:
262: /*
263: * Common code for mount and mountroot
264: */
265: static int
266: iso_mountfs(devvp, mp, p, argp)
267: register struct vnode *devvp;
268: struct mount *mp;
269: struct proc *p;
270: struct iso_args *argp;
271: {
272: register struct iso_mnt *isomp = (struct iso_mnt *)0;
273: struct buf *bp = NULL;
274: dev_t dev = devvp->v_rdev;
275: int error = EINVAL;
276: int needclose = 0;
277: int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
278: extern struct vnode *rootvp;
279: int iso_bsize;
280: int iso_blknum;
281: struct iso_volume_descriptor *vdp;
282: struct iso_primary_descriptor *pri;
283: struct iso_directory_record *rootp;
284: int logical_block_size;
285:
286: if (!ronly)
287: return EROFS;
288:
289: /*
290: * Disallow multiple mounts of the same device.
291: * Disallow mounting of a device that is currently in use
292: * (except for root, which might share swap device for miniroot).
293: * Flush out any old buffers remaining from a previous use.
294: */
295: if ( (error = vfs_mountedon(devvp)) )
296: return error;
297: if (vcount(devvp) > 1 && devvp != rootvp)
298: return EBUSY;
299: if ( (error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) )
300: return (error);
301:
302: if ( (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p)) )
303: return error;
304: needclose = 1;
305:
306: /* This is the "logical sector size". The standard says this
307: * should be 2048 or the physical sector size on the device,
308: * whichever is greater. For now, we'll just use a constant.
309: */
310: iso_bsize = ISO_DEFAULT_BLOCK_SIZE;
311:
312: for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
313:
314: if ( (error = bread(devvp, iso_blknum, iso_bsize, NOCRED, &bp)) )
315: {
316: goto out;
317: };
318:
319: vdp = (struct iso_volume_descriptor *)bp->b_data;
320: if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0) {
321: #ifdef DEBUG
322: printf("cd9660_vfsops.c: iso_mountfs: Invalid ID in volume desciptor.\n");
323: #endif
324: error = EINVAL;
325: goto out;
326: }
327:
328: if (isonum_711 (vdp->type) == ISO_VD_END) {
329: #ifdef DEBUG
330: printf("cd9660_vfsops.c: iso_mountfs: isonum_711() != ISO_VD_END.\n");
331: #endif
332: error = EINVAL;
333: goto out;
334: }
335:
336: if (isonum_711 (vdp->type) == ISO_VD_PRIMARY)
337: break;
338: brelse(bp);
339: }
340:
341: if (isonum_711 (vdp->type) != ISO_VD_PRIMARY) {
342: #ifdef DEBUG
343: printf("cd9660_vfsops.c: iso_mountfs: isnum_711() != ISO_VD_PRIMARY.\n");
344: #endif
345: error = EINVAL;
346: goto out;
347: }
348:
349: pri = (struct iso_primary_descriptor *)vdp;
350:
351: logical_block_size = isonum_723 (pri->logical_block_size);
352:
353: if (logical_block_size < DEV_BSIZE || logical_block_size > MAXBSIZE
354: || (logical_block_size & (logical_block_size - 1)) != 0) {
355: error = EINVAL;
356: goto out;
357: }
358:
359: rootp = (struct iso_directory_record *)pri->root_directory_record;
360:
361: MALLOC(isomp, struct iso_mnt *, sizeof *isomp, M_ISOFSMNT, M_WAITOK);
362: bzero((caddr_t)isomp, sizeof *isomp);
363: isomp->logical_block_size = logical_block_size;
364: isomp->volume_space_size = isonum_733 (pri->volume_space_size);
365: bcopy (rootp, isomp->root, sizeof isomp->root);
366: isomp->root_extent = isonum_733 (rootp->extent);
367: isomp->root_size = isonum_733 (rootp->size);
368:
369: /*
370: * getattrlist wants the volume name, create date and modify date
371: */
372:
373: /* Remove any trailing white space */
374: if ( strlen(pri->volume_id) ) {
375: char *myPtr;
376:
377: myPtr = pri->volume_id + strlen( pri->volume_id ) - 1;
378: while ( *myPtr == ' ' && myPtr >= pri->volume_id ) {
379: *myPtr = 0x00;
380: myPtr--;
381: }
382: }
383: /* YYY need to use secondary volume descriptor name for kanji disks */
384: bcopy(pri->volume_id, isomp->volume_id, sizeof(isomp->volume_id));
385: cd9660_tstamp_conv17(pri->creation_date, &isomp->creation_date);
386: cd9660_tstamp_conv17(pri->modification_date, &isomp->modification_date);
387:
388: #if 0
389: kprintf("\n************************************************************************* \n");
390: kprintf( "iso_mountfs - pri->id is \"%c%c%c%c%c\" \n",
391: pri->id[0], pri->id[1], pri->id[2], pri->id[3], pri->id[4] );
392: kprintf( "iso_mountfs - pri->CDXASignature is \"%c%c%c%c%c%c%c%c\" \n",
393: pri->CDXASignature[0], pri->CDXASignature[1], pri->CDXASignature[2],
394: pri->CDXASignature[3], pri->CDXASignature[4], pri->CDXASignature[5],
395: pri->CDXASignature[6], pri->CDXASignature[7] );
396: #endif
397:
398: /* See if this is a CD-XA volume */
399: if ( bcmp( pri->CDXASignature, ISO_XA_ID, sizeof(pri->CDXASignature) ) == 0 )
400: isomp->im_flags2 |= IMF2_IS_CDXA;
401:
402: isomp->im_bmask = logical_block_size - 1;
403: isomp->im_bshift = 0;
404: while ((1 << isomp->im_bshift) < isomp->logical_block_size)
405: isomp->im_bshift++;
406:
407: bp->b_flags |= B_AGE;
408: brelse(bp);
409: bp = NULL;
410:
411: mp->mnt_data = (qaddr_t)isomp;
412: mp->mnt_stat.f_fsid.val[0] = (long)dev;
413: mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
414: mp->mnt_maxsymlinklen = 0;
415: mp->mnt_flag |= MNT_LOCAL;
416: isomp->im_mountp = mp;
417: isomp->im_dev = dev;
418: isomp->im_devvp = devvp;
419:
420: devvp->v_specflags |= SI_MOUNTEDON;
421:
422: /* Check the Rock Ridge Extention support */
423: if (!(argp->flags & ISOFSMNT_NORRIP)) {
424: if ( (error = bread(isomp->im_devvp,
425: (isomp->root_extent + isonum_711(rootp->ext_attr_length)),
426: isomp->logical_block_size, NOCRED, &bp)) )
427: goto out;
428:
429: rootp = (struct iso_directory_record *)bp->b_data;
430:
431: if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) {
432: argp->flags |= ISOFSMNT_NORRIP;
433: } else {
434: argp->flags &= ~ISOFSMNT_GENS;
435: }
436:
437: /*
438: * The contents are valid,
439: * but they will get reread as part of another vnode, so...
440: */
441: bp->b_flags |= B_AGE;
442: brelse(bp);
443: bp = NULL;
444: }
445: isomp->im_flags = argp->flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS|ISOFSMNT_EXTATT);
446: switch (isomp->im_flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS)) {
447: default:
448: isomp->iso_ftype = ISO_FTYPE_DEFAULT;
449: break;
450: case ISOFSMNT_GENS|ISOFSMNT_NORRIP:
451: isomp->iso_ftype = ISO_FTYPE_9660;
452: break;
453: case 0:
454: isomp->iso_ftype = ISO_FTYPE_RRIP;
455: break;
456: }
457:
458: return 0;
459: out:
460: if (bp)
461: brelse(bp);
462: if (needclose)
463: (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
464: if (isomp) {
465: FREE((caddr_t)isomp, M_ISOFSMNT);
466: mp->mnt_data = (qaddr_t)0;
467: }
468:
469: /* Clear the mounted on bit in the devvp If it */
470: /* not set, this is a nop and there is no way to */
471: /* get here with it set unless we did it. If you*/
472: /* are making code changes which makes the above */
473: /* assumption not true, change this code. */
474:
475: devvp->v_specflags &= ~SI_MOUNTEDON;
476:
477: return error;
478: }
479:
480: /*
481: * Make a filesystem operational.
482: * Nothing to do at the moment.
483: */
484: /* ARGSUSED */
485: int
486: cd9660_start(mp, flags, p)
487: struct mount *mp;
488: int flags;
489: struct proc *p;
490: {
491: return 0;
492: }
493:
494: /*
495: * unmount system call
496: */
497: int
498: cd9660_unmount(mp, mntflags, p)
499: struct mount *mp;
500: int mntflags;
501: struct proc *p;
502: {
503: register struct iso_mnt *isomp;
504: int error, flags = 0;
505:
506: if ( (mntflags & MNT_FORCE) )
507: flags |= FORCECLOSE;
508: #if 0
509: mntflushbuf(mp, 0);
510: if (mntinvalbuf(mp))
511: return EBUSY;
512: #endif
513: if ( (error = vflush(mp, NULLVP, flags)) )
514: return (error);
515:
516: isomp = VFSTOISOFS(mp);
517:
518: #ifdef ISODEVMAP
519: if (isomp->iso_ftype == ISO_FTYPE_RRIP)
520: iso_dunmap(isomp->im_dev);
521: #endif
522:
523: isomp->im_devvp->v_specflags &= ~SI_MOUNTEDON;
524: error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, p);
525: vrele(isomp->im_devvp);
526: FREE((caddr_t)isomp, M_ISOFSMNT);
527: mp->mnt_data = (qaddr_t)0;
528: mp->mnt_flag &= ~MNT_LOCAL;
529: return (error);
530: }
531:
532: /*
533: * Return root of a filesystem
534: */
535: int
536: cd9660_root(mp, vpp)
537: struct mount *mp;
538: struct vnode **vpp;
539: {
540: struct iso_mnt *imp = VFSTOISOFS(mp);
541: struct iso_directory_record *dp =
542: (struct iso_directory_record *)imp->root;
543: ino_t ino = isodirino(dp, imp);
544:
545: /*
546: * With RRIP we must use the `.' entry of the root directory.
547: * Simply tell vget, that it's a relocated directory.
548: */
549: return (cd9660_vget_internal(mp, ino, vpp,
550: imp->iso_ftype == ISO_FTYPE_RRIP, dp, current_proc()));
551: }
552:
553: /*
554: * Do operations associated with quotas, not supported
555: */
556: /* ARGSUSED */
557: int
558: cd9660_quotactl(mp, cmd, uid, arg, p)
559: struct mount *mp;
560: int cmd;
561: uid_t uid;
562: caddr_t arg;
563: struct proc *p;
564: {
565:
566: return (EOPNOTSUPP);
567: }
568:
569: /*
570: * Get file system statistics.
571: */
572: int
573: cd9660_statfs(mp, sbp, p)
574: struct mount *mp;
575: register struct statfs *sbp;
576: struct proc *p;
577: {
578: register struct iso_mnt *isomp;
579:
580: isomp = VFSTOISOFS(mp);
581:
582: #ifdef COMPAT_09
583: sbp->f_type = 5;
584: #else
585: sbp->f_type = 0;
586: #endif
587: sbp->f_bsize = isomp->logical_block_size;
588: sbp->f_iosize = sbp->f_bsize; /* XXX */
589: sbp->f_blocks = isomp->volume_space_size;
590: sbp->f_bfree = 0; /* total free blocks */
591: sbp->f_bavail = 0; /* blocks free for non superuser */
592: sbp->f_files = 0; /* total files */
593: sbp->f_ffree = 0; /* free file nodes */
594: if (sbp != &mp->mnt_stat) {
595: bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
596: bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
597: }
598:
599: strncpy( sbp->f_fstypename, mp->mnt_vfc->vfc_name, (MFSNAMELEN - 1) );
600: sbp->f_fstypename[(MFSNAMELEN - 1)] = '\0';
601:
602: /* Use the first spare for flags: */
603: sbp->f_spare[0] = isomp->im_flags;
604: return 0;
605: }
606:
607: /* ARGSUSED */
608: int
609: cd9660_sync(mp, waitfor, cred, p)
610: struct mount *mp;
611: int waitfor;
612: struct ucred *cred;
613: struct proc *p;
614: {
615: return (0);
616: }
617:
618: /*
619: * File handle to vnode
620: *
621: * Have to be really careful about stale file handles:
622: * - check that the inode number is in range
623: * - call iget() to get the locked inode
624: * - check for an unallocated inode (i_mode == 0)
625: * - check that the generation number matches
626: */
627:
628: struct ifid {
629: ushort ifid_len;
630: ushort ifid_pad;
631: int ifid_ino;
632: long ifid_start;
633: };
634:
635: /* ARGSUSED */
636: int
637: cd9660_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
638: register struct mount *mp;
639: struct fid *fhp;
640: struct mbuf *nam;
641: struct vnode **vpp;
642: int *exflagsp;
643: struct ucred **credanonp;
644: {
645: struct ifid *ifhp = (struct ifid *)fhp;
646: register struct iso_node *ip;
647: register struct netcred *np;
648: register struct iso_mnt *imp = VFSTOISOFS(mp);
649: struct vnode *nvp;
650: int error;
651:
652: #ifdef ISOFS_DBG
653: printf("fhtovp: ino %d, start %ld\n",
654: ifhp->ifid_ino, ifhp->ifid_start);
655: #endif
656:
657: /*
658: * Get the export permission structure for this <mp, client> tuple.
659: */
660: np = vfs_export_lookup(mp, &imp->im_export, nam);
661: if (np == NULL)
662: return (EACCES);
663:
664: if ( (error = VFS_VGET(mp, &ifhp->ifid_ino, &nvp)) ) {
665: *vpp = NULLVP;
666: return (error);
667: }
668: ip = VTOI(nvp);
669: if (ip->inode.iso_mode == 0) {
670: vput(nvp);
671: *vpp = NULLVP;
672: return (ESTALE);
673: }
674: *vpp = nvp;
675: *exflagsp = np->netc_exflags;
676: *credanonp = &np->netc_anon;
677: return (0);
678: }
679:
680: int
681: cd9660_vget(mp, ino, vpp)
682: struct mount *mp;
683: void *ino;
684: struct vnode **vpp;
685: {
686:
687: /*
688: * XXXX
689: * It would be nice if we didn't always set the `relocated' flag
690: * and force the extra read, but I don't want to think about fixing
691: * that right now.
692: */
693:
694: return ( cd9660_vget_internal( mp, *(ino_t*)ino, vpp, 0,
695: (struct iso_directory_record *) 0,
696: current_proc()) );
697: }
698:
699: int
700: cd9660_vget_internal(mp, ino, vpp, relocated, isodir, p)
701: struct mount *mp;
702: ino_t ino;
703: struct vnode **vpp;
704: int relocated;
705: struct iso_directory_record *isodir;
706: struct proc *p;
707: {
708: register struct iso_mnt *imp;
709: struct iso_node *ip;
710: struct buf *bp;
711: struct vnode *vp, *nvp;
712: dev_t dev;
713: int error;
714:
715: imp = VFSTOISOFS(mp);
716: dev = imp->im_dev;
717: if ((*vpp = cd9660_ihashget(dev, ino, p)) != NULLVP)
718: return (0);
719:
720: /* Allocate a new vnode/iso_node. */
721: if ( (error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp)) ) {
722: *vpp = NULLVP;
723: return (error);
724: }
725: MALLOC(ip, struct iso_node *, sizeof(struct iso_node), M_ISOFSNODE,
726: M_WAITOK);
727: bzero((caddr_t)ip, sizeof(struct iso_node));
728: lockinit(&ip->i_lock, PINOD,"isonode",0,0);
729: vp->v_data = ip;
730: ip->i_vnode = vp;
731: ip->i_dev = dev;
732: ip->i_number = ino;
733:
734: /*
735: * Put it onto its hash chain and lock it so that other requests for
736: * this inode will block if they arrive while we are sleeping waiting
737: * for old data structures to be purged or for the contents of the
738: * disk portion of this inode to be read.
739: */
740: cd9660_ihashins(ip);
741:
742: if (isodir == 0) {
743: int lbn, off;
744:
745: lbn = lblkno(imp, ino);
746: if (lbn >= imp->volume_space_size) {
747: vput(vp);
748: printf("fhtovp: lbn exceed volume space %d\n", lbn);
749: return (ESTALE);
750: }
751:
752: off = blkoff(imp, ino);
753: if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
754: vput(vp);
755: printf("fhtovp: crosses block boundary %d\n",
756: off + ISO_DIRECTORY_RECORD_SIZE);
757: return (ESTALE);
758: }
759:
760: error = bread(imp->im_devvp,
761: lbn,
762: imp->logical_block_size, NOCRED, &bp);
763: if (error) {
764: vput(vp);
765: brelse(bp);
766: printf("fhtovp: bread error %d\n",error);
767: return (error);
768: }
769: isodir = (struct iso_directory_record *)(bp->b_data + off);
770:
771: if (off + isonum_711(isodir->length) >
772: imp->logical_block_size) {
773: vput(vp);
774: if (bp != 0)
775: brelse(bp);
776: printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
777: off +isonum_711(isodir->length), off,
778: isonum_711(isodir->length));
779: return (ESTALE);
780: }
781:
782: /*
783: * for directories we can get parentID from adjacent parent directory record
784: */
785: if ((isonum_711(isodir->flags) & directoryBit) && (isodir->name[0] == 0)) {
786: struct iso_directory_record *pdp;
787:
788: pdp = (struct iso_directory_record *) ((char *)bp->b_data + isonum_711(isodir->length));
789: if ((isonum_711(pdp->flags) & directoryBit) && (pdp->name[0] == 1))
790: ip->i_parent = isodirino(pdp, imp);
791:
792: }
793: #if 0
794: if (isonum_733(isodir->extent) +
795: isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {
796: if (bp != 0)
797: brelse(bp);
798: printf("fhtovp: file start miss %d vs %d\n",
799: isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length),
800: ifhp->ifid_start);
801: return (ESTALE);
802: }
803: #endif
804: } else
805: bp = 0;
806:
807: ip->i_mnt = imp;
808: ip->i_devvp = imp->im_devvp;
809: VREF(ip->i_devvp);
810:
811: if (relocated) {
812: /*
813: * On relocated directories we must
814: * read the `.' entry out of a dir.
815: */
816: ip->iso_start = ino >> imp->im_bshift;
817: if (bp != 0)
818: brelse(bp);
819: if ( (error = VOP_BLKATOFF(vp, (off_t)0, NULL, &bp)) ) {
820: vput(vp);
821: return (error);
822: }
823: isodir = (struct iso_directory_record *)bp->b_data;
824: }
825:
826: /*
827: * get apple extensions to ISO directory record or use defaults
828: * when there are no apple extensions.
829: */
830: if ( (isonum_711( isodir->flags ) & directoryBit) == 0 )
831: {
832: /* This is an ISO directory record for a file */
833: DRGetTypeCreatorAndFlags( imp, isodir, &ip->i_FileType,
834: &ip->i_Creator, &ip->i_FinderFlags );
835: }
836:
837: ip->iso_extent = isonum_733(isodir->extent);
838: ip->i_size = isonum_733(isodir->size);
839: ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
840:
841: /*
842: * if we have a valid name, fill in i_name
843: */
844: if (((u_char)isodir->name[0]) > 1) {
845: u_short namelen;
846:
847: if (imp->iso_ftype == ISO_FTYPE_RRIP) {
848: ino_t inump = 0;
849:
850: cd9660_rrip_getname(isodir, ip->i_name, &namelen, &inump, imp);
851: } else {
852: isofntrans (isodir->name, isonum_711(isodir->name_len),
853: ip->i_name, &namelen,
854: imp->iso_ftype == ISO_FTYPE_9660,
855: isonum_711(isodir->flags) & associatedBit);
856: }
857:
858: if (namelen > (sizeof(ip->i_name) - 1))
859: namelen = sizeof(ip->i_name) - 1;
860: ip->i_name[namelen] = '\0';
861: }
862:
863: /*
864: * Setup time stamp, attribute
865: */
866: vp->v_type = VNON;
867: switch (imp->iso_ftype) {
868: default: /* ISO_FTYPE_9660 */
869: {
870: struct buf *bp2;
871: int off;
872: if ((imp->im_flags & ISOFSMNT_EXTATT)
873: && (off = isonum_711(isodir->ext_attr_length)))
874: VOP_BLKATOFF(vp, (off_t)-(off << imp->im_bshift), NULL,
875: &bp2);
876: else
877: bp2 = NULL;
878: cd9660_defattr(isodir, ip, bp2);
879: cd9660_deftstamp(isodir, ip, bp2);
880: if (bp2)
881: brelse(bp2);
882: break;
883: }
884: case ISO_FTYPE_RRIP:
885: cd9660_rrip_analyze(isodir, ip, imp);
886: break;
887: }
888:
889: if (bp != 0)
890: brelse(bp);
891:
892: /*
893: * Initialize the associated vnode
894: */
895: switch (vp->v_type = IFTOVT(ip->inode.iso_mode)) {
896: case VFIFO:
897: #ifdef FIFO
898: vp->v_op = cd9660_fifoop_p;
899: break;
900: #else
901: vput(vp);
902: return (EOPNOTSUPP);
903: #endif /* FIFO */
904: case VCHR:
905: case VBLK:
906: /*
907: * if device, look at device number table for translation
908: */
909: #ifdef ISODEVMAP
910: if (dp = iso_dmap(dev, ino, 0))
911: ip->inode.iso_rdev = dp->d_dev;
912: #endif
913: vp->v_op = cd9660_specop_p;
914: if ( (nvp = checkalias(vp, ip->inode.iso_rdev, mp)) ) {
915: /*
916: * Discard unneeded vnode, but save its iso_node.
917: */
918: cd9660_ihashrem(ip);
919: VOP_UNLOCK(vp, 0, p);
920: nvp->v_data = vp->v_data;
921: vp->v_data = NULL;
922: vp->v_op = spec_vnodeop_p;
923: vrele(vp);
924: vgone(vp);
925: /*
926: * Reinitialize aliased inode.
927: */
928: vp = nvp;
929: ip->i_vnode = vp;
930: cd9660_ihashins(ip);
931: }
932: break;
933: default:
934: break;
935: }
936:
937: if (ip->iso_extent == imp->root_extent) {
938: vp->v_flag |= VROOT;
939: ip->i_parent = 1; /* root's parent is always 1 by convention */
940: }
941: /*
942: * XXX need generation number?
943: */
944:
945: *vpp = vp;
946: return (0);
947: }
948:
949:
950: /************************************************************************
951: *
952: * Function: DRGetTypeCreatorAndFlags
953: *
954: * Purpose: Set up the fileType, fileCreator and fileFlags
955: *
956: * Returns: none
957: *
958: * Side Effects: sets *theTypePtr, *theCreatorPtr, and *theFlagsPtr
959: *
960: * Description:
961: *
962: * Revision History:
963: * 28 Jul 88 BL�B Added a new extension type of 6, which allows
964: * the specification of four of the finder flags.
965: * We let the creator of the disk just copy over
966: * the finder flags, but we only look at always
967: * switch launch, system, bundle, and locked bits.
968: * 15 Aug 88 BL�B The Apple extensions to ISO 9660 implemented the
969: * padding field at the end of a directory record
970: * incorrectly.
971: * 19 Jul 89 BG Rewrote routine to handle the "new" Apple
972: * Extensions definition, as well as take into
973: * account the possibility of "other" definitions.
974: * 02 Nov 89 BG Corrected the 'AA' SystemUseID processing to
975: * check for SystemUseID == 2 (HFS). Was incorrectly
976: * checking for SystemUseID == 1 (ProDOS) before.
977: * 18 Mar 92 CMP Fixed the check for whether len_fi was odd or even.
978: * Before it would always assume even for an XA record.
979: * 26 Dec 97 jwc Swiped from MacOS implementation of ISO 9660 CD-ROM support
980: * and modified to work in Rhapsody file system.
981: *
982: *********************************************************************** */
983:
984: static void DRGetTypeCreatorAndFlags( struct iso_mnt * theMountPointPtr,
985: struct iso_directory_record * theDirRecPtr,
986: u_int32_t * theTypePtr,
987: u_int32_t * theCreatorPtr,
988: u_int16_t * theFlagsPtr )
989: {
990: int foundStuff;
991: u_int32_t myType;
992: u_int32_t myCreator;
993: AppleExtension *myAppleExtPtr;
994: NewAppleExtension *myNewAppleExtPtr;
995: u_int16_t myFinderFlags;
996: char *myPtr;
997:
998: foundStuff = 1;
999: myType = 0L;
1000: myCreator = 0L;
1001: myFinderFlags = 0;
1002: *theFlagsPtr = 0x0000;
1003:
1004: /* handle the fact that our original apple extensions didn't take
1005: into account the padding byte on a file name */
1006:
1007: myPtr = &theDirRecPtr->name[ (isonum_711(theDirRecPtr->name_len)) ];
1008:
1009: /* if string length is even, bump myPtr for padding byte */
1010: if ( ((isonum_711(theDirRecPtr->name_len)) & 0x01) == 0 )
1011: myPtr++;
1012: myAppleExtPtr = (AppleExtension *) myPtr;
1013:
1014: /* checking for whether or not the new 'AA' code is being called (and if so, correctly) */
1015: if ( (isonum_711(theDirRecPtr->length)) <=
1016: ISO_DIRECTORY_RECORD_SIZE + (isonum_711(theDirRecPtr->name_len)) )
1017: {
1018: foundStuff = 0;
1019: goto DoneLooking;
1020: }
1021:
1022: if ( myAppleExtPtr->signature[0] == 'B' && myAppleExtPtr->signature[1] == 'A' )
1023: {
1024: int i;
1025:
1026: switch ( isonum_711(myAppleExtPtr->systemUseID) )
1027: {
1028: case 0x00: /* nothing there. use default */
1029: foundStuff = 0;
1030: break;
1031: case 0x02: /* no icon */
1032: case 0x04: /* icon, no bundle bit */
1033: for ( i = 0; i < 4; i++ )
1034: myType = (myType << 8) | myAppleExtPtr->fileType[i];
1035:
1036: for ( i = 0; i < 4; i++ )
1037: myCreator = (myCreator << 8) | myAppleExtPtr->fileCreator[i];
1038:
1039: *theFlagsPtr |= fInitedBit;
1040: break;
1041: case 0x03: /* no icon, bundle bit */
1042: case 0x05: /* icon and bundle bit */
1043: for ( i = 0; i < 4; i++ )
1044: myType = (myType << 8) | myAppleExtPtr->fileType[i];
1045:
1046: for ( i = 0; i < 4; i++ )
1047: myCreator = (myCreator << 8) | myAppleExtPtr->fileCreator[i];
1048:
1049: *theFlagsPtr |= fInitedBit | fHasBundleBit;
1050: break;
1051: case 0x06: /* finder flags in word at end */
1052: for ( i = 0; i < 4; i++ )
1053: myType = (myType << 8) | myAppleExtPtr->fileType[i];
1054:
1055: for ( i = 0; i < 4; i++ )
1056: myCreator = (myCreator << 8) | myAppleExtPtr->fileCreator[i];
1057:
1058: myFinderFlags =
1059: (myAppleExtPtr->finderFlags[0] << 8) | myAppleExtPtr->finderFlags[1];
1060:
1061: /* just check the following four bits--all others always set to 0 */
1062: myFinderFlags &= (fAlwaysBit | fSystemBit | fHasBundleBit | fLockedBit);
1063: *theFlagsPtr |= (fInitedBit | myFinderFlags);
1064: break;
1065: default:
1066: foundStuff = 0;
1067: }
1068: goto DoneLooking;
1069: }
1070:
1071: /*
1072: * If signature[]s != 'BA', then (1) this is not an old-style disc and we
1073: * need to look at ALL available SystemUse possibilities; (2) this could
1074: * possibly be a CD-XA style disc and our offset calculations need to
1075: * take this into account.
1076: */
1077:
1078: foundStuff = 0; /* now we default to *false* until we find a good one */
1079: myPtr = (char *) myAppleExtPtr;
1080:
1081: if ( (theMountPointPtr->im_flags2 & IMF2_IS_CDXA) != 0 )
1082: myPtr += 14;/* add in CD-XA fixed record offset (tnx, Phillips) */
1083: myNewAppleExtPtr = (NewAppleExtension *) myPtr;
1084:
1085: /* calculate the "real" end of the directory record information */
1086: myPtr = ((char *) theDirRecPtr) + (isonum_711(theDirRecPtr->length));
1087: while( (char *) myNewAppleExtPtr < myPtr ) /* end of directory buffer */
1088: {
1089: /*
1090: * If we get here, we can assume that ALL further entries in this
1091: * directory record are of the form:
1092: *
1093: * struct OptionalSystemUse
1094: * {
1095: * byte Signature[2];
1096: * byte systemUseID;
1097: * byte OSULength;
1098: * byte fileType[4]; # only if HFS
1099: * byte fileCreator[4]; # only if HFS
1100: * byte finderFlags[2]; # only if HFS
1101: * };
1102: *
1103: * This means that we can examine the Signature bytes to see if they are 'AA'
1104: * (the NEW Apple extension signature). If they are, deal with them. If they
1105: * aren't, the OSULength field will tell us how long this extension info is
1106: * (including the signature and length bytes) and that will allow us to walk
1107: * the OptionalSystemUse records until we hit the end of them or run off the
1108: * end of the directory record.
1109: */
1110: u_char *myFromPtr, *myToPtr;
1111: union
1112: {
1113: u_int32_t fourchars;
1114: u_char chars[4];
1115: } myChars;
1116:
1117: if ( myNewAppleExtPtr->signature[0] == 'A' && myNewAppleExtPtr->signature[1] == 'A' )
1118: {
1119: if ( isonum_711(myNewAppleExtPtr->systemUseID) == 2 ) /* HFS */
1120: {
1121: foundStuff = 1; /* we got one! */
1122:
1123: myFromPtr = &myNewAppleExtPtr->fileType[0];
1124: myToPtr = &myChars.chars[0];
1125: *myToPtr++ = *myFromPtr++;
1126: *myToPtr++ = *myFromPtr++;
1127: *myToPtr++ = *myFromPtr++;
1128: *myToPtr = *myFromPtr;
1129: myType = myChars.fourchars; /* copy file type to user var */
1130:
1131: myFromPtr = &myNewAppleExtPtr->fileCreator[0];
1132: myToPtr = &myChars.chars[0];
1133: *myToPtr++ = *myFromPtr++;
1134: *myToPtr++ = *myFromPtr++;
1135: *myToPtr++ = *myFromPtr++;
1136: *myToPtr = *myFromPtr;
1137: myCreator = myChars.fourchars; /* copy creator to user var */
1138:
1139: myFromPtr = &myNewAppleExtPtr->finderFlags[0];
1140: myToPtr = &myChars.chars[2]; /* *flags* is a short */
1141: myChars.fourchars = 0;
1142: *myToPtr++ = *myFromPtr++;
1143: *myToPtr = *myFromPtr;
1144: myFinderFlags = myChars.fourchars;
1145: myFinderFlags &= ( fAlwaysBit | fSystemBit | fHasBundleBit | fLockedBit );
1146: *theFlagsPtr = (myFinderFlags | fInitedBit); /* return Finder flags to user var */
1147:
1148: break; /* exit the loop */
1149: }
1150: }
1151:
1152: /*
1153: * Check to see if we have a reasonable OSULength value.
1154: * ZERO is not an acceptable value. Nor is any value less than 4.
1155: */
1156:
1157: if ( (isonum_711(myNewAppleExtPtr->OSULength)) < 4 )
1158: break; /* not acceptable - get out! */
1159:
1160: /* otherwise, step past this SystemUse record */
1161: (char *)myNewAppleExtPtr += (isonum_711(myNewAppleExtPtr->OSULength));
1162:
1163: } // end of while loop
1164:
1165: DoneLooking:
1166: if ( foundStuff != 0 )
1167: {
1168: *theTypePtr = myType;
1169: *theCreatorPtr = myCreator;
1170: }
1171: else
1172: {
1173: *theTypePtr = DEFAULTTYPE;
1174: *theCreatorPtr = DEFAULTCREATOR;
1175: *theFlagsPtr |= fInitedBit;
1176: }
1177:
1178: return;
1179:
1180: } /* DRGetTypeCreatorAndFlags */
1181:
1182:
1183: /*
1184: * Vnode pointer to File handle
1185: */
1186: /* ARGSUSED */
1187: int
1188: cd9660_vptofh(vp, fhp)
1189: struct vnode *vp;
1190: struct fid *fhp;
1191: {
1192: register struct iso_node *ip = VTOI(vp);
1193: register struct ifid *ifhp;
1194:
1195: ifhp = (struct ifid *)fhp;
1196: ifhp->ifid_len = sizeof(struct ifid);
1197:
1198: ifhp->ifid_ino = ip->i_number;
1199: ifhp->ifid_start = ip->iso_start;
1200:
1201: #ifdef ISOFS_DBG
1202: printf("vptofh: ino %d, start %ld\n",
1203: ifhp->ifid_ino,ifhp->ifid_start);
1204: #endif
1205: return 0;
1206: }
1207:
1208: /*
1209: * Fast-FileSystem only?
1210: */
1211: int
1212: cd9660_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
1213: int * name;
1214: u_int namelen;
1215: void* oldp;
1216: size_t * oldlenp;
1217: void * newp;
1218: size_t newlen;
1219: struct proc * p;
1220: {
1221: return EOPNOTSUPP;
1222: }
1223:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.