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 382 /* Keep searching for the path elements until all are found */ 383 while (!last_in_path) 384 { 385 /* Get next name in path */ 386 for (i = name_index; i < strlen(path); i++) 387 { 388 if (path[i] == '/') break; 389 name[i - name_index] = path[i]; 390 } 391 last_in_path = 392 (i == strlen(path) || (i == strlen(path) - 1 && path[i] == '/')); 393 name[i-name_index] = '\0'; 394 name_index = i + 1; 395 396 /* Get block of next directory */ 397 block = iso_733(dir_ptr->first_block) + iso_711(dir_ptr->ext_attr_length); 398 nr_of_blocks = (iso_733(dir_ptr->size) + (BLOCK_SIZE-1)) >> BLOCK_SHIFT; 399 400 /* Search for file in dir entry */ 401 found = 0; 402 for (j=0; j < nr_of_blocks && !found; j++) 403 { 404 /* Read a directory block */ 405 read_device(block*BLOCK_SIZE, BLOCK_SIZE, Buffer); 406 block++; 407 408 dir_ptr = (struct dir_entry *) Buffer; 409 410 offset = 0; 411 /* Compare with all entries in this block */ 412 while (iso_711(dir_ptr->length) > 0 && offset < BLOCK_SIZE) 413 { 414 if (iso_cmp(name, dir_ptr, 415 (Read_Dir || !last_in_path)) == 0) 416 { 417 found = 1; 418 break; 419 } 420 /* Next entry */ 421 offset += iso_711(dir_ptr->length); 422 dir_ptr = (struct dir_entry *) (Buffer + offset); 423 } 424 } 425 if (!found) return NULL_DIR; /* path element not found */ 426 } 427 return dir_ptr; 428 } 429 430 431 void recurse_dir(path, dir_ptr) 432 char *path; 433 struct dir_entry *dir_ptr; 434 { 435 /* Recursively descend all directories starting with dir_ptr */ 436 437 char tmp_path[MAX_PATH_LENGTH]; 438 int i,j, path_length; 439 long block, saveblock, dblock; 440 int nr_of_blocks; 441 int offset = 0; 442 443 444 /* Save block number and nr of blocks of current dir entry because 445 * list_dir changes dir_ptr 446 */ 447 block = iso_733(dir_ptr->first_block) + iso_711(dir_ptr->ext_attr_length); 448 nr_of_blocks = (iso_733(dir_ptr->size) + (BLOCK_SIZE-1)) >> BLOCK_SHIFT; 449 450 /* Add a trailing / to path if necessary */ 451 path_length = strlen(path); 452 if (path[path_length-1] != '/') 453 { 454 path[path_length++] = '/'; 455 path[path_length] = '\0'; 456 } 457 458 /* Print current path of directory, and list contents of directory */ 459 fprintf(STDOUT,"directory %s:\n\n", path); 460 list_dir(dir_ptr); 461 fprintf(STDOUT,"\n\n"); 462 463 for (j=0; j < nr_of_blocks; j++) 464 { 465 read_device(block*BLOCK_SIZE, BLOCK_SIZE, Buffer); 466 saveblock = block++; 467 468 /* Save buffer, because the next recursive call destroys 469 * the global Buffer 470 */ 471 dir_ptr = (struct dir_entry *) Buffer; 472 473 /* Search this dir entry for directories */ 474 offset = 0; 475 while (iso_711(dir_ptr->length) != 0 && offset < BLOCK_SIZE) 476 { 477 /* Is current file a directory and not the . or .. entries */ 478 if (IS_DIR(dir_ptr) && !IS_DOT(dir_ptr) && !IS_DOT_DOT(dir_ptr)) 479 { 480 /* setup path for next recursive call */ 481 for (i=0; i<path_length; i++) tmp_path[i] = path[i]; 482 for (i=0;i<iso_711(dir_ptr->name_length) && dir_ptr->name[i] != ';';i++) 483 tmp_path[i+path_length] = LOWER_CASE(dir_ptr->name[i]); 484 tmp_path[i+path_length] = '/'; 485 tmp_path[i+1+path_length] = '\0'; 486 487 /* Read block of directory we found */ 488 dblock = iso_733(dir_ptr->first_block); 489 read_device(dblock*BLOCK_SIZE, BLOCK_SIZE, Buffer); 490 491 /* And start all over again with this entry */ 492 recurse_dir(tmp_path, (struct dir_entry *) Buffer); 493 494 /* get the block we were looking at */ 495 read_device(saveblock*BLOCK_SIZE, BLOCK_SIZE, Buffer); 496 } 497 498 /* Go to the next file in this directory */ 499 offset += iso_711(dir_ptr->length); 500 dir_ptr = (struct dir_entry *) (Buffer + offset); 501 } 502 } 503 } 504 505 506 void list_dir(dir_ptr) 507 struct dir_entry *dir_ptr; 508 { 509 /* List all entries in a directory */ 510 int tty; 511 long block; 512 int nr_of_blocks; 513 int i,j; 514 int offset = 0; 515 char name[NR_OF_CHARS+NR_OF_BLANKS+1]; 516 int name_len; 517 int column = 0; 518 int skip = 0; 519 520 tty = isatty(STDOUT_FILENO); 521 /* Get first block of directory */ 522 block = iso_733(dir_ptr->first_block) + iso_711(dir_ptr->ext_attr_length); 523 nr_of_blocks = (iso_733(dir_ptr->size) + (BLOCK_SIZE-1)) >> BLOCK_SHIFT; 524 525 /* Read all directory blocks and display their contents */ 526 for (j=0; j < nr_of_blocks; j++) 527 { 528 read_device(block*BLOCK_SIZE, BLOCK_SIZE, Buffer); 529 block++; 530 531 dir_ptr = (struct dir_entry *) (Buffer); 532 offset = 0; 533 while (iso_711(dir_ptr->length) != 0 && offset < BLOCK_SIZE) 534 { 535 name_len = 0; 536 if (IS_DOT(dir_ptr)) 537 { 538 name[name_len++] = '.'; 539 if (!Verbose) skip = 1; 540 } 541 else 542 { 543 if (IS_DOT_DOT(dir_ptr)) 544 { 545 name[name_len++] = '.'; 546 name[name_len++] = '.'; 547 if (!Verbose) skip = 1; 548 } 549 else 550 { 551 for (i=0; i<iso_711(dir_ptr->name_length) && 552 i<NR_OF_CHARS; i++) 553 { 554 if (dir_ptr->name[i] == ';') break; 555 name[name_len++] = LOWER_CASE(dir_ptr->name[i]); 556 } 557 if (IS_DIR(dir_ptr) && tty) name[name_len++] = '/'; 558 } 559 } 560 if (!skip) 561 { 562 if (ByteOffset) 563 { 564 fprintf (STDOUT, "%10ld ", 565 (iso_733(dir_ptr->first_block) + iso_711(dir_ptr->ext_attr_length)) 566 * BLOCK_SIZE); 567 } 568 if (Verbose || ByteOffset) 569 { 570 fprintf (STDOUT, "%10ld ", iso_733(dir_ptr->size)); 571 } 572 if (Verbose) 573 { 574 print_dir_date(dir_ptr->date); 575 fprintf (STDOUT, " "); 576 } 577 if(!tty) 578 name[name_len] = '\0'; 579 else { 580 for(i=name_len; i<(NR_OF_CHARS+NR_OF_BLANKS); i++) name[i] = ' '; 581 name[NR_OF_CHARS+NR_OF_BLANKS] = '\0'; 582 } 583 fprintf(STDOUT, "%s", name); 584 if (!(Verbose || ByteOffset)) 585 { 586 column++; 587 if (column >= NR_OF_COLS || !tty) 588 { 589 column = 0; 590 fprintf(STDOUT,"\n"); 591 } 592 } 593 else fprintf(STDOUT,"\n"); 594 } 595 skip = 0; 596 offset += iso_711(dir_ptr->length); 597 dir_ptr = (struct dir_entry *) (Buffer+offset); 598 } 599 } 600 if (!Verbose && column) fprintf(STDOUT,"\n"); 601 } 602 603 604 void print_dir_date(date) 605 char *date; 606 { 607 /* Print date in a directory entry */ 608 609 int m; 610 611 m = iso_711(&date[1]) - 1; 612 if(m < 0 || m > 11) 613 fprintf(STDOUT, " "); 614 else 615 fprintf(STDOUT,"%.3s",&months[m*3]); 616 617 fprintf (STDOUT, " %02d %04d %02d:%02d:%02d", 618 date[2], 619 1900+date[0], 620 date[3], 621 date[4], 622 date[5]); 623 } 624 625 626 void list_file(dir_ptr) 627 struct dir_entry *dir_ptr; 628 { 629 /* List contents of a file */ 630 631 int i; 632 long block; 633 long size; 634 char c; 635 636 block = iso_733(dir_ptr->first_block); 637 size = iso_733(dir_ptr->size); 638 639 if (ByteOffset) { 640 fprintf(STDOUT, "%ld %ld\n", block*BLOCK_SIZE, size); 641 return; 642 } 643 644 while (size > 0) 645 if (Aflag == 1) { 646 read_device(block*BLOCK_SIZE, BLOCK_SIZE, Buffer); 647 for (i=0; ((i < size) && (i < BLOCK_SIZE)); i++) 648 if (Buffer[i] != '\r') fprintf(STDOUT, "%c", Buffer[i]); 649 size-= BLOCK_SIZE; 650 block++; 651 } else { 652 read_device(block*BLOCK_SIZE, BLOCK_SIZE, Buffer); 653 for (i=0; ((i < size) && (i < BLOCK_SIZE)); i++) 654 fprintf(STDOUT, "%c", Buffer[i]); 655 size-= BLOCK_SIZE; 656 block++; 657 } 658 } 659 660 661 void print_date(date) 662 char *date; 663 { 664 /* Print the date in a volume descriptor */ 665 666 fprintf (STDOUT, "%c%c-%c%c-%c%c%c%c %c%c:%c%c:%c%c", 667 date[4], 668 date[5], 669 date[6], 670 date[7], 671 date[0], 672 date[1], 673 date[2], 674 date[3], 675 date[8], 676 date[9], 677 date[10], 678 date[11], 679 date[12], 680 date[13]); 681 } 682 683 void iso_info(vol_desc) 684 struct iso9660_descriptor *vol_desc; 685 { 686 int i; 687 688 fprintf (STDOUT, "Format: ISO9660 \n"); 689 fprintf (STDOUT, "System id: "); 690 for (i=0; i< sizeof(vol_desc->system_id); i++) 691 fprintf(STDOUT, "%c", vol_desc->system_id[i]); 692 fprintf (STDOUT, "\n"); 693 fprintf (STDOUT, "Volume id: "); 694 for (i=0; i< sizeof(vol_desc->volume_id); i++) 695 fprintf(STDOUT, "%c", vol_desc->volume_id[i]); 696 fprintf (STDOUT, "\n"); 697 fprintf (STDOUT, "Volume size: %ld Kb\n", iso_733(vol_desc->volume_size)*2); 698 fprintf (STDOUT, "Block size: %d bytes \n", iso_723(vol_desc->block_size)); 699 fprintf (STDOUT, "Creation date: "); 700 print_date(vol_desc->creation_date); 701 fprintf(STDOUT, "\n"); 702 fprintf (STDOUT, "Modification date: "); 703 print_date(vol_desc->mod_date); 704 fprintf (STDOUT, "\n"); 705 fprintf (STDOUT, "Expiration date: "); 706 print_date(vol_desc->exp_date); 707 fprintf (STDOUT, "\n"); 708 fprintf (STDOUT, "Effective date: "); 709 print_date(vol_desc->eff_date); 710 fprintf (STDOUT, "\n"); 711 } 712 713 714 void hs_info(vol_desc) 715 struct high_sierra_descriptor *vol_desc; 716 { 717 int i; 718 719 fprintf (STDOUT, "Format: HIGH SIERRA \n"); 720 fprintf (STDOUT, "System id: "); 721 for (i=0; i< sizeof(vol_desc->system_id); i++) 722 fprintf(STDOUT, "%c", vol_desc->system_id[i]); 723 fprintf (STDOUT, "\n"); 724 fprintf (STDOUT, "Volume id: "); 725 for (i=0; i< sizeof(vol_desc->volume_id); i++) 726 fprintf(STDOUT, "%c", vol_desc->volume_id[i]); 727 fprintf (STDOUT, "\n"); 728 fprintf (STDOUT, "Volume size: %ld Kb\n", (iso_733(vol_desc->volume_size)*2)); 729 fprintf (STDOUT, "Block size: %d bytes \n", iso_723(vol_desc->block_size)); 730 } 731 732 733 int valid_fs() 734 { 735 736 int i; 737 738 /* search for a volume descriptor */ 739 for (i=16; i<100; i++) 740 { 741 742 read_device((long)(i)*BLOCK_SIZE, BLOCK_SIZE, Buffer); 743 744 Iso_Vol_Desc = (struct iso9660_descriptor *) Buffer; 745 Hs_Vol_Desc = (struct high_sierra_descriptor *) Buffer; 746 747 if (strncmp(Iso_Vol_Desc->id, ISO9660_ID, sizeof Iso_Vol_Desc->id) == 0) 748 { 749 /* iso_info(Iso_Vol_Desc); */ 750 Iso9660 = 1; 751 break; 752 } 753 754 if (strncmp(Hs_Vol_Desc->id, HIGH_SIERRA_ID, sizeof Hs_Vol_Desc->id) == 0) 755 { 756 /* hs_info(Hs_Vol_Desc); */ 757 High_Sierra = 1; 758 break; 759 } 760 } 761 762 if (i >= 100) return 0; 763 return 1; 764 } 765 766 767 void read_device(offset, nr_of_bytes, buffer) 768 long offset; 769 int nr_of_bytes; 770 char *buffer; 771 { 772 int bytes_read; 773 774 if (lseek(Device, offset, SEEK_SET) == -1) 775 { 776 fflush (stdout); 777 fprintf (STDERR, "seek error: %s\n", strerror(errno)); 778 exit(1); 779 } 780 781 bytes_read = read(Device, buffer, nr_of_bytes); 782 if (bytes_read != nr_of_bytes) 783 { 784 fprintf (STDERR, "read error: %s\n", 785 bytes_read >= 0 ? "Short read" : strerror(errno)); 786 exit (1); 787 } 788 } 789 790 791 /* The ISO9660 functions */ 792 793 int iso_711 (c) 794 char *c; 795 { 796 return (*c & 0xff); 797 } 798 799 800 int iso_712 (c) 801 char *c; 802 { 803 int n; 804 805 n = *c; 806 if (n & 0x80) n |= 0xffffff00; 807 return n; 808 } 809 810 int iso_721 (c) 811 char *c; 812 { 813 return ((c[0] & 0xff) | ((c[1] & 0xff) << 8)); 814 } 815 816 int iso_722 (c) 817 char *c; 818 { 819 return (((c[0] & 0xff) << 8) | (c[1] & 0xff)); 820 } 821 822 int iso_723 (c) 823 char *c; 824 { 825 if (c[0] != c[3] || c[1] != c[2]) 826 { 827 fprintf (STDERR, "Invalid ISO 7.2.3 number\n"); 828 exit (1); 829 } 830 return (iso_721 (c)); 831 } 832 833 long iso_731 (c) 834 char *c; 835 { 836 return ((long)(c[0] & 0xff) 837 | ((long)(c[1] & 0xff) << 8) 838 | ((long)(c[2] & 0xff) << 16) 839 | ((long)(c[3] & 0xff) << 24)); 840 } 841 842 843 long iso_732 (c) 844 char *c; 845 { 846 return (((long)(c[0] & 0xff) << 24) 847 | (((long)c[1] & 0xff) << 16) 848 | (((long)c[2] & 0xff) << 8) 849 | ((long)c[3] & 0xff)); 850 } 851 852 long iso_733 (c) 853 char *c; 854 { 855 int i; 856 857 for (i = 0; i < 4; i++) 858 { 859 if (c[i] != c[7-i]) 860 { 861 fprintf (STDERR, "Invalid ISO 7.3.3 number\n"); 862 exit (1); 863 } 864 } 865 return (iso_731(c)); 866 } 867