1 /* 2 * isoread.c 3 * 4 * isoread reads a file system in ISO9660 or HIGH SIERRA format from 5 * a given device. 6 * 7 * Apr 5 1995 Michel R. Prevenier 8 * Nov 16 1996 Kees J. Bot -- bug fix: isoread filename matching 9 * Dec 7 1997 Albert S. Woodhull -- bug fix: return values 10 * " " : isodir filename handling 11 * -- added : isoread -a option 12 * Mar 21 2000 Michael A. Temari -- bug fix: look_up only searched first 13 * : block of directory 14 * : stack overflow in recurse_dir 15 * : and various other bugs 16 * Apr 14 2002 Michael A. Temari -- bug fix: fixed recursing directories 17 * : and printing dates 2000 and 18 * : later 19 * May 14 2002 Kees J. Bot -- bug fix: fixed error messages 20 * Mar 14 2003 Kees J. Bot -- added : iso{dir,read} -B option 21 * Jul 24 2003 Michael A. Temari -- bug fix: bytes to blocks roundup fix 22 */ 23 24 #include <ctype.h> 25 #include <errno.h> 26 #include <limits.h> 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <fcntl.h> 30 #include <stdlib.h> 31 #include <stdio.h> 32 #include <string.h> 33 #include <time.h> 34 #include <sys/times.h> 35 #include <unistd.h> 36 37 /* 38 * definitions used by the ISO9660 and HIGH SIERRA file system 39 */ 40 41 #define ISO9660_ID "CD001" 42 #define HIGH_SIERRA_ID "CDROM" 43 #define BLOCK_SIZE 2048 44 #define BLOCK_SHIFT 11 45 46 47 /* Fields in a ISO9660 volume descriptor */ 48 struct iso9660_descriptor 49 { 50 char type[1]; 51 char id[5]; 52 char version[1]; 53 char reserved1[1]; 54 char system_id[32]; 55 char volume_id[32]; 56 char reserved2[8]; 57 char volume_size[8]; 58 char reserved3[32]; 59 char volume_set_size[4]; 60 char volume_seq_nr[4]; 61 char block_size[4]; 62 char path_table_size[8]; 63 char type_l_path_table[4]; 64 char opt_type_l_path_table[4]; 65 char type_m_path_table[4]; 66 char opt_type_m_path_table[4]; 67 char root_dir_entry[34]; 68 char vol_set_id[128]; 69 char publ_id[128]; 70 char prep_id[128]; 71 char appl_id[128]; 72 char copyright_file_id[37]; 73 char abstract_file_id[37]; 74 char bibl_file_id[37]; 75 char creation_date[17]; 76 char mod_date[17]; 77 char exp_date[17]; 78 char eff_date[17]; 79 char file_struc_version[1]; 80 char reserved4[1]; 81 char appl_data[512]; 82 char reserved5[653]; 83 }; 84 85 86 /* Fields in a High Sierra volume descriptor */ 87 struct high_sierra_descriptor 88 { 89 char reserved1[8]; 90 char type[1]; 91 char id[5]; 92 char version[1]; 93 char reserved2[1]; 94 char system_id[32]; 95 char volume_id[32]; 96 char reserved3[8]; 97 char volume_size[8]; 98 char reserved4[32]; 99 char vol_set_size[4]; 100 char volume_seq_nr[4]; 101 char block_size[4]; 102 char path_table_size[8]; 103 char type_l_path_table[4]; 104 char reserved5[28]; 105 char root_dir_entry[34]; 106 }; 107 108 109 /* Fields in a directory entry */ 110 struct dir_entry 111 { 112 char length[1]; 113 char ext_attr_length[1]; 114 char first_block[8]; 115 char size[8]; 116 char date[7]; 117 char flags[1]; 118 char file_unit_size[1]; 119 char interleave[1]; 120 char volume_seq_nr[4]; 121 char name_length[1]; 122 char name[1]; 123 }; 124 125 126 #define STDOUT stdout 127 #define STDERR stderr 128 #define NULL_DIR (struct dir_entry *) 0 129 #define MAX_NAME_LENGTH 255 130 #define MAX_PATH_LENGTH 1024 131 132 #define NR_OF_CHARS 13 133 #define NR_OF_BLANKS 2 134 #define NR_OF_COLS (80 / (NR_OF_CHARS + NR_OF_BLANKS)) 135 136 /* This macro always returns a lower case character */ 137 #define LOWER_CASE(CHR) (CHR >= 'A' && CHR <= 'Z' ? CHR | 0x20 : CHR) 138 139 /* Macro's for determining . , .. and normal directory entries */ 140 #define IS_DOT(PTR) (PTR->name_length[0] == 1 && PTR->name[0] == 0 ? 1 : 0) 141 #define IS_DOT_DOT(PTR) (PTR->name_length[0] == 1 && PTR->name[0] == 1 ? 1 : 0) 142 #define IS_DIR(PTR) (PTR->flags[-High_Sierra] & 2 ? 1 : 0) 143 144 145 int main(int argc, char **argv); 146 int iso_cmp(char *name, struct dir_entry *dir_ptr, int dir_flag); 147 void list_dir(struct dir_entry *dir_ptr); 148 void list_file(struct dir_entry *dir_ptr); 149 struct dir_entry *look_up(char *name); 150 void recurse_dir(char *path, struct dir_entry *dir_ptr); 151 void read_device(long offset, int nr_of_bytes, char *buffer); 152 int valid_fs(void); 153 void usage(void); 154 void print_date(char *date); 155 void print_dir_date(char *date); 156 void iso_info(struct iso9660_descriptor *vol_desc); 157 void hs_info(struct high_sierra_descriptor *vol_desc); 158 int iso_711(char *c); 159 int iso_712(char *c); 160 int iso_721(char *c); 161 int iso_722(char *c); 162 int iso_723(char *c); 163 long iso_731(char *c); 164 long iso_732(char *c); 165 long iso_733(char *c); 166 167 168 char Buffer[BLOCK_SIZE]; /* buffer to hold read data */ 169 int Device; /* global file descriptor */ 170 struct iso9660_descriptor *Iso_Vol_Desc; /* iso9660 volume descriptor */ 171 struct high_sierra_descriptor *Hs_Vol_Desc; /* high sierra volume descriptor */ 172 int High_Sierra = 0; /* 1 = high sierra format */ 173 int Iso9660 = 0; /* 1 = iso9660 format */ 174 175 /* This comes in handy when printing the date */ 176 char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; 177 178 /* Flags displaying what to do */ 179 int Read_File = 0; /* 1 = Read file */ 180 int Read_Dir = 0; /* 1 = Read directory entry */ 181 int Read_Info = 0; /* 1 = Read volume descriptor */ 182 int Recurse = 0; /* 1 = Recursively descend directories */ 183 int Verbose = 0; /* 1 = Print all info on directories */ 184 int ByteOffset = 0; /* 1 = Print byte offset and length of files */ 185 int Aflag = 0; /* 1 = Suppress output of \r */ 186 187 int iso_cmp(name, dir_ptr, dir_flag) 188 char *name; 189 struct dir_entry *dir_ptr; 190 int dir_flag; 191 { 192 /* Compare name with directory entries, looking for match with a dirname. 193 * An iso9660 filename is terminated by ";n", where n will probably 194 * be 1. A directory name is not terminated by anything special, it may be 195 * followed by a \0 if padding is needed to put the following directory 196 * entry on an even address. 197 */ 198 int i; 199 int len; 200 201 /* First match the filename */ 202 len = strlen(name); 203 if (len > iso_711(dir_ptr->name_length)) return 1; 204 for (i = 0; i < len; i++) 205 { 206 if (dir_ptr->name[i] == ';') return 1; /* found end of a filename */ 207 if (name[i] != LOWER_CASE(dir_ptr->name[i])) return 1; /* match failed */ 208 } 209 if (dir_ptr->name[i] != ';' && i != len) return 1; /* incomplete match */ 210 211 /* The filename is ok, now look at the file type */ 212 if (dir_flag && !IS_DIR(dir_ptr)) return 1; /* File type not correct */ 213 214 return 0; 215 } 216 217 218 void usage() 219 { 220 if (Read_Dir) 221 fprintf (STDERR, "Usage: isodir [-lrB] inputfile [dir]\n"); 222 else if (Read_Info) 223 fprintf (STDERR, "Usage: isoinfo inputfile\n"); 224 else 225 fprintf (STDERR, "Usage: isoread [-a] inputfile file\n"); 226 exit(1); 227 } 228 229 230 int main(argc, argv) 231 int argc; 232 char **argv; 233 { 234 struct dir_entry *entry; 235 char path[MAX_PATH_LENGTH]; 236 char *input_file; 237 char *basename; 238 char *file_name; 239 int i,j; 240 241 /* Read arguments */ 242 basename = argv[0]; 243 while (*argv[0] != '\0') 244 if (*argv[0]++ == '/') basename = argv[0]; 245 246 if (strcmp(basename,"isodir") == 0) Read_Dir = 1; 247 else if (strcmp(basename,"isoinfo") == 0) Read_Info = 1; 248 else Read_File = 1; 249 250 if ((argc > 5 && Read_Dir) || (argc != 2 && Read_Info) || 251 (argc > 4 && Read_File)) usage(); 252 253 i = 1; 254 255 while (i < argc && argv[i][0] == '-') 256 { 257 char *opt = argv[i++] + 1; 258 259 if (opt[0] == '-' && opt[1] == '\0') break; 260 261 while (*opt != '\0') 262 { 263 if (Read_Info) usage(); 264 if (Read_Dir) 265 switch (*opt++) 266 { 267 case 'r': Recurse = 1; break; 268 case 'l': Verbose = 1; break; 269 case 'B': ByteOffset = 1; break; 270 default: usage(); 271 } 272 if (Read_File) 273 switch (*opt++) 274 { 275 case 'a': Aflag = 1; break; 276 case 'B': ByteOffset = 1; break; 277 default: usage(); 278 } 279 } 280 } 281 282 if (i >= argc) usage(); 283 input_file = argv[i++]; 284 285 if (Read_File) 286 { 287 if (i >= argc) usage(); 288 file_name = argv[i++]; 289 } 290 291 if (Read_Dir) 292 { 293 file_name = "/"; 294 if (i < argc) 295 { 296 file_name = argv[i++]; 297 } 298 } 299 300 if (i < argc) usage(); 301 302 if (Read_File || Read_Dir) 303 { 304 for (i=0; file_name[i] != '\0'; i++) 305 path[i] = LOWER_CASE(file_name[i]); 306 path[i] = '\0'; 307 } 308 309 /* Open file system (file or device) */ 310 if ((Device = open(input_file, O_RDONLY)) < 0) 311 { 312 fprintf (STDERR, "cannot open %s: %s\n", input_file, strerror(errno)); 313 exit(-1); 314 } 315 316 317 if (!valid_fs()) 318 { 319 fprintf (STDERR, "File system not in ISO9660 or HIGH SIERRA format \n"); 320 exit(-1); 321 } 322 323 324 if (Read_Info) 325 { 326 if (Iso9660) 327 iso_info(Iso_Vol_Desc); 328 else 329 hs_info(Hs_Vol_Desc); 330 exit(0); 331 } 332 333 /* Lookup file */ 334 if ((entry = look_up(path)) != NULL_DIR) 335 { 336 if (Read_Dir) 337 if (Recurse) recurse_dir(path,entry); 338 else list_dir(entry); 339 else 340 list_file(entry); 341 } 342 else 343 { 344 if (Read_Dir) 345 fprintf (STDERR, "Directory"); 346 else 347 fprintf (STDERR, "File"); 348 fprintf (STDERR, " %s not found\n", path); 349 exit(-1); 350 } 351 return 0; 352 } 353 354 355 struct dir_entry *look_up(path) 356 char *path; 357 { 358 /* Lookup a file name */ 359 360 struct dir_entry *dir_ptr; 361 long block; 362 int nr_of_blocks; 363 int offset; 364 char name[MAX_NAME_LENGTH + 1]; 365 int name_index = 0; 366 int last_in_path = 0; 367 int found; 368 int i,j; 369 370 /* Get the right dir entry structure */ 371 if (Iso9660) 372 dir_ptr = (struct dir_entry *) Iso_Vol_Desc->root_dir_entry; 373 else 374 dir_ptr = (struct dir_entry *) Hs_Vol_Desc->root_dir_entry; 375 376 /* If we look for the root we already have the right entry */ 377 if (path[0] == '/') 378 if (strlen(path) == 1) return dir_ptr; 379 else name_index = 1; /* first name in path */ 380 381 /* Keep searching for the path elements until all are found */ 382 while (!last_in_path) 383 { 384 /* Get next name in path */ 385 for (i = name_index; i < strlen(path); i++) 386 { 387 if (path[i] == '/') break; 388 name[i - name_index] = path[i]; 389 } 390 last_in_path = 391 (i == strlen(path) || (i == strlen(path) - 1 && path[i] == '/')); 392 name[i-name_index] = '\0'; 393 name_index = i + 1; 394 395 /* Get block of next directory */ 396 block = iso_733(dir_ptr->first_block) + iso_711(dir_ptr->ext_attr_length); 397 nr_of_blocks = (iso_733(dir_ptr->size) + (BLOCK_SIZE-1)) >> BLOCK_SHIFT; 398 399 /* Search for file in dir entry */ 400 found = 0; 401 for (j=0; j < nr_of_blocks && !found; j++) 402 { 403 /* Read a directory block */ 404 read_device(block*BLOCK_SIZE, BLOCK_SIZE, Buffer); 405 block++; 406 407 dir_ptr = (struct dir_entry *) Buffer; 408 409 offset = 0; 410 /* Compare with all entries in this block */ 411 while (iso_711(dir_ptr->length) > 0 && offset < BLOCK_SIZE) 412 { 413 if (iso_cmp(name, dir_ptr, 414 (Read_Dir || (!Read_Dir && !last_in_path))) == 0) 415 { 416 found = 1; 417 break; 418 } 419 /* Next entry */ 420 offset += iso_711(dir_ptr->length); 421 dir_ptr = (struct dir_entry *) (Buffer + offset); 422 } 423 } 424 if (!found) return NULL_DIR; /* path element not found */ 425 } 426 return dir_ptr; 427 } 428 429 430 void recurse_dir(path, dir_ptr) 431 char *path; 432 struct dir_entry *dir_ptr; 433 { 434 /* Recursively descend all directories starting with dir_ptr */ 435 436 char tmp_path[MAX_PATH_LENGTH]; 437 int i,j, path_length; 438 long block, saveblock, dblock; 439 int nr_of_blocks; 440 int offset = 0; 441 442 443 /* Save block number and nr of blocks of current dir entry because 444 * list_dir changes dir_ptr 445 */ 446 block = iso_733(dir_ptr->first_block) + iso_711(dir_ptr->ext_attr_length); 447 nr_of_blocks = (iso_733(dir_ptr->size) + (BLOCK_SIZE-1)) >> BLOCK_SHIFT; 448 449 /* Add a trailing / to path if necessary */ 450 path_length = strlen(path); 451 if (path[path_length-1] != '/') 452 { 453 path[path_length++] = '/'; 454 path[path_length] = '\0'; 455 } 456 457 /* Print current path of directory, and list contents of directory */ 458 fprintf(STDOUT,"directory %s:\n\n", path); 459 list_dir(dir_ptr); 460 fprintf(STDOUT,"\n\n"); 461 462 for (j=0; j < nr_of_blocks; j++) 463 { 464 read_device(block*BLOCK_SIZE, BLOCK_SIZE, Buffer); 465 saveblock = block++; 466 467 /* Save buffer, because the next recursive call destroys 468 * the global Buffer 469 */ 470 dir_ptr = (struct dir_entry *) Buffer; 471 472 /* Search this dir entry for directories */ 473 offset = 0; 474 while (iso_711(dir_ptr->length) != 0 && offset < BLOCK_SIZE) 475 { 476 /* Is current file a directory and not the . or .. entries */ 477 if (IS_DIR(dir_ptr) && !IS_DOT(dir_ptr) && !IS_DOT_DOT(dir_ptr)) 478 { 479 /* setup path for next recursive call */ 480 for (i=0; i<path_length; i++) tmp_path[i] = path[i]; 481 for (i=0;i<iso_711(dir_ptr->name_length) && dir_ptr->name[i] != ';';i++) 482 tmp_path[i+path_length] = LOWER_CASE(dir_ptr->name[i]); 483 tmp_path[i+path_length] = '/'; 484 tmp_path[i+1+path_length] = '\0'; 485 486 /* Read block of directory we found */ 487 dblock = iso_733(dir_ptr->first_block); 488 read_device(dblock*BLOCK_SIZE, BLOCK_SIZE, Buffer); 489 490 /* And start all over again with this entry */ 491 recurse_dir(tmp_path, (struct dir_entry *) Buffer); 492 493 /* get the block we were looking at */ 494 read_device(saveblock*BLOCK_SIZE, BLOCK_SIZE, Buffer); 495 } 496 497 /* Go to the next file in this directory */ 498 offset += iso_711(dir_ptr->length); 499 dir_ptr = (struct dir_entry *) (Buffer + offset); 500 } 501 } 502 } 503 504 505 void list_dir(dir_ptr) 506 struct dir_entry *dir_ptr; 507 { 508 /* List all entries in a directory */ 509 int tty; 510 long block; 511 int nr_of_blocks; 512 int i,j; 513 int offset = 0; 514 char name[NR_OF_CHARS+NR_OF_BLANKS+1]; 515 int name_len; 516 int column = 0; 517 int skip = 0; 518 519 tty = isatty(STDOUT_FILENO); 520 /* Get first block of directory */ 521 block = iso_733(dir_ptr->first_block) + iso_711(dir_ptr->ext_attr_length); 522 nr_of_blocks = (iso_733(dir_ptr->size) + (BLOCK_SIZE-1)) >> BLOCK_SHIFT; 523 524 /* Read all directory blocks and display their contents */ 525 for (j=0; j < nr_of_blocks; j++) 526 { 527 read_device(block*BLOCK_SIZE, BLOCK_SIZE, Buffer); 528 block++; 529 530 dir_ptr = (struct dir_entry *) (Buffer); 531 offset = 0; 532 while (iso_711(dir_ptr->length) != 0 && offset < BLOCK_SIZE) 533 { 534 name_len = 0; 535 if (IS_DOT(dir_ptr)) 536 { 537 name[name_len++] = '.'; 538 if (!Verbose) skip = 1; 539 } 540 else 541 { 542 if (IS_DOT_DOT(dir_ptr)) 543 { 544 name[name_len++] = '.'; 545 name[name_len++] = '.'; 546 if (!Verbose) skip = 1; 547 } 548 else 549 { 550 for (i=0; i<iso_711(dir_ptr->name_length) && 551 i<NR_OF_CHARS; i++) 552 { 553 if (dir_ptr->name[i] == ';') break; 554 name[name_len++] = LOWER_CASE(dir_ptr->name[i]); 555 } 556 if (IS_DIR(dir_ptr) && tty) name[name_len++] = '/'; 557 } 558 } 559 if (!skip) 560 { 561 if (ByteOffset) 562 { 563 fprintf (STDOUT, "%10ld ", 564 (iso_733(dir_ptr->first_block) + iso_711(dir_ptr->ext_attr_length)) 565 * BLOCK_SIZE); 566 } 567 if (Verbose || ByteOffset) 568 { 569 fprintf (STDOUT, "%10ld ", iso_733(dir_ptr->size)); 570 } 571 if (Verbose) 572 { 573 print_dir_date(dir_ptr->date); 574 fprintf (STDOUT, " "); 575 } 576 if(!tty) 577 name[name_len] = '\0'; 578 else { 579 for(i=name_len; i<(NR_OF_CHARS+NR_OF_BLANKS); i++) name[i] = ' '; 580 name[NR_OF_CHARS+NR_OF_BLANKS] = '\0'; 581 } 582 fprintf(STDOUT, "%s", name); 583 if (!(Verbose || ByteOffset)) 584 { 585 column++; 586 if (column >= NR_OF_COLS || !tty) 587 { 588 column = 0; 589 fprintf(STDOUT,"\n"); 590 } 591 } 592 else fprintf(STDOUT,"\n"); 593 } 594 skip = 0; 595 offset += iso_711(dir_ptr->length); 596 dir_ptr = (struct dir_entry *) (Buffer+offset); 597 } 598 } 599 if (!Verbose && column) fprintf(STDOUT,"\n"); 600 } 601 602 603 void print_dir_date(date) 604 char *date; 605 { 606 /* Print date in a directory entry */ 607 608 int m; 609 610 m = iso_711(&date[1]) - 1; 611 if(m < 0 || m > 11) 612 fprintf(STDOUT, " "); 613 else 614 fprintf(STDOUT,"%.3s",&months[m*3]); 615 616 fprintf (STDOUT, " %02d %04d %02d:%02d:%02d", 617 date[2], 618 1900+date[0], 619 date[3], 620 date[4], 621 date[5]); 622 } 623 624 625 void list_file(dir_ptr) 626 struct dir_entry *dir_ptr; 627 { 628 /* List contents of a file */ 629 630 int i; 631 long block; 632 long size; 633 char c; 634 635 block = iso_733(dir_ptr->first_block); 636 size = iso_733(dir_ptr->size); 637 638 if (ByteOffset) { 639 fprintf(STDOUT, "%ld %ld\n", block*BLOCK_SIZE, size); 640 return; 641 } 642 643 while (size > 0) 644 if (Aflag == 1) { 645 read_device(block*BLOCK_SIZE, BLOCK_SIZE, Buffer); 646 for (i=0; ((i < size) && (i < BLOCK_SIZE)); i++) 647 if (Buffer[i] != '\r') fprintf(STDOUT, "%c", Buffer[i]); 648 size-= BLOCK_SIZE; 649 block++; 650 } else { 651 read_device(block*BLOCK_SIZE, BLOCK_SIZE, Buffer); 652 for (i=0; ((i < size) && (i < BLOCK_SIZE)); i++) 653 fprintf(STDOUT, "%c", Buffer[i]); 654 size-= BLOCK_SIZE; 655 block++; 656 } 657 } 658 659 660 void print_date(date) 661 char *date; 662 { 663 /* Print the date in a volume descriptor */ 664 665 fprintf (STDOUT, "%c%c-%c%c-%c%c%c%c %c%c:%c%c:%c%c", 666 date[4], 667 date[5], 668 date[6], 669 date[7], 670 date[0], 671 date[1], 672 date[2], 673 date[3], 674 date[8], 675 date[9], 676 date[10], 677 date[11], 678 date[12], 679 date[13]); 680 } 681 682 void iso_info(vol_desc) 683 struct iso9660_descriptor *vol_desc; 684 { 685 int i; 686 687 fprintf (STDOUT, "Format: ISO9660 \n"); 688 fprintf (STDOUT, "System id: "); 689 for (i=0; i< sizeof(vol_desc->system_id); i++) 690 fprintf(STDOUT, "%c", vol_desc->system_id[i]); 691 fprintf (STDOUT, "\n"); 692 fprintf (STDOUT, "Volume id: "); 693 for (i=0; i< sizeof(vol_desc->volume_id); i++) 694 fprintf(STDOUT, "%c", vol_desc->volume_id[i]); 695 fprintf (STDOUT, "\n"); 696 fprintf (STDOUT, "Volume size: %ld Kb\n", iso_733(vol_desc->volume_size)*2); 697 fprintf (STDOUT, "Block size: %d bytes \n", iso_723(vol_desc->block_size)); 698 fprintf (STDOUT, "Creation date: "); 699 print_date(vol_desc->creation_date); 700 fprintf(STDOUT, "\n"); 701 fprintf (STDOUT, "Modification date: "); 702 print_date(vol_desc->mod_date); 703 fprintf (STDOUT, "\n"); 704 fprintf (STDOUT, "Expiration date: "); 705 print_date(vol_desc->exp_date); 706 fprintf (STDOUT, "\n"); 707 fprintf (STDOUT, "Effective date: "); 708 print_date(vol_desc->eff_date); 709 fprintf (STDOUT, "\n"); 710 } 711 712 713 void hs_info(vol_desc) 714 struct high_sierra_descriptor *vol_desc; 715 { 716 int i; 717 718 fprintf (STDOUT, "Format: HIGH SIERRA \n"); 719 fprintf (STDOUT, "System id: "); 720 for (i=0; i< sizeof(vol_desc->system_id); i++) 721 fprintf(STDOUT, "%c", vol_desc->system_id[i]); 722 fprintf (STDOUT, "\n"); 723 fprintf (STDOUT, "Volume id: "); 724 for (i=0; i< sizeof(vol_desc->volume_id); i++) 725 fprintf(STDOUT, "%c", vol_desc->volume_id[i]); 726 fprintf (STDOUT, "\n"); 727 fprintf (STDOUT, "Volume size: %ld Kb\n", (iso_733(vol_desc->volume_size)*2)); 728 fprintf (STDOUT, "Block size: %d bytes \n", iso_723(vol_desc->block_size)); 729 } 730 731 732 int valid_fs() 733 { 734 735 int i; 736 737 /* search for a volume descriptor */ 738 for (i=16; i<100; i++) 739 { 740 741 read_device((long)(i)*BLOCK_SIZE, BLOCK_SIZE, Buffer); 742 743 Iso_Vol_Desc = (struct iso9660_descriptor *) Buffer; 744 Hs_Vol_Desc = (struct high_sierra_descriptor *) Buffer; 745 746 if (strncmp(Iso_Vol_Desc->id, ISO9660_ID, sizeof Iso_Vol_Desc->id) == 0) 747 { 748 /* iso_info(Iso_Vol_Desc); */ 749 Iso9660 = 1; 750 break; 751 } 752 753 if (strncmp(Hs_Vol_Desc->id, HIGH_SIERRA_ID, sizeof Hs_Vol_Desc->id) == 0) 754 { 755 /* hs_info(Hs_Vol_Desc); */ 756 High_Sierra = 1; 757 break; 758 } 759 } 760 761 if (i >= 100) return 0; 762 return 1; 763 } 764 765 766 void read_device(offset, nr_of_bytes, buffer) 767 long offset; 768 int nr_of_bytes; 769 char *buffer; 770 { 771 int bytes_read; 772 773 if (lseek(Device, offset, SEEK_SET) == -1) 774 { 775 fflush (stdout); 776 fprintf (STDERR, "seek error: %s\n", strerror(errno)); 777 exit(1); 778 } 779 780 bytes_read = read(Device, buffer, nr_of_bytes); 781 if (bytes_read != nr_of_bytes) 782 { 783 fprintf (STDERR, "read error: %s\n", 784 bytes_read >= 0 ? "Short read" : strerror(errno)); 785 exit (1); 786 } 787 } 788 789 790 /* The ISO9660 functions */ 791 792 int iso_711 (c) 793 char *c; 794 { 795 return (*c & 0xff); 796 } 797 798 799 int iso_712 (c) 800 char *c; 801 { 802 int n; 803 804 n = *c; 805 if (n & 0x80) n |= 0xffffff00; 806 return n; 807 } 808 809 int iso_721 (c) 810 char *c; 811 { 812 return ((c[0] & 0xff) | ((c[1] & 0xff) << 8)); 813 } 814 815 int iso_722 (c) 816 char *c; 817 { 818 return (((c[0] & 0xff) << 8) | (c[1] & 0xff)); 819 } 820 821 int iso_723 (c) 822 char *c; 823 { 824 if (c[0] != c[3] || c[1] != c[2]) 825 { 826 fprintf (STDERR, "Invalid ISO 7.2.3 number\n"); 827 exit (1); 828 } 829 return (iso_721 (c)); 830 } 831 832 long iso_731 (c) 833 char *c; 834 { 835 return ((long)(c[0] & 0xff) 836 | ((long)(c[1] & 0xff) << 8) 837 | ((long)(c[2] & 0xff) << 16) 838 | ((long)(c[3] & 0xff) << 24)); 839 } 840 841 842 long iso_732 (c) 843 char *c; 844 { 845 return (((long)(c[0] & 0xff) << 24) 846 | (((long)c[1] & 0xff) << 16) 847 | (((long)c[2] & 0xff) << 8) 848 | ((long)c[3] & 0xff)); 849 } 850 851 long iso_733 (c) 852 char *c; 853 { 854 int i; 855 856 for (i = 0; i < 4; i++) 857 { 858 if (c[i] != c[7-i]) 859 { 860 fprintf (STDERR, "Invalid ISO 7.3.3 number\n"); 861 exit (1); 862 } 863 } 864 return (iso_731(c)); 865 } 866