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

  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: isoinfo.c,v 1.2 1997/03/22 02:20:28 eric Rel $";
  24.  
  25. /*
  26.  * Simple program to dump contents of iso9660 image in more usable format.
  27.  *
  28.  * Usage:
  29.  * To list contents of image (with or without RR):
  30.  *    isoinfo -l [-R] -i imagefile
  31.  * To extract file from image:
  32.  *    isoinfo -i imagefile -x xtractfile > outfile
  33.  * To generate a "find" like list of files:
  34.  *    isoinfo -f -i imagefile
  35.  */
  36.  
  37. #include "../config.h"
  38.  
  39. #include <stdio.h>
  40. #include <signal.h>
  41. #include <sys/stat.h>
  42.  
  43. #ifdef __svr4__
  44. #include <stdlib.h>
  45. #else
  46. extern int optind;
  47. extern char *optarg;
  48. /* extern int getopt (int __argc, char **__argv, char *__optstring); */
  49. #endif
  50.  
  51. FILE * infile;
  52. int use_rock = 0;
  53. int do_listing = 0;
  54. int do_find = 0;
  55. char * xtract = 0;
  56.  
  57. struct stat fstat_buf;
  58. char name_buf[256];
  59. char xname[256];
  60. unsigned char date_buf[9];
  61. unsigned int sector_offset = 0;
  62.  
  63. unsigned char buffer[2048];
  64.  
  65. #define PAGE sizeof(buffer)
  66.  
  67. #define ISODCL(from, to) (to - from + 1)
  68.  
  69.  
  70. int
  71. isonum_731 (char * p)
  72. {
  73.     return ((p[0] & 0xff)
  74.         | ((p[1] & 0xff) << 8)
  75.         | ((p[2] & 0xff) << 16)
  76.         | ((p[3] & 0xff) << 24));
  77. }
  78.  
  79.  
  80. int
  81. isonum_733 (unsigned char * p)
  82. {
  83.     return (isonum_731 (p));
  84. }
  85.  
  86. struct iso_primary_descriptor {
  87.     unsigned char type            [ISODCL (  1,   1)]; /* 711 */
  88.     unsigned char id                [ISODCL (  2,   6)];
  89.     unsigned char version            [ISODCL (  7,   7)]; /* 711 */
  90.     unsigned char unused1            [ISODCL (  8,   8)];
  91.     unsigned char system_id            [ISODCL (  9,  40)]; /* aunsigned chars */
  92.     unsigned char volume_id            [ISODCL ( 41,  72)]; /* dunsigned chars */
  93.     unsigned char unused2            [ISODCL ( 73,  80)];
  94.     unsigned char volume_space_size        [ISODCL ( 81,  88)]; /* 733 */
  95.     unsigned char unused3            [ISODCL ( 89, 120)];
  96.     unsigned char volume_set_size        [ISODCL (121, 124)]; /* 723 */
  97.     unsigned char volume_sequence_number    [ISODCL (125, 128)]; /* 723 */
  98.     unsigned char logical_block_size        [ISODCL (129, 132)]; /* 723 */
  99.     unsigned char path_table_size        [ISODCL (133, 140)]; /* 733 */
  100.     unsigned char type_l_path_table        [ISODCL (141, 144)]; /* 731 */
  101.     unsigned char opt_type_l_path_table    [ISODCL (145, 148)]; /* 731 */
  102.     unsigned char type_m_path_table        [ISODCL (149, 152)]; /* 732 */
  103.     unsigned char opt_type_m_path_table    [ISODCL (153, 156)]; /* 732 */
  104.     unsigned char root_directory_record    [ISODCL (157, 190)]; /* 9.1 */
  105.     unsigned char volume_set_id        [ISODCL (191, 318)]; /* dunsigned chars */
  106.     unsigned char publisher_id        [ISODCL (319, 446)]; /* achars */
  107.     unsigned char preparer_id        [ISODCL (447, 574)]; /* achars */
  108.     unsigned char application_id        [ISODCL (575, 702)]; /* achars */
  109.     unsigned char copyright_file_id        [ISODCL (703, 739)]; /* 7.5 dchars */
  110.     unsigned char abstract_file_id        [ISODCL (740, 776)]; /* 7.5 dchars */
  111.     unsigned char bibliographic_file_id    [ISODCL (777, 813)]; /* 7.5 dchars */
  112.     unsigned char creation_date        [ISODCL (814, 830)]; /* 8.4.26.1 */
  113.     unsigned char modification_date        [ISODCL (831, 847)]; /* 8.4.26.1 */
  114.     unsigned char expiration_date        [ISODCL (848, 864)]; /* 8.4.26.1 */
  115.     unsigned char effective_date        [ISODCL (865, 881)]; /* 8.4.26.1 */
  116.     unsigned char file_structure_version    [ISODCL (882, 882)]; /* 711 */
  117.     unsigned char unused4            [ISODCL (883, 883)];
  118.     unsigned char application_data        [ISODCL (884, 1395)];
  119.     unsigned char unused5            [ISODCL (1396, 2048)];
  120. };
  121.  
  122. struct iso_directory_record {
  123.     unsigned char length            [ISODCL (1, 1)]; /* 711 */
  124.     unsigned char ext_attr_length        [ISODCL (2, 2)]; /* 711 */
  125.     unsigned char extent            [ISODCL (3, 10)]; /* 733 */
  126.     unsigned char size            [ISODCL (11, 18)]; /* 733 */
  127.     unsigned char date            [ISODCL (19, 25)]; /* 7 by 711 */
  128.     unsigned char flags            [ISODCL (26, 26)];
  129.     unsigned char file_unit_size        [ISODCL (27, 27)]; /* 711 */
  130.     unsigned char interleave            [ISODCL (28, 28)]; /* 711 */
  131.     unsigned char volume_sequence_number    [ISODCL (29, 32)]; /* 723 */
  132.     unsigned char name_len        [ISODCL (33, 33)]; /* 711 */
  133.     unsigned char name            [1];
  134. };
  135.  
  136.  
  137. int parse_rr(unsigned char * pnt, int len, int cont_flag)
  138. {
  139.     int slen;
  140.     int ncount;
  141.     int extent;
  142.     int cont_extent, cont_offset, cont_size;
  143.     int flag1, flag2;
  144.     unsigned char *pnts;
  145.     char symlink[1024];
  146.     int goof;
  147.  
  148.     symlink[0] = 0;
  149.  
  150.     cont_extent = cont_offset = cont_size = 0;
  151.  
  152.     ncount = 0;
  153.     flag1 = flag2 = 0;
  154.     while(len >= 4){
  155.         if(pnt[3] != 1) {
  156.           printf("**BAD RRVERSION");
  157.           return;
  158.         };
  159.         ncount++;
  160.         if(pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff;
  161.         if(strncmp(pnt, "PX", 2) == 0) flag2 |= 1;
  162.         if(strncmp(pnt, "PN", 2) == 0) flag2 |= 2;
  163.         if(strncmp(pnt, "SL", 2) == 0) flag2 |= 4;
  164.         if(strncmp(pnt, "NM", 2) == 0) flag2 |= 8;
  165.         if(strncmp(pnt, "CL", 2) == 0) flag2 |= 16;
  166.         if(strncmp(pnt, "PL", 2) == 0) flag2 |= 32;
  167.         if(strncmp(pnt, "RE", 2) == 0) flag2 |= 64;
  168.         if(strncmp(pnt, "TF", 2) == 0) flag2 |= 128;
  169.  
  170.         if(strncmp(pnt, "PX", 2) == 0) {
  171.             fstat_buf.st_mode = isonum_733(pnt+4);
  172.             fstat_buf.st_nlink = isonum_733(pnt+12);
  173.             fstat_buf.st_uid = isonum_733(pnt+20);
  174.             fstat_buf.st_gid = isonum_733(pnt+28);
  175.         };
  176.  
  177.         if(strncmp(pnt, "NM", 2) == 0) {
  178.           strncpy(name_buf, pnt+5, pnt[2] - 5);
  179.           name_buf[pnt[2] - 5] = 0;
  180.         }
  181.  
  182.         if(strncmp(pnt, "CE", 2) == 0) {
  183.             cont_extent = isonum_733(pnt+4);
  184.             cont_offset = isonum_733(pnt+12);
  185.             cont_size = isonum_733(pnt+20);
  186.         };
  187.  
  188.         if(strncmp(pnt, "PL", 2) == 0 || strncmp(pnt, "CL", 2) == 0) {
  189.             extent = isonum_733(pnt+4);
  190.         };
  191.  
  192.         if(strncmp(pnt, "SL", 2) == 0) {
  193.                 int cflag;
  194.  
  195.             cflag = pnt[4];
  196.             pnts = pnt+5;
  197.             slen = pnt[2] - 5;
  198.             while(slen >= 1){
  199.                 switch(pnts[0] & 0xfe){
  200.                 case 0:
  201.                     strncat(symlink, pnts+2, pnts[1]);
  202.                     break;
  203.                 case 2:
  204.                     strcat (symlink, ".");
  205.                     break;
  206.                 case 4:
  207.                     strcat (symlink, "..");
  208.                     break;
  209.                 case 8:
  210.                     if((pnts[0] & 1) == 0)strcat (symlink, "/");
  211.                     break;
  212.                 case 16:
  213.                     strcat(symlink,"/mnt");
  214.                     printf("Warning - mount point requested");
  215.                     break;
  216.                 case 32:
  217.                     strcat(symlink,"kafka");
  218.                     printf("Warning - host_name requested");
  219.                     break;
  220.                 default:
  221.                     printf("Reserved bit setting in symlink", goof++);
  222.                     break;
  223.                 };
  224.                 if((pnts[0] & 0xfe) && pnts[1] != 0) {
  225.                     printf("Incorrect length in symlink component");
  226.                 };
  227.                 if((pnts[0] & 1) == 0) strcat(symlink,"/");
  228.  
  229.                 slen -= (pnts[1] + 2);
  230.                 pnts += (pnts[1] + 2);
  231.                 if(xname[0] == 0) strcpy(xname, "-> ");
  232.                 strcat(xname, symlink);
  233.                };
  234.             symlink[0] = 0;
  235.         };
  236.  
  237.         len -= pnt[2];
  238.         pnt += pnt[2];
  239.         if(len <= 3 && cont_extent) {
  240.           unsigned char sector[2048];
  241.           lseek(fileno(infile), (cont_extent - sector_offset) << 11, 0);
  242.           read(fileno(infile), sector, sizeof(sector));
  243.           flag2 |= parse_rr(§or[cont_offset], cont_size, 1);
  244.         };
  245.     };
  246.     return flag2;
  247. }
  248.  
  249. int 
  250. dump_rr(struct iso_directory_record * idr)
  251. {
  252.     int len;
  253.     unsigned char * pnt;
  254.  
  255.     len = idr->length[0] & 0xff;
  256.     len -= sizeof(struct iso_directory_record);
  257.     len += sizeof(idr->name);
  258.     len -= idr->name_len[0];
  259.     pnt = (unsigned char *) idr;
  260.     pnt += sizeof(struct iso_directory_record);
  261.     pnt -= sizeof(idr->name);
  262.     pnt += idr->name_len[0];
  263.     if((idr->name_len[0] & 1) == 0){
  264.         pnt++;
  265.         len--;
  266.     };
  267.     parse_rr(pnt, len, 0);
  268. }
  269.  
  270. struct todo
  271. {
  272.   struct todo * next;
  273.   char * name;
  274.   int extent;
  275.   int length;
  276. };
  277.  
  278. struct todo * todo_idr = NULL;
  279.  
  280. char * months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
  281.                "Aug", "Sep", "Oct", "Nov", "Dec"};
  282.  
  283. dump_stat(int extent)
  284. {
  285.   int i;
  286.   char outline[80];
  287.  
  288.   memset(outline, ' ', sizeof(outline));
  289.  
  290.   if(S_ISREG(fstat_buf.st_mode))
  291.     outline[0] = '-';
  292.   else   if(S_ISDIR(fstat_buf.st_mode))
  293.     outline[0] = 'd';
  294.   else   if(S_ISLNK(fstat_buf.st_mode))
  295.     outline[0] = 'l';
  296.   else   if(S_ISCHR(fstat_buf.st_mode))
  297.     outline[0] = 'c';
  298.   else   if(S_ISBLK(fstat_buf.st_mode))
  299.     outline[0] = 'b';
  300.   else   if(S_ISFIFO(fstat_buf.st_mode))
  301.     outline[0] = 'f';
  302.   else   if(S_ISSOCK(fstat_buf.st_mode))
  303.     outline[0] = 's';
  304.   else
  305.     outline[0] = '?';
  306.  
  307.   memset(outline+1, '-', 9);
  308.   if( fstat_buf.st_mode & S_IRUSR )
  309.     outline[1] = 'r';
  310.   if( fstat_buf.st_mode & S_IWUSR )
  311.     outline[2] = 'w';
  312.   if( fstat_buf.st_mode & S_IXUSR )
  313.     outline[3] = 'x';
  314.  
  315.   if( fstat_buf.st_mode & S_IRGRP )
  316.     outline[4] = 'r';
  317.   if( fstat_buf.st_mode & S_IWGRP )
  318.     outline[5] = 'w';
  319.   if( fstat_buf.st_mode & S_IXGRP )
  320.     outline[6] = 'x';
  321.  
  322.   if( fstat_buf.st_mode & S_IROTH )
  323.     outline[7] = 'r';
  324.   if( fstat_buf.st_mode & S_IWOTH )
  325.     outline[8] = 'w';
  326.   if( fstat_buf.st_mode & S_IXOTH )
  327.     outline[9] = 'x';
  328.  
  329.   sprintf(outline+11, "%3d", fstat_buf.st_nlink);
  330.   sprintf(outline+15, "%4o", fstat_buf.st_uid);
  331.   sprintf(outline+20, "%4o", fstat_buf.st_gid);
  332.   sprintf(outline+33, "%8d", fstat_buf.st_size);
  333.  
  334.   if( date_buf[1] >= 1 && date_buf[1] <= 12 )
  335.     {
  336.       memcpy(outline+42, months[date_buf[1]-1], 3);
  337.     }
  338.  
  339.   sprintf(outline+46, "%2d", date_buf[2]);
  340.   sprintf(outline+49, "%4d", date_buf[0]+1900);
  341.  
  342.   sprintf(outline+54, "[%6d]", extent);
  343.  
  344.   for(i=0; i<63; i++)
  345.     if(outline[i] == 0) outline[i] = ' ';
  346.   outline[63] = 0;
  347.  
  348.   printf("%s %s %s\n", outline, name_buf, xname);
  349. }
  350.  
  351. extract_file(struct iso_directory_record * idr)
  352. {
  353.   int extent, len, tlen;
  354.   unsigned char buff[2048];
  355.  
  356.   extent = isonum_733(idr->extent);
  357.   len = isonum_733(idr->size);
  358.  
  359.   while(len > 0)
  360.     {
  361.       lseek(fileno(infile), (extent - sector_offset) << 11, 0);
  362.       tlen = (len > sizeof(buff) ? sizeof(buff) : len);
  363.       read(fileno(infile), buff, tlen);
  364.       len -= tlen;
  365.       extent++;
  366.       write(1, buff, tlen);
  367.     }
  368. }
  369.  
  370. parse_dir(char * rootname, int extent, int len){
  371.   unsigned int k;
  372.   char testname[256];
  373.   struct todo * td;
  374.   int i, j;
  375.   struct iso_directory_record * idr;
  376.  
  377.  
  378.   if( do_listing)
  379.     printf("\nDirectory listing of %s\n", rootname);
  380.  
  381.   while(len > 0 )
  382.     {
  383.       lseek(fileno(infile), (extent - sector_offset) << 11, 0);
  384.       read(fileno(infile), buffer, sizeof(buffer));
  385.       len -= sizeof(buffer);
  386.       extent++;
  387.       i = 0;
  388.       while(1==1){
  389.     idr = (struct iso_directory_record *) &buffer[i];
  390.     if(idr->length[0] == 0) break;
  391.     memset(&fstat_buf, 0, sizeof(fstat_buf));
  392.     name_buf[0] = xname[0] = 0;
  393.     fstat_buf.st_size = isonum_733(idr->size);
  394.     if( idr->flags[0] & 2)
  395.       fstat_buf.st_mode |= S_IFDIR;
  396.     else
  397.       fstat_buf.st_mode |= S_IFREG;    
  398.     if(idr->name_len[0] == 1 && idr->name[0] == 0)
  399.       strcpy(name_buf, ".");
  400.     else if(idr->name_len[0] == 1 && idr->name[0] == 1)
  401.       strcpy(name_buf, "..");
  402.     else {
  403.       strncpy(name_buf, idr->name, idr->name_len[0]);
  404.       name_buf[idr->name_len[0]] = 0;
  405.     };
  406.     memcpy(date_buf, idr->date, 9);
  407.     if(use_rock) dump_rr(idr);
  408.     if(   (idr->flags[0] & 2) != 0
  409.        && (idr->name_len[0] != 1
  410.            || (idr->name[0] != 0 && idr->name[0] != 1)))
  411.       {
  412.         /*
  413.          * Add this directory to the todo list.
  414.          */
  415.         td = todo_idr;
  416.         if( td != NULL ) 
  417.           {
  418.         while(td->next != NULL) td = td->next;
  419.         td->next = (struct todo *) malloc(sizeof(*td));
  420.         td = td->next;
  421.           }
  422.         else
  423.           {
  424.         todo_idr = td = (struct todo *) malloc(sizeof(*td));
  425.           }
  426.         td->next = NULL;
  427.         td->extent = isonum_733(idr->extent);
  428.         td->length = isonum_733(idr->size);
  429.         td->name = (char *) malloc(strlen(rootname) 
  430.                        + strlen(name_buf) + 2);
  431.         strcpy(td->name, rootname);
  432.         strcat(td->name, name_buf);
  433.         strcat(td->name, "/");
  434.       }
  435.     else
  436.       {
  437.         strcpy(testname, rootname);
  438.         strcat(testname, name_buf);
  439.         if(xtract && strcmp(xtract, testname) == 0)
  440.           {
  441.         extract_file(idr);
  442.           }
  443.       }
  444.     if(   do_find
  445.        && (idr->name_len[0] != 1
  446.            || (idr->name[0] != 0 && idr->name[0] != 1)))
  447.       {
  448.         strcpy(testname, rootname);
  449.         strcat(testname, name_buf);
  450.         printf("%s\n", testname);
  451.       }
  452.     if(do_listing)
  453.       dump_stat(isonum_733(idr->extent));
  454.     i += buffer[i];
  455.     if (i > 2048 - sizeof(struct iso_directory_record)) break;
  456.       }
  457.     }
  458. }
  459.  
  460. usage()
  461. {
  462.   fprintf(stderr, "isoinfo -i filename [-l] [-R] [-x filename] [-f] [-N nsect]\n");
  463. }
  464.  
  465. main(int argc, char * argv[]){
  466.   int c;
  467.   char buffer[2048];
  468.   int nbyte;
  469.   char * filename = NULL;
  470.   int i,j;
  471.   int toc_offset = 0;
  472.   struct todo * td;
  473.   struct iso_primary_descriptor ipd;
  474.   struct iso_directory_record * idr;
  475.  
  476.   if(argc < 2) return 0;
  477.   while ((c = getopt(argc, argv, "i:Rlx:fN:T:")) != EOF)
  478.     switch (c)
  479.       {
  480.       case 'f':
  481.     do_find++;
  482.     break;
  483.       case 'R':
  484.     use_rock++;
  485.     break;
  486.       case 'l':
  487.     do_listing++;
  488.     break;
  489.       case 'T':
  490.     /*
  491.      * This is used if we have a complete multi-session
  492.      * disc that we want/need to play with.
  493.      * Here we specify the offset where we want to
  494.      * start searching for the TOC.
  495.      */
  496.     toc_offset = atol(optarg);
  497.     break;
  498.       case 'N':
  499.     /*
  500.      * Use this if we have an image of a single session
  501.      * and we need to list the directory contents.
  502.      * This is the session block number of the start
  503.      * of the session.
  504.      */
  505.     sector_offset = atol(optarg);
  506.     break;
  507.       case 'i':
  508.     filename = optarg;
  509.     break;
  510.       case 'x':
  511.     xtract = optarg;
  512.     break;
  513.       default:
  514.     usage();
  515.     exit(1);
  516.       }
  517.   
  518.   if( filename == NULL )
  519.   {
  520.     fprintf(stderr, "Error - file not specified\n");
  521.       exit(1);
  522.   }
  523.  
  524.   infile = fopen(filename,"rb");
  525.  
  526.   if( infile == NULL )
  527.   {
  528.     fprintf(stderr,"Unable to open file %s\n", filename);
  529.     exit(1);
  530.   }
  531.  
  532.   /*
  533.    * Absolute sector offset, so don't subtract sector_offset here.
  534.    */
  535.   lseek(fileno(infile), (16 + toc_offset) <<11, 0);
  536.   read(fileno(infile), &ipd, sizeof(ipd));
  537.  
  538.   idr = (struct iso_directory_record *) &ipd.root_directory_record;
  539.  
  540.   parse_dir("/", isonum_733(idr->extent), isonum_733(idr->size));
  541.   td = todo_idr;
  542.   while(td)
  543.     {
  544.       parse_dir(td->name, td->extent, td->length);
  545.       td = td->next;
  546.     }
  547.  
  548.   fclose(infile);
  549. }
  550.   
  551.  
  552.  
  553.  
  554.