"Fossies" - the Fresh Open Source Software Archive

Member "libcdio-2.1.0/lib/driver/cd_types.c" (12 Aug 2018, 10786 Bytes) of package /linux/privat/libcdio-2.1.0.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "cd_types.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.94_vs_1.0.0.

    1 /*
    2   Copyright (C) 2003-2005, 2006, 2008, 2011, 2013
    3   Rocky Bernstein <rocky@gnu.org>
    4 
    5   This program is free software: you can redistribute it and/or modify
    6   it under the terms of the GNU General Public License as published by
    7   the Free Software Foundation, either version 3 of the License, or
    8   (at your option) any later version.
    9 
   10   This program is distributed in the hope that it will be useful,
   11   but WITHOUT ANY WARRANTY; without even the implied warranty of
   12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13   GNU General Public License for more details.
   14 
   15   You should have received a copy of the GNU General Public License
   16   along with this program.  If not, see <http://www.gnu.org/licenses/>.
   17 */
   18 /*
   19    This tries to determine what kind of CD-image or filesystems on a
   20    track we've got.
   21 */
   22 #ifdef HAVE_CONFIG_H
   23 # include "config.h"
   24 # define __CDIO_CONFIG_H__ 1
   25 #endif
   26 
   27 #ifdef HAVE_STDIO_H
   28 #include <stdio.h>
   29 #endif
   30 
   31 #ifdef HAVE_STDLIB_H
   32 #include <stdlib.h>
   33 #endif
   34 
   35 #ifdef HAVE_UNISTD_H
   36 #include <unistd.h>
   37 #endif
   38 
   39 #ifdef HAVE_STRING_H
   40 #include <string.h>
   41 #endif
   42 
   43 #include <cdio/cdio.h>
   44 #include <cdio/iso9660.h>
   45 #include <cdio/logging.h>
   46 #include <cdio/util.h>
   47 #include <cdio/cd_types.h>
   48 
   49 /*
   50 Subject:   -65- How can I read an IRIX (EFS) CD-ROM on a machine which
   51                 doesn't use EFS?
   52 Date: 18 Jun 1995 00:00:01 EST
   53 
   54   You want 'efslook', at
   55   ftp://viz.tamu.edu/pub/sgi/software/efslook.tar.gz.
   56 
   57 and
   58 ! Robert E. Seastrom <rs@access4.digex.net>'s software (with source
   59 ! code) for using an SGI CD-ROM on a Macintosh is at
   60 ! ftp://bifrost.seastrom.com/pub/mac/CDROM-Jumpstart.sit151.hqx.
   61 
   62 */
   63 
   64 /** The below variables are trickery to force enum symbol values to be
   65     recorded in debug symbol tables. They are used to allow one to refer
   66     to the enumeration value names in the typedefs above in a debugger
   67     and debugger expressions.
   68 */
   69 cdio_fs_cap_t debug_cdio_fs_cap;
   70 cdio_fs_t     debug_cdio_fs;
   71 
   72 static char buffer[6][CDIO_CD_FRAMESIZE_RAW];  /* for CD-Data */
   73 
   74 /* Some interesting sector numbers stored in the above buffer. */
   75 #define ISO_SUPERBLOCK_SECTOR  16  /* buffer[0] */
   76 #define UFS_SUPERBLOCK_SECTOR   4  /* buffer[2] */
   77 #define BOOT_SECTOR            17  /* buffer[3] */
   78 #define VCD_INFO_SECTOR       150  /* buffer[4] */
   79 #define XISO_SECTOR        32  /* buffer[4] */
   80 #define UDFX_SECTOR        32  /* buffer[4] */
   81 #define UDF_ANCHOR_SECTOR     256  /* buffer[5] */
   82 
   83 
   84 typedef struct signature
   85 {
   86   unsigned int buf_num;
   87   unsigned int offset;
   88   char sig_str[60];
   89   char description[60];
   90 } signature_t;
   91 
   92 static const signature_t sigs[] =
   93   {
   94 /*buffer[x] off look for     description */
   95     {0,     0, "MICROSOFT*XBOX*MEDIA", "XBOX CD"},
   96     {0,     1, "BEA01",      "UDF"},
   97     {0,     1, ISO_STANDARD_ID,      "ISO 9660"},
   98     {0,     1, "CD-I",       "CD-I"},
   99     {0,     8, "CDTV",       "CDTV"},
  100     {0,     8, "CD-RTOS",    "CD-RTOS"},
  101     {0,     9, "CDROM",      "HIGH SIERRA"},
  102     {0,    16, "CD-BRIDGE",  "BRIDGE"},
  103     {0,  ISO_XA_MARKER_OFFSET, ISO_XA_MARKER_STRING,   "XA"},
  104     {1,    64, "PPPPHHHHOOOOTTTTOOOO____CCCCDDDD",  "PHOTO CD"},
  105     {1, 0x438, "\x53\xef",   "EXT2 FS"},
  106     {2,  1372, "\x54\x19\x01\x0", "UFS"},
  107     {3,     7, "EL TORITO",  "BOOTABLE"},
  108     {4,     0, "VIDEO_CD",   "VIDEO CD"},
  109     {4,     0, "SUPERVCD",   "SVCD or Chaoji VCD"}
  110   };
  111 
  112 
  113 /* The below index into the above sigs array. Make sure things match. */
  114 #define INDEX_XISO      0 /* Microsoft X-BOX filesystem */
  115 #define INDEX_UDF       1
  116 #define INDEX_ISOFS     2
  117 #define INDEX_CD_I      3
  118 #define INDEX_CDTV      4
  119 #define INDEX_CD_RTOS   5
  120 #define INDEX_HS        6
  121 #define INDEX_BRIDGE    7
  122 #define INDEX_XA        8
  123 #define INDEX_PHOTO_CD  9
  124 #define INDEX_EXT2     10
  125 #define INDEX_UFS      11
  126 #define INDEX_BOOTABLE 12
  127 #define INDEX_VIDEO_CD 13 /* Video CD */
  128 #define INDEX_SVCD     14 /* CVD *or* SVCD */
  129 
  130 
  131 /*
  132    Read a particular block into the global array to be used for further
  133    analysis later.
  134 */
  135 static driver_return_code_t
  136 _cdio_read_block(const CdIo_t *p_cdio, int superblock, uint32_t offset,
  137          uint8_t bufnum, track_t i_track)
  138 {
  139   unsigned int track_sec_count = cdio_get_track_sec_count(p_cdio, i_track);
  140   memset(buffer[bufnum], 0, CDIO_CD_FRAMESIZE);
  141 
  142   if ( track_sec_count < superblock) {
  143     cdio_debug("reading block %u skipped track %d has only %u sectors\n",
  144            superblock, i_track, track_sec_count);
  145     return DRIVER_OP_ERROR;
  146   }
  147 
  148   cdio_debug("about to read sector %lu\n",
  149          (long unsigned int) offset+superblock);
  150 
  151   return cdio_read_data_sectors (p_cdio, buffer[bufnum], offset+superblock,
  152                  ISO_BLOCKSIZE, 1);
  153 }
  154 
  155 /*
  156    Return true if the previously read-in buffer contains a "signature" that
  157    matches index "num".
  158  */
  159 static bool
  160 _cdio_is_it(int num)
  161 {
  162   const signature_t *sigp=&sigs[num];
  163   int len=strlen(sigp->sig_str);
  164 
  165   /* TODO: check that num < largest sig. */
  166   return 0 == memcmp(&buffer[sigp->buf_num][sigp->offset], sigp->sig_str, len);
  167 }
  168 
  169 static int
  170 _cdio_is_hfs(void)
  171 {
  172   return (0 == memcmp(&buffer[1][512],"PM",2)) ||
  173     (0 == memcmp(&buffer[1][512],"TS",2)) ||
  174     (0 == memcmp(&buffer[1][1024], "BD",2));
  175 }
  176 
  177 static int
  178 _cdio_is_3do(void)
  179 {
  180   return (0 == memcmp(&buffer[1][0],"\x01\x5a\x5a\x5a\x5a\x5a\x01", 7)) &&
  181     (0 == memcmp(&buffer[1][40], "CD-ROM", 6));
  182 }
  183 
  184 static int
  185 _cdio_is_joliet(void)
  186 {
  187   return 2 == buffer[3][0] && buffer[3][88] == 0x25 && buffer[3][89] == 0x2f;
  188 }
  189 
  190 static int
  191 _cdio_is_UDF(void)
  192 {
  193   return 2 == ((uint16_t)buffer[5][0] | ((uint16_t)buffer[5][1] << 8));
  194 }
  195 
  196 /* ISO 9660 volume space in M2F1_SECTOR_SIZE byte units */
  197 static int
  198 _cdio_get_iso9660_fs_sec_count(void)
  199 {
  200   return ((buffer[0][80] & 0xff) |
  201      ((buffer[0][81] & 0xff) << 8) |
  202      ((buffer[0][82] & 0xff) << 16) |
  203      ((buffer[0][83] & 0xff) << 24));
  204 }
  205 
  206 static uint8_t
  207 _cdio_get_joliet_level( void )
  208 {
  209   switch (buffer[3][90]) {
  210   case 0x40: return 1;
  211   case 0x43: return 2;
  212   case 0x45: return 3;
  213   }
  214   return 0;
  215 }
  216 
  217 /*
  218    Try to determine what kind of CD-image and/or filesystem we
  219    have at track i_track. Return information about the CD image
  220    is returned in cdio_analysis and the return value.
  221 */
  222 cdio_fs_anal_t
  223 cdio_guess_cd_type(const CdIo_t *p_cdio, int start_session, track_t i_track,
  224            /*out*/ cdio_iso_analysis_t *iso_analysis)
  225 {
  226   int ret = CDIO_FS_UNKNOWN;
  227   bool sector0_read_ok;
  228 
  229   if (TRACK_FORMAT_AUDIO == cdio_get_track_format(p_cdio, i_track))
  230     return CDIO_FS_AUDIO;
  231 
  232   if ( DRIVER_OP_SUCCESS !=
  233        _cdio_read_block(p_cdio, ISO_PVD_SECTOR, start_session, 0, i_track) )
  234     return CDIO_FS_UNKNOWN;
  235 
  236   if ( _cdio_is_it(INDEX_XISO) )
  237     return CDIO_FS_ANAL_XISO;
  238 
  239   if ( DRIVER_OP_SUCCESS != _cdio_read_block(p_cdio, ISO_SUPERBLOCK_SECTOR,
  240                          start_session, 0, i_track) )
  241     return ret;
  242 
  243   if ( _cdio_is_it(INDEX_UDF) ) {
  244     /* Detect UDF version
  245        Test if we have a valid version of UDF the xbox can read natively */
  246     if (_cdio_read_block(p_cdio, 35, start_session, 5, i_track) < 0)
  247       return CDIO_FS_UNKNOWN;
  248 
  249      iso_analysis->UDFVerMinor=(unsigned int)buffer[5][240];
  250      iso_analysis->UDFVerMajor=(unsigned int)buffer[5][241];
  251      /* Read disc label */
  252      if (_cdio_read_block(p_cdio, 32, start_session, 5, i_track) < 0)
  253        return CDIO_FS_UDF;
  254 
  255      strncpy(iso_analysis->iso_label, buffer[5]+25, 33);
  256      iso_analysis->iso_label[32] = '\0';
  257      return CDIO_FS_UDF;
  258    }
  259 
  260   /* We have something that smells of a filesystem. */
  261   if (_cdio_is_it(INDEX_CD_I) && _cdio_is_it(INDEX_CD_RTOS)
  262       && !_cdio_is_it(INDEX_BRIDGE) && !_cdio_is_it(INDEX_XA)) {
  263     return (CDIO_FS_INTERACTIVE | CDIO_FS_ANAL_ISO9660_ANY);
  264   } else {
  265     /* read sector 0 ONLY, when NO greenbook CD-I !!!! */
  266 
  267     sector0_read_ok =
  268       _cdio_read_block(p_cdio, 0, start_session, 1, i_track) == 0;
  269 
  270     if (_cdio_is_it(INDEX_HS))
  271       ret |= CDIO_FS_HIGH_SIERRA;
  272     else if (_cdio_is_it(INDEX_ISOFS)) {
  273       if (_cdio_is_it(INDEX_CD_RTOS) && _cdio_is_it(INDEX_BRIDGE))
  274     ret = (CDIO_FS_ISO_9660_INTERACTIVE | CDIO_FS_ANAL_ISO9660_ANY);
  275       else if (_cdio_is_hfs())
  276     ret = CDIO_FS_ISO_HFS;
  277       else
  278     ret = (CDIO_FS_ISO_9660 | CDIO_FS_ANAL_ISO9660_ANY);
  279       iso_analysis->isofs_size = _cdio_get_iso9660_fs_sec_count();
  280       strncpy(iso_analysis->iso_label, buffer[0]+40,33);
  281       iso_analysis->iso_label[32] = '\0';
  282 
  283       if ( _cdio_read_block(p_cdio, UDF_ANCHOR_SECTOR, start_session, 5,
  284                 i_track) < 0)
  285     return ret;
  286 
  287       /* Maybe there is an UDF anchor in IOS session
  288      so its ISO/UDF session and we prefere UDF */
  289       if ( _cdio_is_UDF() ) {
  290     /* Detect UDF version.
  291        Test if we have a valid version of UDF the xbox can read natively */
  292     if ( _cdio_read_block(p_cdio, 35, start_session, 5, i_track) < 0)
  293       return ret;
  294 
  295     iso_analysis->UDFVerMinor=(unsigned int)buffer[5][240];
  296     iso_analysis->UDFVerMajor=(unsigned int)buffer[5][241];
  297 #if 0
  298     /*  We are using ISO/UDF cd's as iso,
  299         no need to get UDF disc label */
  300     if (_cdio_read_block(p_cdio, 32, start_session, 5, i_track) < 0)
  301       return ret;
  302     stnrcpy(iso_analysis->iso_label, buffer[5]+25, 33);
  303     iso_analysis->iso_label[32] = '\0';
  304 #endif
  305     ret=CDIO_FS_ISO_UDF;
  306       }
  307 
  308 #if 0
  309       if (_cdio_is_rockridge())
  310     ret |= CDIO_FS_ANAL_ROCKRIDGE;
  311 #endif
  312 
  313       if (_cdio_read_block(p_cdio, BOOT_SECTOR, start_session, 3, i_track) < 0)
  314     return ret;
  315 
  316       if (_cdio_is_joliet()) {
  317     iso_analysis->joliet_level = _cdio_get_joliet_level();
  318     ret |= (CDIO_FS_ANAL_JOLIET | CDIO_FS_ANAL_ISO9660_ANY);
  319       }
  320       if (_cdio_is_it(INDEX_BOOTABLE))
  321     ret |= CDIO_FS_ANAL_BOOTABLE;
  322 
  323       if ( _cdio_is_it(INDEX_XA) && _cdio_is_it(INDEX_ISOFS)
  324       && !(sector0_read_ok && _cdio_is_it(INDEX_PHOTO_CD)) ) {
  325 
  326         if ( _cdio_read_block(p_cdio, VCD_INFO_SECTOR, start_session, 4,
  327                  i_track) < 0 )
  328       return ret;
  329 
  330     if (_cdio_is_it(INDEX_BRIDGE) && _cdio_is_it(INDEX_CD_RTOS)) {
  331       ret |= CDIO_FS_ANAL_ISO9660_ANY;
  332       if (_cdio_is_it(INDEX_VIDEO_CD))  ret |= CDIO_FS_ANAL_VIDEOCD;
  333       else if (_cdio_is_it(INDEX_SVCD)) ret |= CDIO_FS_ANAL_SVCD;
  334     } else if (_cdio_is_it(INDEX_SVCD)) ret |= CDIO_FS_ANAL_CVD;
  335 
  336       }
  337     }
  338     else if (_cdio_is_hfs())          ret |= CDIO_FS_HFS;
  339     else if (sector0_read_ok && _cdio_is_it(INDEX_EXT2))
  340       ret |= (CDIO_FS_EXT2 | CDIO_FS_ANAL_ISO9660_ANY);
  341     else if (_cdio_is_3do())          ret |= CDIO_FS_3DO;
  342     else {
  343       if ( _cdio_read_block(p_cdio, UFS_SUPERBLOCK_SECTOR, start_session, 2,
  344                 i_track) < 0 )
  345     return ret;
  346 
  347       if (sector0_read_ok && _cdio_is_it(INDEX_UFS))
  348     ret |= CDIO_FS_UFS;
  349       else
  350     ret |= CDIO_FS_UNKNOWN;
  351     }
  352   }
  353 
  354   /* other checks */
  355   if (_cdio_is_it(INDEX_XA))
  356     ret |= (CDIO_FS_ANAL_XA | CDIO_FS_ANAL_ISO9660_ANY);
  357   if (_cdio_is_it(INDEX_PHOTO_CD))
  358     ret |= (CDIO_FS_ANAL_PHOTO_CD | CDIO_FS_ANAL_ISO9660_ANY);
  359   if (_cdio_is_it(INDEX_CDTV))
  360     ret |= CDIO_FS_ANAL_CDTV;
  361   return ret;
  362 }