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