~ubuntu-branches/ubuntu/edgy/libcdio/edgy-updates

« back to all changes in this revision

Viewing changes to lib/driver/cd_types.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2005-11-15 16:53:23 UTC
  • mfrom: (3.1.1 etch)
  • Revision ID: james.westby@ubuntu.com-20051115165323-peroku75syl2j36u
Tags: 0.76-1ubuntu1
* Sync to new Debian version, manually apply Ubuntu patches:
  - debian/control: Remove dpkg-awk build dependency.
  - debian/rules: hardcode $LIBCDEV. This keeps the diff small (compared to
    the original patch of changing every ${libcdev} occurence).

Show diffs side-by-side

added added

removed removed

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