configure: when detecting linux include directory for kernel compiler use target...
[AROS.git] / rom / filesys / CDVDFS / src / main.c
blobf4a82668a4d80f9a1049435245be18a418f0f4a0
1 /* main.c:
3 * Interactive test program for the ISO- and Rock-Ridge-support
4 * routines.
6 * ----------------------------------------------------------------------
7 * This code is (C) Copyright 1993,1994 by Frank Munkert.
8 * All rights reserved.
9 * This software may be freely distributed and redistributed for
10 * non-commercial purposes, provided this notice is included.
11 * ----------------------------------------------------------------------
12 * History:
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.
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
32 #include <dos/var.h>
33 #include <devices/trackdisk.h>
35 #include <clib/alib_protos.h>
37 #include <proto/dos.h>
38 #include <proto/exec.h>
40 #include "cdrom.h"
41 #include "iso9660.h"
42 #include "joliet.h"
43 #include "rock.h"
44 #include "hfs.h"
45 #include "charset.h"
46 #include "globals.h"
48 #ifdef LATTICE
49 #include <pragmas/dos_pragmas.h>
50 #include <pragmas/exec_pragmas.h>
51 extern struct Library *SysBase, *DOSBase;
52 #endif
54 #undef DOSBase
56 #define STD_BUFFERS 20
58 #ifdef DEBUG_SECTORS
59 void dbprintf (char *p_dummy, ...)
62 #endif
64 struct CDVDBase glob;
65 struct CDVDBase *global = &glob;
67 void Cleanup (void)
69 if (global->g_cd)
70 Cleanup_CDROM (global->g_cd);
72 if (CodesetsBase)
73 CloseLibrary(CodesetsBase);
74 if (UtilityBase)
75 CloseLibrary ((struct Library*) UtilityBase);
78 void Usage (void)
80 fprintf (stderr,
81 "Usage: cdrom command [parameters]\n"
82 "Commands:\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"
109 exit (1);
112 char *MKSTR (char *p_in, int p_length, char *p_out)
114 char *res = p_out;
115 int len = p_length;
116 int i;
118 while (len && p_in[len-1] == ' ')
119 len--;
121 for (i=0; i<len; i++)
122 *p_out++ = *p_in++;
124 *p_out = 0;
126 return res;
129 void Show_Flags (unsigned char p_flags)
131 if (p_flags & 1)
132 printf ("existence ");
133 if (p_flags & 2)
134 printf ("directory ");
135 if (p_flags & 4)
136 printf ("associated ");
137 if (p_flags & 8)
138 printf ("record ");
139 if (p_flags & 16)
140 printf ("protection ");
141 if (p_flags & 128)
142 printf ("multi-extent ");
145 void Show_Directory_Record (directory_record *p_dir)
147 char buf[256];
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,
155 (int) p_dir->tz);
156 printf ("Flags: %d (", (int) p_dir->flags);
157 Show_Flags (p_dir->flags);
158 printf (")\n");
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)
164 printf ("(00)\n");
165 else if (p_dir->file_id[0] == 1)
166 printf ("(01)\n");
167 else
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)
173 uint32_t sec = 0;
174 int cmp;
175 int i;
177 for (;;) {
178 if (!Read_Chunk (p_cd, sec)) {
179 fprintf (stderr, "cannot read sector 16\n");
180 exit (1);
182 for (i=0; i<4; i++) {
183 cmp = p_cd->buffer[i<<9] * 256 + p_cd->buffer[(i<<9)+1];
184 if (cmp == p_val)
185 printf ("sector %lu, block %d\n", (unsigned long)sec, i);
187 sec++;
191 void Show_Primary_Volume_Descriptor (CDROM *p_cd)
193 prim_vol_desc *pvd;
194 char buf[129];
195 int blk;
196 t_mdb mdb;
197 t_hdr_node hdr;
198 int skip;
199 t_ulong offset, svd_offset;
200 int protocol;
201 t_bool hfs;
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");
208 return;
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);
231 exit (1);
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);
268 if (hfs) {
269 if ((blk = HFS_Find_Master_Directory_Block (p_cd, &mdb)) < 0) {
270 printf ("No master directory block found\n");
271 exit (1);
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)
308 int cnt = 0;
309 int pos = 0;
311 if (!Read_Chunk (p_cd, p_location)) {
312 fprintf (stderr, "cannot read sector %lu\n", (unsigned long)p_location);
313 exit (1);
316 while (cnt < p_length) {
317 directory_record *dir = (directory_record *) (p_cd->buffer + pos);
319 if (dir->length == 0)
320 break;
321 Show_Directory_Record (dir);
322 cnt += dir->length;
323 pos += dir->length;
324 if (cnt < p_length) {
325 printf ("------------------------------------------------------------\n");
326 if (pos >= 2048) {
327 if (!Read_Chunk (p_cd, ++p_location)) {
328 fprintf (stderr, "cannot read sector %lu\n", (unsigned long)p_location);
329 exit (1);
331 pos = 0;
337 void Show_Root_Directory (CDROM *p_cd)
339 prim_vol_desc *pvd;
341 if (!Read_Chunk (p_cd, 16)) {
342 fprintf (stderr, "cannot read sector 16\n");
343 exit (1);
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)
353 int skip;
354 t_ulong offset, svd_offset;
356 switch (Which_Protocol (p_cd, TRUE, TRUE, &skip, &offset, &svd_offset)) {
357 case PRO_ROCK:
358 printf ("Rock Ridge protocol, skip length = %d\n", skip);
359 break;
360 case PRO_ISO:
361 printf ("ISO-9660 protocol, offset = %lu\n", (unsigned long)offset);
362 break;
363 case PRO_JOLIET:
364 printf ("Joliet protocol, offset = %lu SVD offset = %lu\n", (unsigned long)offset, (unsigned long)svd_offset);
365 break;
366 case PRO_HFS:
367 printf ("Macintosh HFS protocol\n");
368 break;
369 case PRO_HIGH_SIERRA:
370 printf ("High Sierra protocol\n");
371 break;
372 default:
373 printf ("Unknown protocol, iso_errno = %d\n", global->iso_errno);
374 break;
378 void Try_To_Open (CDROM *p_cd, char *p_directory, char *p_name)
380 VOLUME *vol;
381 CDROM_OBJ *top = NULL;
382 CDROM_OBJ *home;
383 CDROM_OBJ *obj;
384 CDROM_OBJ *parent;
385 char pathname[256];
387 if (!(vol = Open_Volume (p_cd, 1, 1))) {
388 fprintf (stderr, "cannot open volume; iso_errno = %d\n", global->iso_errno);
389 exit (1);
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");
395 Close_Volume (vol);
396 exit (1);
399 if (!(home = Open_Object (top, p_directory))) {
400 fprintf (stderr, "cannot open top level directory\n");
401 Close_Object (top);
402 Close_Volume (vol);
403 exit (1);
405 } else {
406 if (!(home = Open_Top_Level_Directory (vol))) {
407 fprintf (stderr, "cannot open home directory;"
408 " iso_errno = %d\n", global->iso_errno);
409 Close_Volume (vol);
410 exit (1);
413 obj = Open_Object (home, p_name);
414 if (obj) {
415 CDROM_INFO info;
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) {
422 char linkname[256];
423 printf ("Link to ");
424 if (Get_Link_Name (obj, linkname, sizeof (linkname)))
425 printf ("'%s'\n", linkname);
426 else
427 printf ("unknown file or directory\n");
429 if (Full_Path_Name (obj, pathname, sizeof (pathname)))
430 printf ("Full path name: %s\n", pathname);
431 else
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);
436 printf ("\n");
437 printf ("INFO Comment = ");
438 fwrite (info.comment, info.comment_length, 1, stdout);
439 printf ("\n");
440 } else
441 printf ("CANNOT FIND INFO FOR OBJECT!\n");
442 if (p_directory == (char *) -1) {
443 parent = Find_Parent (obj);
444 if (parent) {
445 printf ("parent found, location = %lu\n",
446 (unsigned long)Location (parent));
447 Close_Object (parent);
448 } else
449 printf ("parent not found, iso_errno = %d\n", global->iso_errno);
451 Close_Object (obj);
452 } else {
453 if (global->iso_errno == ISOERR_NOT_FOUND)
454 printf ("Object '%s' not found\n", p_name);
455 else
456 printf ("Object '%s': iso_errno = %d\n", p_name, global->iso_errno);
459 if (top)
460 Close_Object (top);
461 Close_Object (home);
462 Close_Volume (vol);
465 void Show_File_Contents (CDROM *p_cd, char *p_name)
467 VOLUME *vol;
468 CDROM_OBJ *home;
469 CDROM_OBJ *obj;
470 #define THEBUFSIZE 99
471 char buffer[THEBUFSIZE];
472 int cnt;
474 if (!(vol = Open_Volume (p_cd, 1, 1))) {
475 fprintf (stderr, "cannot open volume; iso_errno = %d\n", global->iso_errno);
476 exit (1);
479 if (!(home = Open_Top_Level_Directory (vol))) {
480 fprintf (stderr, "cannot open top level directory;"
481 " iso_errno = %d\n", global->iso_errno);
482 Close_Volume (vol);
483 exit (1);
485 obj = Open_Object (home, p_name);
486 if (obj) {
487 for (;;) {
488 cnt = Read_From_File (obj, buffer, THEBUFSIZE);
489 if (cnt == -1) {
490 fprintf (stderr, "cannot read from file!\n");
491 break;
493 if (cnt == 0)
494 break;
495 fwrite (buffer, cnt, 1, stdout);
498 putchar ('\n');
499 Close_Object (obj);
500 } else {
501 fprintf (stderr, "Object '%s': iso_errno = %d\n", p_name, global->iso_errno);
504 Close_Object (home);
505 Close_Volume (vol);
509 void Print_System_Use_Fields (CDROM *p_cd, directory_record *p_dir,
510 int p_skip_size, int p_long)
512 int system_use_pos;
513 int slen;
514 uint32_t length = p_dir->length;
515 unsigned char *buf = (unsigned char *) p_dir;
517 printf (" system use fields: ");
518 if (p_long)
519 putchar ('\n');
521 system_use_pos = 33 + p_dir->file_id_length;
522 if (system_use_pos & 1)
523 system_use_pos++;
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;
533 printf ("/ ");
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))
538 return;
539 buf = p_cd->buffer;
540 system_use_pos = offset;
541 continue;
542 /* look for system use field terminator: */
543 } else if (buf[system_use_pos] == 'S' &&
544 buf[system_use_pos+1] == 'T') {
545 printf ("ST");
546 break;
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);
553 printf (") ");
554 } else {
555 if (p_long)
556 printf (" ");
557 putchar (buf[system_use_pos]);
558 putchar (buf[system_use_pos+1]);
559 putchar (' ');
560 if (p_long) {
561 int i;
562 for (i=0; i < slen-2; i++) {
563 if (i && (i & 15) == 0)
564 printf ("\n ");
565 printf ("%2.2x ", (int) buf[system_use_pos+i+2]);
570 if (p_long)
571 putchar ('\n');
573 system_use_pos += slen;
576 putchar ('\n');
579 void Show_Subdirectory (CDROM_OBJ *p_home, char *p_name, int p_long_info,
580 int p_recursive)
582 CDROM_OBJ *obj;
583 CDROM_INFO info;
584 VOLUME *vol = p_home->volume;
585 obj = Open_Object (p_home, p_name);
586 if (obj) {
587 uint32_t offset = 0;
589 while (Examine_Next (obj, &info, &offset)) {
590 directory_record *dir = info.suppl_info;
591 fwrite (info.name, info.name_length, 1, stdout);
592 if (info.symlink_f)
593 printf (" (symbolic link)");
594 else if (info.directory_f)
595 printf (" (dir)");
596 printf ("\n");
597 if (p_long_info && dir) {
598 printf (" %02d.%02d.%02d %02d:%02d:%02d ",
599 (int) dir->day,
600 (int) dir->month,
601 (int) dir->year,
602 (int) dir->hour,
603 (int) dir->minute,
604 (int) dir->second);
605 printf ("%lu ", (unsigned long)dir->data_length);
606 printf ("loc=%lu ", (unsigned long)dir->extent_loc);
607 Show_Flags (dir->flags);
608 putchar ('\n');
609 if (dir->ext_attr_length)
610 printf (" contains extended attribute record\n");
611 if (dir->gap_size)
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,
616 p_long_info == 2);
620 Close_Object (obj);
621 } else {
622 fprintf (stderr, "Object '%s': iso_errno = %d\n", p_name, global->iso_errno);
623 return;
626 if (p_recursive) {
627 obj = Open_Object (p_home, p_name);
628 if (obj) {
629 uint32_t offset = 0;
631 while (Examine_Next (obj, &info, &offset)) {
632 if (info.directory_f) {
633 char *name = malloc (strlen (p_name) + info.name_length + 2);
634 int len;
635 if (!name) {
636 fprintf (stderr, "out of memory\n");
637 exit (1);
639 if (Is_Top_Level_Object (obj))
640 name[0] = 0;
641 else
642 sprintf (name, "%s/", p_name);
643 len = strlen (name) + info.name_length;
644 memcpy (name + strlen (name), info.name, info.name_length);
645 name[len] = 0;
646 printf ("\n%s:\n", name);
647 Show_Subdirectory (p_home, name, p_long_info, TRUE);
648 free (name);
651 Close_Object (obj);
652 } else {
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)
662 VOLUME *vol;
663 CDROM_OBJ *home;
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);
670 exit (1);
673 if (!(home = Open_Top_Level_Directory (vol))) {
674 fprintf (stderr, "cannot open top level directory;"
675 " iso_errno = %d\n", global->iso_errno);
676 Close_Volume (vol);
677 exit (1);
680 Show_Subdirectory (home, p_name, long_info, recursive);
682 Close_Object (home);
683 Close_Volume (vol);
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)
693 int i, j, s;
694 int off;
696 if (p_sector < 0)
697 return;
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);
702 exit (1);
704 for (off=0, i=0; i<128; i++) {
705 printf ("%02x:%03x0: ", s, i);
706 for (j=0; j<16; j++)
707 printf ("%02x ", (int) p_cd->buffer[off++]);
708 off -= 16;
709 putchar (' ');
710 for (j=0; j<16; j++) {
711 unsigned char c = p_cd->buffer[off++];
712 if (32<=c && c<=127)
713 putchar (c);
714 else
715 putchar ('.');
717 putchar ('\n');
722 int Get_Device_And_Unit (void)
724 int len;
725 char buf[10];
727 len = GetVar ((UBYTE *) "CDROM_DEVICE", (UBYTE *) global->g_device,
728 sizeof (global->g_device), 0);
729 if (len < 0)
730 return 0;
731 if (len >= sizeof (global->g_device)) {
732 fprintf (stderr, "CDROM_DEVICE too long\n");
733 exit (1);
735 global->g_device[len] = 0;
737 len = GetVar ((UBYTE *) "CDROM_UNIT", (UBYTE *) buf,
738 sizeof (buf), 0);
739 if (len < 0)
740 return 0;
741 if (len >= sizeof (buf)) {
742 fprintf (stderr, "CDROM_UNIT too long\n");
743 exit (1);
745 buf[len] = 0;
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;
754 return 1;
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)
765 t_inquiry_data data;
767 if (!Inquire (p_cd, &data)) {
768 fprintf (stderr, "cannot access CDROM drive\n");
769 return;
772 if ((data.peripheral_type & 0x1f) != 5) {
773 if ((data.peripheral_type & 0x1f) == 8)
774 printf ("Drive type: medium changer\n");
775 else
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);
785 putchar ('\n');
786 printf ("Conforms to : SCSI-%d\n", (int) (data.version & 0x7));
789 void Show_Table_Of_Contents (CDROM *p_cd)
791 uint32_t toc_len;
792 t_toc_data *toc;
793 short i, len;
795 if (!(toc = Read_TOC (p_cd, &toc_len))) {
796 fprintf (stderr, "cannot read table of contents\n");
797 return;
800 len = toc_len / 8;
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);
804 else
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)
814 t_mdb mdb;
815 t_node_descr *node;
816 t_hdr_node *hdr;
817 t_idx_record *idx;
818 t_leaf_record *leaf;
819 t_file_record *file;
820 t_dir_thread_record *thread;
821 char *cp;
822 int blk;
823 int i;
824 char buf[100];
826 blk = HFS_Find_Master_Directory_Block (p_cd, &mdb);
827 if (blk < 0) {
828 fprintf (stderr, "cannot find master directory block\n");
829 return;
832 node = HFS_Get_Node (p_cd, blk, &mdb, p_node);
833 if (!node) {
834 fprintf (stderr, "cannot find node %lu\n", (unsigned long)p_node);
835 return;
838 switch (node->Type) {
839 case 0:
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);
849 break;
850 case 1:
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);
860 break;
861 case 2:
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);
865 break;
866 case 0xff:
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)
874 cp++;
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);
879 printf ("' (");
880 switch (*cp) {
881 case 1:
882 printf ("directory 0x%08lx)\n", (unsigned long)*(t_ulong *)(cp+6));
883 break;
884 case 2:
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);
900 break;
901 case 3:
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);
905 printf ("')\n");
906 break;
907 case 4:
908 printf ("file thread)\n");
909 break;
910 default:
911 printf ("unknown)\n");
912 break;
915 break;
916 default:
917 printf ("unknown node type\n");
918 return;
923 void Play_Audio (CDROM *p_cd, int p_stop)
925 int result;
927 if (p_stop)
928 result = Stop_Play_Audio (p_cd);
929 else
930 result = Start_Play_Audio (p_cd);
932 if (!result)
933 fprintf (stderr, "cannot perform operation\n");
936 void Find_Offset_Of_Last_Session (CDROM *p_cd)
938 uint32_t last;
940 if (!Find_Last_Session (p_cd, &last)) {
941 fprintf (stderr, "cannot determine offset of last session\n");
942 } else {
943 printf ("offset of last session: %lu\n", (unsigned long)last);
947 void Test_Trackdisk_Device (CDROM *p_cd)
949 int state, num;
951 for (;;) {
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",
961 num);
962 Delay (50);
966 int main (int argc, char *argv[])
968 global->g_cd = NULL;
969 global->g_memory_type = MEMF_CHIP;
970 atexit (Cleanup);
972 if (argc < 2)
973 Usage ();
975 if (!(UtilityBase = (APTR)OpenLibrary("utility.library", 37))) {
976 fprintf (stderr, "cannot open utility.library\n");
977 exit (1);
980 if (!Get_Device_And_Unit ()) {
981 fprintf (stderr,
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"
985 "e.g.\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"
995 exit (1);
998 CodesetsBase = NULL;
999 InitCharset(global);
1001 global->g_cd = Open_CDROM (global, global->g_device, global->g_unit, global->g_memory_type,
1002 STD_BUFFERS, 0);
1003 if (!global->g_cd) {
1004 fprintf (stderr, "cannot open CDROM, error code = %d\n", global->g_cdrom_errno);
1005 exit (1);
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);
1052 else
1053 Usage ();
1055 exit (0);