home *** CD-ROM | disk | FTP | other *** search
/ Dream 49 / Amiga_Dream_49.iso / beos / utils / mkisofs-1.000 / mkisofs-1.11-beos / diag / isovfy.c < prev    next >
C/C++ Source or Header  |  1997-04-09  |  15KB  |  514 lines

  1. /*
  2.  * File isovfy.c - verify consistency of iso9660 filesystem.
  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: isovfy.c,v 1.2 1997/02/23 19:13:23 eric Rel $";
  24.  
  25. #include <stdio.h>
  26. #include <signal.h>
  27.  
  28. FILE * infile;
  29. int blocksize;
  30.  
  31. #define PAGE sizeof(buffer)
  32.  
  33. #define ISODCL(from, to) (to - from + 1)
  34.  
  35. struct iso_primary_descriptor {
  36.     unsigned char type            [ISODCL (  1,   1)]; /* 711 */
  37.     unsigned char id                [ISODCL (  2,   6)];
  38.     unsigned char version            [ISODCL (  7,   7)]; /* 711 */
  39.     unsigned char unused1            [ISODCL (  8,   8)];
  40.     unsigned char system_id            [ISODCL (  9,  40)]; /* aunsigned chars */
  41.     unsigned char volume_id            [ISODCL ( 41,  72)]; /* dunsigned chars */
  42.     unsigned char unused2            [ISODCL ( 73,  80)];
  43.     unsigned char volume_space_size        [ISODCL ( 81,  88)]; /* 733 */
  44.     unsigned char unused3            [ISODCL ( 89, 120)];
  45.     unsigned char volume_set_size        [ISODCL (121, 124)]; /* 723 */
  46.     unsigned char volume_sequence_number    [ISODCL (125, 128)]; /* 723 */
  47.     unsigned char logical_block_size        [ISODCL (129, 132)]; /* 723 */
  48.     unsigned char path_table_size        [ISODCL (133, 140)]; /* 733 */
  49.     unsigned char type_l_path_table        [ISODCL (141, 144)]; /* 731 */
  50.     unsigned char opt_type_l_path_table    [ISODCL (145, 148)]; /* 731 */
  51.     unsigned char type_m_path_table        [ISODCL (149, 152)]; /* 732 */
  52.     unsigned char opt_type_m_path_table    [ISODCL (153, 156)]; /* 732 */
  53.     unsigned char root_directory_record    [ISODCL (157, 190)]; /* 9.1 */
  54.     unsigned char volume_set_id        [ISODCL (191, 318)]; /* dunsigned chars */
  55.     unsigned char publisher_id        [ISODCL (319, 446)]; /* achars */
  56.     unsigned char preparer_id        [ISODCL (447, 574)]; /* achars */
  57.     unsigned char application_id        [ISODCL (575, 702)]; /* achars */
  58.     unsigned char copyright_file_id        [ISODCL (703, 739)]; /* 7.5 dchars */
  59.     unsigned char abstract_file_id        [ISODCL (740, 776)]; /* 7.5 dchars */
  60.     unsigned char bibliographic_file_id    [ISODCL (777, 813)]; /* 7.5 dchars */
  61.     unsigned char creation_date        [ISODCL (814, 830)]; /* 8.4.26.1 */
  62.     unsigned char modification_date        [ISODCL (831, 847)]; /* 8.4.26.1 */
  63.     unsigned char expiration_date        [ISODCL (848, 864)]; /* 8.4.26.1 */
  64.     unsigned char effective_date        [ISODCL (865, 881)]; /* 8.4.26.1 */
  65.     unsigned char file_structure_version    [ISODCL (882, 882)]; /* 711 */
  66.     unsigned char unused4            [ISODCL (883, 883)];
  67.     unsigned char application_data        [ISODCL (884, 1395)];
  68.     unsigned char unused5            [ISODCL (1396, 2048)];
  69. };
  70.  
  71. struct iso_directory_record {
  72.     unsigned char length            [ISODCL (1, 1)]; /* 711 */
  73.     unsigned char ext_attr_length        [ISODCL (2, 2)]; /* 711 */
  74.     unsigned char extent            [ISODCL (3, 10)]; /* 733 */
  75.     unsigned char size            [ISODCL (11, 18)]; /* 733 */
  76.     unsigned char date            [ISODCL (19, 25)]; /* 7 by 711 */
  77.     unsigned char flags            [ISODCL (26, 26)];
  78.     unsigned char file_unit_size        [ISODCL (27, 27)]; /* 711 */
  79.     unsigned char interleave            [ISODCL (28, 28)]; /* 711 */
  80.     unsigned char volume_sequence_number    [ISODCL (29, 32)]; /* 723 */
  81.     unsigned char name_len        [ISODCL (33, 33)]; /* 711 */
  82.     unsigned char name            [38];
  83. };
  84.  
  85. int
  86. isonum_723 (char * p)
  87. {
  88. #if 0
  89.     if (p[0] != p[3] || p[1] != p[2]) {
  90.         fprintf (stderr, "invalid format 7.2.3 number\n");
  91.         exit (1);
  92.     }
  93. #endif
  94.     return (isonum_721 (p));
  95. }
  96.  
  97. int
  98. isonum_721 (char * p)
  99. {
  100.     return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
  101. }
  102.  
  103. int
  104. isonum_711 (char * p)
  105. {
  106.     return (*p & 0xff);
  107. }
  108.  
  109. int
  110. isonum_731 (char * p)
  111. {
  112.     return ((p[0] & 0xff)
  113.         | ((p[1] & 0xff) << 8)
  114.         | ((p[2] & 0xff) << 16)
  115.         | ((p[3] & 0xff) << 24));
  116. }
  117.  
  118. int
  119. isonum_722 (char * p)
  120. {
  121.     return ((p[1] & 0xff)
  122.         | ((p[0] & 0xff) << 8));
  123. }
  124.  
  125. int
  126. isonum_732 (char * p)
  127. {
  128.     return ((p[3] & 0xff)
  129.         | ((p[2] & 0xff) << 8)
  130.         | ((p[1] & 0xff) << 16)
  131.         | ((p[0] & 0xff) << 24));
  132. }
  133.  
  134. int
  135. isonum_733 (unsigned char * p)
  136. {
  137.     return (isonum_731 (p));
  138. }
  139.  
  140. char lbuffer[1024];
  141. int iline;
  142. int rr_goof;
  143.  
  144.  
  145. int 
  146. dump_rr(struct iso_directory_record * idr){
  147.     int len;
  148.     char * pnt;
  149.  
  150.     len = idr->length[0] & 0xff;
  151.     len -= (sizeof(struct iso_directory_record) - sizeof(idr->name));
  152.     len -= idr->name_len[0];
  153.     pnt = (char *) idr;
  154.     pnt += (sizeof(struct iso_directory_record) - sizeof(idr->name));
  155.     pnt += idr->name_len[0];
  156.  
  157.     if((idr->name_len[0] & 1) == 0){
  158.         pnt++;
  159.         len--;
  160.     };
  161.  
  162.     rr_goof = 0;
  163.     parse_rr(pnt, len, 0);
  164.     return rr_goof;
  165. }
  166.  
  167. int parse_rr(unsigned char * pnt, int len, int cont_flag)
  168. {
  169.     int slen;
  170.     int ncount;
  171.     int flag1, flag2;
  172.     int extent;
  173.     unsigned char *pnts;
  174.     int cont_extent, cont_offset, cont_size;
  175.     char symlink[1024];
  176.     iline += sprintf(lbuffer+iline," RRlen=%d ", len);
  177.  
  178.     cont_extent = cont_offset = cont_size = 0;
  179.  
  180.     symlink[0] = 0;
  181.  
  182.     ncount = 0;
  183.     flag1 = flag2 = 0;
  184.     while(len >= 4){
  185.         if(ncount) iline += sprintf(lbuffer+iline,",");
  186.         else iline += sprintf(lbuffer+iline,"[");
  187.         iline += sprintf(lbuffer+iline,"%c%c", pnt[0], pnt[1]);
  188.  
  189.         if(pnt[0] < 'A' || pnt[0] > 'Z' || pnt[1] < 'A' || 
  190.            pnt[1] > 'Z') {
  191.             iline += sprintf(lbuffer+iline,"**BAD SUSP %d %d]", 
  192.                      pnt[0], pnt[1], rr_goof++);
  193.             return flag2;
  194.         };
  195.  
  196.         if(pnt[3] != 1) {
  197.             iline += sprintf(lbuffer+iline,"**BAD RRVERSION", rr_goof++);
  198.             return flag2;
  199.         };
  200.         ncount++;
  201.         if(pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff;
  202.         if(strncmp(pnt, "PX", 2) == 0) flag2 |= 1;
  203.         if(strncmp(pnt, "PN", 2) == 0) flag2 |= 2;
  204.         if(strncmp(pnt, "SL", 2) == 0) flag2 |= 4;
  205.         if(strncmp(pnt, "NM", 2) == 0) flag2 |= 8;
  206.         if(strncmp(pnt, "CL", 2) == 0) flag2 |= 16;
  207.         if(strncmp(pnt, "PL", 2) == 0) flag2 |= 32;
  208.         if(strncmp(pnt, "RE", 2) == 0) flag2 |= 64;
  209.         if(strncmp(pnt, "TF", 2) == 0) flag2 |= 128;
  210.  
  211.         if(strncmp(pnt, "CE", 2) == 0) {
  212.             cont_extent = isonum_733(pnt+4);
  213.             cont_offset = isonum_733(pnt+12);
  214.             cont_size = isonum_733(pnt+20);
  215.             iline += sprintf(lbuffer+iline, "=[%x,%x,%d]",
  216.                      cont_extent, cont_offset, cont_size);
  217.               };
  218.  
  219.         if(strncmp(pnt, "PL", 2) == 0 || strncmp(pnt, "CL", 2) == 0) {
  220.             extent = isonum_733(pnt+4);
  221.             iline += sprintf(lbuffer+iline,"=%x", extent);
  222.             if(extent == 0) rr_goof++;
  223.         };
  224.         if(strncmp(pnt, "SL", 2) == 0) {
  225.             pnts = pnt+5;
  226.             slen = pnt[2] - 5;
  227.             while(slen >= 1){
  228.                 switch(pnts[0] & 0xfe){
  229.                 case 0:
  230.                     strncat(symlink, pnts+2, pnts[1]);
  231.                     break;
  232.                 case 2:
  233.                     strcat (symlink, ".");
  234.                     break;
  235.                 case 4:
  236.                     strcat (symlink, "..");
  237.                     break;
  238.                 case 8:
  239.                     strcat (symlink, "/");
  240.                     break;
  241.                 case 16:
  242.                     strcat(symlink,"/mnt");
  243.                     iline += sprintf(lbuffer+iline,"Warning - mount point requested");
  244.                     break;
  245.                 case 32:
  246.                     strcat(symlink,"kafka");
  247.                     iline += sprintf(lbuffer+iline,"Warning - host_name requested");
  248.                     break;
  249.                 default:
  250.                     iline += sprintf(lbuffer+iline,"Reserved bit setting in symlink", rr_goof++);
  251.                     break;
  252.                 };
  253.                 if((pnts[0] & 0xfe) && pnts[1] != 0) {
  254.                     iline += sprintf(lbuffer+iline,"Incorrect length in symlink component");
  255.                 };
  256.                 if((pnts[0] & 1) == 0)
  257.                   strcat(symlink,"/");
  258.                 slen -= (pnts[1] + 2);
  259.                 pnts += (pnts[1] + 2);
  260.                 
  261.                };
  262.             if(symlink[0] != 0) {
  263.               iline += sprintf(lbuffer+iline,"=%s", symlink);
  264.               symlink[0] = 0;
  265.             }
  266.         };
  267.  
  268.         len -= pnt[2];
  269.         pnt += pnt[2];
  270.         if(len <= 3 && cont_extent) {
  271.           unsigned char sector[2048];
  272.           lseek(fileno(infile), cont_extent * blocksize, 0);
  273.           read(fileno(infile), sector, sizeof(sector));
  274.           flag2 |= parse_rr(§or[cont_offset], cont_size, 1);
  275.         };
  276.     };
  277.     if(ncount) iline += sprintf(lbuffer+iline,"]");
  278.     if (!cont_flag && flag1 && flag1 != flag2) 
  279.       iline += sprintf(lbuffer+iline,"Flag %x != %x", flag1, flag2, rr_goof++);
  280.     return flag2;
  281. }
  282.  
  283.  
  284. int dir_count = 0;
  285. int dir_size_count = 0;
  286. int ngoof = 0;
  287.  
  288.  
  289. check_tree(int file_addr, int file_size, int parent_addr){
  290.   unsigned char buffer[2048];
  291.   unsigned int k;
  292.   int rflag;
  293.   int i, i1, j, goof;
  294.   int extent, size;
  295.   int line;
  296.   int orig_file_addr, parent_file_addr;
  297.   struct iso_directory_record * idr;
  298.  
  299.   i1 = 0;
  300.  
  301.   orig_file_addr = file_addr / blocksize;  /* Actual extent of this directory */
  302.   parent_file_addr = parent_addr / blocksize;
  303.  
  304.   if((dir_count % 100) == 0) printf("[%d %d]\n", dir_count, dir_size_count);
  305. #if 0
  306.   printf("Starting directory %d %d %d\n", file_addr, file_size, parent_addr);
  307. #endif
  308.  
  309.   dir_count++;
  310.   dir_size_count += file_size / blocksize;
  311.  
  312.   if(file_size & 0x3ff) printf("********Directory has unusual size\n");
  313.  
  314.   for(k=0; k < (file_size / sizeof(buffer)); k++){
  315.       lseek(fileno(infile), file_addr, 0);
  316.       read(fileno(infile), buffer, sizeof(buffer));
  317.       i = 0;
  318.       while(1==1){
  319.           goof = iline=0;
  320.           idr = (struct iso_directory_record *) &buffer[i];
  321.           if(idr->length[0] == 0) break;
  322.           iline += sprintf(&lbuffer[iline],"%3d ", idr->length[0]);
  323.           extent = isonum_733(idr->extent);
  324.           size = isonum_733(idr->size);
  325.           iline += sprintf(&lbuffer[iline],"%5x ", extent);
  326.           iline += sprintf(&lbuffer[iline],"%8d ", size);
  327.           iline += sprintf (&lbuffer[iline], "%c", (idr->flags[0] & 2) ? '*' : ' '); 
  328.  
  329.           if(idr->name_len[0] > 33)
  330.             iline += sprintf(&lbuffer[iline],"File name length=(%d)",
  331.                      idr->name_len[0], goof++);
  332.           else if(idr->name_len[0] == 1 && idr->name[0] == 0) {
  333.               iline += sprintf(&lbuffer[iline],".             ");
  334.               rflag = 0;
  335.               if(orig_file_addr !=isonum_733(idr->extent) + isonum_711(idr->ext_attr_length))
  336.                   iline += sprintf(&lbuffer[iline],"***** Directory has null extent.", goof++);
  337.               if(i1)
  338.                   iline += sprintf(&lbuffer[iline],"***** . not  first entry.", rr_goof++);
  339.           } else if(idr->name_len[0] == 1 && idr->name[0] == 1) {
  340.               iline += sprintf(&lbuffer[iline],"..            ");
  341.               rflag = 0;
  342.               if(parent_file_addr !=isonum_733(idr->extent) + isonum_711(idr->ext_attr_length))
  343.                   iline += sprintf(&lbuffer[iline],"***** Directory has null extent.", goof++);
  344.               if(i1 != 1)
  345.                   iline += sprintf(&lbuffer[iline],"***** .. not second entry.", rr_goof++);
  346.               
  347.           } else {
  348.                   if(i1 < 2) iline += sprintf(&lbuffer[iline]," Improper sorting.", rr_goof++);
  349.               for(j=0; j<idr->name_len[0]; j++) iline += sprintf(&lbuffer[iline],"%c", idr->name[j]);
  350.               for(j=0; j<14 -idr->name_len[0]; j++) iline += sprintf(&lbuffer[iline]," ");
  351.               rflag = 1;
  352.           };
  353.  
  354.           if(size && extent == 0) iline += sprintf(&lbuffer[iline],"****Extent==0, size != 0", goof++);
  355. #if 0
  356.           /* This is apparently legal. */
  357.           if(size == 0 && extent) iline += sprintf(&lbuffer[iline],"****Extent!=0, size == 0", goof++);
  358. #endif
  359.  
  360.           if(idr->flags[0] & 0xf5)
  361.               iline += sprintf(&lbuffer[iline],"Flags=(%x) ", idr->flags[0], goof++);
  362.  
  363.           if(idr->interleave[0])
  364.               iline += sprintf(&lbuffer[iline],"Interleave=(%d) ", idr->interleave[0], goof++);
  365.  
  366.           if(idr->file_unit_size[0])
  367.               iline += sprintf(&lbuffer[iline],"File unit size=(%d) ", idr->file_unit_size[0], goof++);
  368.  
  369.           if(idr->volume_sequence_number[0] != 1)
  370.               iline += sprintf(&lbuffer[iline],"Volume sequence number=(%d) ", idr->volume_sequence_number[0], goof++);
  371.  
  372.           goof += dump_rr(idr);
  373.           iline += sprintf(&lbuffer[iline],"\n");
  374.  
  375.  
  376.           if(goof){
  377.                   ngoof++;
  378.               lbuffer[iline++] = 0;
  379.               printf("%x: %s", orig_file_addr, lbuffer);
  380.           };
  381.  
  382.  
  383.  
  384.           if(rflag && (idr->flags[0] & 2)) check_tree((isonum_733(idr->extent) + isonum_711(idr->ext_attr_length)) * blocksize,
  385.                            isonum_733(idr->size),
  386.                            orig_file_addr * blocksize);
  387.           i += buffer[i];
  388.           i1++;
  389.           if (i > 2048 - sizeof(struct iso_directory_record)) break;
  390.       };
  391.       file_addr += sizeof(buffer);
  392.   };
  393.   fflush(stdout);
  394. }
  395.  
  396.  
  397. /* This function simply dumps the contents of the path tables.  No
  398.    consistency checking takes place, although this would proably be a good
  399.    idea. */
  400.  
  401. struct path_table_info{
  402.   char * name;
  403.   unsigned int extent;
  404.   unsigned short index;
  405.   unsigned short parent;
  406. };
  407.  
  408.  
  409. check_path_tables(int typel_extent, int typem_extent, int path_table_size){
  410.   int file_addr;
  411.   int count;
  412.   int j;
  413.   char * pnt;
  414.   char * typel, *typem;
  415.  
  416.   /* Now read in the path tables */
  417.  
  418.   typel = (char *) malloc(path_table_size);
  419.   lseek(fileno(infile), typel_extent * blocksize, 0);
  420.   read(fileno(infile), typel, path_table_size);
  421.  
  422.   typem = (char *) malloc(path_table_size);
  423.   lseek(fileno(infile), typem_extent * blocksize, 0);
  424.   read(fileno(infile), typem, path_table_size);
  425.  
  426.   j = path_table_size;
  427.   pnt = typel;
  428.   count = 1;
  429.   while(j){
  430.       int namelen, extent, index;
  431.       char name[32];
  432.       namelen = *pnt++; pnt++;
  433.       extent = isonum_731(pnt); pnt += 4;
  434.       index = isonum_721(pnt); pnt+= 2;
  435.       j -= 8+namelen;
  436.       memset(name, 0, sizeof(name));
  437.  
  438.       strncpy(name, pnt, namelen);
  439.       pnt += namelen;
  440.       if(j & 1) { j--; pnt++;};
  441.       printf("%4.4d %4.4d %8.8x %s\n",count++, index, extent, name);
  442.   };
  443.  
  444.   j = path_table_size;
  445.   pnt = typem;
  446.   count = 1;
  447.   while(j){
  448.       int namelen, extent, index;
  449.       char name[32];
  450.       namelen = *pnt++; pnt++;
  451.       extent = isonum_732(pnt); pnt += 4;
  452.       index = isonum_722(pnt); pnt+= 2;
  453.       j -= 8+namelen;
  454.       memset(name, 0, sizeof(name));
  455.  
  456.       strncpy(name, pnt, namelen);
  457.       pnt += namelen;
  458.       if(j & 1) { j--; pnt++;};
  459.       printf("%4.4d %4.4d %8.8x %s\n", count++, index, extent, name);
  460.   };
  461.  
  462. }
  463.  
  464. main(int argc, char * argv[]){
  465.   int file_addr, file_size;
  466.   char c;
  467.   int nbyte;
  468.   struct iso_primary_descriptor ipd;
  469.   struct iso_directory_record * idr;
  470.   int typel_extent, typem_extent;
  471.   int path_table_size;
  472.   int i,j;
  473.   if(argc < 2) return 0;
  474.   infile = fopen(argv[1],"rb");
  475.  
  476.  
  477.   file_addr = 32768;
  478.   lseek(fileno(infile), file_addr, 0);
  479.   read(fileno(infile), &ipd, sizeof(ipd));
  480.  
  481.   idr = (struct iso_directory_record *) &ipd.root_directory_record;
  482.  
  483.   blocksize = isonum_723(ipd.logical_block_size);
  484.   if( blocksize != 512 && blocksize != 1024 && blocksize != 2048 )
  485.     {
  486.       blocksize = 2048;
  487.     }
  488.  
  489.   file_addr = isonum_733(idr->extent) + isonum_711(idr->ext_attr_length);
  490.   file_size = isonum_733(idr->size);
  491.  
  492.   printf("Root at extent %x, %d bytes\n", file_addr, file_size);
  493.   file_addr = file_addr * blocksize;
  494.  
  495.   check_tree(file_addr, file_size, file_addr);
  496.  
  497.   typel_extent = isonum_731(ipd.type_l_path_table);
  498.   typem_extent = isonum_732(ipd.type_m_path_table);
  499.   path_table_size = isonum_733(ipd.path_table_size);
  500.  
  501.   /* Enable this to get the dump of the path tables */
  502. #if 0
  503.   check_path_tables(typel_extent, typem_extent, path_table_size);
  504. #endif
  505.  
  506.   fclose(infile);
  507.  
  508.   if(!ngoof) printf("No errors found\n");
  509. }
  510.   
  511.  
  512.  
  513.  
  514.