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