1 /* 2 * File isodump.c - dump iso9660 directory information. 3 * 4 5 Written by Eric Youngdale (1993). 6 7 Copyright 1993 Yggdrasil Computing, Incorporated 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2, or (at your option) 12 any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 22 23 static char rcsid[] ="$Id: isodump.c,v 1.1 2000/10/10 20:40:28 beck Exp $"; 24 25 #include "../config.h" 26 27 #include <stdio.h> 28 #ifdef HAVE_TERMIOS_H 29 #include <termios.h> 30 #include <sys/ioctl.h> 31 #else 32 #include <termio.h> 33 #endif 34 #include <signal.h> 35 36 FILE * infile; 37 int file_addr; 38 unsigned char buffer[2048]; 39 unsigned char search[64]; 40 int blocksize; 41 42 #define PAGE sizeof(buffer) 43 44 #define ISODCL(from, to) (to - from + 1) 45 46 47 int 48 isonum_731 (char * p) 49 { 50 return ((p[0] & 0xff) 51 | ((p[1] & 0xff) << 8) 52 | ((p[2] & 0xff) << 16) 53 | ((p[3] & 0xff) << 24)); 54 } 55 56 int 57 isonum_721 (char * p) 58 { 59 return ((p[0] & 0xff) | ((p[1] & 0xff) << 8)); 60 } 61 62 int 63 isonum_723 (char * p) 64 { 65 #if 0 66 if (p[0] != p[3] || p[1] != p[2]) { 67 fprintf (stderr, "invalid format 7.2.3 number\n"); 68 exit (1); 69 } 70 #endif 71 return (isonum_721 (p)); 72 } 73 74 75 int 76 isonum_733 (unsigned char * p) 77 { 78 return (isonum_731 ((char *)p)); 79 } 80 81 struct iso_primary_descriptor { 82 unsigned char type [ISODCL ( 1, 1)]; /* 711 */ 83 unsigned char id [ISODCL ( 2, 6)]; 84 unsigned char version [ISODCL ( 7, 7)]; /* 711 */ 85 unsigned char unused1 [ISODCL ( 8, 8)]; 86 unsigned char system_id [ISODCL ( 9, 40)]; /* aunsigned chars */ 87 unsigned char volume_id [ISODCL ( 41, 72)]; /* dunsigned chars */ 88 unsigned char unused2 [ISODCL ( 73, 80)]; 89 unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ 90 unsigned char unused3 [ISODCL ( 89, 120)]; 91 unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */ 92 unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ 93 unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */ 94 unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */ 95 unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */ 96 unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ 97 unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */ 98 unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ 99 unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ 100 unsigned char volume_set_id [ISODCL (191, 318)]; /* dunsigned chars */ 101 unsigned char publisher_id [ISODCL (319, 446)]; /* achars */ 102 unsigned char preparer_id [ISODCL (447, 574)]; /* achars */ 103 unsigned char application_id [ISODCL (575, 702)]; /* achars */ 104 unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ 105 unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ 106 unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ 107 unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ 108 unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ 109 unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ 110 unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ 111 unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */ 112 unsigned char unused4 [ISODCL (883, 883)]; 113 unsigned char application_data [ISODCL (884, 1395)]; 114 unsigned char unused5 [ISODCL (1396, 2048)]; 115 }; 116 117 struct iso_directory_record { 118 unsigned char length [ISODCL (1, 1)]; /* 711 */ 119 unsigned char ext_attr_length [ISODCL (2, 2)]; /* 711 */ 120 unsigned char extent [ISODCL (3, 10)]; /* 733 */ 121 unsigned char size [ISODCL (11, 18)]; /* 733 */ 122 unsigned char date [ISODCL (19, 25)]; /* 7 by 711 */ 123 unsigned char flags [ISODCL (26, 26)]; 124 unsigned char file_unit_size [ISODCL (27, 27)]; /* 711 */ 125 unsigned char interleave [ISODCL (28, 28)]; /* 711 */ 126 unsigned char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ 127 unsigned char name_len [ISODCL (33, 33)]; /* 711 */ 128 unsigned char name [1]; 129 }; 130 131 #ifdef HAVE_TERMIOS_H 132 struct termios savetty; 133 struct termios newtty; 134 #else 135 struct termio savetty; 136 struct termio newtty; 137 #endif 138 139 reset_tty(){ 140 #ifdef HAVE_TERMIOS_H 141 if(tcsetattr(0, TCSANOW, &savetty) == -1) 142 #else 143 if(ioctl(0, TCSETAF, &savetty)==-1) 144 #endif 145 { 146 printf("cannot put tty into normal mode\n"); 147 exit(1); 148 } 149 } 150 151 set_tty(){ 152 #ifdef HAVE_TERMIOS_H 153 if(tcsetattr(0, TCSANOW, &newtty) == -1) 154 #else 155 if(ioctl(0, TCSETAF, &newtty)==-1) 156 #endif 157 { 158 printf("cannot put tty into raw mode\n"); 159 exit(1); 160 } 161 } 162 163 /* Come here when we get a suspend signal from the terminal */ 164 165 void 166 onsusp (int signo) 167 { 168 /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */ 169 signal(SIGTTOU, SIG_IGN); 170 reset_tty (); 171 fflush (stdout); 172 signal(SIGTTOU, SIG_DFL); 173 /* Send the TSTP signal to suspend our process group */ 174 signal(SIGTSTP, SIG_DFL); 175 /* sigsetmask(0);*/ 176 kill (0, SIGTSTP); 177 /* Pause for station break */ 178 179 /* We're back */ 180 signal (SIGTSTP, onsusp); 181 set_tty (); 182 } 183 184 185 186 crsr2(int row, int col){ 187 printf("\033[%d;%dH",row,col); 188 } 189 190 int parse_rr(unsigned char * pnt, int len, int cont_flag) 191 { 192 int slen; 193 int ncount; 194 int extent; 195 int cont_extent, cont_offset, cont_size; 196 int flag1, flag2; 197 unsigned char *pnts; 198 char symlink[1024]; 199 char name[1024]; 200 int goof; 201 /* printf(" RRlen=%d ", len); */ 202 203 symlink[0] = 0; 204 205 cont_extent = cont_offset = cont_size = 0; 206 207 ncount = 0; 208 flag1 = flag2 = 0; 209 while(len >= 4){ 210 if(ncount) printf(","); 211 else printf("["); 212 printf("%c%c", pnt[0], pnt[1]); 213 if(pnt[3] != 1) { 214 printf("**BAD RRVERSION"); 215 return; 216 }; 217 ncount++; 218 if(pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff; 219 if(strncmp(pnt, "PX", 2) == 0) flag2 |= 1; 220 if(strncmp(pnt, "PN", 2) == 0) flag2 |= 2; 221 if(strncmp(pnt, "SL", 2) == 0) flag2 |= 4; 222 if(strncmp(pnt, "NM", 2) == 0) { 223 slen = pnt[2] - 5; 224 pnts = pnt+5; 225 if( (pnt[4] & 6) != 0 ) 226 { 227 printf("*"); 228 } 229 memset(name, 0, sizeof(name)); 230 memcpy(name, pnts, slen); 231 printf("=%s", name); 232 flag2 |= 8; 233 } 234 if(strncmp(pnt, "CL", 2) == 0) flag2 |= 16; 235 if(strncmp(pnt, "PL", 2) == 0) flag2 |= 32; 236 if(strncmp(pnt, "RE", 2) == 0) flag2 |= 64; 237 if(strncmp(pnt, "TF", 2) == 0) flag2 |= 128; 238 239 if(strncmp(pnt, "PX", 2) == 0) { 240 extent = isonum_733(pnt+12); 241 printf("=%x", extent); 242 }; 243 244 if(strncmp(pnt, "CE", 2) == 0) { 245 cont_extent = isonum_733(pnt+4); 246 cont_offset = isonum_733(pnt+12); 247 cont_size = isonum_733(pnt+20); 248 printf("=[%x,%x,%d]", cont_extent, cont_offset, 249 cont_size); 250 }; 251 252 if(strncmp(pnt, "PL", 2) == 0 || strncmp(pnt, "CL", 2) == 0) { 253 extent = isonum_733(pnt+4); 254 printf("=%x", extent); 255 }; 256 257 if(strncmp(pnt, "SL", 2) == 0) { 258 int cflag; 259 260 cflag = pnt[4]; 261 pnts = pnt+5; 262 slen = pnt[2] - 5; 263 while(slen >= 1){ 264 switch(pnts[0] & 0xfe){ 265 case 0: 266 strncat(symlink, pnts+2, pnts[1]); 267 break; 268 case 2: 269 strcat (symlink, "."); 270 break; 271 case 4: 272 strcat (symlink, ".."); 273 break; 274 case 8: 275 if((pnts[0] & 1) == 0)strcat (symlink, "/"); 276 break; 277 case 16: 278 strcat(symlink,"/mnt"); 279 printf("Warning - mount point requested"); 280 break; 281 case 32: 282 strcat(symlink,"kafka"); 283 printf("Warning - host_name requested"); 284 break; 285 default: 286 printf("Reserved bit setting in symlink", goof++); 287 break; 288 }; 289 if((pnts[0] & 0xfe) && pnts[1] != 0) { 290 printf("Incorrect length in symlink component"); 291 }; 292 if((pnts[0] & 1) == 0) strcat(symlink,"/"); 293 294 slen -= (pnts[1] + 2); 295 pnts += (pnts[1] + 2); 296 297 }; 298 if(cflag) strcat(symlink, "+"); 299 printf("=%s", symlink); 300 symlink[0] = 0; 301 }; 302 303 len -= pnt[2]; 304 pnt += pnt[2]; 305 if(len <= 3 && cont_extent) { 306 unsigned char sector[2048]; 307 lseek(fileno(infile), cont_extent * blocksize, 0); 308 read(fileno(infile), sector, sizeof(sector)); 309 flag2 |= parse_rr(§or[cont_offset], cont_size, 1); 310 }; 311 }; 312 if(ncount) printf("]"); 313 if (!cont_flag && flag1 != flag2) 314 printf("Flag %x != %x", flag1, flag2, goof++); 315 return flag2; 316 } 317 318 int 319 dump_rr(struct iso_directory_record * idr) 320 { 321 int len; 322 unsigned char * pnt; 323 324 len = idr->length[0] & 0xff; 325 len -= sizeof(struct iso_directory_record); 326 len += sizeof(idr->name); 327 len -= idr->name_len[0]; 328 pnt = (unsigned char *) idr; 329 pnt += sizeof(struct iso_directory_record); 330 pnt -= sizeof(idr->name); 331 pnt += idr->name_len[0]; 332 if((idr->name_len[0] & 1) == 0){ 333 pnt++; 334 len--; 335 }; 336 parse_rr(pnt, len, 0); 337 } 338 339 340 showblock(int flag){ 341 unsigned int k; 342 int i, j; 343 int line; 344 struct iso_directory_record * idr; 345 lseek(fileno(infile), file_addr, 0); 346 read(fileno(infile), buffer, sizeof(buffer)); 347 for(i=0;i<60;i++) printf("\n"); 348 fflush(stdout); 349 i = line = 0; 350 if(flag) { 351 while(1==1){ 352 crsr2(line+3,1); 353 idr = (struct iso_directory_record *) &buffer[i]; 354 if(idr->length[0] == 0) break; 355 printf("%3d ", idr->length[0]); 356 printf("[%2d] ", idr->volume_sequence_number[0]); 357 printf("%5x ", isonum_733(idr->extent)); 358 printf("%8d ", isonum_733(idr->size)); 359 printf ((idr->flags[0] & 2) ? "*" : " "); 360 if(idr->name_len[0] == 1 && idr->name[0] == 0) 361 printf(". "); 362 else if(idr->name_len[0] == 1 && idr->name[0] == 1) 363 printf(".. "); 364 else { 365 for(j=0; j<idr->name_len[0]; j++) printf("%c", idr->name[j]); 366 for(j=0; j<14 -idr->name_len[0]; j++) printf(" "); 367 }; 368 dump_rr(idr); 369 printf("\n"); 370 i += buffer[i]; 371 if (i > 2048 - sizeof(struct iso_directory_record)) break; 372 line++; 373 }; 374 }; 375 printf("\n"); 376 printf(" Zone, zone offset: %6x %4.4x ",file_addr / blocksize, 377 file_addr & (blocksize - 1)); 378 fflush(stdout); 379 } 380 381 getbyte() 382 { 383 char c1; 384 c1 = buffer[file_addr & (blocksize-1)]; 385 file_addr++; 386 if ((file_addr & (blocksize-1)) == 0) showblock(0); 387 return c1; 388 } 389 390 main(int argc, char * argv[]){ 391 char c; 392 char buffer[2048]; 393 int nbyte; 394 int i,j; 395 struct iso_primary_descriptor ipd; 396 struct iso_directory_record * idr; 397 398 if(argc < 2) return 0; 399 infile = fopen(argv[1],"rb"); 400 401 file_addr = 16 << 11; 402 lseek(fileno(infile), file_addr, 0); 403 read(fileno(infile), &ipd, sizeof(ipd)); 404 405 idr = (struct iso_directory_record *) &ipd.root_directory_record; 406 407 blocksize = isonum_723((char *)ipd.logical_block_size); 408 if( blocksize != 512 && blocksize != 1024 && blocksize != 2048 ) 409 { 410 blocksize = 2048; 411 } 412 413 file_addr = isonum_733(idr->extent); 414 415 file_addr = file_addr * blocksize; 416 417 /* Now setup the keyboard for single character input. */ 418 #ifdef HAVE_TERMIOS_H 419 if(tcgetattr(0, &savetty) == -1) 420 #else 421 if(ioctl(0, TCGETA, &savetty) == -1) 422 #endif 423 { 424 printf("stdin must be a tty\n"); 425 exit(1); 426 } 427 newtty=savetty; 428 newtty.c_lflag&=~ICANON; 429 newtty.c_lflag&=~ECHO; 430 newtty.c_cc[VMIN]=1; 431 set_tty(); 432 signal(SIGTSTP, onsusp); 433 434 do{ 435 if(file_addr < 0) file_addr = 0; 436 showblock(1); 437 read (0, &c, 1); 438 if (c == 'a') file_addr -= blocksize; 439 if (c == 'b') file_addr += blocksize; 440 if (c == 'g') { 441 crsr2(20,1); 442 printf("Enter new starting block (in hex):"); 443 scanf("%x",&file_addr); 444 file_addr = file_addr * blocksize; 445 crsr2(20,1); 446 printf(" "); 447 }; 448 if (c == 'f') { 449 crsr2(20,1); 450 printf("Enter new search string:"); 451 fgets((char *)search,sizeof(search),stdin); 452 while(search[strlen(search)-1] == '\n') search[strlen(search)-1] = 0; 453 crsr2(20,1); 454 printf(" "); 455 }; 456 if (c == '+') { 457 while(1==1){ 458 while(1==1){ 459 c = getbyte(&file_addr); 460 if (c == search[0]) break; 461 }; 462 for (j=1;j<strlen(search);j++) 463 if(search[j] != getbyte()) break; 464 if(j==strlen(search)) break; 465 }; 466 file_addr &= ~(blocksize-1); 467 showblock(1); 468 }; 469 if (c == 'q') break; 470 } while(1==1); 471 reset_tty(); 472 fclose(infile); 473 } 474 475 476 477 478