diff options
Diffstat (limited to 'gnu/usr.sbin/mkisofs/diag')
-rw-r--r-- | gnu/usr.sbin/mkisofs/diag/README | 78 | ||||
-rw-r--r-- | gnu/usr.sbin/mkisofs/diag/dump.c | 205 | ||||
-rw-r--r-- | gnu/usr.sbin/mkisofs/diag/isodump.c | 478 | ||||
-rw-r--r-- | gnu/usr.sbin/mkisofs/diag/isoinfo.8 | 125 | ||||
-rw-r--r-- | gnu/usr.sbin/mkisofs/diag/isoinfo.c | 554 | ||||
-rw-r--r-- | gnu/usr.sbin/mkisofs/diag/isovfy.c | 514 |
6 files changed, 1954 insertions, 0 deletions
diff --git a/gnu/usr.sbin/mkisofs/diag/README b/gnu/usr.sbin/mkisofs/diag/README new file mode 100644 index 00000000000..92315118f7a --- /dev/null +++ b/gnu/usr.sbin/mkisofs/diag/README @@ -0,0 +1,78 @@ +# $OpenBSD: README,v 1.1 1997/09/15 06:01:53 downsj Exp $ +# +# $From: README,v 1.1 1997/02/23 16:14:56 eric Rel $ +# + I am enclosing 3 test programs that I use to verify the +integrity of an iso9660 disc. The first one (isodump) is pretty +simple - it dumps to the screen the contents of the various +directories. The second one (isovfy) goes through and looks for +problems of one kind or another. + + To use, type something like "./isodump /dev/ramdisk" or +"./isodump /dev/scd0", depending upon where the iso9660 disc is. It +starts by displaying the files in the first sector of the root +directory. It has some pretty simple one letter commands that you +can use to traverse the directory tree. + + a - move back one sector. + b - move forward one sector. + g - go to new logical sector. + q - quit + +The a and b commands do not try and stop you from going past the +beginning or end of a sector, and the g command does not have any way +of knowing whether the sector you request is actually a directory or +not. + + The output is displayed in several columns. The first column +is the total length of the directory record for the file. The second +column (in [] brackets) is the volume number. Next comes the starting +extent number (in hex), and then comes the file size in bytes. Then +cones the filename (not the Rock Ridge version), and this is preceeded +by an "*" if the file is a directory. After this is a summary of the +Rock Ridge fields present along with a display of the translation of +the symbolic link name if the SL Rock Ridge record is present. + + I tailored this program for debugging some of the problems +that I was having earlier. The idea is that you can tailor it +to test for problems that you might be having, so it is not intended +as a be-all and end-all dump program. + + If you move to a sector that does not contain directory +information, the results are unpredictable. + + The second program, isovfy, is run in the same way as isodump, +except that you do not have to do much except let it run. I have it +written to verify all kinds of different things, and as people find +other sorts of problems other tests could be added. + + The third program, dump.c, basically does a hexdump of the cd. +This is screen oriented, and there are some simple commands: + + a - move back one sector. + b - move forward one sector. + f - enter new search string. + + - search forward for search string. + g - go to new logical sector. + q - quit + + + Note that with the 'g' command, sectors are always given in +hex, and represent 2048 byte sectors (as on the cdrom). If you know +how to decode a raw iso9660 directory, you can pick out the starting +extent number from the hexdump and know where to go from there. The +starting extent appears something like 30 bytes prior to the start of +the iso9660 (not Rock Ridge) filename, and it appears in a 7.3.3 +format (meaning that it occupies 8 bytes, 4 in little endian format, +and 4 in big endian format). Thus you should see a mirror image of +the bytes when looking at the extent number. + + The isovfy program can also dump the contents of the path +tables, but this capability is commented out right now. Feel free +to enable this to see what is in the tables. Ultimately I may fix +it so that this checks the integrity of the tables as well. + + The isovfy program gives warnings about things like files that +have a size of 0 but have an extent number assigned. The mkisofs program +should never do this, but the YM software does leave these around. +I think it is probably harmless in the YM case.~ diff --git a/gnu/usr.sbin/mkisofs/diag/dump.c b/gnu/usr.sbin/mkisofs/diag/dump.c new file mode 100644 index 00000000000..be97d711482 --- /dev/null +++ b/gnu/usr.sbin/mkisofs/diag/dump.c @@ -0,0 +1,205 @@ +/* $OpenBSD: dump.c,v 1.1 1997/09/15 06:01:53 downsj Exp $ */ +/* + * File dump.c - dump a file/device both in hex and in ASCII. + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +static char rcsid[] ="$From: dump.c,v 1.2 1997/02/23 19:10:49 eric Rel $"; + +#include "../config.h" + +#include <stdio.h> +#ifdef HAVE_TERMIOS_H +#include <termios.h> +#include <sys/ioctl.h> +#else +#include <termio.h> +#endif +#include <signal.h> + +FILE * infile; +int file_addr; +unsigned char buffer[256]; +unsigned char search[64]; + +#define PAGE 256 + +#ifdef HAVE_TERMIOS_H +struct termios savetty; +struct termios newtty; +#else +struct termio savetty; +struct termio newtty; +#endif + +reset_tty(){ +#ifdef HAVE_TERMIOS_H + if(tcsetattr(0, TCSANOW, &savetty) == -1) +#else + if(ioctl(0, TCSETAF, &savetty)==-1) +#endif + { + printf("cannot put tty into normal mode\n"); + exit(1); + } +} + +set_tty(){ +#ifdef HAVE_TERMIOS_H + if(tcsetattr(0, TCSANOW, &newtty) == -1) +#else + if(ioctl(0, TCSETAF, &newtty)==-1) +#endif + { + printf("cannot put tty into raw mode\n"); + exit(1); + } +} + + +/* Come here when we get a suspend signal from the terminal */ + +void +onsusp (int sig) +{ + /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */ + signal(SIGTTOU, SIG_IGN); + reset_tty (); + fflush (stdout); + signal(SIGTTOU, SIG_DFL); + /* Send the TSTP signal to suspend our process group */ + signal(SIGTSTP, SIG_DFL); +/* sigsetmask(0);*/ + kill (0, SIGTSTP); + /* Pause for station break */ + + /* We're back */ + signal (SIGTSTP, onsusp); + set_tty (); +} + + + +crsr2(int row, int col){ + printf("\033[%d;%dH",row,col); +} + +showblock(int flag){ + unsigned int k; + int i, j; + lseek(fileno(infile), file_addr, 0); + read(fileno(infile), buffer, sizeof(buffer)); + if(flag) { + for(i=0;i<16;i++){ + crsr2(i+3,1); + printf("%8.8x ",file_addr+(i<<4)); + for(j=15;j>=0;j--){ + printf("%2.2x",buffer[(i<<4)+j]); + if(!(j & 0x3)) printf(" "); + }; + for(j=0;j< 16;j++){ + k = buffer[(i << 4) + j]; + if(k >= ' ' && k < 0x80) printf("%c",k); + else printf("."); + }; + } + }; + crsr2(20,1); + printf(" Zone, zone offset: %6x %4.4x ",file_addr>>11, file_addr & 0x7ff); + fflush(stdout); +} + +getbyte() +{ + char c1; + c1 = buffer[file_addr & (PAGE-1)]; + file_addr++; + if ((file_addr & (PAGE-1)) == 0) showblock(0); + return c1; +} + +main(int argc, char * argv[]){ + char c; + int nbyte; + int i,j; + if(argc < 2) return 0; + infile = fopen(argv[1],"rb"); + for(i=0;i<30;i++) printf("\n"); + file_addr = 0; +/* Now setup the keyboard for single character input. */ +#ifdef HAVE_TERMIOS_H + if(tcgetattr(0, &savetty) == -1) +#else + if(ioctl(0, TCGETA, &savetty) == -1) +#endif + { + printf("stdin must be a tty\n"); + exit(1); + } + newtty=savetty; + newtty.c_lflag&=~ICANON; + newtty.c_lflag&=~ECHO; + newtty.c_cc[VMIN]=1; + set_tty(); + signal(SIGTSTP, onsusp); + + do{ + if(file_addr < 0) file_addr = 0; + showblock(1); + read (0, &c, 1); + if (c == 'a') file_addr -= PAGE; + if (c == 'b') file_addr += PAGE; + if (c == 'g') { + crsr2(20,1); + printf("Enter new starting block (in hex):"); + scanf("%x",&file_addr); + file_addr = file_addr << 11; + crsr2(20,1); + printf(" "); + }; + if (c == 'f') { + crsr2(20,1); + printf("Enter new search string:"); + fgets(search,sizeof(search),stdin); + while(search[strlen(search)-1] == '\n') search[strlen(search)-1] = 0; + crsr2(20,1); + printf(" "); + }; + if (c == '+') { + while(1==1){ + while(1==1){ + c = getbyte(&file_addr); + if (c == search[0]) break; + }; + for (j=1;j<strlen(search);j++) + if(search[j] != getbyte()) break; + if(j==strlen(search)) break; + }; + file_addr &= ~(PAGE-1); + showblock(1); + }; + if (c == 'q') break; + } while(1==1); + reset_tty(); + fclose(infile); +} + + + + diff --git a/gnu/usr.sbin/mkisofs/diag/isodump.c b/gnu/usr.sbin/mkisofs/diag/isodump.c new file mode 100644 index 00000000000..f15dae69b64 --- /dev/null +++ b/gnu/usr.sbin/mkisofs/diag/isodump.c @@ -0,0 +1,478 @@ +/* $OpenBSD: isodump.c,v 1.1 1997/09/15 06:01:53 downsj Exp $ */ +/* + * File isodump.c - dump iso9660 directory information. + * + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +static char rcsid[] ="$From: isodump.c,v 1.2 1997/02/23 19:11:24 eric Rel $"; + +#include "../config.h" + +#include <stdio.h> +#ifdef HAVE_TERMIOS_H +#include <termios.h> +#include <sys/ioctl.h> +#else +#include <termio.h> +#endif +#include <signal.h> + +FILE * infile; +int file_addr; +unsigned char buffer[2048]; +unsigned char search[64]; +int blocksize; + +#define PAGE sizeof(buffer) + +#define ISODCL(from, to) (to - from + 1) + + +int +isonum_731 (char * p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + +int +isonum_721 (char * p) +{ + return ((p[0] & 0xff) | ((p[1] & 0xff) << 8)); +} + +int +isonum_723 (char * p) +{ +#if 0 + if (p[0] != p[3] || p[1] != p[2]) { + fprintf (stderr, "invalid format 7.2.3 number\n"); + exit (1); + } +#endif + return (isonum_721 (p)); +} + + +int +isonum_733 (unsigned char * p) +{ + return (isonum_731 (p)); +} + +struct iso_primary_descriptor { + unsigned char type [ISODCL ( 1, 1)]; /* 711 */ + unsigned char id [ISODCL ( 2, 6)]; + unsigned char version [ISODCL ( 7, 7)]; /* 711 */ + unsigned char unused1 [ISODCL ( 8, 8)]; + unsigned char system_id [ISODCL ( 9, 40)]; /* aunsigned chars */ + unsigned char volume_id [ISODCL ( 41, 72)]; /* dunsigned chars */ + unsigned char unused2 [ISODCL ( 73, 80)]; + unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ + unsigned char unused3 [ISODCL ( 89, 120)]; + unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */ + unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ + unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */ + unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */ + unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */ + unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ + unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */ + unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ + unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ + unsigned char volume_set_id [ISODCL (191, 318)]; /* dunsigned chars */ + unsigned char publisher_id [ISODCL (319, 446)]; /* achars */ + unsigned char preparer_id [ISODCL (447, 574)]; /* achars */ + unsigned char application_id [ISODCL (575, 702)]; /* achars */ + unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ + unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ + unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ + unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ + unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ + unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ + unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ + unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */ + unsigned char unused4 [ISODCL (883, 883)]; + unsigned char application_data [ISODCL (884, 1395)]; + unsigned char unused5 [ISODCL (1396, 2048)]; +}; + +struct iso_directory_record { + unsigned char length [ISODCL (1, 1)]; /* 711 */ + unsigned char ext_attr_length [ISODCL (2, 2)]; /* 711 */ + unsigned char extent [ISODCL (3, 10)]; /* 733 */ + unsigned char size [ISODCL (11, 18)]; /* 733 */ + unsigned char date [ISODCL (19, 25)]; /* 7 by 711 */ + unsigned char flags [ISODCL (26, 26)]; + unsigned char file_unit_size [ISODCL (27, 27)]; /* 711 */ + unsigned char interleave [ISODCL (28, 28)]; /* 711 */ + unsigned char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ + unsigned char name_len [ISODCL (33, 33)]; /* 711 */ + unsigned char name [1]; +}; + +#ifdef HAVE_TERMIOS_H +struct termios savetty; +struct termios newtty; +#else +struct termio savetty; +struct termio newtty; +#endif + +reset_tty(){ +#ifdef HAVE_TERMIOS_H + if(tcsetattr(0, TCSANOW, &savetty) == -1) +#else + if(ioctl(0, TCSETAF, &savetty)==-1) +#endif + { + printf("cannot put tty into normal mode\n"); + exit(1); + } +} + +set_tty(){ +#ifdef HAVE_TERMIOS_H + if(tcsetattr(0, TCSANOW, &newtty) == -1) +#else + if(ioctl(0, TCSETAF, &newtty)==-1) +#endif + { + printf("cannot put tty into raw mode\n"); + exit(1); + } +} + +/* Come here when we get a suspend signal from the terminal */ + +void +onsusp (int signo) +{ + /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */ + signal(SIGTTOU, SIG_IGN); + reset_tty (); + fflush (stdout); + signal(SIGTTOU, SIG_DFL); + /* Send the TSTP signal to suspend our process group */ + signal(SIGTSTP, SIG_DFL); +/* sigsetmask(0);*/ + kill (0, SIGTSTP); + /* Pause for station break */ + + /* We're back */ + signal (SIGTSTP, onsusp); + set_tty (); +} + + + +crsr2(int row, int col){ + printf("\033[%d;%dH",row,col); +} + +int parse_rr(unsigned char * pnt, int len, int cont_flag) +{ + int slen; + int ncount; + int extent; + int cont_extent, cont_offset, cont_size; + int flag1, flag2; + unsigned char *pnts; + char symlink[1024]; + char name[1024]; + int goof; +/* printf(" RRlen=%d ", len); */ + + symlink[0] = 0; + + cont_extent = cont_offset = cont_size = 0; + + ncount = 0; + flag1 = flag2 = 0; + while(len >= 4){ + if(ncount) printf(","); + else printf("["); + printf("%c%c", pnt[0], pnt[1]); + if(pnt[3] != 1) { + printf("**BAD RRVERSION"); + return; + }; + ncount++; + if(pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff; + if(strncmp(pnt, "PX", 2) == 0) flag2 |= 1; + if(strncmp(pnt, "PN", 2) == 0) flag2 |= 2; + if(strncmp(pnt, "SL", 2) == 0) flag2 |= 4; + if(strncmp(pnt, "NM", 2) == 0) { + slen = pnt[2] - 5; + pnts = pnt+5; + if( (pnt[4] & 6) != 0 ) + { + printf("*"); + } + memset(name, 0, sizeof(name)); + memcpy(name, pnts, slen); + printf("=%s", name); + flag2 |= 8; + } + if(strncmp(pnt, "CL", 2) == 0) flag2 |= 16; + if(strncmp(pnt, "PL", 2) == 0) flag2 |= 32; + if(strncmp(pnt, "RE", 2) == 0) flag2 |= 64; + if(strncmp(pnt, "TF", 2) == 0) flag2 |= 128; + + if(strncmp(pnt, "PX", 2) == 0) { + extent = isonum_733(pnt+12); + printf("=%x", extent); + }; + + if(strncmp(pnt, "CE", 2) == 0) { + cont_extent = isonum_733(pnt+4); + cont_offset = isonum_733(pnt+12); + cont_size = isonum_733(pnt+20); + printf("=[%x,%x,%d]", cont_extent, cont_offset, + cont_size); + }; + + if(strncmp(pnt, "PL", 2) == 0 || strncmp(pnt, "CL", 2) == 0) { + extent = isonum_733(pnt+4); + printf("=%x", extent); + }; + + if(strncmp(pnt, "SL", 2) == 0) { + int cflag; + + cflag = pnt[4]; + pnts = pnt+5; + slen = pnt[2] - 5; + while(slen >= 1){ + switch(pnts[0] & 0xfe){ + case 0: + strncat(symlink, pnts+2, pnts[1]); + break; + case 2: + strcat (symlink, "."); + break; + case 4: + strcat (symlink, ".."); + break; + case 8: + if((pnts[0] & 1) == 0)strcat (symlink, "/"); + break; + case 16: + strcat(symlink,"/mnt"); + printf("Warning - mount point requested"); + break; + case 32: + strcat(symlink,"kafka"); + printf("Warning - host_name requested"); + break; + default: + printf("Reserved bit setting in symlink", goof++); + break; + }; + if((pnts[0] & 0xfe) && pnts[1] != 0) { + printf("Incorrect length in symlink component"); + }; + if((pnts[0] & 1) == 0) strcat(symlink,"/"); + + slen -= (pnts[1] + 2); + pnts += (pnts[1] + 2); + + }; + if(cflag) strcat(symlink, "+"); + printf("=%s", symlink); + symlink[0] = 0; + }; + + len -= pnt[2]; + pnt += pnt[2]; + if(len <= 3 && cont_extent) { + unsigned char sector[2048]; + lseek(fileno(infile), cont_extent * blocksize, 0); + read(fileno(infile), sector, sizeof(sector)); + flag2 |= parse_rr(§or[cont_offset], cont_size, 1); + }; + }; + if(ncount) printf("]"); + if (!cont_flag && flag1 != flag2) + printf("Flag %x != %x", flag1, flag2, goof++); + return flag2; +} + +int +dump_rr(struct iso_directory_record * idr) +{ + int len; + unsigned char * pnt; + + len = idr->length[0] & 0xff; + len -= sizeof(struct iso_directory_record); + len += sizeof(idr->name); + len -= idr->name_len[0]; + pnt = (unsigned char *) idr; + pnt += sizeof(struct iso_directory_record); + pnt -= sizeof(idr->name); + pnt += idr->name_len[0]; + if((idr->name_len[0] & 1) == 0){ + pnt++; + len--; + }; + parse_rr(pnt, len, 0); +} + + +showblock(int flag){ + unsigned int k; + int i, j; + int line; + struct iso_directory_record * idr; + lseek(fileno(infile), file_addr, 0); + read(fileno(infile), buffer, sizeof(buffer)); + for(i=0;i<60;i++) printf("\n"); + fflush(stdout); + i = line = 0; + if(flag) { + while(1==1){ + crsr2(line+3,1); + idr = (struct iso_directory_record *) &buffer[i]; + if(idr->length[0] == 0) break; + printf("%3d ", idr->length[0]); + printf("[%2d] ", idr->volume_sequence_number[0]); + printf("%5x ", isonum_733(idr->extent)); + printf("%8d ", isonum_733(idr->size)); + printf ((idr->flags[0] & 2) ? "*" : " "); + if(idr->name_len[0] == 1 && idr->name[0] == 0) + printf(". "); + else if(idr->name_len[0] == 1 && idr->name[0] == 1) + printf(".. "); + else { + for(j=0; j<idr->name_len[0]; j++) printf("%c", idr->name[j]); + for(j=0; j<14 -idr->name_len[0]; j++) printf(" "); + }; + dump_rr(idr); + printf("\n"); + i += buffer[i]; + if (i > 2048 - sizeof(struct iso_directory_record)) break; + line++; + }; + }; + printf("\n"); + printf(" Zone, zone offset: %6x %4.4x ",file_addr / blocksize, + file_addr & (blocksize - 1)); + fflush(stdout); +} + +getbyte() +{ + char c1; + c1 = buffer[file_addr & (blocksize-1)]; + file_addr++; + if ((file_addr & (blocksize-1)) == 0) showblock(0); + return c1; +} + +main(int argc, char * argv[]){ + char c; + char buffer[2048]; + int nbyte; + int i,j; + struct iso_primary_descriptor ipd; + struct iso_directory_record * idr; + + if(argc < 2) return 0; + infile = fopen(argv[1],"rb"); + + file_addr = 16 << 11; + lseek(fileno(infile), file_addr, 0); + read(fileno(infile), &ipd, sizeof(ipd)); + + idr = (struct iso_directory_record *) &ipd.root_directory_record; + + blocksize = isonum_723(ipd.logical_block_size); + if( blocksize != 512 && blocksize != 1024 && blocksize != 2048 ) + { + blocksize = 2048; + } + + file_addr = isonum_733(idr->extent); + + file_addr = file_addr * blocksize; + +/* Now setup the keyboard for single character input. */ +#ifdef HAVE_TERMIOS_H + if(tcgetattr(0, &savetty) == -1) +#else + if(ioctl(0, TCGETA, &savetty) == -1) +#endif + { + printf("stdin must be a tty\n"); + exit(1); + } + newtty=savetty; + newtty.c_lflag&=~ICANON; + newtty.c_lflag&=~ECHO; + newtty.c_cc[VMIN]=1; + set_tty(); + signal(SIGTSTP, onsusp); + + do{ + if(file_addr < 0) file_addr = 0; + showblock(1); + read (0, &c, 1); + if (c == 'a') file_addr -= blocksize; + if (c == 'b') file_addr += blocksize; + if (c == 'g') { + crsr2(20,1); + printf("Enter new starting block (in hex):"); + scanf("%x",&file_addr); + file_addr = file_addr * blocksize; + crsr2(20,1); + printf(" "); + }; + if (c == 'f') { + crsr2(20,1); + printf("Enter new search string:"); + fgets(search,sizeof(search),stdin); + while(search[strlen(search)-1] == '\n') search[strlen(search)-1] = 0; + crsr2(20,1); + printf(" "); + }; + if (c == '+') { + while(1==1){ + while(1==1){ + c = getbyte(&file_addr); + if (c == search[0]) break; + }; + for (j=1;j<strlen(search);j++) + if(search[j] != getbyte()) break; + if(j==strlen(search)) break; + }; + file_addr &= ~(blocksize-1); + showblock(1); + }; + if (c == 'q') break; + } while(1==1); + reset_tty(); + fclose(infile); +} + + + + diff --git a/gnu/usr.sbin/mkisofs/diag/isoinfo.8 b/gnu/usr.sbin/mkisofs/diag/isoinfo.8 new file mode 100644 index 00000000000..041e5d2af42 --- /dev/null +++ b/gnu/usr.sbin/mkisofs/diag/isoinfo.8 @@ -0,0 +1,125 @@ +.\" $OpenBSD: isoinfo.8,v 1.1 1997/09/15 06:01:53 downsj Exp $ +.\" +.\" $From: isoinfo.8,v 1.1 1997/02/23 19:08:53 eric Rel $ +.\" +.\" -*- nroff -*- +.TH ISOINFO 8 "23 Feb 1997" "Version 1.10b8" +.SH NAME +isoinfo, isovfy, inodump \- Utility programs for dumping and verifying iso9660 +images. +.SH SYNOPSIS +.B isodump +.I isoimage +.PP +.B isoinfo +[ +.B \-R +] +[ +.B \-f +] +[ +.B \-l +] +[ +.B \-T +] +[ +.B \-N +] +[ +.B \-i +.I isoimage +] +[ +.B \-x +.I path +] +.PP +.B isovfy +.I isoimage +.SH DESCRIPTION +.B isodump +is a crude utility to interactively display the contents of iso9660 images +in order to verify directory integrity. The initial screen is a display +of the first part of the root directory, and the prompt shows you the +extent number and offset in the extent. You can use the 'a' and 'b' +commands to move backwards and forwards within the image. The 'g' command +allows you to goto an arbitrary extent, and the 'f' command specifies +a search string to be used. The '+' command searches forward for the next +instance of the search string, and the 'q' command exits +.B isodump. +.PP +.B isoinfo +is a utility to perform directory like listings of iso9660 images. +.PP +.B isovfy +is a utility to verify the integrity of an iso9660 image. Most of the tests +in +.B isovfy +were added after bugs were discovered in early versions of +.B mkisofs. +It isn't all that clear how useful this is anymore, but it doesn't hurt to +have this around. + +.SH OPTIONS +Only the +.B isoinfo +program has any command line options. These are: +.TP +.I -f +generate output as if a 'find . -print' command had been run on the iso9660 +image. You should not use the +.B -l +image with the +.B -f +option. +.TP +.I -i iso_image +Specifies the path of the iso9660 image that we wish to examine. +.TP +.I -l +generate output as if a 'ls -lR' command had been run on the iso9660 image. +You should not use the +.B -f +image with the +.B -l +option. +.TP +.I -N sector +Quick hack to help examine single session disc files that are to be written to +a multi-session disc. The sector number specified is the sector number at +which the iso9660 image should be written when send to the cd-writer. Not +used for the first session on the disc. +.TP +.I \-R +Extract information from Rock Ridge extensions (if present) for permissions, +file names and ownerships. +.TP +.I -T sector +Quick hack to help examine multi-session images that have already been burned +to a multi-session disc. The sector number specified is the sector number for +the start of the session we wish to display. +.TP +.I -x pathname +Extract specified file to stdout. +.SH AUTHOR +Eric Youngdale <ericy@gnu.ai.mit.edu> or <eric@andante.jic.com> is to blame +for these shoddy hacks. Patches to improve general usability would be +gladly accepted. +.SH BUGS +The user interface really sucks. +.SH FUTURE IMPROVEMENTS +These utilities are really quick hacks, which are very useful for debugging +problems in mkisofs or in an iso9660 filesystem. In the long run, it would +be nice to have a daemon that would NFS export a iso9660 image. +.PP +The isoinfo program is probably the program that is of the most use to +the general user. +.SH AVAILABILITY +These utilities come with the mkisofs package, and the primary ftp site +is tsx-11.mit.edu in /pub/linux/BETA/cdrom/mkisofs and many other mirror +sites. Despite the name, the software is not beta. +.SH SEE ALSO +mkisofs(8) + diff --git a/gnu/usr.sbin/mkisofs/diag/isoinfo.c b/gnu/usr.sbin/mkisofs/diag/isoinfo.c new file mode 100644 index 00000000000..f0bc41798d2 --- /dev/null +++ b/gnu/usr.sbin/mkisofs/diag/isoinfo.c @@ -0,0 +1,554 @@ +/* $OpenBSD: isoinfo.c,v 1.1 1997/09/15 06:01:53 downsj Exp $ */ +/* + * File isodump.c - dump iso9660 directory information. + * + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +static char rcsid[] ="$From: isoinfo.c,v 1.2 1997/03/22 02:20:28 eric Rel $"; + +/* + * Simple program to dump contents of iso9660 image in more usable format. + * + * Usage: + * To list contents of image (with or without RR): + * isoinfo -l [-R] -i imagefile + * To extract file from image: + * isoinfo -i imagefile -x xtractfile > outfile + * To generate a "find" like list of files: + * isoinfo -f -i imagefile + */ + +#include "../config.h" + +#include <stdio.h> +#include <signal.h> +#include <sys/stat.h> + +#ifdef __svr4__ +#include <stdlib.h> +#else +extern int optind; +extern char *optarg; +/* extern int getopt (int __argc, char **__argv, char *__optstring); */ +#endif + +FILE * infile; +int use_rock = 0; +int do_listing = 0; +int do_find = 0; +char * xtract = 0; + +struct stat fstat_buf; +char name_buf[256]; +char xname[256]; +unsigned char date_buf[9]; +unsigned int sector_offset = 0; + +unsigned char buffer[2048]; + +#define PAGE sizeof(buffer) + +#define ISODCL(from, to) (to - from + 1) + + +int +isonum_731 (char * p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + + +int +isonum_733 (unsigned char * p) +{ + return (isonum_731 (p)); +} + +struct iso_primary_descriptor { + unsigned char type [ISODCL ( 1, 1)]; /* 711 */ + unsigned char id [ISODCL ( 2, 6)]; + unsigned char version [ISODCL ( 7, 7)]; /* 711 */ + unsigned char unused1 [ISODCL ( 8, 8)]; + unsigned char system_id [ISODCL ( 9, 40)]; /* aunsigned chars */ + unsigned char volume_id [ISODCL ( 41, 72)]; /* dunsigned chars */ + unsigned char unused2 [ISODCL ( 73, 80)]; + unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ + unsigned char unused3 [ISODCL ( 89, 120)]; + unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */ + unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ + unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */ + unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */ + unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */ + unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ + unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */ + unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ + unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ + unsigned char volume_set_id [ISODCL (191, 318)]; /* dunsigned chars */ + unsigned char publisher_id [ISODCL (319, 446)]; /* achars */ + unsigned char preparer_id [ISODCL (447, 574)]; /* achars */ + unsigned char application_id [ISODCL (575, 702)]; /* achars */ + unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ + unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ + unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ + unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ + unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ + unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ + unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ + unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */ + unsigned char unused4 [ISODCL (883, 883)]; + unsigned char application_data [ISODCL (884, 1395)]; + unsigned char unused5 [ISODCL (1396, 2048)]; +}; + +struct iso_directory_record { + unsigned char length [ISODCL (1, 1)]; /* 711 */ + unsigned char ext_attr_length [ISODCL (2, 2)]; /* 711 */ + unsigned char extent [ISODCL (3, 10)]; /* 733 */ + unsigned char size [ISODCL (11, 18)]; /* 733 */ + unsigned char date [ISODCL (19, 25)]; /* 7 by 711 */ + unsigned char flags [ISODCL (26, 26)]; + unsigned char file_unit_size [ISODCL (27, 27)]; /* 711 */ + unsigned char interleave [ISODCL (28, 28)]; /* 711 */ + unsigned char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ + unsigned char name_len [ISODCL (33, 33)]; /* 711 */ + unsigned char name [1]; +}; + + +int parse_rr(unsigned char * pnt, int len, int cont_flag) +{ + int slen; + int ncount; + int extent; + int cont_extent, cont_offset, cont_size; + int flag1, flag2; + unsigned char *pnts; + char symlink[1024]; + int goof; + + symlink[0] = 0; + + cont_extent = cont_offset = cont_size = 0; + + ncount = 0; + flag1 = flag2 = 0; + while(len >= 4){ + if(pnt[3] != 1) { + printf("**BAD RRVERSION"); + return; + }; + ncount++; + if(pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff; + if(strncmp(pnt, "PX", 2) == 0) flag2 |= 1; + if(strncmp(pnt, "PN", 2) == 0) flag2 |= 2; + if(strncmp(pnt, "SL", 2) == 0) flag2 |= 4; + if(strncmp(pnt, "NM", 2) == 0) flag2 |= 8; + if(strncmp(pnt, "CL", 2) == 0) flag2 |= 16; + if(strncmp(pnt, "PL", 2) == 0) flag2 |= 32; + if(strncmp(pnt, "RE", 2) == 0) flag2 |= 64; + if(strncmp(pnt, "TF", 2) == 0) flag2 |= 128; + + if(strncmp(pnt, "PX", 2) == 0) { + fstat_buf.st_mode = isonum_733(pnt+4); + fstat_buf.st_nlink = isonum_733(pnt+12); + fstat_buf.st_uid = isonum_733(pnt+20); + fstat_buf.st_gid = isonum_733(pnt+28); + }; + + if(strncmp(pnt, "NM", 2) == 0) { + strncpy(name_buf, pnt+5, pnt[2] - 5); + name_buf[pnt[2] - 5] = 0; + } + + if(strncmp(pnt, "CE", 2) == 0) { + cont_extent = isonum_733(pnt+4); + cont_offset = isonum_733(pnt+12); + cont_size = isonum_733(pnt+20); + }; + + if(strncmp(pnt, "PL", 2) == 0 || strncmp(pnt, "CL", 2) == 0) { + extent = isonum_733(pnt+4); + }; + + if(strncmp(pnt, "SL", 2) == 0) { + int cflag; + + cflag = pnt[4]; + pnts = pnt+5; + slen = pnt[2] - 5; + while(slen >= 1){ + switch(pnts[0] & 0xfe){ + case 0: + strncat(symlink, pnts+2, pnts[1]); + break; + case 2: + strcat (symlink, "."); + break; + case 4: + strcat (symlink, ".."); + break; + case 8: + if((pnts[0] & 1) == 0)strcat (symlink, "/"); + break; + case 16: + strcat(symlink,"/mnt"); + printf("Warning - mount point requested"); + break; + case 32: + strcat(symlink,"kafka"); + printf("Warning - host_name requested"); + break; + default: + printf("Reserved bit setting in symlink", goof++); + break; + }; + if((pnts[0] & 0xfe) && pnts[1] != 0) { + printf("Incorrect length in symlink component"); + }; + if((pnts[0] & 1) == 0) strcat(symlink,"/"); + + slen -= (pnts[1] + 2); + pnts += (pnts[1] + 2); + if(xname[0] == 0) strcpy(xname, "-> "); + strcat(xname, symlink); + }; + symlink[0] = 0; + }; + + len -= pnt[2]; + pnt += pnt[2]; + if(len <= 3 && cont_extent) { + unsigned char sector[2048]; + lseek(fileno(infile), (cont_extent - sector_offset) << 11, 0); + read(fileno(infile), sector, sizeof(sector)); + flag2 |= parse_rr(§or[cont_offset], cont_size, 1); + }; + }; + return flag2; +} + +int +dump_rr(struct iso_directory_record * idr) +{ + int len; + unsigned char * pnt; + + len = idr->length[0] & 0xff; + len -= sizeof(struct iso_directory_record); + len += sizeof(idr->name); + len -= idr->name_len[0]; + pnt = (unsigned char *) idr; + pnt += sizeof(struct iso_directory_record); + pnt -= sizeof(idr->name); + pnt += idr->name_len[0]; + if((idr->name_len[0] & 1) == 0){ + pnt++; + len--; + }; + parse_rr(pnt, len, 0); +} + +struct todo +{ + struct todo * next; + char * name; + int extent; + int length; +}; + +struct todo * todo_idr = NULL; + +char * months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", + "Aug", "Sep", "Oct", "Nov", "Dec"}; + +dump_stat(int extent) +{ + int i; + char outline[80]; + + memset(outline, ' ', sizeof(outline)); + + if(S_ISREG(fstat_buf.st_mode)) + outline[0] = '-'; + else if(S_ISDIR(fstat_buf.st_mode)) + outline[0] = 'd'; + else if(S_ISLNK(fstat_buf.st_mode)) + outline[0] = 'l'; + else if(S_ISCHR(fstat_buf.st_mode)) + outline[0] = 'c'; + else if(S_ISBLK(fstat_buf.st_mode)) + outline[0] = 'b'; + else if(S_ISFIFO(fstat_buf.st_mode)) + outline[0] = 'f'; + else if(S_ISSOCK(fstat_buf.st_mode)) + outline[0] = 's'; + else + outline[0] = '?'; + + memset(outline+1, '-', 9); + if( fstat_buf.st_mode & S_IRUSR ) + outline[1] = 'r'; + if( fstat_buf.st_mode & S_IWUSR ) + outline[2] = 'w'; + if( fstat_buf.st_mode & S_IXUSR ) + outline[3] = 'x'; + + if( fstat_buf.st_mode & S_IRGRP ) + outline[4] = 'r'; + if( fstat_buf.st_mode & S_IWGRP ) + outline[5] = 'w'; + if( fstat_buf.st_mode & S_IXGRP ) + outline[6] = 'x'; + + if( fstat_buf.st_mode & S_IROTH ) + outline[7] = 'r'; + if( fstat_buf.st_mode & S_IWOTH ) + outline[8] = 'w'; + if( fstat_buf.st_mode & S_IXOTH ) + outline[9] = 'x'; + + sprintf(outline+11, "%3d", fstat_buf.st_nlink); + sprintf(outline+15, "%4o", fstat_buf.st_uid); + sprintf(outline+20, "%4o", fstat_buf.st_gid); + sprintf(outline+33, "%8d", fstat_buf.st_size); + + if( date_buf[1] >= 1 && date_buf[1] <= 12 ) + { + memcpy(outline+42, months[date_buf[1]-1], 3); + } + + sprintf(outline+46, "%2d", date_buf[2]); + sprintf(outline+49, "%4d", date_buf[0]+1900); + + sprintf(outline+54, "[%6d]", extent); + + for(i=0; i<63; i++) + if(outline[i] == 0) outline[i] = ' '; + outline[63] = 0; + + printf("%s %s %s\n", outline, name_buf, xname); +} + +extract_file(struct iso_directory_record * idr) +{ + int extent, len, tlen; + unsigned char buff[2048]; + + extent = isonum_733(idr->extent); + len = isonum_733(idr->size); + + while(len > 0) + { + lseek(fileno(infile), (extent - sector_offset) << 11, 0); + tlen = (len > sizeof(buff) ? sizeof(buff) : len); + read(fileno(infile), buff, tlen); + len -= tlen; + extent++; + write(1, buff, tlen); + } +} + +parse_dir(char * rootname, int extent, int len){ + unsigned int k; + char testname[256]; + struct todo * td; + int i, j; + struct iso_directory_record * idr; + + + if( do_listing) + printf("\nDirectory listing of %s\n", rootname); + + while(len > 0 ) + { + lseek(fileno(infile), (extent - sector_offset) << 11, 0); + read(fileno(infile), buffer, sizeof(buffer)); + len -= sizeof(buffer); + extent++; + i = 0; + while(1==1){ + idr = (struct iso_directory_record *) &buffer[i]; + if(idr->length[0] == 0) break; + memset(&fstat_buf, 0, sizeof(fstat_buf)); + name_buf[0] = xname[0] = 0; + fstat_buf.st_size = isonum_733(idr->size); + if( idr->flags[0] & 2) + fstat_buf.st_mode |= S_IFDIR; + else + fstat_buf.st_mode |= S_IFREG; + if(idr->name_len[0] == 1 && idr->name[0] == 0) + strcpy(name_buf, "."); + else if(idr->name_len[0] == 1 && idr->name[0] == 1) + strcpy(name_buf, ".."); + else { + strncpy(name_buf, idr->name, idr->name_len[0]); + name_buf[idr->name_len[0]] = 0; + }; + memcpy(date_buf, idr->date, 9); + if(use_rock) dump_rr(idr); + if( (idr->flags[0] & 2) != 0 + && (idr->name_len[0] != 1 + || (idr->name[0] != 0 && idr->name[0] != 1))) + { + /* + * Add this directory to the todo list. + */ + td = todo_idr; + if( td != NULL ) + { + while(td->next != NULL) td = td->next; + td->next = (struct todo *) malloc(sizeof(*td)); + td = td->next; + } + else + { + todo_idr = td = (struct todo *) malloc(sizeof(*td)); + } + td->next = NULL; + td->extent = isonum_733(idr->extent); + td->length = isonum_733(idr->size); + td->name = (char *) malloc(strlen(rootname) + + strlen(name_buf) + 2); + strcpy(td->name, rootname); + strcat(td->name, name_buf); + strcat(td->name, "/"); + } + else + { + strcpy(testname, rootname); + strcat(testname, name_buf); + if(xtract && strcmp(xtract, testname) == 0) + { + extract_file(idr); + } + } + if( do_find + && (idr->name_len[0] != 1 + || (idr->name[0] != 0 && idr->name[0] != 1))) + { + strcpy(testname, rootname); + strcat(testname, name_buf); + printf("%s\n", testname); + } + if(do_listing) + dump_stat(isonum_733(idr->extent)); + i += buffer[i]; + if (i > 2048 - sizeof(struct iso_directory_record)) break; + } + } +} + +usage() +{ + fprintf(stderr, "isoinfo -i filename [-l] [-R] [-x filename] [-f] [-N nsect]\n"); +} + +main(int argc, char * argv[]){ + int c; + char buffer[2048]; + int nbyte; + char * filename = NULL; + int i,j; + int toc_offset = 0; + struct todo * td; + struct iso_primary_descriptor ipd; + struct iso_directory_record * idr; + + if(argc < 2) return 0; + while ((c = getopt(argc, argv, "i:Rlx:fN:T:")) != EOF) + switch (c) + { + case 'f': + do_find++; + break; + case 'R': + use_rock++; + break; + case 'l': + do_listing++; + break; + case 'T': + /* + * This is used if we have a complete multi-session + * disc that we want/need to play with. + * Here we specify the offset where we want to + * start searching for the TOC. + */ + toc_offset = atol(optarg); + break; + case 'N': + /* + * Use this if we have an image of a single session + * and we need to list the directory contents. + * This is the session block number of the start + * of the session. + */ + sector_offset = atol(optarg); + break; + case 'i': + filename = optarg; + break; + case 'x': + xtract = optarg; + break; + default: + usage(); + exit(1); + } + + if( filename == NULL ) + { + fprintf(stderr, "Error - file not specified\n"); + exit(1); + } + + infile = fopen(filename,"rb"); + + if( infile == NULL ) + { + fprintf(stderr,"Unable to open file %s\n", filename); + exit(1); + } + + /* + * Absolute sector offset, so don't subtract sector_offset here. + */ + lseek(fileno(infile), (16 + toc_offset) <<11, 0); + read(fileno(infile), &ipd, sizeof(ipd)); + + idr = (struct iso_directory_record *) &ipd.root_directory_record; + + parse_dir("/", isonum_733(idr->extent), isonum_733(idr->size)); + td = todo_idr; + while(td) + { + parse_dir(td->name, td->extent, td->length); + td = td->next; + } + + fclose(infile); +} + + + + diff --git a/gnu/usr.sbin/mkisofs/diag/isovfy.c b/gnu/usr.sbin/mkisofs/diag/isovfy.c new file mode 100644 index 00000000000..f10447889f3 --- /dev/null +++ b/gnu/usr.sbin/mkisofs/diag/isovfy.c @@ -0,0 +1,514 @@ +/* $OpenBSD: isovfy.c,v 1.1 1997/09/15 06:01:53 downsj Exp $ */ +/* + * File isovfy.c - verify consistency of iso9660 filesystem. + * + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +static char rcsid[] ="$From: isovfy.c,v 1.2 1997/02/23 19:13:23 eric Rel $"; + +#include <stdio.h> +#include <signal.h> + +FILE * infile; +int blocksize; + +#define PAGE sizeof(buffer) + +#define ISODCL(from, to) (to - from + 1) + +struct iso_primary_descriptor { + unsigned char type [ISODCL ( 1, 1)]; /* 711 */ + unsigned char id [ISODCL ( 2, 6)]; + unsigned char version [ISODCL ( 7, 7)]; /* 711 */ + unsigned char unused1 [ISODCL ( 8, 8)]; + unsigned char system_id [ISODCL ( 9, 40)]; /* aunsigned chars */ + unsigned char volume_id [ISODCL ( 41, 72)]; /* dunsigned chars */ + unsigned char unused2 [ISODCL ( 73, 80)]; + unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ + unsigned char unused3 [ISODCL ( 89, 120)]; + unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */ + unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ + unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */ + unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */ + unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */ + unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ + unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */ + unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ + unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ + unsigned char volume_set_id [ISODCL (191, 318)]; /* dunsigned chars */ + unsigned char publisher_id [ISODCL (319, 446)]; /* achars */ + unsigned char preparer_id [ISODCL (447, 574)]; /* achars */ + unsigned char application_id [ISODCL (575, 702)]; /* achars */ + unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ + unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ + unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ + unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ + unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ + unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ + unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ + unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */ + unsigned char unused4 [ISODCL (883, 883)]; + unsigned char application_data [ISODCL (884, 1395)]; + unsigned char unused5 [ISODCL (1396, 2048)]; +}; + +struct iso_directory_record { + unsigned char length [ISODCL (1, 1)]; /* 711 */ + unsigned char ext_attr_length [ISODCL (2, 2)]; /* 711 */ + unsigned char extent [ISODCL (3, 10)]; /* 733 */ + unsigned char size [ISODCL (11, 18)]; /* 733 */ + unsigned char date [ISODCL (19, 25)]; /* 7 by 711 */ + unsigned char flags [ISODCL (26, 26)]; + unsigned char file_unit_size [ISODCL (27, 27)]; /* 711 */ + unsigned char interleave [ISODCL (28, 28)]; /* 711 */ + unsigned char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ + unsigned char name_len [ISODCL (33, 33)]; /* 711 */ + unsigned char name [38]; +}; + +int +isonum_723 (char * p) +{ +#if 0 + if (p[0] != p[3] || p[1] != p[2]) { + fprintf (stderr, "invalid format 7.2.3 number\n"); + exit (1); + } +#endif + return (isonum_721 (p)); +} + +int +isonum_721 (char * p) +{ + return ((p[0] & 0xff) | ((p[1] & 0xff) << 8)); +} + +int +isonum_711 (char * p) +{ + return (*p & 0xff); +} + +int +isonum_731 (char * p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + +int +isonum_722 (char * p) +{ + return ((p[1] & 0xff) + | ((p[0] & 0xff) << 8)); +} + +int +isonum_732 (char * p) +{ + return ((p[3] & 0xff) + | ((p[2] & 0xff) << 8) + | ((p[1] & 0xff) << 16) + | ((p[0] & 0xff) << 24)); +} + +int +isonum_733 (unsigned char * p) +{ + return (isonum_731 (p)); +} + +char lbuffer[1024]; +int iline; +int rr_goof; + + +int +dump_rr(struct iso_directory_record * idr){ + int len; + char * pnt; + + len = idr->length[0] & 0xff; + len -= (sizeof(struct iso_directory_record) - sizeof(idr->name)); + len -= idr->name_len[0]; + pnt = (char *) idr; + pnt += (sizeof(struct iso_directory_record) - sizeof(idr->name)); + pnt += idr->name_len[0]; + + if((idr->name_len[0] & 1) == 0){ + pnt++; + len--; + }; + + rr_goof = 0; + parse_rr(pnt, len, 0); + return rr_goof; +} + +int parse_rr(unsigned char * pnt, int len, int cont_flag) +{ + int slen; + int ncount; + int flag1, flag2; + int extent; + unsigned char *pnts; + int cont_extent, cont_offset, cont_size; + char symlink[1024]; + iline += sprintf(lbuffer+iline," RRlen=%d ", len); + + cont_extent = cont_offset = cont_size = 0; + + symlink[0] = 0; + + ncount = 0; + flag1 = flag2 = 0; + while(len >= 4){ + if(ncount) iline += sprintf(lbuffer+iline,","); + else iline += sprintf(lbuffer+iline,"["); + iline += sprintf(lbuffer+iline,"%c%c", pnt[0], pnt[1]); + + if(pnt[0] < 'A' || pnt[0] > 'Z' || pnt[1] < 'A' || + pnt[1] > 'Z') { + iline += sprintf(lbuffer+iline,"**BAD SUSP %d %d]", + pnt[0], pnt[1], rr_goof++); + return flag2; + }; + + if(pnt[3] != 1) { + iline += sprintf(lbuffer+iline,"**BAD RRVERSION", rr_goof++); + return flag2; + }; + ncount++; + if(pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff; + if(strncmp(pnt, "PX", 2) == 0) flag2 |= 1; + if(strncmp(pnt, "PN", 2) == 0) flag2 |= 2; + if(strncmp(pnt, "SL", 2) == 0) flag2 |= 4; + if(strncmp(pnt, "NM", 2) == 0) flag2 |= 8; + if(strncmp(pnt, "CL", 2) == 0) flag2 |= 16; + if(strncmp(pnt, "PL", 2) == 0) flag2 |= 32; + if(strncmp(pnt, "RE", 2) == 0) flag2 |= 64; + if(strncmp(pnt, "TF", 2) == 0) flag2 |= 128; + + if(strncmp(pnt, "CE", 2) == 0) { + cont_extent = isonum_733(pnt+4); + cont_offset = isonum_733(pnt+12); + cont_size = isonum_733(pnt+20); + iline += sprintf(lbuffer+iline, "=[%x,%x,%d]", + cont_extent, cont_offset, cont_size); + }; + + if(strncmp(pnt, "PL", 2) == 0 || strncmp(pnt, "CL", 2) == 0) { + extent = isonum_733(pnt+4); + iline += sprintf(lbuffer+iline,"=%x", extent); + if(extent == 0) rr_goof++; + }; + if(strncmp(pnt, "SL", 2) == 0) { + pnts = pnt+5; + slen = pnt[2] - 5; + while(slen >= 1){ + switch(pnts[0] & 0xfe){ + case 0: + strncat(symlink, pnts+2, pnts[1]); + break; + case 2: + strcat (symlink, "."); + break; + case 4: + strcat (symlink, ".."); + break; + case 8: + strcat (symlink, "/"); + break; + case 16: + strcat(symlink,"/mnt"); + iline += sprintf(lbuffer+iline,"Warning - mount point requested"); + break; + case 32: + strcat(symlink,"kafka"); + iline += sprintf(lbuffer+iline,"Warning - host_name requested"); + break; + default: + iline += sprintf(lbuffer+iline,"Reserved bit setting in symlink", rr_goof++); + break; + }; + if((pnts[0] & 0xfe) && pnts[1] != 0) { + iline += sprintf(lbuffer+iline,"Incorrect length in symlink component"); + }; + if((pnts[0] & 1) == 0) + strcat(symlink,"/"); + slen -= (pnts[1] + 2); + pnts += (pnts[1] + 2); + + }; + if(symlink[0] != 0) { + iline += sprintf(lbuffer+iline,"=%s", symlink); + symlink[0] = 0; + } + }; + + len -= pnt[2]; + pnt += pnt[2]; + if(len <= 3 && cont_extent) { + unsigned char sector[2048]; + lseek(fileno(infile), cont_extent * blocksize, 0); + read(fileno(infile), sector, sizeof(sector)); + flag2 |= parse_rr(§or[cont_offset], cont_size, 1); + }; + }; + if(ncount) iline += sprintf(lbuffer+iline,"]"); + if (!cont_flag && flag1 && flag1 != flag2) + iline += sprintf(lbuffer+iline,"Flag %x != %x", flag1, flag2, rr_goof++); + return flag2; +} + + +int dir_count = 0; +int dir_size_count = 0; +int ngoof = 0; + + +check_tree(int file_addr, int file_size, int parent_addr){ + unsigned char buffer[2048]; + unsigned int k; + int rflag; + int i, i1, j, goof; + int extent, size; + int line; + int orig_file_addr, parent_file_addr; + struct iso_directory_record * idr; + + i1 = 0; + + orig_file_addr = file_addr / blocksize; /* Actual extent of this directory */ + parent_file_addr = parent_addr / blocksize; + + if((dir_count % 100) == 0) printf("[%d %d]\n", dir_count, dir_size_count); +#if 0 + printf("Starting directory %d %d %d\n", file_addr, file_size, parent_addr); +#endif + + dir_count++; + dir_size_count += file_size / blocksize; + + if(file_size & 0x3ff) printf("********Directory has unusual size\n"); + + for(k=0; k < (file_size / sizeof(buffer)); k++){ + lseek(fileno(infile), file_addr, 0); + read(fileno(infile), buffer, sizeof(buffer)); + i = 0; + while(1==1){ + goof = iline=0; + idr = (struct iso_directory_record *) &buffer[i]; + if(idr->length[0] == 0) break; + iline += sprintf(&lbuffer[iline],"%3d ", idr->length[0]); + extent = isonum_733(idr->extent); + size = isonum_733(idr->size); + iline += sprintf(&lbuffer[iline],"%5x ", extent); + iline += sprintf(&lbuffer[iline],"%8d ", size); + iline += sprintf (&lbuffer[iline], "%c", (idr->flags[0] & 2) ? '*' : ' '); + + if(idr->name_len[0] > 33) + iline += sprintf(&lbuffer[iline],"File name length=(%d)", + idr->name_len[0], goof++); + else if(idr->name_len[0] == 1 && idr->name[0] == 0) { + iline += sprintf(&lbuffer[iline],". "); + rflag = 0; + if(orig_file_addr !=isonum_733(idr->extent) + isonum_711(idr->ext_attr_length)) + iline += sprintf(&lbuffer[iline],"***** Directory has null extent.", goof++); + if(i1) + iline += sprintf(&lbuffer[iline],"***** . not first entry.", rr_goof++); + } else if(idr->name_len[0] == 1 && idr->name[0] == 1) { + iline += sprintf(&lbuffer[iline],".. "); + rflag = 0; + if(parent_file_addr !=isonum_733(idr->extent) + isonum_711(idr->ext_attr_length)) + iline += sprintf(&lbuffer[iline],"***** Directory has null extent.", goof++); + if(i1 != 1) + iline += sprintf(&lbuffer[iline],"***** .. not second entry.", rr_goof++); + + } else { + if(i1 < 2) iline += sprintf(&lbuffer[iline]," Improper sorting.", rr_goof++); + for(j=0; j<idr->name_len[0]; j++) iline += sprintf(&lbuffer[iline],"%c", idr->name[j]); + for(j=0; j<14 -idr->name_len[0]; j++) iline += sprintf(&lbuffer[iline]," "); + rflag = 1; + }; + + if(size && extent == 0) iline += sprintf(&lbuffer[iline],"****Extent==0, size != 0", goof++); +#if 0 + /* This is apparently legal. */ + if(size == 0 && extent) iline += sprintf(&lbuffer[iline],"****Extent!=0, size == 0", goof++); +#endif + + if(idr->flags[0] & 0xf5) + iline += sprintf(&lbuffer[iline],"Flags=(%x) ", idr->flags[0], goof++); + + if(idr->interleave[0]) + iline += sprintf(&lbuffer[iline],"Interleave=(%d) ", idr->interleave[0], goof++); + + if(idr->file_unit_size[0]) + iline += sprintf(&lbuffer[iline],"File unit size=(%d) ", idr->file_unit_size[0], goof++); + + if(idr->volume_sequence_number[0] != 1) + iline += sprintf(&lbuffer[iline],"Volume sequence number=(%d) ", idr->volume_sequence_number[0], goof++); + + goof += dump_rr(idr); + iline += sprintf(&lbuffer[iline],"\n"); + + + if(goof){ + ngoof++; + lbuffer[iline++] = 0; + printf("%x: %s", orig_file_addr, lbuffer); + }; + + + + if(rflag && (idr->flags[0] & 2)) check_tree((isonum_733(idr->extent) + isonum_711(idr->ext_attr_length)) * blocksize, + isonum_733(idr->size), + orig_file_addr * blocksize); + i += buffer[i]; + i1++; + if (i > 2048 - sizeof(struct iso_directory_record)) break; + }; + file_addr += sizeof(buffer); + }; + fflush(stdout); +} + + +/* This function simply dumps the contents of the path tables. No + consistency checking takes place, although this would proably be a good + idea. */ + +struct path_table_info{ + char * name; + unsigned int extent; + unsigned short index; + unsigned short parent; +}; + + +check_path_tables(int typel_extent, int typem_extent, int path_table_size){ + int file_addr; + int count; + int j; + char * pnt; + char * typel, *typem; + + /* Now read in the path tables */ + + typel = (char *) malloc(path_table_size); + lseek(fileno(infile), typel_extent * blocksize, 0); + read(fileno(infile), typel, path_table_size); + + typem = (char *) malloc(path_table_size); + lseek(fileno(infile), typem_extent * blocksize, 0); + read(fileno(infile), typem, path_table_size); + + j = path_table_size; + pnt = typel; + count = 1; + while(j){ + int namelen, extent, index; + char name[32]; + namelen = *pnt++; pnt++; + extent = isonum_731(pnt); pnt += 4; + index = isonum_721(pnt); pnt+= 2; + j -= 8+namelen; + memset(name, 0, sizeof(name)); + + strncpy(name, pnt, namelen); + pnt += namelen; + if(j & 1) { j--; pnt++;}; + printf("%4.4d %4.4d %8.8x %s\n",count++, index, extent, name); + }; + + j = path_table_size; + pnt = typem; + count = 1; + while(j){ + int namelen, extent, index; + char name[32]; + namelen = *pnt++; pnt++; + extent = isonum_732(pnt); pnt += 4; + index = isonum_722(pnt); pnt+= 2; + j -= 8+namelen; + memset(name, 0, sizeof(name)); + + strncpy(name, pnt, namelen); + pnt += namelen; + if(j & 1) { j--; pnt++;}; + printf("%4.4d %4.4d %8.8x %s\n", count++, index, extent, name); + }; + +} + +main(int argc, char * argv[]){ + int file_addr, file_size; + char c; + int nbyte; + struct iso_primary_descriptor ipd; + struct iso_directory_record * idr; + int typel_extent, typem_extent; + int path_table_size; + int i,j; + if(argc < 2) return 0; + infile = fopen(argv[1],"rb"); + + + file_addr = 32768; + lseek(fileno(infile), file_addr, 0); + read(fileno(infile), &ipd, sizeof(ipd)); + + idr = (struct iso_directory_record *) &ipd.root_directory_record; + + blocksize = isonum_723(ipd.logical_block_size); + if( blocksize != 512 && blocksize != 1024 && blocksize != 2048 ) + { + blocksize = 2048; + } + + file_addr = isonum_733(idr->extent) + isonum_711(idr->ext_attr_length); + file_size = isonum_733(idr->size); + + printf("Root at extent %x, %d bytes\n", file_addr, file_size); + file_addr = file_addr * blocksize; + + check_tree(file_addr, file_size, file_addr); + + typel_extent = isonum_731(ipd.type_l_path_table); + typem_extent = isonum_732(ipd.type_m_path_table); + path_table_size = isonum_733(ipd.path_table_size); + + /* Enable this to get the dump of the path tables */ +#if 0 + check_path_tables(typel_extent, typem_extent, path_table_size); +#endif + + fclose(infile); + + if(!ngoof) printf("No errors found\n"); +} + + + + |