2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 /* $NetBSD: cd9660_vfsops.c,v 1.18 1995/03/09 12:05:36 mycroft Exp $ */
32 * The Regents of the University of California. All rights reserved.
34 * This code is derived from software contributed to Berkeley
35 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
36 * Support code is derived from software contributed to Berkeley
37 * by Atsushi Murai (amurai@spec.co.jp).
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. All advertising materials mentioning features or use of this software
48 * must display the following acknowledgement:
49 * This product includes software developed by the University of
50 * California, Berkeley and its contributors.
51 * 4. Neither the name of the University nor the names of its contributors
52 * may be used to endorse or promote products derived from this software
53 * without specific prior written permission.
55 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
56 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
59 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
60 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
61 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67 * @(#)cd9660_vfsops.c 8.9 (Berkeley) 12/5/94
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/vnode_internal.h>
73 #include <sys/mount.h>
74 #include <sys/namei.h>
76 #include <sys/kauth.h>
77 #include <sys/kernel.h>
78 #include <miscfs/specfs/specdev.h>
81 #include <sys/ioctl.h>
83 #include <sys/errno.h>
84 #include <sys/malloc.h>
87 #include <sys/utfconv.h>
89 #include <isofs/cd9660/iso.h>
90 #include <isofs/cd9660/iso_rrip.h>
91 #include <isofs/cd9660/cd9660_node.h>
92 #include <isofs/cd9660/cd9660_mount.h>
95 * Minutes, Seconds, Frames (M:S:F)
108 u_char ctrl_adr
; /* typed to be machine and compiler independent */
111 struct CDMSF address
;
117 u_short length
; /* in native cpu endian */
118 u_char first_session
;
120 struct CDTOC_Desc trackdesc
[1];
123 #define MSF_TO_LBA(msf) \
124 (((((msf).minute * 60UL) + (msf).second) * 75UL) + (msf).frame - 150)
126 u_char isonullname
[] = "\0";
128 struct vfsops cd9660_vfsops
= {
146 * Called by vfs_mountroot when iso is going to be mounted as root.
148 * Name is updated by mount(8) after booting.
150 #define ROOTNAME "root_device"
152 static int iso_mountfs(struct vnode
*devvp
, struct mount
*mp
, struct user_iso_args
*argp
,
153 vfs_context_t context
);
155 static void DRGetTypeCreatorAndFlags(
156 struct iso_mnt
* theMountPointPtr
,
157 struct iso_directory_record
* theDirRecPtr
,
158 u_int32_t
* theTypePtr
,
159 u_int32_t
* theCreatorPtr
,
160 u_int16_t
* theFlagsPtr
);
163 cd9660_mountroot(mount_t mp
, vnode_t rvp
, vfs_context_t context
)
166 struct user_iso_args args
;
168 args
.flags
= ISOFSMNT_ROOT
;
171 args
.toc
= USER_ADDR_NULL
;
173 if ((error
= iso_mountfs(rvp
, mp
, &args
, context
)))
176 (void)cd9660_statfs(mp
, vfs_statfs(mp
), context
);
187 cd9660_mount(mount_t mp
, vnode_t devvp
, user_addr_t data
, vfs_context_t context
)
189 struct user_iso_args args
;
191 struct iso_mnt
*imp
= NULL
;
193 if (vfs_context_is64bit(context
)) {
194 error
= copyin(data
, (caddr_t
)&args
, sizeof(args
));
197 struct iso_args temp
;
198 error
= copyin(data
, (caddr_t
)&temp
, sizeof(temp
));
199 args
.flags
= temp
.flags
;
200 args
.ssector
= temp
.ssector
;
201 args
.toc_length
= temp
.toc_length
;
202 args
.toc
= CAST_USER_ADDR_T(temp
.toc
);
211 * If updating, check whether changing from read-only to
212 * read/write; if there is no device name, that's all we do.
214 if (vfs_isupdate(mp
)) {
215 imp
= VFSTOISOFS(mp
);
219 if ( !vfs_isupdate(mp
))
220 error
= iso_mountfs(devvp
, mp
, &args
, context
);
222 if (devvp
!= imp
->im_devvp
)
223 error
= EINVAL
; /* needs translation */
229 /* Indicate that we don't support volfs */
230 vfs_clearflags(mp
, MNT_DOVOLFS
);
236 * Find the BSD device for the physical disk corresponding to the
237 * mount point's device. We use this physical device to read whole
238 * (2352 byte) sectors from the CD to get the content for the video
241 * The "path" argument is the path to the block device that the volume
242 * is being mounted on (args.fspec). It should be of the form:
244 * where the last "s0" part is stripped off to determine the physical
245 * device's path. It is assumed to be in user memory.
247 static struct vnode
*
248 cd9660_phys_device(mount_t mp
, vfs_context_t context
)
251 char whole_path
[64]; // path to "whole" device
254 struct vnode
*result
;
255 struct vfsstatfs
* sfs
;
257 sfs
= vfs_statfs(mp
);
260 if (strlen(sfs
->f_mntfromname
) >= sizeof(whole_path
))
263 /* Make a copy of the mount from name, then remove trailing "s...". */
264 strlcpy(whole_path
, sfs
->f_mntfromname
, sizeof(whole_path
));
267 * I would use strrchr or rindex here, but those are declared __private_extern__,
268 * and can't be used across component boundaries at this time.
270 for (s
=whole_path
, saved
=NULL
; *s
; ++s
)
275 /* Lookup the "whole" device. */
276 NDINIT(&nd
, LOOKUP
, FOLLOW
, UIO_SYSSPACE
, CAST_USER_ADDR_T(whole_path
), context
);
279 printf("isofs: Cannot find physical device: %s\n", whole_path
);
284 /* Open the "whole" device. */
285 err
= VNOP_OPEN(nd
.ni_vp
, FREAD
, context
);
288 printf("isofs: Cannot open physical device: %s\n", whole_path
);
298 * See if the given CD-ROM XA disc appears to be a Video CD
299 * (version < 2.0; so, not SVCD). If so, fill in the extent
300 * information for the MPEGAV directory, set the VCD flag,
304 cd9660_find_video_dir(struct iso_mnt
*isomp
)
307 struct vnode
*rvp
= NULL
;
308 struct vnode
*videovp
= NULL
;
309 struct componentname cn
;
310 char dirname
[] = "MPEGAV";
312 result
= 0; /* Assume not a video CD */
314 err
= cd9660_root(isomp
->im_mountp
, &rvp
, NULL
);
316 printf("cd9660_find_video_dir: cd9660_root failed (%d)\n", err
);
317 return 0; /* couldn't find video dir */
320 cn
.cn_nameiop
= LOOKUP
;
321 cn
.cn_flags
= ISLASTCN
;
322 cn
.cn_context
= vfs_context_current();
323 cn
.cn_pnbuf
= dirname
;
324 cn
.cn_pnlen
= sizeof(dirname
)-1;
325 cn
.cn_nameptr
= cn
.cn_pnbuf
;
326 cn
.cn_namelen
= cn
.cn_pnlen
;
328 err
= VNOP_LOOKUP(rvp
, &videovp
, &cn
, cn
.cn_context
);
330 struct iso_node
*ip
= VTOI(videovp
);
331 result
= 1; /* Looks like video CD */
332 isomp
->video_dir_start
= ip
->iso_start
;
333 isomp
->video_dir_end
= ip
->iso_start
+ (ip
->i_size
>> isomp
->im_bshift
);
334 isomp
->im_flags2
|= IMF2_IS_VCD
;
344 * Common code for mount and mountroot
347 iso_mountfs(struct vnode
*devvp
, struct mount
*mp
, struct user_iso_args
*argp
,
348 vfs_context_t context
)
350 struct iso_mnt
*isomp
= (struct iso_mnt
*)0;
351 struct buf
*bp
= NULL
;
352 struct buf
*pribp
= NULL
, *supbp
= NULL
;
353 dev_t dev
= vnode_specrdev(devvp
);
356 u_long iso_bsize
, orig_bsize
;
359 struct iso_volume_descriptor
*vdp
= NULL
;
360 struct iso_primary_descriptor
*pri
= NULL
;
361 struct iso_primary_descriptor
*sup
= NULL
;
362 struct iso_directory_record
*rootp
;
363 int logical_block_size
;
365 int blkoff
= argp
->ssector
;
370 /* Advisory locking should be handled at the VFS layer */
371 vfs_setlocklocal(mp
);
373 /* Finish initializing hash tables */
376 if ((error
= VNOP_IOCTL(devvp
, DKIOCGETBLOCKSIZE
,
377 (caddr_t
)&orig_bsize
, 0, context
)))
380 /* This is the "logical sector size". The standard says this
381 * should be 2048 or the physical sector size on the device,
382 * whichever is greater. For now, we'll just use a constant.
384 iso_bsize
= ISO_DEFAULT_BLOCK_SIZE
;
386 /* tell IOKit that we're assuming 2K sectors */
387 if ((error
= VNOP_IOCTL(devvp
, DKIOCSETBLOCKSIZE
,
388 (caddr_t
)&iso_bsize
, FWRITE
, context
)))
392 for (iso_blknum
= 16 + blkoff
; iso_blknum
< (100 + blkoff
); iso_blknum
++) {
393 if ((error
= (int)buf_bread(devvp
, (daddr64_t
)((unsigned)iso_blknum
), iso_bsize
, NOCRED
, &bp
))) {
400 printf("iso_mountfs: buf_bread error %d reading block %d\n", error
, iso_blknum
);
404 vdp
= (struct iso_volume_descriptor
*)((char *)0 + buf_dataptr(bp
));
405 if (bcmp (vdp
->volume_desc_id
, ISO_STANDARD_ID
, sizeof(vdp
->volume_desc_id
)) != 0) {
407 printf("cd9660_vfsops.c: iso_mountfs: "
408 "Invalid ID in volume desciptor.\n");
410 /* There should be a primary volume descriptor followed by any
411 * secondary volume descriptors, then an end volume descriptor.
412 * Some discs are mastered without an end volume descriptor or
413 * they have the type field set and the volume descriptor ID is
414 * not set. If we at least found a primary volume descriptor,
424 vdtype
= isonum_711 (vdp
->type
);
425 if (vdtype
== ISO_VD_END
)
428 if (vdtype
== ISO_VD_PRIMARY
) {
432 pri
= (struct iso_primary_descriptor
*)vdp
;
434 } else if(vdtype
== ISO_VD_SUPPLEMENTARY
) {
438 sup
= (struct iso_primary_descriptor
*)vdp
;
440 if ((argp
->flags
& ISOFSMNT_NOJOLIET
) == 0) {
442 * some Joliet CDs are "out-of-spec and don't correctly
443 * set the SVD flags. We ignore the flags and rely soely
446 if (bcmp(sup
->escape_seq
, ISO_UCS2_Level_1
, 3) == 0)
448 else if (bcmp(sup
->escape_seq
, ISO_UCS2_Level_2
, 3) == 0)
450 else if (bcmp(sup
->escape_seq
, ISO_UCS2_Level_3
, 3) == 0)
477 logical_block_size
= isonum_723 (pri
->logical_block_size
);
479 if (logical_block_size
< DEV_BSIZE
|| logical_block_size
> MAXBSIZE
480 || (logical_block_size
& (logical_block_size
- 1)) != 0) {
485 rootp
= (struct iso_directory_record
*)pri
->root_directory_record
;
487 MALLOC(isomp
, struct iso_mnt
*, sizeof(*isomp
), M_ISOFSMNT
, M_WAITOK
);
488 bzero((caddr_t
)isomp
, sizeof(*isomp
));
489 isomp
->im_sector_size
= ISO_DEFAULT_BLOCK_SIZE
;
490 isomp
->logical_block_size
= logical_block_size
;
491 isomp
->volume_space_size
= isonum_733 (pri
->volume_space_size
);
493 * Since an ISO9660 multi-session CD can also access previous
494 * sessions, we have to include them into the space consider-
495 * ations. This doesn't yield a very accurate number since
496 * parts of the old sessions might be inaccessible now, but we
497 * can't do much better. This is also important for the NFS
498 * filehandle validation.
500 isomp
->volume_space_size
+= blkoff
;
501 bcopy (rootp
, isomp
->root
, sizeof(isomp
->root
));
502 isomp
->root_extent
= isonum_733 (rootp
->extent
);
503 isomp
->root_size
= isonum_733 (rootp
->size
);
506 * getattrlist wants the volume name, create date and modify date
509 /* Remove any trailing white space */
510 if ( strlen(pri
->volume_id
) ) {
513 myPtr
= pri
->volume_id
+ strlen( pri
->volume_id
) - 1;
514 while ( *myPtr
== ' ' && myPtr
>= pri
->volume_id
) {
520 if (pri
->volume_id
[0] == 0)
521 strlcpy(isomp
->volume_id
, ISO_DFLT_VOLUME_ID
, sizeof(isomp
->volume_id
));
523 bcopy(pri
->volume_id
, isomp
->volume_id
, sizeof(isomp
->volume_id
));
524 cd9660_tstamp_conv17(pri
->creation_date
, &isomp
->creation_date
);
525 cd9660_tstamp_conv17(pri
->modification_date
, &isomp
->modification_date
);
527 /* See if this is a CD-XA volume */
528 if (bcmp( pri
->CDXASignature
, ISO_XA_ID
,
529 sizeof(pri
->CDXASignature
) ) == 0 ) {
530 isomp
->im_flags2
|= IMF2_IS_CDXA
;
533 isomp
->im_bmask
= logical_block_size
- 1;
534 isomp
->im_bshift
= 0;
535 while ((1 << isomp
->im_bshift
) < isomp
->logical_block_size
)
542 vfs_setfsprivate(mp
, (void *)isomp
);
543 vfs_statfs(mp
)->f_fsid
.val
[0] = (long)dev
;
544 vfs_statfs(mp
)->f_fsid
.val
[1] = vfs_typenum(mp
);
545 vfs_setmaxsymlen(mp
, 0);
546 vfs_setflags(mp
, MNT_LOCAL
);
548 isomp
->im_mountp
= mp
;
550 isomp
->im_devvp
= devvp
;
553 * If the logical block size is not 2K then we must
554 * set the block device's physical block size to this
555 * disc's logical block size.
558 if (logical_block_size
!= iso_bsize
) {
559 iso_bsize
= logical_block_size
;
560 if ((error
= VNOP_IOCTL(devvp
, DKIOCSETBLOCKSIZE
,
561 (caddr_t
)&iso_bsize
, FWRITE
, context
)))
565 /* Check the Rock Ridge Extention support */
566 if (!(argp
->flags
& ISOFSMNT_NORRIP
)) {
567 if ( (error
= (int)buf_bread(isomp
->im_devvp
,
568 (daddr64_t
)((unsigned)((isomp
->root_extent
+ isonum_711(rootp
->ext_attr_length
)))),
569 isomp
->logical_block_size
, NOCRED
, &bp
)) ) {
571 printf("iso_mountfs: buf_bread error %d reading block %d\n",
572 error
, isomp
->root_extent
+ isonum_711(rootp
->ext_attr_length
));
573 argp
->flags
|= ISOFSMNT_NORRIP
;
576 rootp
= (struct iso_directory_record
*)((char *)0 + buf_dataptr(bp
));
578 if ((isomp
->rr_skip
= cd9660_rrip_offset(rootp
,isomp
)) < 0) {
579 argp
->flags
|= ISOFSMNT_NORRIP
;
581 argp
->flags
&= ~ISOFSMNT_GENS
;
585 * The contents are valid,
586 * but they will get reread as part of another vnode, so...
594 isomp
->im_flags
= argp
->flags
& (ISOFSMNT_NORRIP
| ISOFSMNT_GENS
|
595 ISOFSMNT_EXTATT
| ISOFSMNT_NOJOLIET
);
597 switch (isomp
->im_flags
&(ISOFSMNT_NORRIP
|ISOFSMNT_GENS
)) {
599 isomp
->iso_ftype
= ISO_FTYPE_DEFAULT
;
601 case ISOFSMNT_GENS
|ISOFSMNT_NORRIP
:
602 isomp
->iso_ftype
= ISO_FTYPE_9660
;
605 isomp
->iso_ftype
= ISO_FTYPE_RRIP
;
609 /* Decide whether to use the Joliet descriptor */
611 if (isomp
->iso_ftype
!= ISO_FTYPE_RRIP
&& joliet_level
!= 0) {
618 * On Joliet CDs use the UCS-2 volume identifier.
620 * This name can have up to 16 UCS-2 chars.
622 convflags
= UTF_DECOMPOSED
| UTF_BIG_ENDIAN
;
623 uchp
= (u_int16_t
*)sup
->volume_id
;
624 for (i
= 0; i
< 16 && uchp
[i
]; ++i
);
625 if ((utf8_encodestr((u_int16_t
*)sup
->volume_id
, (i
* 2), vol_id
,
626 &convbytes
, sizeof(vol_id
), 0, convflags
) == 0)
627 && convbytes
&& (vol_id
[0] != ' ')) {
630 /* Remove trailing spaces */
631 strp
= vol_id
+ convbytes
- 1;
632 while (strp
> vol_id
&& *strp
== ' ')
634 bcopy(vol_id
, isomp
->volume_id
, convbytes
+ 1);
637 rootp
= (struct iso_directory_record
*)
638 sup
->root_directory_record
;
639 bcopy (rootp
, isomp
->root
, sizeof(isomp
->root
));
640 isomp
->root_extent
= isonum_733 (rootp
->extent
);
641 isomp
->root_size
= isonum_733 (rootp
->size
);
643 isomp
->iso_ftype
= ISO_FTYPE_JOLIET
;
651 /* If there was a TOC in the arguments, copy it in. */
652 if (argp
->flags
& ISOFSMNT_TOC
) {
653 MALLOC(isomp
->toc
, struct CDTOC
*, argp
->toc_length
, M_ISOFSMNT
, M_WAITOK
);
654 if ((error
= copyin(argp
->toc
, isomp
->toc
, argp
->toc_length
)))
658 /* See if this could be a Video CD */
659 if ((isomp
->im_flags2
& IMF2_IS_CDXA
) && cd9660_find_video_dir(isomp
)) {
660 /* Get the 2352-bytes-per-block device. */
661 isomp
->phys_devvp
= cd9660_phys_device(mp
, context
);
664 /* Fill the default statfs information */
665 (void) cd9660_statfs(mp
, vfs_statfs(mp
), context
);
669 if (orig_bsize
!= iso_bsize
) {
670 (void)VNOP_IOCTL(devvp
, DKIOCSETBLOCKSIZE
,
671 (caddr_t
)&orig_bsize
, FWRITE
, context
);
683 FREE((caddr_t
)isomp
->toc
, M_ISOFSMNT
);
684 FREE((caddr_t
)isomp
, M_ISOFSMNT
);
686 vfs_setfsprivate(mp
, (void *)0);
692 * Make a filesystem operational.
693 * Nothing to do at the moment.
697 cd9660_start(__unused
struct mount
*mp
, __unused
int flags
,
698 __unused vfs_context_t context
)
704 * unmount system call
707 cd9660_unmount(struct mount
*mp
, int mntflags
, vfs_context_t context
)
709 struct iso_mnt
*isomp
;
710 int error
, flags
= 0;
713 if ( (mntflags
& MNT_FORCE
) ) {
718 if ( (error
= vflush(mp
, NULLVP
, flags
)) && !force
)
721 isomp
= VFSTOISOFS(mp
);
724 if (isomp
->iso_ftype
== ISO_FTYPE_RRIP
)
725 iso_dunmap(isomp
->im_dev
);
727 if (isomp
->phys_devvp
) {
728 error
= VNOP_CLOSE(isomp
->phys_devvp
, FREAD
, context
);
731 vnode_put(isomp
->phys_devvp
);
735 FREE((caddr_t
)isomp
->toc
, M_ISOFSMNT
);
736 FREE((caddr_t
)isomp
, M_ISOFSMNT
);
742 * Return root of a filesystem
745 cd9660_root(struct mount
*mp
, struct vnode
**vpp
, __unused vfs_context_t context
)
747 struct iso_mnt
*imp
= VFSTOISOFS(mp
);
748 struct iso_directory_record
*dp
=
749 (struct iso_directory_record
*)imp
->root
;
750 ino_t ino
= isodirino(dp
, imp
);
753 * With RRIP we must use the `.' entry of the root directory.
754 * Simply tell vget, that it's a relocated directory.
756 return (cd9660_vget_internal(mp
, ino
, vpp
, NULL
, NULL
,
757 imp
->iso_ftype
== ISO_FTYPE_RRIP
, dp
, current_proc()));
761 * Get file system statistics.
765 cd9660_statfs(struct mount
*mp
, struct vfsstatfs
*sbp
,
766 __unused vfs_context_t context
)
768 struct iso_mnt
*isomp
;
770 isomp
= VFSTOISOFS(mp
);
779 sbp
->f_bsize
= (uint32_t)isomp
->logical_block_size
;
780 sbp
->f_iosize
= (size_t)sbp
->f_bsize
; /* XXX */
781 sbp
->f_blocks
= (uint64_t)((unsigned long)isomp
->volume_space_size
);
782 sbp
->f_bfree
= (uint64_t)0; /* total free blocks */
783 sbp
->f_bavail
= (uint64_t)0; /* blocks free for non superuser */
784 sbp
->f_files
= (uint64_t)0; /* total files */
785 sbp
->f_ffree
= (uint64_t)0; /* free file nodes */
786 sbp
->f_fstypename
[(MFSTYPENAMELEN
- 1)] = '\0';
789 * Subtypes (flavors) for ISO 9660
791 * 1: ISO-9660 (Joliet)
792 * 2: ISO-9660 (Rockridge)
794 if (isomp
->iso_ftype
== ISO_FTYPE_JOLIET
)
795 sbp
->f_fssubtype
= 1;
796 else if (isomp
->iso_ftype
== ISO_FTYPE_RRIP
)
797 sbp
->f_fssubtype
= 2;
799 sbp
->f_fssubtype
= 0;
801 /* DO NOT use the first spare for flags; it's been reassigned for another use: */
802 /* sbp->f_spare[0] = isomp->im_flags; */
807 int cd9660_vfs_getattr(struct mount
*mp
, struct vfs_attr
*fsap
, __unused vfs_context_t context
)
810 struct vfsstatfs
*stats
= vfs_statfs(mp
);
812 imp
= VFSTOISOFS(mp
);
815 * We don't know reasonable values for f_objcount, f_filecount,
816 * f_dircount, f_maxobjcount so don't bother making up (poor)
817 * numbers like 10.3.x and earlier did.
820 VFSATTR_RETURN(fsap
, f_iosize
, stats
->f_iosize
);
821 VFSATTR_RETURN(fsap
, f_blocks
, stats
->f_blocks
);
822 VFSATTR_RETURN(fsap
, f_bfree
, stats
->f_bfree
);
823 VFSATTR_RETURN(fsap
, f_bavail
, stats
->f_bavail
);
824 VFSATTR_RETURN(fsap
, f_bused
, stats
->f_blocks
);
826 /* We don't have file counts, so don't return them */
828 /* f_fsid and f_owner should be handled by VFS */
830 /* We don't have a value for f_uuid */
832 if (VFSATTR_IS_ACTIVE(fsap
, f_capabilities
)) {
833 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_FORMAT
] =
834 (imp
->iso_ftype
== ISO_FTYPE_RRIP
? VOL_CAP_FMT_SYMBOLICLINKS
: 0) |
835 (imp
->iso_ftype
== ISO_FTYPE_RRIP
? VOL_CAP_FMT_HARDLINKS
: 0) |
836 (imp
->iso_ftype
== ISO_FTYPE_RRIP
|| imp
->iso_ftype
== ISO_FTYPE_JOLIET
837 ? VOL_CAP_FMT_CASE_SENSITIVE
: 0) |
838 VOL_CAP_FMT_CASE_PRESERVING
|
839 VOL_CAP_FMT_FAST_STATFS
;
840 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_INTERFACES
] =
841 VOL_CAP_INT_ATTRLIST
|
842 VOL_CAP_INT_NFSEXPORT
;
843 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_RESERVED1
] = 0;
844 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_RESERVED2
] = 0;
846 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_FORMAT
] =
847 VOL_CAP_FMT_PERSISTENTOBJECTIDS
|
848 VOL_CAP_FMT_SYMBOLICLINKS
|
849 VOL_CAP_FMT_HARDLINKS
|
850 VOL_CAP_FMT_JOURNAL
|
851 VOL_CAP_FMT_JOURNAL_ACTIVE
|
852 VOL_CAP_FMT_NO_ROOT_TIMES
|
853 VOL_CAP_FMT_SPARSE_FILES
|
854 VOL_CAP_FMT_ZERO_RUNS
|
855 VOL_CAP_FMT_CASE_SENSITIVE
|
856 VOL_CAP_FMT_CASE_PRESERVING
|
857 VOL_CAP_FMT_FAST_STATFS
|
858 VOL_CAP_FMT_2TB_FILESIZE
;
859 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_INTERFACES
] =
860 VOL_CAP_INT_SEARCHFS
|
861 VOL_CAP_INT_ATTRLIST
|
862 VOL_CAP_INT_NFSEXPORT
|
863 VOL_CAP_INT_ALLOCATE
|
864 VOL_CAP_INT_ADVLOCK
|
866 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_RESERVED1
] = 0;
867 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_RESERVED2
] = 0;
869 VFSATTR_SET_SUPPORTED(fsap
, f_capabilities
);
872 if (VFSATTR_IS_ACTIVE(fsap
, f_attributes
)) {
874 * VFS should really set these based on the vfs_attr and vnop_attr
875 * fields the file system supports, combined with the conversions
876 * VFS has implemented.
879 #define ISOFS_ATTR_CMN_VALIDMASK (ATTR_CMN_VALIDMASK & ~(ATTR_CMN_PAROBJID | ATTR_CMN_CRTIME | ATTR_CMN_BKUPTIME | ATTR_CMN_PARENTID))
880 #define ISOFS_ATTR_VOL_VALIDMASK (ATTR_VOL_VALIDMASK & ~(ATTR_VOL_OBJCOUNT | ATTR_VOL_FILECOUNT | ATTR_VOL_DIRCOUNT | ATTR_VOL_MAXOBJCOUNT | ATTR_VOL_NAME))
881 #define ISOFS_ATTR_DIR_VALIDMASK (ATTR_DIR_VALIDMASK & ~(ATTR_DIR_ENTRYCOUNT))
883 fsap
->f_attributes
.validattr
.commonattr
= ISOFS_ATTR_CMN_VALIDMASK
;
884 fsap
->f_attributes
.validattr
.volattr
= ISOFS_ATTR_VOL_VALIDMASK
;
885 fsap
->f_attributes
.validattr
.dirattr
= ISOFS_ATTR_DIR_VALIDMASK
;
886 fsap
->f_attributes
.validattr
.fileattr
= ATTR_FILE_VALIDMASK
;
887 fsap
->f_attributes
.validattr
.forkattr
= ATTR_FORK_VALIDMASK
;
889 fsap
->f_attributes
.nativeattr
.commonattr
= ISOFS_ATTR_CMN_VALIDMASK
;
890 fsap
->f_attributes
.nativeattr
.volattr
= ISOFS_ATTR_VOL_VALIDMASK
;
891 fsap
->f_attributes
.nativeattr
.dirattr
= ISOFS_ATTR_DIR_VALIDMASK
;
892 fsap
->f_attributes
.nativeattr
.fileattr
= ATTR_FILE_VALIDMASK
;
893 fsap
->f_attributes
.nativeattr
.forkattr
= ATTR_FORK_VALIDMASK
;
895 VFSATTR_SET_SUPPORTED(fsap
, f_attributes
);
898 VFSATTR_RETURN(fsap
, f_create_time
, imp
->creation_date
);
899 VFSATTR_RETURN(fsap
, f_modify_time
, imp
->modification_date
);
900 /* No explicit access time, so let VFS pick a default value */
901 /* No explicit backup time, so let VFS pick a default value */
908 cd9660_sync(__unused
struct mount
*mp
, __unused
int waitfor
,
909 __unused vfs_context_t context
)
916 * File handle to vnode
918 * Have to be really careful about stale file handles:
919 * - check that the inode number is in range
920 * - call iget() to get the locked inode
921 * - check for an unallocated inode (i_mode == 0)
922 * - check that the generation number matches
932 cd9660_fhtovp(mount_t mp
, int fhlen
, unsigned char *fhp
, vnode_t
*vpp
, vfs_context_t context
)
934 struct ifid
*ifhp
= (struct ifid
*)fhp
;
939 if (fhlen
< (int)sizeof(struct ifid
))
943 printf("fhtovp: ino %d, start %ld\n",
944 ifhp
->ifid_ino
, ifhp
->ifid_start
);
947 if ( (error
= VFS_VGET(mp
, (ino64_t
)ntohl(ifhp
->ifid_ino
), &nvp
, context
)) ) {
952 if (ip
->inode
.iso_mode
== 0) {
962 * Scan the TOC for the track which contains the given sector.
964 * If there is no matching track, or no TOC, then return -1.
967 cd9660_track_for_sector(struct CDTOC
*toc
, u_int sector
)
969 int i
, tracks
, result
;
974 tracks
= toc
->length
/ sizeof(struct CDTOC_Desc
);
976 result
= -1; /* Sentinel in case we don't find the right track. */
977 for (i
=0; i
<tracks
; ++i
) {
978 if (toc
->trackdesc
[i
].point
< 100 && MSF_TO_LBA(toc
->trackdesc
[i
].p
) <= sector
) {
979 result
= toc
->trackdesc
[i
].point
;
987 * Determine whether the given node is really a video CD video
988 * file. Return non-zero if it appears to be a video file.
991 cd9660_is_video_file(struct iso_node
*ip
, struct iso_mnt
*imp
)
996 /* Check whether this could really be a Video CD at all */
997 if (((imp
->im_flags2
& IMF2_IS_VCD
) == 0) ||
998 imp
->phys_devvp
== NULL
||
1001 return 0; /* Doesn't even look like VCD... */
1004 /* Make sure it is a file */
1005 if ((ip
->inode
.iso_mode
& S_IFMT
) != S_IFREG
)
1006 return 0; /* Not even a file... */
1009 * And in the right directory. This assumes the same inode
1010 * number convention that cd9660_vget_internal uses (that
1011 * part of the inode number is the block containing the
1012 * file's directory entry).
1014 lbn
= lblkno(imp
, ip
->i_number
);
1015 if (lbn
< imp
->video_dir_start
|| lbn
>= imp
->video_dir_end
)
1016 return 0; /* Not in the correct directory */
1019 * If we get here, the file should be a video file, but
1020 * do a couple of extra sanity checks just to be sure.
1021 * First, verify the form of the name
1023 if (strlen(ip
->i_namep
) != 11 || /* Wrong length? */
1024 bcmp(ip
->i_namep
+7, ".DAT", 4) || /* Wrong extension? */
1025 (bcmp(ip
->i_namep
, "AVSEQ", 5) && /* Wrong beginning? */
1026 bcmp(ip
->i_namep
, "MUSIC", 5)))
1028 return 0; /* Invalid name format */
1032 * Verify that AVSEQnn.DAT is in track #(nn+1). This would
1033 * not be appropriate for Super Video CD, which allows
1034 * multiple sessions, so the track numbers might not
1035 * match up like this.
1037 track
= (ip
->i_namep
[5] - '0') * 10 + ip
->i_namep
[6] - '0';
1038 if (track
!= (cd9660_track_for_sector(imp
->toc
, ip
->iso_start
) - 1))
1040 return 0; /* Wrong number in name */
1043 /* It must be a video file if we got here. */
1048 cd9660_vget(struct mount
*mp
, ino64_t ino
, struct vnode
**vpp
, __unused vfs_context_t context
)
1052 * It would be nice if we didn't always set the `relocated' flag
1053 * and force the extra read, but I don't want to think about fixing
1057 return ( cd9660_vget_internal( mp
, (ino_t
)ino
, vpp
, NULL
, NULL
,
1058 0, (struct iso_directory_record
*) 0, current_proc()) );
1062 cd9660_vget_internal(mount_t mp
, ino_t ino
, vnode_t
*vpp
, vnode_t dvp
,
1063 struct componentname
*cnp
, int relocated
,
1064 struct iso_directory_record
*isodir
, proc_t p
)
1066 struct iso_mnt
*imp
;
1067 struct iso_node
*ip
;
1072 struct vnode_fsparam vfsp
;
1074 int is_video_file
= 0;
1077 imp
= VFSTOISOFS(mp
);
1080 /* Check for unmount in progress */
1081 if (mp
->mnt_kern_flag
& MNTK_UNMOUNT
)
1085 MALLOC_ZONE(ip
, struct iso_node
*, sizeof(struct iso_node
),
1086 M_ISOFSNODE
, M_WAITOK
);
1088 * MALLOC_ZONE may block, so check for the inode being
1089 * present in the hash after we get back...
1090 * we also assume that we're under a filesystem lock
1091 * so that we're not reentered between the ihashget and
1094 if ((*vpp
= cd9660_ihashget(dev
, ino
, p
)) != NULLVP
) {
1095 FREE_ZONE(ip
, sizeof(struct iso_node
), M_ISOFSNODE
);
1098 bzero((caddr_t
)ip
, sizeof(struct iso_node
));
1102 ip
->i_namep
= &isonullname
[0];
1104 ip
->i_devvp
= imp
->im_devvp
;
1106 SET(ip
->i_flag
, ISO_INALLOC
);
1108 * Put it onto its hash chain and lock it so that other requests for
1109 * this inode will block if they arrive while we are sleeping waiting
1110 * for old data structures to be purged or for the contents of the
1111 * disk portion of this inode to be read.
1113 cd9660_ihashins(ip
);
1118 lbn
= lblkno(imp
, ino
);
1120 if (lbn
>= imp
->volume_space_size
) {
1121 printf("fhtovp: lbn exceed volume space %d\n", lbn
);
1125 off
= blkoff(imp
, ino
);
1127 if (off
+ ISO_DIRECTORY_RECORD_SIZE
> imp
->logical_block_size
) {
1128 printf("fhtovp: crosses block boundary %d\n",
1129 off
+ ISO_DIRECTORY_RECORD_SIZE
);
1134 error
= (int)buf_bread(imp
->im_devvp
, (daddr64_t
)((unsigned)lbn
),
1135 imp
->logical_block_size
, NOCRED
, &bp
);
1137 printf("fhtovp: buf_bread error %d\n",error
);
1140 isodir
= (struct iso_directory_record
*)(buf_dataptr(bp
) + off
);
1142 if (off
+ isonum_711(isodir
->length
) > imp
->logical_block_size
) {
1143 printf("fhtovp: directory crosses block boundary "
1144 "%d[off=%d/len=%d]\n",
1145 off
+isonum_711(isodir
->length
), off
,
1146 isonum_711(isodir
->length
));
1152 * for directories we can get parentID from adjacent
1153 * parent directory record
1155 if ((isonum_711(isodir
->flags
) & directoryBit
)
1156 && (isodir
->name
[0] == 0)) {
1157 struct iso_directory_record
*pdp
;
1159 pdp
= (struct iso_directory_record
*)
1160 ((char *)0 + buf_dataptr(bp
) + isonum_711(isodir
->length
));
1161 if ((isonum_711(pdp
->flags
) & directoryBit
)
1162 && (pdp
->name
[0] == 1))
1163 ip
->i_parent
= isodirino(pdp
, imp
);
1174 * On relocated directories we must
1175 * read the `.' entry out of a dir.
1177 ip
->iso_start
= ino
>> imp
->im_bshift
;
1179 * caclulate the correct lbn to read block 0
1180 * of this node... this used to be a cd9660_blkatoff, but
1181 * that requires the vnode to already be 'cooked'... in
1182 * the new world, we don't create a vnode until the inode
1183 * has been fully initialized... cd9660_blkatoff generates
1184 * a buf_bread for im_sector_size associated with the node's vp
1185 * I'm replacing it with a buf_bread for the same size and from
1186 * the same location on the disk, but associated with the devvp
1188 lbn
= (daddr64_t
)((unsigned)ip
->iso_start
) + 0;
1190 if ((error
= (int)buf_bread(imp
->im_devvp
, lbn
, imp
->im_sector_size
, NOCRED
, &bp
)))
1193 isodir
= (struct iso_directory_record
*)((char *)0 + buf_dataptr(bp
));
1197 * go get apple extensions to ISO directory record or use
1198 * defaults when there are no apple extensions.
1200 if ( ((isonum_711( isodir
->flags
) & directoryBit
) == 0) &&
1201 (imp
->iso_ftype
!= ISO_FTYPE_RRIP
) ) {
1202 /* This is an ISO directory record for a file */
1203 DRGetTypeCreatorAndFlags(imp
, isodir
, &ip
->i_FileType
,
1204 &ip
->i_Creator
, &ip
->i_FinderFlags
);
1206 if (isonum_711(isodir
->flags
) & associatedBit
)
1207 ip
->i_flag
|= ISO_ASSOCIATED
;
1211 * Shadow the ISO 9660 invisible state to the FinderInfo
1213 if (isonum_711(isodir
->flags
) & existenceBit
) {
1214 ip
->i_FinderFlags
|= fInvisibleBit
;
1217 ip
->iso_extent
= isonum_733(isodir
->extent
);
1218 ip
->i_size
= isonum_733(isodir
->size
);
1219 ip
->iso_start
= isonum_711(isodir
->ext_attr_length
) + ip
->iso_extent
;
1221 * account for AppleDouble header
1223 if (ip
->i_flag
& ISO_ASSOCIATED
)
1224 ip
->i_size
+= ADH_SIZE
;
1227 * if we have a valid name, fill in i_namep with UTF-8 name
1229 if (isonum_711(isodir
->name_len
) != 0) {
1234 MALLOC(utf8namep
, u_char
*, ISO_RRIP_NAMEMAX
+ 1, M_TEMP
, M_WAITOK
);
1235 namelen
= isonum_711(isodir
->name_len
);
1237 switch (imp
->iso_ftype
) {
1238 case ISO_FTYPE_RRIP
:
1239 cd9660_rrip_getname(isodir
, utf8namep
, &namelen
, &inump
, imp
);
1242 case ISO_FTYPE_JOLIET
:
1243 ucsfntrans((u_int16_t
*)isodir
->name
, namelen
,
1244 utf8namep
, &namelen
,
1245 isonum_711(isodir
->flags
) & directoryBit
, ip
->i_flag
& ISO_ASSOCIATED
);
1249 isofntrans (isodir
->name
, namelen
,
1250 utf8namep
, &namelen
,
1251 imp
->iso_ftype
== ISO_FTYPE_9660
, ip
->i_flag
& ISO_ASSOCIATED
);
1254 utf8namep
[namelen
] = '\0';
1255 MALLOC(ip
->i_namep
, u_char
*, namelen
+ 1, M_TEMP
, M_WAITOK
);
1256 bcopy(utf8namep
, ip
->i_namep
, namelen
+ 1);
1257 FREE(utf8namep
, M_TEMP
);
1261 * Setup time stamp, attribute
1263 switch (imp
->iso_ftype
) {
1264 default: /* ISO_FTYPE_9660 */
1270 if ((imp
->im_flags
& ISOFSMNT_EXTATT
) && (off
= isonum_711(isodir
->ext_attr_length
))) {
1272 lbn
= (daddr64_t
)((unsigned)ip
->iso_start
- off
);
1274 if ((error
= (int)buf_bread(imp
->im_devvp
, lbn
, imp
->im_sector_size
, NOCRED
, &bp2
))) {
1282 cd9660_defattr(isodir
, ip
, bp2
);
1283 cd9660_deftstamp(isodir
, ip
, bp2
);
1289 case ISO_FTYPE_RRIP
:
1290 cd9660_rrip_analyze(isodir
, ip
, imp
);
1294 * See if this is a Video CD file. If so, we must adjust the
1295 * length to account for larger sectors plus the RIFF header.
1296 * We also must substitute the vnop_read and vnop_pagein functions.
1298 * The cd9660_is_video_file routine assumes that the inode has
1299 * been completely set up; it refers to several fields.
1301 * This must be done before we release bp, because isodir
1302 * points into bp's data.
1304 if (cd9660_is_video_file(ip
, imp
))
1306 cd9660_xa_init(ip
, isodir
);
1310 if (ip
->iso_extent
== imp
->root_extent
) {
1311 ip
->i_parent
= 1; /* root's parent is always 1 by convention */
1312 /* mode type must be S_IFDIR */
1313 ip
->inode
.iso_mode
= (ip
->inode
.iso_mode
& ~S_IFMT
) | S_IFDIR
;
1315 vtype
= IFTOVT(ip
->inode
.iso_mode
);
1317 if (vtype
== VFIFO
) {
1323 if (vtype
== VCHR
|| vtype
== VBLK
) {
1324 struct iso_dnode
*dp
;
1326 if (dp
= iso_dmap(dev
, ino
, 0))
1327 ip
->inode
.iso_rdev
= dp
->d_dev
;
1331 * create the associated vnode
1333 //bzero(&vfsp, sizeof(struct vnode_fsparam));
1335 vfsp
.vnfs_vtype
= vtype
;
1336 vfsp
.vnfs_str
= "cd9660";
1337 vfsp
.vnfs_dvp
= dvp
;
1338 vfsp
.vnfs_fsnode
= ip
;
1339 vfsp
.vnfs_cnp
= cnp
;
1342 vfsp
.vnfs_vops
= cd9660_cdxaop_p
;
1343 else if (vtype
== VFIFO
)
1344 vfsp
.vnfs_vops
= cd9660_fifoop_p
;
1345 else if (vtype
== VBLK
|| vtype
== VCHR
)
1346 vfsp
.vnfs_vops
= cd9660_specop_p
;
1348 vfsp
.vnfs_vops
= cd9660_vnodeop_p
;
1350 if (vtype
== VBLK
|| vtype
== VCHR
)
1351 vfsp
.vnfs_rdev
= ip
->inode
.iso_rdev
;
1355 vfsp
.vnfs_filesize
= ip
->i_size
;
1357 if (dvp
&& cnp
&& (cnp
->cn_flags
& MAKEENTRY
))
1358 vfsp
.vnfs_flags
= 0;
1360 vfsp
.vnfs_flags
= VNFS_NOCACHE
;
1362 /* Tag root directory */
1363 if (ip
->iso_extent
== imp
->root_extent
)
1364 vfsp
.vnfs_markroot
= 1;
1366 vfsp
.vnfs_markroot
= 0;
1368 vfsp
.vnfs_marksystem
= 0;
1370 if ( (error
= vnode_create(VNCREATE_FLAVOR
, VCREATESIZE
, &vfsp
, &vp
)) )
1375 vnode_ref(ip
->i_devvp
);
1377 vnode_settag(vp
, VT_ISOFS
);
1383 CLR(ip
->i_flag
, ISO_INALLOC
);
1385 if (ISSET(ip
->i_flag
, ISO_INWALLOC
))
1393 cd9660_ihashrem(ip
);
1395 if (ISSET(ip
->i_flag
, ISO_INWALLOC
))
1398 FREE_ZONE(ip
, sizeof(struct iso_node
), M_ISOFSNODE
);
1404 /************************************************************************
1406 * Function: DRGetTypeCreatorAndFlags
1408 * Purpose: Set up the fileType, fileCreator and fileFlags
1412 * Side Effects: sets *theTypePtr, *theCreatorPtr, and *theFlagsPtr
1417 * 28 Jul 88 BL¡B Added a new extension type of 6, which allows
1418 * the specification of four of the finder flags.
1419 * We let the creator of the disk just copy over
1420 * the finder flags, but we only look at always
1421 * switch launch, system, bundle, and locked bits.
1422 * 15 Aug 88 BL¡B The Apple extensions to ISO 9660 implemented the
1423 * padding field at the end of a directory record
1425 * 19 Jul 89 BG Rewrote routine to handle the "new" Apple
1426 * Extensions definition, as well as take into
1427 * account the possibility of "other" definitions.
1428 * 02 Nov 89 BG Corrected the 'AA' SystemUseID processing to
1429 * check for SystemUseID == 2 (HFS). Was incorrectly
1430 * checking for SystemUseID == 1 (ProDOS) before.
1431 * 18 Mar 92 CMP Fixed the check for whether len_fi was odd or even.
1432 * Before it would always assume even for an XA record.
1433 * 26 Dec 97 jwc Swiped from MacOS implementation of ISO 9660 CD-ROM
1434 * support and modified to work in MacOSX file system.
1436 *********************************************************************** */
1439 DRGetTypeCreatorAndFlags( struct iso_mnt
* theMountPointPtr
,
1440 struct iso_directory_record
* theDirRecPtr
,
1441 u_int32_t
* theTypePtr
,
1442 u_int32_t
* theCreatorPtr
,
1443 u_int16_t
* theFlagsPtr
)
1447 u_int32_t myCreator
;
1448 AppleExtension
*myAppleExtPtr
;
1449 NewAppleExtension
*myNewAppleExtPtr
;
1450 u_int16_t myFinderFlags
;
1454 myType
= 0x3f3f3f3f;
1455 myCreator
= 0x3f3f3f3f;
1457 *theFlagsPtr
= 0x0000;
1460 * handle the fact that our original apple extensions didn't take
1461 * into account the padding byte on a file name
1464 myPtr
= &theDirRecPtr
->name
[ (isonum_711(theDirRecPtr
->name_len
)) ];
1466 /* if string length is even, bump myPtr for padding byte */
1467 if ( ((isonum_711(theDirRecPtr
->name_len
)) & 0x01) == 0 )
1469 myAppleExtPtr
= (AppleExtension
*) myPtr
;
1472 * checking for whether or not the new 'AA' code is being
1473 * called (and if so, correctly)
1475 if ( (isonum_711(theDirRecPtr
->length
)) <=
1476 ISO_DIRECTORY_RECORD_SIZE
+ (isonum_711(theDirRecPtr
->name_len
)) ) {
1481 foundStuff
= 0; /* now we default to *false* until we find a good one */
1482 myPtr
= (char *) myAppleExtPtr
;
1484 if ( (theMountPointPtr
->im_flags2
& IMF2_IS_CDXA
) != 0 )
1485 myPtr
+= 14;/* add in CD-XA fixed record offset (tnx, Phillips) */
1486 myNewAppleExtPtr
= (NewAppleExtension
*) myPtr
;
1489 * Calculate the "real" end of the directory record information.
1491 * Note: We always read the first 4 bytes of the System-Use data, so
1492 * adjust myPtr down so we don't read off the end of the directory!
1494 myPtr
= ((char *) theDirRecPtr
) + (isonum_711(theDirRecPtr
->length
));
1495 myPtr
-= sizeof(NewAppleExtension
) - 1;
1496 while( (char *) myNewAppleExtPtr
< myPtr
) /* end of directory buffer */
1499 * If we get here, we can assume that ALL further entries in this
1500 * directory record are of the form:
1502 * struct OptionalSystemUse
1504 * byte Signature[2];
1507 * byte fileType[4]; # only if HFS
1508 * byte fileCreator[4]; # only if HFS
1509 * byte finderFlags[2]; # only if HFS
1512 * This means that we can examine the Signature bytes to see
1513 * if they are 'AA' (the NEW Apple extension signature).
1514 * If they are, deal with them. If they aren't,
1515 * the OSULength field will tell us how long this extension
1516 * info is (including the signature and length bytes) and that
1517 * will allow us to walk the OptionalSystemUse records until
1518 * we hit the end of them or run off the end of the
1521 u_char
*myFromPtr
, *myToPtr
;
1524 u_int32_t fourchars
;
1528 if ( (myNewAppleExtPtr
->signature
[0] == 'A') &&
1529 (myNewAppleExtPtr
->signature
[1] == 'A') ) {
1530 if ( isonum_711(myNewAppleExtPtr
->systemUseID
) == 2 ) {
1532 foundStuff
= 1; /* we got one! */
1534 myFromPtr
= &myNewAppleExtPtr
->fileType
[0];
1535 myToPtr
= &myChars
.chars
[0];
1536 *myToPtr
++ = *myFromPtr
++;
1537 *myToPtr
++ = *myFromPtr
++;
1538 *myToPtr
++ = *myFromPtr
++;
1539 *myToPtr
= *myFromPtr
;
1540 myType
= myChars
.fourchars
; /* copy file type to user var */
1542 myFromPtr
= &myNewAppleExtPtr
->fileCreator
[0];
1543 myToPtr
= &myChars
.chars
[0];
1544 *myToPtr
++ = *myFromPtr
++;
1545 *myToPtr
++ = *myFromPtr
++;
1546 *myToPtr
++ = *myFromPtr
++;
1547 *myToPtr
= *myFromPtr
;
1548 myCreator
= myChars
.fourchars
; /* copy creator to user var */
1550 myFromPtr
= &myNewAppleExtPtr
->finderFlags
[0];
1551 myToPtr
= &myChars
.chars
[2]; /* *flags* is a short */
1552 myChars
.fourchars
= 0;
1553 *myToPtr
++ = *myFromPtr
++;
1554 *myToPtr
= *myFromPtr
;
1555 myFinderFlags
= myChars
.fourchars
;
1557 ( fAlwaysBit
| fSystemBit
| fHasBundleBit
| fLockedBit
);
1558 /* return Finder flags to user var */
1559 *theFlagsPtr
= (myFinderFlags
| fInitedBit
);
1561 break; /* exit the loop */
1566 * Check to see if we have a reasonable OSULength value.
1567 * ZERO is not an acceptable value. Nor is any value less than 4.
1570 if ( (isonum_711(myNewAppleExtPtr
->OSULength
)) < 4 )
1571 break; /* not acceptable - get out! */
1573 /* otherwise, step past this SystemUse record */
1574 (char *)myNewAppleExtPtr
+= (isonum_711(myNewAppleExtPtr
->OSULength
));
1576 } /* end of while loop */
1579 if ( foundStuff
!= 0 ) {
1580 *theTypePtr
= myType
;
1581 *theCreatorPtr
= myCreator
;
1589 } /* DRGetTypeCreatorAndFlags */
1593 * Vnode pointer to File handle
1597 cd9660_vptofh(struct vnode
*vp
, int *fhlenp
, unsigned char *fhp
, __unused vfs_context_t context
)
1599 struct iso_node
*ip
= VTOI(vp
);
1602 if (*fhlenp
< (int)sizeof(struct ifid
))
1605 ifhp
= (struct ifid
*)fhp
;
1607 ifhp
->ifid_ino
= htonl(ip
->i_number
);
1608 ifhp
->ifid_start
= htonl(ip
->iso_start
);
1609 *fhlenp
= sizeof(struct ifid
);
1612 printf("vptofh: ino %d, start %ld\n",
1613 ifhp
->ifid_ino
,ifhp
->ifid_start
);
1619 * Fast-FileSystem only?
1622 cd9660_sysctl(__unused
int *name
, __unused u_int namelen
, __unused user_addr_t oldp
,
1623 __unused
size_t *oldlenp
, __unused user_addr_t newp
,
1624 __unused
size_t newlen
, __unused vfs_context_t context
)