xref: /openbsd/gnu/usr.sbin/mkhybrid/src/diag/isodump.c (revision 73471bf0)
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(&sector[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