3 * Interactive test program for the ISO- and Rock-Ridge-support
6 * ----------------------------------------------------------------------
7 * This code is (C) Copyright 1993,1994 by Frank Munkert.
9 * This software may be freely distributed and redistributed for
10 * non-commercial purposes, provided this notice is included.
11 * ----------------------------------------------------------------------
14 * 28-Dec-12 neil Adapted to new Read_TOC API.
15 * 06-Mar-09 error - Removed madness, fixed insanity. Cleanup started
16 * 18-Aug-07 sonic - Now builds on AROS.
17 * 06-May-07 sonic - Added separate "g" option for listing directories in Joliet format.
18 * - Added support for protection bits and file comments.
19 * 08-Mar-07 sonic - Removed redundant "TRACKDISK" option.
20 * - Removed unneeded dealing with block length.
21 * 31-Mar-07 sonic Added support for Joliet and character set translation.
22 * 17-Feb-94 fmu Fixed typo.
23 * 28-Nov-93 fmu Improved "cdrom d" command.
24 * 12-Oct-93 fmu "Show path table" function removed.
25 * 09-Oct-93 fmu Open utility.library.
33 #include <devices/trackdisk.h>
35 #include <clib/alib_protos.h>
37 #include <proto/dos.h>
38 #include <proto/exec.h>
49 #include <pragmas/dos_pragmas.h>
50 #include <pragmas/exec_pragmas.h>
51 extern struct Library
*SysBase
, *DOSBase
;
56 #define STD_BUFFERS 20
59 void dbprintf (char *p_dummy
, ...)
65 struct CDVDBase
*global
= &glob
;
70 Cleanup_CDROM (global
->g_cd
);
73 CloseLibrary(CodesetsBase
);
75 CloseLibrary ((struct Library
*) UtilityBase
);
81 "Usage: cdrom command [parameters]\n"
83 " a Show information on CDROM drive\n"
84 " b Read table of contents\n"
85 " c name Show contents of file 'name'\n"
86 " d[rl] dir Show contents of directory 'dir' (use ISO names)\n"
87 " r=also show subdirectories, l=show additional information\n"
88 " e[r[l|L]] dir Show contents of directory 'dir' (use Rock Ridge names)\n"
89 " r=also show subdirectories, l=show system use field names\n"
90 " L=show names and contents of system use fields\n"
91 " g[rl] dir Show contents of girectory 'dir' (use Joliet names)\n"
92 " r=also show subdirectories, l=show additional information\n"
93 " f dir name Change to directory 'dir' and try to find object 'name'\n"
94 " i Check which protocol is used\n"
95 " j [01] 0=start audio, 1=stop motor\n"
96 " l Find offset of last session\n"
97 " m num Read catalog node 'num' (MacHFS only)\n"
98 " o name Try to open object 'name'\n"
99 " r Read contents of root directory\n"
100 " s num [cnt] Read 'cnt' sectors, starting at sector 'num'\n"
101 " t name Try to open parent of object 'name'\n"
102 " v Read primary volume descriptor\n"
103 " x dens [length] Select mode: dens=density code,\n"
104 " length=block length (default: 2048)\n"
105 " z Send test unit ready command\n"
106 " T Test trackdisk device\n"
107 "Use \":\" as the name of the root directory\n"
112 char *MKSTR (char *p_in
, int p_length
, char *p_out
)
118 while (len
&& p_in
[len
-1] == ' ')
121 for (i
=0; i
<len
; i
++)
129 void Show_Flags (unsigned char p_flags
)
132 printf ("existence ");
134 printf ("directory ");
136 printf ("associated ");
140 printf ("protection ");
142 printf ("multi-extent ");
145 void Show_Directory_Record (directory_record
*p_dir
)
149 printf ("Extended Attr Record Length: %d\n", (int) p_dir
->ext_attr_length
);
150 printf ("Location of Extent: %lu\n", (unsigned long)p_dir
->extent_loc
);
151 printf ("Data Length: %lu\n", (unsigned long)p_dir
->data_length
);
152 printf ("Recording Date and Time: %02d.%02d.19%02d %02d:%02d:%02d %+d\n",
153 (int) p_dir
->day
, (int) p_dir
->month
, (int) p_dir
->year
,
154 (int) p_dir
->hour
, (int) p_dir
->minute
, (int) p_dir
->second
,
156 printf ("Flags: %d (", (int) p_dir
->flags
);
157 Show_Flags (p_dir
->flags
);
159 printf ("File Unit Size: %d\n", (int) p_dir
->file_unit_size
);
160 printf ("Gap Size: %d\n", (int) p_dir
->gap_size
);
161 printf ("Volume Sequence Number: %hu\n", p_dir
->sequence
);
162 printf ("File Identifier: ");
163 if (p_dir
->file_id
[0] == 0)
165 else if (p_dir
->file_id
[0] == 1)
168 printf ("%s\n", MKSTR (p_dir
->file_id
, p_dir
->file_id_length
, buf
));
171 void Find_Block_Starting_With (CDROM
*p_cd
, int p_val
)
178 if (!Read_Chunk (p_cd
, sec
)) {
179 fprintf (stderr
, "cannot read sector 16\n");
182 for (i
=0; i
<4; i
++) {
183 cmp
= p_cd
->buffer
[i
<<9] * 256 + p_cd
->buffer
[(i
<<9)+1];
185 printf ("sector %lu, block %d\n", (unsigned long)sec
, i
);
191 void Show_Primary_Volume_Descriptor (CDROM
*p_cd
)
199 t_ulong offset
, svd_offset
;
203 hfs
= Uses_HFS_Protocol (p_cd
, &skip
);
204 protocol
= Which_Protocol (p_cd
, TRUE
, TRUE
, &skip
, &offset
, &svd_offset
);
206 if (protocol
== PRO_UNKNOWN
) {
207 printf ("Unknown protocol\n");
211 if (protocol
== PRO_HIGH_SIERRA
) {
212 printf ("High sierra protocol (not supported)\n");
215 if ((protocol
== PRO_ROCK
|| protocol
== PRO_ISO
) && hfs
)
216 printf ("Multi-platform disk: HFS & ISO\n");
218 if (protocol
== PRO_ROCK
)
219 printf ("Rock Ridge extensions available, skip size = %d\n", skip
);
221 if (protocol
== PRO_ISO
|| protocol
== PRO_JOLIET
)
222 printf ("Data track offset = %lu\n", (unsigned long)offset
);
224 if (protocol
== PRO_JOLIET
)
225 printf ("Joliet SVD offset = %lu\n", (unsigned long)svd_offset
);
227 if (protocol
== PRO_ISO
|| protocol
== PRO_ROCK
|| protocol
== PRO_JOLIET
) {
229 if (!Read_Chunk (p_cd
, 16 + offset
)) {
230 fprintf (stderr
, "cannot read sector %lu\n", 16 + (unsigned long)offset
);
234 pvd
= (prim_vol_desc
*) p_cd
->buffer
;
235 printf ("--- ISO-9660: ---\n");
236 printf ("Volume Descriptor Type: %d\n", (int) pvd
->type
);
237 printf ("Standard Identifier: %s\n", MKSTR (pvd
->id
,5,buf
));
238 printf ("Volume Descriptor Version: %d\n", (int) pvd
->version
);
239 printf ("System Identifier: %s\n", MKSTR (pvd
->system_id
,32,buf
));
240 printf ("Volume Identifier: %s\n", MKSTR (pvd
->volume_id
,32,buf
));
241 printf ("Volume Space Size: %lu\n", (unsigned long) pvd
->space_size
);
242 printf ("Volume Set Size: %hu\n", pvd
->set_size
);
243 printf ("Volume Sequence Number: %hu\n", pvd
->sequence
);
244 printf ("Logical Block Size: %hu\n", pvd
->block_size
);
245 printf ("Path Table Size: %lu\n", (unsigned long) pvd
->path_size
);
246 printf ("Location of Occ of M Path Table: %lu\n", (unsigned long) pvd
->table
);
247 printf ("Location of Occ of Opt M Path T: %lu\n", (unsigned long) pvd
->opt_table
);
248 printf ("Volume Set Identifier: %s\n",
249 MKSTR (pvd
->volume_set_id
,128,buf
));
250 printf ("Publisher Identifier: %s\n",
251 MKSTR (pvd
->publisher_id
,128,buf
));
252 printf ("Data Preparer Identifier: %s\n",
253 MKSTR (pvd
->data_preparer
,128,buf
));
254 printf ("Application Identifier: %s\n",
255 MKSTR (pvd
->application_id
,128,buf
));
256 printf ("Copyright File Identifier: %s\n",
257 MKSTR (pvd
->copyright
,37,buf
));
258 printf ("Abstract File Identifier: %s\n",
259 MKSTR (pvd
->abstract_file_id
,37,buf
));
260 printf ("Bibliographic File Identifier: %s\n",
261 MKSTR (pvd
->bibliographic_id
,37,buf
));
262 printf ("File Structure Version: %d\n",
263 (int) pvd
->file_structure_version
);
264 printf ("ROOT DIRECTORY RECORD:\n");
265 Show_Directory_Record (&pvd
->root
);
269 if ((blk
= HFS_Find_Master_Directory_Block (p_cd
, &mdb
)) < 0) {
270 printf ("No master directory block found\n");
273 printf ("--- MacHFS: ---\n");
274 printf ("Master directory block located at block %d\n", blk
);
275 printf ("Volume signature: 0x%hx\n", mdb
.SigWord
);
276 printf ("Date/Time of creation: %lu\n", (unsigned long)mdb
.CrDate
);
277 printf ("Date/Time of last modification: %lu\n", (unsigned long)mdb
.LsMod
);
278 printf ("Volume attributes: 0x%hx\n", mdb
.Atrb
);
279 printf ("Number of files in root dir: %u\n", mdb
.NmFls
);
280 printf ("Allocation block size: %lu bytes\n", (unsigned long)mdb
.AlBlkSiz
);
281 printf ("Loc of first allocation block: %u\n", mdb
.AlBlSt
);
282 printf ("Volume name: %s\n",
283 MKSTR ((char *) mdb
.VolName
, mdb
.VolNameLen
,buf
));
284 printf ("Number of files in volume: %lu\n", (unsigned long)mdb
.FilCnt
);
285 printf ("Number of dirs in volume: %lu\n", (unsigned long)mdb
.DirCnt
);
286 printf ("Size of catalog file: %lu allocation blocks\n",
287 (unsigned long)mdb
.CTFlSize
);
288 printf ("Extent record for catalog file:\n");
289 printf (" 1. allocation block: %10lu length: %10lu\n",
290 (unsigned long)mdb
.CTExtRec
[0].StABN
, (unsigned long)mdb
.CTExtRec
[0].NumABlks
);
291 printf (" 2. allocation block: %10lu length: %10lu\n",
292 (unsigned long)mdb
.CTExtRec
[1].StABN
, (unsigned long)mdb
.CTExtRec
[1].NumABlks
);
293 printf (" 3. allocation block: %10lu length: %10lu\n",
294 (unsigned long)mdb
.CTExtRec
[2].StABN
, (unsigned long)mdb
.CTExtRec
[2].NumABlks
);
295 if (!HFS_Get_Header_Node (p_cd
, blk
, &mdb
, &hdr
))
296 printf ("*** Cannot read header node!!!\n");
297 printf ("Header node:\n");
298 printf ("Depth of tree: %u\n", hdr
.Depth
);
299 printf ("Number of root node: %lu\n", (unsigned long)hdr
.Root
);
300 printf ("Number of leaf records in tree: %lu\n", (unsigned long)hdr
.NRecs
);
301 printf ("Number of first leaf node: %lu\n", (unsigned long)hdr
.FNode
);
302 printf ("Number of last leaf node: %lu\n", (unsigned long)hdr
.LNode
);
306 void Show_Directory (CDROM
*p_cd
, uint32_t p_location
, uint32_t p_length
)
311 if (!Read_Chunk (p_cd
, p_location
)) {
312 fprintf (stderr
, "cannot read sector %lu\n", (unsigned long)p_location
);
316 while (cnt
< p_length
) {
317 directory_record
*dir
= (directory_record
*) (p_cd
->buffer
+ pos
);
319 if (dir
->length
== 0)
321 Show_Directory_Record (dir
);
324 if (cnt
< p_length
) {
325 printf ("------------------------------------------------------------\n");
327 if (!Read_Chunk (p_cd
, ++p_location
)) {
328 fprintf (stderr
, "cannot read sector %lu\n", (unsigned long)p_location
);
337 void Show_Root_Directory (CDROM
*p_cd
)
341 if (!Read_Chunk (p_cd
, 16)) {
342 fprintf (stderr
, "cannot read sector 16\n");
346 pvd
= (prim_vol_desc
*) p_cd
->buffer
;
348 Show_Directory (p_cd
, pvd
->root
.extent_loc
, pvd
->root
.data_length
);
351 void Check_Protocol (CDROM
*p_cd
)
354 t_ulong offset
, svd_offset
;
356 switch (Which_Protocol (p_cd
, TRUE
, TRUE
, &skip
, &offset
, &svd_offset
)) {
358 printf ("Rock Ridge protocol, skip length = %d\n", skip
);
361 printf ("ISO-9660 protocol, offset = %lu\n", (unsigned long)offset
);
364 printf ("Joliet protocol, offset = %lu SVD offset = %lu\n", (unsigned long)offset
, (unsigned long)svd_offset
);
367 printf ("Macintosh HFS protocol\n");
369 case PRO_HIGH_SIERRA
:
370 printf ("High Sierra protocol\n");
373 printf ("Unknown protocol, iso_errno = %d\n", global
->iso_errno
);
378 void Try_To_Open (CDROM
*p_cd
, char *p_directory
, char *p_name
)
381 CDROM_OBJ
*top
= NULL
;
387 if (!(vol
= Open_Volume (p_cd
, 1, 1))) {
388 fprintf (stderr
, "cannot open volume; iso_errno = %d\n", global
->iso_errno
);
392 if (p_directory
&& p_directory
!= (char *) -1) {
393 if (!(top
= Open_Top_Level_Directory (vol
))) {
394 fprintf (stderr
, "cannot open top level directory\n");
399 if (!(home
= Open_Object (top
, p_directory
))) {
400 fprintf (stderr
, "cannot open top level directory\n");
406 if (!(home
= Open_Top_Level_Directory (vol
))) {
407 fprintf (stderr
, "cannot open home directory;"
408 " iso_errno = %d\n", global
->iso_errno
);
413 obj
= Open_Object (home
, p_name
);
416 printf ("%s '%s' found, location = %lu\n",
417 obj
->symlink_f
? "Symbolic link" :
418 obj
->directory_f
? "Directory" : "File",
419 p_name
, (unsigned long)Location (obj
));
420 printf ("Protection bits: 0x%08lX\n", (unsigned long)obj
->protection
);
421 if (obj
->symlink_f
) {
424 if (Get_Link_Name (obj
, linkname
, sizeof (linkname
)))
425 printf ("'%s'\n", linkname
);
427 printf ("unknown file or directory\n");
429 if (Full_Path_Name (obj
, pathname
, sizeof (pathname
)))
430 printf ("Full path name: %s\n", pathname
);
432 printf ("Full path name unknown\n");
433 if (CDROM_Info (obj
, &info
)) {
434 printf ("INFO Name = ");
435 fwrite (info
.name
, info
.name_length
, 1, stdout
);
437 printf ("INFO Comment = ");
438 fwrite (info
.comment
, info
.comment_length
, 1, stdout
);
441 printf ("CANNOT FIND INFO FOR OBJECT!\n");
442 if (p_directory
== (char *) -1) {
443 parent
= Find_Parent (obj
);
445 printf ("parent found, location = %lu\n",
446 (unsigned long)Location (parent
));
447 Close_Object (parent
);
449 printf ("parent not found, iso_errno = %d\n", global
->iso_errno
);
453 if (global
->iso_errno
== ISOERR_NOT_FOUND
)
454 printf ("Object '%s' not found\n", p_name
);
456 printf ("Object '%s': iso_errno = %d\n", p_name
, global
->iso_errno
);
465 void Show_File_Contents (CDROM
*p_cd
, char *p_name
)
470 #define THEBUFSIZE 99
471 char buffer
[THEBUFSIZE
];
474 if (!(vol
= Open_Volume (p_cd
, 1, 1))) {
475 fprintf (stderr
, "cannot open volume; iso_errno = %d\n", global
->iso_errno
);
479 if (!(home
= Open_Top_Level_Directory (vol
))) {
480 fprintf (stderr
, "cannot open top level directory;"
481 " iso_errno = %d\n", global
->iso_errno
);
485 obj
= Open_Object (home
, p_name
);
488 cnt
= Read_From_File (obj
, buffer
, THEBUFSIZE
);
490 fprintf (stderr
, "cannot read from file!\n");
495 fwrite (buffer
, cnt
, 1, stdout
);
501 fprintf (stderr
, "Object '%s': iso_errno = %d\n", p_name
, global
->iso_errno
);
509 void Print_System_Use_Fields (CDROM
*p_cd
, directory_record
*p_dir
,
510 int p_skip_size
, int p_long
)
514 uint32_t length
= p_dir
->length
;
515 unsigned char *buf
= (unsigned char *) p_dir
;
517 printf (" system use fields: ");
521 system_use_pos
= 33 + p_dir
->file_id_length
;
522 if (system_use_pos
& 1)
524 system_use_pos
+= p_skip_size
;
526 /* the system use field must be at least 4 bytes long */
527 while (system_use_pos
+ 3 < length
) {
528 slen
= buf
[system_use_pos
+2];
529 /* look for continuation area: */
530 if (buf
[system_use_pos
] == 'C' &&
531 buf
[system_use_pos
+1] == 'E') {
532 uint32_t newloc
, offset
;
534 memcpy (&newloc
, buf
+ system_use_pos
+ 8, 4);
535 memcpy (&offset
, buf
+ system_use_pos
+ 16, 4);
536 memcpy (&length
, buf
+ system_use_pos
+ 24, 4);
537 if (!Read_Chunk (p_cd
, newloc
))
540 system_use_pos
= offset
;
542 /* look for system use field terminator: */
543 } else if (buf
[system_use_pos
] == 'S' &&
544 buf
[system_use_pos
+1] == 'T') {
547 } else if (buf
[system_use_pos
] == 'S' &&
548 /* special handling for SL field: */
549 buf
[system_use_pos
+1] == 'L') {
550 printf ("SL(%s%d,", (buf
[system_use_pos
+4] & 1)? "cont " : "",
551 (int) buf
[system_use_pos
+5]);
552 fwrite (buf
+ system_use_pos
+ 7, buf
[system_use_pos
+6], 1, stdout
);
557 putchar (buf
[system_use_pos
]);
558 putchar (buf
[system_use_pos
+1]);
562 for (i
=0; i
< slen
-2; i
++) {
563 if (i
&& (i
& 15) == 0)
565 printf ("%2.2x ", (int) buf
[system_use_pos
+i
+2]);
573 system_use_pos
+= slen
;
579 void Show_Subdirectory (CDROM_OBJ
*p_home
, char *p_name
, int p_long_info
,
584 VOLUME
*vol
= p_home
->volume
;
585 obj
= Open_Object (p_home
, p_name
);
589 while (Examine_Next (obj
, &info
, &offset
)) {
590 directory_record
*dir
= info
.suppl_info
;
591 fwrite (info
.name
, info
.name_length
, 1, stdout
);
593 printf (" (symbolic link)");
594 else if (info
.directory_f
)
597 if (p_long_info
&& dir
) {
598 printf (" %02d.%02d.%02d %02d:%02d:%02d ",
605 printf ("%lu ", (unsigned long)dir
->data_length
);
606 printf ("loc=%lu ", (unsigned long)dir
->extent_loc
);
607 Show_Flags (dir
->flags
);
609 if (dir
->ext_attr_length
)
610 printf (" contains extended attribute record\n");
612 printf (" is recorded in interleaved mode\n");
613 if (vol
->protocol
== PRO_ROCK
)
614 Print_System_Use_Fields (vol
->cd
, dir
,
615 ((t_iso_vol_info
*) vol
->vol_info
)->skip
,
622 fprintf (stderr
, "Object '%s': iso_errno = %d\n", p_name
, global
->iso_errno
);
627 obj
= Open_Object (p_home
, p_name
);
631 while (Examine_Next (obj
, &info
, &offset
)) {
632 if (info
.directory_f
) {
633 char *name
= malloc (strlen (p_name
) + info
.name_length
+ 2);
636 fprintf (stderr
, "out of memory\n");
639 if (Is_Top_Level_Object (obj
))
642 sprintf (name
, "%s/", p_name
);
643 len
= strlen (name
) + info
.name_length
;
644 memcpy (name
+ strlen (name
), info
.name
, info
.name_length
);
646 printf ("\n%s:\n", name
);
647 Show_Subdirectory (p_home
, name
, p_long_info
, TRUE
);
653 fprintf (stderr
, "Object '%s': iso_errno = %d\n", p_name
, global
->iso_errno
);
659 void Show_Dir_Contents (CDROM
*p_cd
, char *p_name
, int p_rock_ridge
,
660 int p_joliet
, char *p_options
)
664 int long_info
= strchr (p_options
, 'l') ? 1 :
665 strchr (p_options
, 'L') ? 2 : 0;
666 t_bool recursive
= (strchr (p_options
, 'r') != NULL
);
668 if (!(vol
= Open_Volume (p_cd
, p_rock_ridge
, p_joliet
))) {
669 fprintf (stderr
, "cannot open volume; iso_errno = %d\n", global
->iso_errno
);
673 if (!(home
= Open_Top_Level_Directory (vol
))) {
674 fprintf (stderr
, "cannot open top level directory;"
675 " iso_errno = %d\n", global
->iso_errno
);
680 Show_Subdirectory (home
, p_name
, long_info
, recursive
);
686 void Send_Test_Unit_Ready (CDROM
*p_cd
)
688 printf ("result = %d\n", Test_Unit_Ready (p_cd
));
691 void Show_Sectors (CDROM
*p_cd
, int p_sector
, int p_cnt
)
699 for (s
=0; s
<p_cnt
; s
++) {
700 if (!Read_Chunk (p_cd
, p_sector
+ s
)) {
701 fprintf (stderr
, "cannot read sector %d\n", p_sector
+ s
);
704 for (off
=0, i
=0; i
<128; i
++) {
705 printf ("%02x:%03x0: ", s
, i
);
707 printf ("%02x ", (int) p_cd
->buffer
[off
++]);
710 for (j
=0; j
<16; j
++) {
711 unsigned char c
= p_cd
->buffer
[off
++];
722 int Get_Device_And_Unit (void)
727 len
= GetVar ((UBYTE
*) "CDROM_DEVICE", (UBYTE
*) global
->g_device
,
728 sizeof (global
->g_device
), 0);
731 if (len
>= sizeof (global
->g_device
)) {
732 fprintf (stderr
, "CDROM_DEVICE too long\n");
735 global
->g_device
[len
] = 0;
737 len
= GetVar ((UBYTE
*) "CDROM_UNIT", (UBYTE
*) buf
,
741 if (len
>= sizeof (buf
)) {
742 fprintf (stderr
, "CDROM_UNIT too long\n");
746 global
->g_unit
= atoi (buf
);
748 if (GetVar ((UBYTE
*) "CDROM_FASTMEM", (UBYTE
*) buf
,
749 sizeof (buf
), 0) > 0) {
750 fprintf (stderr
, "using fastmem\n");
751 global
->g_memory_type
= MEMF_FAST
;
757 void Select_Mode (CDROM
*p_cd
, int p_mode
, int p_block_length
)
759 if (!Mode_Select (p_cd
, p_mode
, p_block_length
))
760 fprintf (stderr
, "mode select command failed!\n");
763 void Show_Drive_Information (CDROM
*p_cd
)
767 if (!Inquire (p_cd
, &data
)) {
768 fprintf (stderr
, "cannot access CDROM drive\n");
772 if ((data
.peripheral_type
& 0x1f) != 5) {
773 if ((data
.peripheral_type
& 0x1f) == 8)
774 printf ("Drive type: medium changer\n");
776 printf ("WARNING: this is not a CDROM drive!\n");
779 printf ("Vendor : ");
780 fwrite (data
.vendor
, sizeof (data
.vendor
), 1, stdout
);
781 printf ("\nProduct : ");
782 fwrite (data
.product
, sizeof (data
.product
), 1, stdout
);
783 printf ("\nRevision : ");
784 fwrite (data
.revision
, sizeof (data
.revision
), 1, stdout
);
786 printf ("Conforms to : SCSI-%d\n", (int) (data
.version
& 0x7));
789 void Show_Table_Of_Contents (CDROM
*p_cd
)
795 if (!(toc
= Read_TOC (p_cd
, &toc_len
))) {
796 fprintf (stderr
, "cannot read table of contents\n");
801 for (i
=0; i
<len
; i
++) {
802 if (toc
[i
].track_number
== 0xAA)
803 printf ("Lead-out track at address %lu\n", (unsigned long)toc
[i
].address
);
805 printf ("Track %d: %s track, start address %lu\n",
806 (int) toc
[i
].track_number
,
807 (toc
[i
].flags
& 4) ? "data" : "audio",
808 (unsigned long)toc
[i
].address
);
812 void Show_Catalog_Node (CDROM
*p_cd
, t_ulong p_node
)
820 t_dir_thread_record
*thread
;
826 blk
= HFS_Find_Master_Directory_Block (p_cd
, &mdb
);
828 fprintf (stderr
, "cannot find master directory block\n");
832 node
= HFS_Get_Node (p_cd
, blk
, &mdb
, p_node
);
834 fprintf (stderr
, "cannot find node %lu\n", (unsigned long)p_node
);
838 switch (node
->Type
) {
840 printf ("Index node:\n");
841 printf ("Fwd=%lu Bwd=%lu Level=%d\n", (unsigned long)node
->FLink
, (unsigned long)node
->BLink
,
842 (int) node
->NHeight
);
843 idx
= (t_idx_record
*) ((char *) node
+ 0xe);
844 for (i
=0; i
<node
->NRecs
; i
++, idx
++) {
845 printf ("Parent ID = 0x%08lx, '", (unsigned long)idx
->parent_id
);
846 fwrite (idx
->name
, idx
->name_length
, 1, stdout
);
847 printf ("', pointer = %lu\n", (unsigned long)idx
->pointer
);
851 printf ("Header node:\n");
852 printf ("Fwd=%lu Bwd=%lu Level=%d\n", (unsigned long)node
->FLink
, (unsigned long)node
->BLink
,
853 (int) node
->NHeight
);
854 hdr
= (t_hdr_node
*) node
;
855 printf ("Depth of tree: %u\n", (unsigned)hdr
->Depth
);
856 printf ("Number of root node: %lu\n", (unsigned long)hdr
->Root
);
857 printf ("Number of leaf records in tree: %lu\n", (unsigned long)hdr
->NRecs
);
858 printf ("Number of first leaf node: %lu\n", (unsigned long)hdr
->FNode
);
859 printf ("Number of last leaf node: %lu\n", (unsigned long)hdr
->LNode
);
862 printf ("Map node:\n");
863 printf ("Fwd=%lu Bwd=%lu Level=%d\n", (unsigned long)node
->FLink
, (unsigned long)node
->BLink
,
864 (int) node
->NHeight
);
867 printf ("Leaf node:\n");
868 printf ("Fwd=%lu Bwd=%lu Level=%d\n", (unsigned long)node
->FLink
, (unsigned long)node
->BLink
,
869 (int) node
->NHeight
);
870 for (i
=0; i
<node
->NRecs
; i
++) {
871 leaf
= (t_leaf_record
*) ((char *) node
+ ((short *) node
)[255-i
]);
872 cp
= (char *) leaf
+ leaf
->length
+ 1;
873 if ((leaf
->length
& 1) == 0)
875 printf ("Parent ID = 0x%08lx, '", (unsigned long)leaf
->parent_id
);
876 memcpy (buf
, leaf
->name
, leaf
->name_length
);
877 Convert_Mac_Characters (buf
, leaf
->name_length
);
878 fwrite (buf
, leaf
->name_length
, 1, stdout
);
882 printf ("directory 0x%08lx)\n", (unsigned long)*(t_ulong
*)(cp
+6));
885 file
= (t_file_record
*) cp
;
886 printf ("file 0x%08lx)\n\tdata length %lu, "
887 "data extents %u-%u/%u-%u/%u-%u\n",
888 (unsigned long)file
->FlNum
,
889 (unsigned long)file
->LgLen
,
890 (unsigned)file
->ExtRec
[0].StABN
, (unsigned)file
->ExtRec
[0].NumABlks
,
891 (unsigned)file
->ExtRec
[1].StABN
, (unsigned)file
->ExtRec
[1].NumABlks
,
892 (unsigned)file
->ExtRec
[2].StABN
, (unsigned)file
->ExtRec
[2].NumABlks
);
893 printf ("\tresource length %lu, resource extents %u-%u/%u-%u/%u-%u\n",
894 (unsigned long)file
->RLgLen
,
895 (unsigned) file
->RExtRec
[0].StABN
, (unsigned) file
->RExtRec
[0].NumABlks
,
896 (unsigned) file
->RExtRec
[1].StABN
, (unsigned) file
->RExtRec
[1].NumABlks
,
897 (unsigned) file
->RExtRec
[2].StABN
, (unsigned) file
->RExtRec
[2].NumABlks
);
898 printf ("\tfirst alloc blk for data fork: %u\n", file
->StBlk
);
899 printf ("\tfirst alloc blk for resource fork: %u\n", file
->RStBlk
);
902 thread
= (t_dir_thread_record
*) cp
;
903 printf ("directory thread 0x%08lu '", (unsigned long)thread
->ParID
);
904 fwrite (thread
->CName
, thread
->CNameLen
, 1, stdout
);
908 printf ("file thread)\n");
911 printf ("unknown)\n");
917 printf ("unknown node type\n");
923 void Play_Audio (CDROM
*p_cd
, int p_stop
)
928 result
= Stop_Play_Audio (p_cd
);
930 result
= Start_Play_Audio (p_cd
);
933 fprintf (stderr
, "cannot perform operation\n");
936 void Find_Offset_Of_Last_Session (CDROM
*p_cd
)
940 if (!Find_Last_Session (p_cd
, &last
)) {
941 fprintf (stderr
, "cannot determine offset of last session\n");
943 printf ("offset of last session: %lu\n", (unsigned long)last
);
947 void Test_Trackdisk_Device (CDROM
*p_cd
)
952 p_cd
->scsireq
->io_Flags
= IOF_QUICK
;
953 p_cd
->scsireq
->io_Command
= TD_CHANGESTATE
;
954 BeginIO ((struct IORequest
*) p_cd
->scsireq
);
955 state
= p_cd
->scsireq
->io_Actual
;
956 p_cd
->scsireq
->io_Flags
= IOF_QUICK
;
957 p_cd
->scsireq
->io_Command
= TD_CHANGENUM
;
958 BeginIO ((struct IORequest
*) p_cd
->scsireq
);
959 num
= p_cd
->scsireq
->io_Actual
;
960 printf ("%s, changenum = %d\n", state
? "no disk present" : "disk present",
966 int main (int argc
, char *argv
[])
969 global
->g_memory_type
= MEMF_CHIP
;
975 if (!(UtilityBase
= (APTR
)OpenLibrary("utility.library", 37))) {
976 fprintf (stderr
, "cannot open utility.library\n");
980 if (!Get_Device_And_Unit ()) {
982 "Please set the following environment variables:\n"
983 " CDROM_DEVICE name of SCSI device\n"
984 " CDROM_UNIT unit number of CDROM drive\n"
986 " setenv CDROM_DEVICE scsi.device\n"
987 " setenv CDROM_UNIT 2\n"
988 "Set the variable CDROM_FASTMEM to any value if you\n"
989 "want to use fast memory for SCSI buffers (does not work\n"
990 "with all SCSI devices!)\n"
991 "Set the variable CDROM_UNICODETABLE to file name of external\n"
992 "Unicode conversion table file if you want to see file names\n"
993 "with national characters on Joliet volumes\n"
1001 global
->g_cd
= Open_CDROM (global
, global
->g_device
, global
->g_unit
, global
->g_memory_type
,
1003 if (!global
->g_cd
) {
1004 fprintf (stderr
, "cannot open CDROM, error code = %d\n", global
->g_cdrom_errno
);
1008 if (argv
[1][0] == 'a' && argc
== 2)
1009 Show_Drive_Information (global
->g_cd
);
1010 else if (argv
[1][0] == 'b' && argc
== 2)
1011 Show_Table_Of_Contents (global
->g_cd
);
1012 else if (argv
[1][0] == 'c' && argc
== 3)
1013 Show_File_Contents (global
->g_cd
, argv
[2]);
1014 else if (argv
[1][0] == 'd' && argc
== 3)
1015 Show_Dir_Contents (global
->g_cd
, argv
[2], 0, 0, argv
[1]+1);
1016 else if (argv
[1][0] == 'e' && argc
== 3)
1017 Show_Dir_Contents (global
->g_cd
, argv
[2], 1, 0, argv
[1]+1);
1018 else if (argv
[1][0] == 'g' && argc
== 3)
1019 Show_Dir_Contents (global
->g_cd
, argv
[2], 0, 1, argv
[1]+1);
1020 else if (argv
[1][0] == 'f' && argc
== 4)
1021 Try_To_Open (global
->g_cd
, argv
[2], argv
[3]);
1022 else if (argv
[1][0] == 'i')
1023 Check_Protocol (global
->g_cd
);
1024 else if (argv
[1][0] == 'j' && argc
== 3)
1025 Play_Audio (global
->g_cd
, atoi (argv
[2]));
1026 else if (argv
[1][0] == 'l' && argc
== 2)
1027 Find_Offset_Of_Last_Session (global
->g_cd
);
1028 else if (argv
[1][0] == 'm' && argc
== 3)
1029 Show_Catalog_Node (global
->g_cd
, atoi (argv
[2]));
1030 else if (argv
[1][0] == 'o' && argc
== 3)
1031 Try_To_Open (global
->g_cd
, NULL
, argv
[2]);
1032 else if (argv
[1][0] == 'r')
1033 Show_Root_Directory (global
->g_cd
);
1034 else if (argv
[1][0] == 's' && argc
== 3)
1035 Show_Sectors (global
->g_cd
, atoi (argv
[2]), 1);
1036 else if (argv
[1][0] == 's' && argc
== 4)
1037 Show_Sectors (global
->g_cd
, atoi (argv
[2]), atoi (argv
[3]));
1038 else if (argv
[1][0] == 't' && argc
== 3)
1039 Try_To_Open (global
->g_cd
, (char *) -1, argv
[2]);
1040 else if (argv
[1][0] == 'v')
1041 Show_Primary_Volume_Descriptor (global
->g_cd
);
1042 else if (argv
[1][0] == 'x' && argc
== 3)
1043 Select_Mode (global
->g_cd
, atoi (argv
[2]), 2048);
1044 else if (argv
[1][0] == 'x' && argc
== 4)
1045 Select_Mode (global
->g_cd
, atoi (argv
[2]), atoi (argv
[3]));
1046 else if (argv
[1][0] == 'y' && argc
== 3)
1047 Find_Block_Starting_With (global
->g_cd
, atoi (argv
[2]));
1048 else if (argv
[1][0] == 'z')
1049 Send_Test_Unit_Ready (global
->g_cd
);
1050 else if (argv
[1][0] == 'T')
1051 Test_Trackdisk_Device (global
->g_cd
);