3 * Support for the Macintosh HFS filing system.
5 * ----------------------------------------------------------------------
6 * This code is (C) Copyright 1993,1994 by Frank Munkert.
8 * This software may be freely distributed and redistributed for
9 * non-commercial purposes, provided this notice is included.
10 * ----------------------------------------------------------------------
13 * 06-Mar-09 error - Removed madness, fixed insanity. Cleanup started
14 * 03-Nov-94 fmu - Fixed bug in HFS_Read_From_File().
15 * - Truncate file names to 30 characters.
16 * 15-Apr-93 fmu - Improved conversion routines.
17 * - Fixed bug in HFS_Find_Parent().
18 * - Fixed bug in date conversion routine.
19 * 02-Jan-93 fmu Improved search method for master directory block.
20 * 03-Dec-93 fmu - Fixed bug in HFS_Find_Leaf_Record().
21 * - Convert ':' and '/' characters.
22 * - Also convert volume names.
23 * 29-Nov-93 fmu New function HFS_Block_Size().
24 * 15-Nov-93 fmu Corrected some typing mistakes in the HFS->ISO conversion
26 * 07-Jul-02 sheutlin various changes when porting to AROS
27 * - global variables are now in a struct Globals *global
28 * - moved some definitions into hfs.h
31 #include <proto/exec.h>
32 #include <proto/utility.h>
42 #include "clib_stuff.h"
44 #define VOL(vol,tag) (((t_hfs_vol_info *)(vol->vol_info))->tag)
45 #define OBJ(obj,tag) (((t_hfs_obj_info *)(obj->obj_info))->tag)
47 /* Number of seconds betweem 01-Jan-1904 and 01-Jan-1978: */
49 #define TIME_DIFF ((74UL * 365 + 19) * 24 * 60 * 60)
51 static char const g_conv_table
[128] = {
52 'Ä', 'Å', 'Ç', 'É', 'Ñ', 'Ö', 'Ü',
53 'á', 'à', 'â', 'ä', 'ã', 'å', 'ç',
54 'é', 'è', 'ê', 'ë', 'í', 'ì', 'î',
55 'ï', 'ñ', 'ó', 'ò', 'ô', 'ö', 'õ',
56 'ú', 'ù', 'û', 'ü', '¿', '°', '¢',
57 '£', '§', '·', '¶', 'ß', '®', '©',
58 '¿', '´', '¨', '¿', 'Æ', 'Ø', '¿',
59 '±', '¿', '¿', '¥', 'µ', 'ð', '¿',
60 '¿', '¿', '¿', 'ª', 'º', '¿', 'æ',
61 'ø', '¿', '¡', '¬', '¿', '¿', '¿',
62 '¿', '«', '»', '¿', ' ', 'À', 'Ã',
63 'Õ', '¿', '¿', '', '-', '\"', '\"',
64 '`', '´', '÷', '¿', 'ÿ', '¿', '/',
65 '¤', '¿', '¿', '¿', '¿', '¿', '.',
66 '¸', '¿', '¿', 'Â', 'Ê', 'Á', 'Ë',
67 'È', 'Í', 'Î', 'Ï', 'Ì', 'Ó', 'Ô',
68 '¿', 'Ò', 'Ú', 'Û', 'Ù', '¿', '^',
69 '~', '', '¿', '·', '°', '¿', '\"',
73 void Convert_Mac_Characters (char *p_buf
, int p_buf_len
)
75 unsigned char *cp
= (unsigned char *) p_buf
;
78 for (i
=0; i
<p_buf_len
; i
++, cp
++)
80 *cp
= g_conv_table
[*cp
-128];
89 void Convert_HFS_Spaces (char *p_buf
, int p_buf_len
)
91 unsigned char *cp
= (unsigned char *) p_buf
;
94 for (i
=0; i
<p_buf_len
; i
++, cp
++)
95 if (*cp
== ' ' || *cp
== 0xA0)
99 t_uchar
*Read_Block(CDROM
*p_cdrom
, t_ulong p_block
) {
100 if (!Read_Chunk(p_cdrom
, p_block
>> 2))
103 return p_cdrom
->buffer
+ ((p_block
& 3) << 9);
106 /* Convert allocation block number into 512 byte block number.
109 t_ulong
AB_to_Block (VOLUME
*p_volume
, t_ulong p_alloc_block
)
111 return p_alloc_block
* (VOL(p_volume
,mdb
).AlBlkSiz
>> 9) +
112 VOL(p_volume
,mdb
).AlBlSt
+ VOL(p_volume
,start_block
);
115 int HFS_Find_Master_Directory_Block(CDROM
*p_cd
, t_mdb
*p_mdb
) {
117 typedef struct partition_map
122 t_ulong pmPyPartStart
;
123 t_ulong pmPartBlkCnt
;
130 block
= Read_Block(p_cd
, 1);
131 if (!block
|| block
[0] != 0x50 || block
[1] != 0x4D)
134 entries
= ((t_partition_map
*) block
)->pmMapBlkCnt
;
135 for (i
=0; i
<entries
; i
++)
137 block
= Read_Block(p_cd
, i
+1);
138 if (!block
|| block
[0] != 0x50 || block
[1] != 0x4D)
143 ((t_partition_map
*) block
)->pmPartType
,
148 result
= ((t_partition_map
*) block
)->pmPyPartStart
+ 2;
149 block
= Read_Block(p_cd
, result
);
150 if (!block
|| block
[0] != 0x42 || block
[1] != 0x44)
154 CopyMem(block
, p_mdb
, sizeof (*p_mdb
));
163 t_bool
Uses_HFS_Protocol(CDROM
*p_cd
, int *p_skip
) {
167 blk
= HFS_Find_Master_Directory_Block(p_cd
, &mdb
);
171 *p_skip
= blk
- 2; /* *p_skip holds the start block of the volume */
175 t_bool HFS_Get_Header_Node
176 (CDROM
*p_cd
, t_ulong p_mdb_pos
, t_mdb
*p_mdb
, t_hdr_node
*p_hdr_node
)
180 p_mdb_pos
- 2 + p_mdb
->AlBlSt
+
181 p_mdb
->CTExtRec
[0].StABN
* (p_mdb
->AlBlkSiz
>> 9)
185 hdr
= (t_hdr_node
*) Read_Block(p_cd
, pos
);
189 CopyMem(hdr
, p_hdr_node
, sizeof (t_hdr_node
));
193 t_node_descr
*HFS_Get_Node
194 (CDROM
*p_cd
, t_ulong p_mdb_pos
, t_mdb
*p_mdb
, t_ulong p_node
)
204 max
+= p_mdb
->CTExtRec
[i
].NumABlks
* (p_mdb
->AlBlkSiz
>> 9);
213 first_node
= (p_mdb_pos
- 2 + p_mdb
->AlBlSt
+
214 p_mdb
->CTExtRec
[i
].StABN
* (p_mdb
->AlBlkSiz
>> 9));
216 pos
= first_node
+ (p_node
- sub
);
218 return (t_node_descr
*) Read_Block(p_cd
, pos
);
221 t_node_descr
*HFS_Node(VOLUME
*p_volume
, t_ulong p_node
) {
222 return HFS_Get_Node (p_volume
->cd
, VOL(p_volume
,start_block
) + 2,
223 &VOL(p_volume
,mdb
), p_node
);
226 void HFS_Load_Catalog_Record
227 (t_catalog_record
*p_cat_rec
, char *p_node
, int p_record
)
229 short *sp
= (short *) p_node
;
233 start
= sp
[255-p_record
];
234 start
+= p_node
[start
] + 1;
238 len
= sp
[254-p_record
] - start
;
239 CopyMem(p_node
+ start
, p_cat_rec
, len
);
243 t_bool
HFS_Find_Next_Leaf(VOLUME
*p_volume
, t_leaf_record_pos
*p_leaf
) {
248 node
= HFS_Node(p_volume
, p_leaf
->node
);
253 if (p_leaf
->record
== node
->NRecs
)
257 node
= HFS_Node(p_volume
, p_leaf
->node
= node
->FLink
);
267 pos
= sp
[255-p_leaf
->record
];
268 CopyMem(node
, &p_leaf
->node_descr
, sizeof (t_node_descr
));
269 CopyMem((char *)node
+pos
, &p_leaf
->leaf_rec
, ((char *) node
)[pos
] + 1);
270 HFS_Load_Catalog_Record(&p_leaf
->cat_rec
, (char *) node
, p_leaf
->record
);
272 if (p_leaf
->leaf_rec
.name_length
> 30)
274 p_leaf
->leaf_rec
.name_length
= 30;
275 *((char *)&p_leaf
->leaf_rec
.name
[0] + 30) = '\0';
281 /* Find leaf record p_leaf->record in node p_leaf->node.
282 * Store the result in *p_leaf.
285 t_bool
HFS_Find_This_Leaf(VOLUME
*p_volume
, t_leaf_record_pos
*p_leaf
) {
290 node
= HFS_Node(p_volume
, p_leaf
->node
);
295 pos
= sp
[255-p_leaf
->record
];
296 CopyMem(node
, &p_leaf
->node_descr
, sizeof (t_node_descr
));
297 CopyMem((char *)node
+pos
, &p_leaf
->leaf_rec
, ((char *) node
)[pos
] + 1);
298 HFS_Load_Catalog_Record(&p_leaf
->cat_rec
, (char *) node
, p_leaf
->record
);
303 /* Find the first leaf record with parent ID p_parent_id.
304 * If the leaf node is found, TRUE is returned and *p_cat_rec will be
305 * loaded with the catalog record. Otherwise, FALSE is returned.
308 t_bool HFS_Find_Leaf_Record
309 (VOLUME
*p_volume
, t_leaf_record_pos
*p_leaf
, t_ulong p_parent_id
)
311 struct CDVDBase
*global
= p_volume
->global
;
315 t_ulong this_node
= VOL(p_volume
,root_node
);
318 node
= HFS_Node(p_volume
, VOL(p_volume
,root_node
));
321 global
->iso_errno
= ISOERR_SCSI_ERROR
;
332 for (i
=0; i
<node
->NRecs
; i
++)
334 t_idx_record
*idx
= (t_idx_record
*) ((char *) node
+ sp
[255-i
]);
335 if (idx
->length
!= 0)
337 if (idx
->parent_id
>= p_parent_id
)
339 next_node
= idx
->pointer
;
343 else if (node
->Type
== 0xff)
350 global
->iso_errno
= ISOERR_INTERNAL
;
356 global
->iso_errno
= ISOERR_INTERNAL
;
360 node
= HFS_Node(p_volume
, next_node
);
363 global
->iso_errno
= ISOERR_SCSI_ERROR
;
366 this_node
= next_node
;
369 p_leaf
->node
= this_node
;
371 CopyMem(node
, &p_leaf
->node_descr
, sizeof (t_node_descr
));
372 CopyMem((char *)node
+0xE, &p_leaf
->leaf_rec
, ((char *) node
)[0xe] + 1);
373 HFS_Load_Catalog_Record(&p_leaf
->cat_rec
, (char *) node
, 0);
375 /* walk forwards until the same key is found: */
378 if (p_leaf
->leaf_rec
.parent_id
== p_parent_id
)
380 if (p_leaf
->leaf_rec
.parent_id
> p_parent_id
)
382 global
->iso_errno
= ISOERR_INTERNAL
;
386 if (!HFS_Find_Next_Leaf(p_volume
, p_leaf
))
388 global
->iso_errno
= ISOERR_INTERNAL
;
394 if (p_leaf
->leaf_rec
.name_length
> 30)
396 p_leaf
->leaf_rec
.name_length
= 30;
397 *((char *)&p_leaf
->leaf_rec
.name
[0] + 30) = '\0';
403 static t_handler
const g_hfs_handler
;
405 t_bool HFS_Init_Vol_Info
406 (VOLUME
*p_volume
, int p_start_block
) {
407 struct CDVDBase
*global
= p_volume
->global
;
412 Here is a good place to check whether the values of the variables
413 g_data_fork_extension and g_resource_fork_extension are OK.
417 global
->g_data_fork_extension
[0] == 0 &&
418 (global
->g_resource_fork_extension
[0] == 0)
420 StrCpy (global
->g_resource_fork_extension
, ".rsrc");
423 Volume info initialization:
426 p_volume
->handler
= &g_hfs_handler
;
428 p_volume
->vol_info
= AllocMem (sizeof (t_hfs_vol_info
), MEMF_PUBLIC
);
429 if (!p_volume
->vol_info
)
431 global
->iso_errno
= ISOERR_NO_MEMORY
;
435 VOL(p_volume
,start_block
) = p_start_block
;
437 if (!(block
= Read_Block(p_volume
->cd
, p_start_block
+ 2)))
439 global
->iso_errno
= ISOERR_SCSI_ERROR
;
440 FreeMem (p_volume
->vol_info
, sizeof (t_hfs_vol_info
));
444 CopyMem(block
, &VOL(p_volume
,mdb
), sizeof (t_mdb
));
448 (p_volume
->cd
, p_start_block
+ 2, &VOL(p_volume
,mdb
), &hdr
)
451 global
->iso_errno
= ISOERR_SCSI_ERROR
;
452 FreeMem (p_volume
->vol_info
, sizeof (t_hfs_vol_info
));
456 VOL(p_volume
,root_node
) = hdr
.Root
;
458 p_volume
->mixed_char_filenames
= TRUE
;
463 void HFS_Close_Vol_Info(VOLUME
*p_volume
)
465 FreeMem (p_volume
->vol_info
, sizeof (t_hfs_vol_info
));
468 CDROM_OBJ
*HFS_Alloc_Obj(struct CDVDBase
*global
) {
469 CDROM_OBJ
*obj
= AllocMem (sizeof (CDROM_OBJ
), MEMF_PUBLIC
| MEMF_CLEAR
);
473 global
->iso_errno
= ISOERR_NO_MEMORY
;
477 obj
->global
= global
;
478 obj
->obj_info
= AllocMem (sizeof (t_hfs_obj_info
), MEMF_PUBLIC
| MEMF_CLEAR
);
481 FreeMem (obj
, sizeof (CDROM_OBJ
));
485 obj
->global
= global
;
490 CDROM_OBJ
*HFS_Open_Top_Level_Directory(VOLUME
*p_volume
) {
491 struct CDVDBase
*global
= p_volume
->global
;
492 CDROM_OBJ
*obj
= HFS_Alloc_Obj(global
);
497 obj
->directory_f
= TRUE
;
498 obj
->volume
= p_volume
;
500 OBJ(obj
,parent_id
) = 1;
501 StrCpy (OBJ(obj
,name
), ":");
502 OBJ(obj
,cat_rec
).d
.DirID
= 2;
507 CDROM_OBJ
*HFS_Open_Object(VOLUME
*p_volume
, char *p_name
, t_ulong p_parent
) {
508 t_leaf_record_pos leaf
;
509 struct CDVDBase
*global
= p_volume
->global
;
513 t_bool data_fork
= FALSE
;
515 if (!HFS_Find_Leaf_Record(p_volume
, &leaf
, p_parent
))
520 type
= leaf
.cat_rec
.d
.type
;
521 if (type
== 1 || type
== 2)
523 if (leaf
.leaf_rec
.parent_id
!= p_parent
)
525 global
->iso_errno
= ISOERR_NOT_FOUND
;
529 CopyMem(leaf
.leaf_rec
.name
, name
, leaf
.leaf_rec
.name_length
);
530 name
[leaf
.leaf_rec
.name_length
] = 0;
532 if (global
->g_convert_hfs_filenames
)
533 Convert_Mac_Characters (name
, leaf
.leaf_rec
.name_length
);
534 if (global
->g_convert_hfs_spaces
)
535 Convert_HFS_Spaces (name
, leaf
.leaf_rec
.name_length
);
539 if (Stricmp ((UBYTE
*) p_name
, (UBYTE
*) name
) == 0)
544 StrCat (name
, global
->g_data_fork_extension
);
545 if (Stricmp ((UBYTE
*) p_name
, (UBYTE
*) name
) == 0)
550 name
[leaf
.leaf_rec
.name_length
] = 0;
551 StrCat (name
, global
->g_resource_fork_extension
);
552 if (Stricmp ((UBYTE
*) p_name
, (UBYTE
*) name
) == 0)
559 if (!HFS_Find_Next_Leaf(p_volume
, &leaf
))
563 obj
= HFS_Alloc_Obj(global
);
564 obj
->directory_f
= (type
== 1);
565 obj
->volume
= p_volume
;
567 OBJ(obj
,data_fork
) = data_fork
;
568 OBJ(obj
,parent_id
) = p_parent
;
569 StrCpy (OBJ(obj
,name
), name
);
570 CopyMem(&leaf
.cat_rec
, &OBJ(obj
,cat_rec
), sizeof (t_catalog_record
));
575 /* Open the object with name p_name in the directory p_dir.
576 * p_name must not contain '/' or ':' characters.
579 CDROM_OBJ
*HFS_Open_Obj_In_Directory(CDROM_OBJ
*p_dir
, char *p_name
) {
580 return HFS_Open_Object(p_dir
->volume
, p_name
, OBJ(p_dir
,cat_rec
).d
.DirID
);
583 CDROM_OBJ
*HFS_Find_Parent(CDROM_OBJ
*p_obj
) {
584 struct CDVDBase
*global
= p_obj
->global
;
585 t_leaf_record_pos leaf
;
587 if (OBJ(p_obj
,parent_id
) == 2)
588 return HFS_Open_Top_Level_Directory(p_obj
->volume
);
590 if (!HFS_Find_Leaf_Record(p_obj
->volume
, &leaf
, OBJ(p_obj
,parent_id
)))
595 if (leaf
.leaf_rec
.parent_id
!= OBJ(p_obj
,parent_id
))
597 global
->iso_errno
= ISOERR_INTERNAL
;
600 if (leaf
.cat_rec
.d
.type
== 3)
603 CopyMem(leaf
.cat_rec
.dt
.CName
, buf
, leaf
.cat_rec
.dt
.CNameLen
);
604 buf
[leaf
.cat_rec
.dt
.CNameLen
] = 0;
605 if (global
->g_convert_hfs_filenames
)
606 Convert_Mac_Characters (buf
, leaf
.cat_rec
.dt
.CNameLen
);
607 if (global
->g_convert_hfs_spaces
)
608 Convert_HFS_Spaces (buf
, leaf
.cat_rec
.dt
.CNameLen
);
609 return HFS_Open_Object(p_obj
->volume
, buf
, leaf
.cat_rec
.dt
.ParID
);
611 if (!HFS_Find_Next_Leaf(p_obj
->volume
, &leaf
))
616 void HFS_Close_Obj(CDROM_OBJ
*p_obj
)
618 FreeMem (p_obj
->obj_info
, sizeof (t_hfs_obj_info
));
619 FreeMem (p_obj
, sizeof (CDROM_OBJ
));
622 int HFS_Read_From_File(CDROM_OBJ
*p_file
, char *p_buffer
, int p_buffer_length
)
624 struct CDVDBase
*global
= p_file
->global
;
626 int remain_block
, remain_file
, remain
;
632 t_bool data_fork
= OBJ(p_file
,data_fork
);
634 t_ulong data_length
= (data_fork
? OBJ(p_file
,cat_rec
).f
.LgLen
:
635 OBJ(p_file
,cat_rec
).f
.RLgLen
);
637 if (p_file
->pos
== data_length
)
639 /* at end of file: */
643 cd
= p_file
->volume
->cd
;
644 first_block
= AB_to_Block
648 OBJ(p_file
,cat_rec
).f
.ExtRec
[0].StABN
:
649 OBJ(p_file
,cat_rec
).f
.RExtRec
[0].StABN
651 block
= first_block
+ (p_file
->pos
>> 9);
652 todo
= p_buffer_length
;
658 if (0 == Read_Chunk(cd
, block
>> 2))
660 global
->iso_errno
= ISOERR_SCSI_ERROR
;
664 data
= cd
->buffer
+ ((block
& 3) << 9);
667 * this is offset within first block
669 pos
= p_file
->pos
& 511;
672 * depending on logical block location, we will have up to 32kB of data here.
673 * we always read in 32768bytes chunks, so the first of 16 sectors in group yields largest amount
675 remain_block
= (SCSI_BUFSIZE
<< 4) - ((block
<< 9) & ((SCSI_BUFSIZE
<< 4) - 1)) - pos
;
678 * how much data left in a file do we have?
680 remain_file
= data_length
- p_file
->pos
;
683 * and how much can we read (file vs block)
685 remain
= (remain_block
< remain_file
) ? remain_block
: remain_file
;
688 * last: how much the *user* wants to read?
690 len
= (todo
< remain
) ? todo
: remain
;
695 CopyMem ((APTR
) (data
+ pos
), (APTR
) (p_buffer
+ buf_pos
), len
);
698 * update position in user buffer
700 * reduce amount of bytes to be read
709 if (p_file
->pos
>= data_length
)
714 * - HFS block size is 512bytes (so we have up to 64 such blocks in a chunk)
715 * - block + 64 moves us to next chunk, while
716 * - &~63 puts us at the beginning of it.
718 block
= (block
+ 64) &~ 63 ;
724 t_bool
HFS_Cdrom_Info(CDROM_OBJ
*p_obj
, CDROM_INFO
*p_info
) {
725 p_info
->symlink_f
= 0;
726 p_info
->directory_f
= p_obj
->directory_f
;
727 p_info
->name_length
= StrLen (OBJ(p_obj
,name
));
728 CopyMem(OBJ(p_obj
,name
), p_info
->name
, p_info
->name_length
);
729 if (p_info
->directory_f
)
731 p_info
->file_length
= 0;
732 p_info
->date
= OBJ(p_obj
,cat_rec
).d
.CrDat
- TIME_DIFF
;
736 if (OBJ(p_obj
,data_fork
))
737 p_info
->file_length
= OBJ(p_obj
,cat_rec
).f
.LgLen
;
739 p_info
->file_length
= OBJ(p_obj
,cat_rec
).f
.RLgLen
;
740 p_info
->date
= OBJ(p_obj
,cat_rec
).f
.CrDat
- TIME_DIFF
;
746 /* The 'offset' is a long integer coded like this:
748 * Bit: | 31 ... 8 | 7 6 | 5 4 3 2 1 0
750 * Contents: | Node number | Fork | Record number
752 * The "Fork" value is encoded as follows:
760 t_bool HFS_Examine_Next
761 (CDROM_OBJ
*p_obj
, CDROM_INFO
*p_info
, uint32_t *p_offset
)
763 struct CDVDBase
*global
= p_obj
->global
;
764 t_leaf_record_pos leaf
;
772 !HFS_Find_Leaf_Record
773 (p_obj
->volume
, &leaf
, OBJ(p_obj
,cat_rec
).d
.DirID
)
779 leaf
.node
= *p_offset
>> 8;
780 leaf
.record
= *p_offset
& 63;
781 fork
= (*p_offset
& 0xC0) >> 6;
785 if (!HFS_Find_This_Leaf(p_obj
->volume
, &leaf
))
790 if (!HFS_Find_Next_Leaf(p_obj
->volume
, &leaf
))
792 if (leaf
.leaf_rec
.parent_id
!= OBJ(p_obj
,cat_rec
).d
.DirID
)
796 if (leaf
.cat_rec
.d
.type
== 1)
798 else if (leaf
.cat_rec
.d
.type
!= 2)
800 else if (fork
!= 0 && leaf
.cat_rec
.f
.LgLen
> 0)
802 else if (leaf
.cat_rec
.f
.RLgLen
> 0)
807 *p_offset
= ((leaf
.node
<< 8) + (fork
<< 6) + leaf
.record
);
811 p_info
->symlink_f
= 0;
812 p_info
->directory_f
= (leaf
.cat_rec
.d
.type
== 1);
813 p_info
->name_length
= leaf
.leaf_rec
.name_length
;
814 CopyMem(leaf
.leaf_rec
.name
, p_info
->name
, leaf
.leaf_rec
.name_length
);
815 if (global
->g_convert_hfs_filenames
)
816 Convert_Mac_Characters (p_info
->name
, p_info
->name_length
);
817 if (global
->g_convert_hfs_spaces
)
818 Convert_HFS_Spaces (p_info
->name
, p_info
->name_length
);
819 if (p_info
->directory_f
)
821 p_info
->file_length
= 0;
822 p_info
->date
= leaf
.cat_rec
.d
.CrDat
- TIME_DIFF
;
830 global
->g_data_fork_extension
,
831 p_info
->name
+ p_info
->name_length
,
832 StrLen (global
->g_data_fork_extension
)
834 p_info
->name_length
+= StrLen (global
->g_data_fork_extension
);
835 p_info
->file_length
= leaf
.cat_rec
.f
.LgLen
;
841 global
->g_resource_fork_extension
,
842 p_info
->name
+ p_info
->name_length
,
843 StrLen (global
->g_resource_fork_extension
)
845 p_info
->name_length
+= StrLen (global
->g_resource_fork_extension
);
846 p_info
->file_length
= leaf
.cat_rec
.f
.RLgLen
;
848 p_info
->date
= leaf
.cat_rec
.f
.CrDat
- TIME_DIFF
;
850 p_info
->suppl_info
= NULL
;
855 void *HFS_Clone_Obj_Info(void *p_info
) {
856 t_hfs_obj_info
*info
= (t_hfs_obj_info
*) p_info
;
859 new = AllocMem (sizeof (t_hfs_obj_info
), MEMF_PUBLIC
);
863 CopyMem(info
, new, sizeof (t_hfs_obj_info
));
868 t_bool
HFS_Is_Top_Level_Obj (CDROM_OBJ
*p_obj
)
870 return OBJ(p_obj
,parent_id
) == 1;
873 t_bool
HFS_Same_Objects (CDROM_OBJ
*p_obj1
, CDROM_OBJ
*p_obj2
)
875 if (OBJ(p_obj1
,cat_rec
).d
.type
!= OBJ(p_obj2
,cat_rec
).d
.type
)
878 if (OBJ(p_obj1
,cat_rec
).d
.type
== 1)
879 return OBJ(p_obj1
,cat_rec
).d
.DirID
== OBJ(p_obj2
,cat_rec
).d
.DirID
;
881 return OBJ(p_obj1
,cat_rec
).f
.FlNum
== OBJ(p_obj2
,cat_rec
).f
.FlNum
;
884 t_ulong
HFS_Creation_Date(VOLUME
*p_volume
)
886 return VOL(p_volume
,mdb
).CrDate
- TIME_DIFF
;
889 /* Return volume size in 2048 byte blocks:
892 t_ulong
HFS_Volume_Size (VOLUME
*p_volume
)
894 return (VOL(p_volume
,mdb
).NmAlBlks
* (VOL(p_volume
,mdb
).AlBlkSiz
>> 9));
897 t_ulong
HFS_Block_Size (VOLUME
*p_volume
)
902 void HFS_Volume_Id(VOLUME
*p_volume
, char *p_buf
, int p_buf_length
) {
903 struct CDVDBase
*global
= p_volume
->global
;
904 int len
= p_buf_length
- 1;
906 if (len
> VOL(p_volume
,mdb
).VolNameLen
)
907 len
= VOL(p_volume
,mdb
).VolNameLen
;
909 CopyMem(VOL(p_volume
,mdb
).VolName
, p_buf
, len
);
912 if (global
->g_convert_hfs_filenames
)
913 Convert_Mac_Characters (p_buf
, len
);
914 if (global
->g_convert_hfs_spaces
)
915 Convert_HFS_Spaces (p_buf
, len
);
918 t_ulong
HFS_Location (CDROM_OBJ
*p_obj
)
920 if (p_obj
->directory_f
) {
921 if (Is_Top_Level_Object (p_obj
))
923 return OBJ(p_obj
,cat_rec
).d
.DirID
;
925 return OBJ(p_obj
,cat_rec
).f
.FlNum
;
928 t_ulong
HFS_File_Length (CDROM_OBJ
*p_obj
)
930 return (OBJ(p_obj
,data_fork
) ?
931 OBJ(p_obj
,cat_rec
).f
.LgLen
:
932 OBJ(p_obj
,cat_rec
).f
.RLgLen
);
935 static t_handler
const g_hfs_handler
= {
937 HFS_Open_Top_Level_Directory
,
938 HFS_Open_Obj_In_Directory
,
945 HFS_Is_Top_Level_Obj
,