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
isonum_731(char * p)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
isonum_721(char * p)57 isonum_721 (char * p)
58 {
59 return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
60 }
61
62 int
isonum_723(char * p)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
isonum_733(unsigned char * p)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
reset_tty()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
set_tty()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
onsusp(int signo)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
crsr2(int row,int col)186 crsr2(int row, int col){
187 printf("\033[%d;%dH",row,col);
188 }
189
parse_rr(unsigned char * pnt,int len,int cont_flag)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
dump_rr(struct iso_directory_record * idr)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
showblock(int flag)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
getbyte()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
main(int argc,char * argv[])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