First attempt at smart iso9660 reading in CD images.

_cdio_stream.*: return is now cdio_driver_return_t
This commit is contained in:
rocky
2005-02-05 04:25:14 +00:00
parent a35a0a61d3
commit d958f062ea
10 changed files with 334 additions and 112 deletions

View File

@@ -46,7 +46,7 @@ development.''
@titlepage @titlepage
@title GNU libcdio library @title GNU libcdio library
@subtitle $Id: libcdio.texi,v 1.38 2005/02/01 03:35:43 rocky Exp $ @subtitle $Id: libcdio.texi,v 1.39 2005/02/05 04:25:14 rocky Exp $
@author Rocky Bernstein et al. @author Rocky Bernstein et al.
@page @page
@@ -1471,7 +1471,7 @@ firmware revision number of a CD drive. For this command to work,
usually a CD to be loaded into the drive; odd since the CD itself is usually a CD to be loaded into the drive; odd since the CD itself is
not used. not used.
This can be found in the distribution as @file{example/scsi-mmc1.c}. This can be found in the distribution as @file{example/mmc1.c}.
@smallexample @smallexample
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@@ -1721,11 +1721,11 @@ paranoia's open. I imagine in many cases such as media players this
may be what will be done since, one may want to get CDDB/CD-Text info may be what will be done since, one may want to get CDDB/CD-Text info
beforehand. beforehand.
@item @code{scsi-mmc1.c} @item @code{mmc1.c}
A program to show issuing a simple MMC command (@code{INQUIRY}). A program to show issuing a simple MMC command (@code{INQUIRY}).
@item @code{scsi-mmc2.c} @item @code{mmc2.c}
A more involved MMC command to list CD and drive features from a A more involved MMC command to list CD and drive features from a
SCSI-MMC @code{GET_CONFIGURATION} command. SCSI-MMC @code{GET_CONFIGURATION} command.

View File

@@ -1,5 +1,5 @@
/* /*
$Id: _cdio_stdio.c,v 1.3 2005/02/03 07:35:15 rocky Exp $ $Id: _cdio_stdio.c,v 1.4 2005/02/05 04:25:14 rocky Exp $
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com> Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
@@ -39,7 +39,7 @@
#include "_cdio_stream.h" #include "_cdio_stream.h"
#include "_cdio_stdio.h" #include "_cdio_stdio.h"
static const char _rcsid[] = "$Id: _cdio_stdio.c,v 1.3 2005/02/03 07:35:15 rocky Exp $"; static const char _rcsid[] = "$Id: _cdio_stdio.c,v 1.4 2005/02/05 04:25:14 rocky Exp $";
#define CDIO_STDIO_BUFSIZE (128*1024) #define CDIO_STDIO_BUFSIZE (128*1024)
@@ -106,27 +106,26 @@ _stdio_free(void *user_data)
of-file indicator for the stream and undoes any effects of the of-file indicator for the stream and undoes any effects of the
ungetc(3) function on the same stream. ungetc(3) function on the same stream.
RETURN VALUE @return upon successful completion, DRIVER_OP_SUCCESS, else,
Upon successful completion, return 0, DRIVER_OP_ERROR is returned and the global variable errno is set to
Otherwise, -1 is returned and the global variable errno is set to indi- indicate the error.
cate the error.
*/ */
static long static driver_return_code_t
_stdio_seek(void *user_data, long offset, int whence) _stdio_seek(void *p_user_data, long i_offset, int whence)
{ {
_UserData *const ud = user_data; _UserData *const ud = p_user_data;
if ( (offset=fseek (ud->fd, offset, whence)) ) { if ( (i_offset=fseek (ud->fd, i_offset, whence)) ) {
cdio_error ("fseek (): %s", strerror (errno)); cdio_error ("fseek (): %s", strerror (errno));
} }
return offset; return i_offset;
} }
static long int static long int
_stdio_stat(void *user_data) _stdio_stat(void *p_user_data)
{ {
const _UserData *const ud = user_data; const _UserData *const ud = p_user_data;
return ud->st_size; return ud->st_size;
} }

View File

@@ -1,5 +1,5 @@
/* /*
$Id: _cdio_stream.c,v 1.5 2005/02/03 07:35:15 rocky Exp $ $Id: _cdio_stream.c,v 1.6 2005/02/05 04:25:14 rocky Exp $
Copyright (C) 2000, 2004, 2005 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2000, 2004, 2005 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2005 Rocky Bernstein <rocky@panix.com> Copyright (C) 2005 Rocky Bernstein <rocky@panix.com>
@@ -35,7 +35,7 @@
#include <cdio/util.h> #include <cdio/util.h>
#include "_cdio_stream.h" #include "_cdio_stream.h"
static const char _rcsid[] = "$Id: _cdio_stream.c,v 1.5 2005/02/03 07:35:15 rocky Exp $"; static const char _rcsid[] = "$Id: _cdio_stream.c,v 1.6 2005/02/05 04:25:14 rocky Exp $";
/* /*
* DataSource implementations * DataSource implementations
@@ -82,21 +82,20 @@ _cdio_stream_open_if_necessary(CdioDataSource_t *p_obj)
of-file indicator for the stream and undoes any effects of the of-file indicator for the stream and undoes any effects of the
ungetc(3) function on the same stream. ungetc(3) function on the same stream.
RETURN VALUE @return unpon successful completion, DRIVER_OP_SUCCESS, else,
Upon successful completion, return 0, DRIVER_OP_ERROR is returned and the global variable errno is set to
Otherwise, -1 is returned and the global variable errno is set to indi- indicate the error.
cate the error.
*/ */
long int driver_return_code_t
cdio_stream_seek(CdioDataSource_t* p_obj, long int offset, int whence) cdio_stream_seek(CdioDataSource_t* p_obj, long int offset, int whence)
{ {
if (!p_obj) return -1; if (!p_obj) return DRIVER_OP_UNINIT;
if (!_cdio_stream_open_if_necessary(p_obj)) if (!_cdio_stream_open_if_necessary(p_obj))
/* errno is set by _cdio_stream_open_if necessary. */ /* errno is set by _cdio_stream_open_if necessary. */
return -1; return DRIVER_OP_ERROR;
if (offset < 0) return -1; if (offset < 0) return DRIVER_OP_ERROR;
if (p_obj->position != offset) { if (p_obj->position != offset) {
#ifdef STREAM_DEBUG #ifdef STREAM_DEBUG

View File

@@ -1,8 +1,8 @@
/* /*
$Id: _cdio_stream.h,v 1.2 2005/01/20 01:00:52 rocky Exp $ $Id: _cdio_stream.h,v 1.3 2005/02/05 04:25:14 rocky Exp $
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -36,7 +36,8 @@ extern "C" {
typedef long(*cdio_data_read_t)(void *user_data, void *buf, long count); typedef long(*cdio_data_read_t)(void *user_data, void *buf, long count);
typedef long(*cdio_data_seek_t)(void *user_data, long offset, int whence); typedef driver_return_code_t(*cdio_data_seek_t)(void *user_data, long offset,
int whence);
typedef long(*cdio_data_stat_t)(void *user_data); typedef long(*cdio_data_stat_t)(void *user_data);
@@ -76,7 +77,7 @@ extern "C" {
We do not distinguish between end-of-file and error, and callers We do not distinguish between end-of-file and error, and callers
must use feof(3) and ferror(3) to determine which occurred. must use feof(3) and ferror(3) to determine which occurred.
*/ */
long cdio_stream_read(CdioDataSource_t* p_obj, void *ptr, long size, long cdio_stream_read(CdioDataSource_t* p_obj, void *ptr, long i_size,
long nmemb); long nmemb);
/*! /*!
@@ -91,12 +92,12 @@ extern "C" {
of-file indicator for the stream and undoes any effects of the of-file indicator for the stream and undoes any effects of the
ungetc(3) function on the same stream. ungetc(3) function on the same stream.
RETURN VALUE @return upon successful completion, DRIVER_OP_SUCCESS, else,
Upon successful completion, return 0, DRIVER_OP_ERROR is returned and the global variable errno is set to
Otherwise, -1 is returned and the global variable errno is set to indi- indicate the error.
cate the error.
*/ */
long int cdio_stream_seek(CdioDataSource_t *p_obj, long offset, int whence); driver_return_code_t cdio_stream_seek(CdioDataSource_t *p_obj, long offset,
int whence);
/*! /*!
Return whatever size of stream reports, I guess unit size is bytes. Return whatever size of stream reports, I guess unit size is bytes.

View File

@@ -1,5 +1,5 @@
/* /*
$Id: read.c,v 1.3 2005/01/23 19:16:58 rocky Exp $ $Id: read.c,v 1.4 2005/02/05 04:25:14 rocky Exp $
Copyright (C) 2005 Rocky Bernstein <rocky@panix.com> Copyright (C) 2005 Rocky Bernstein <rocky@panix.com>
@@ -104,7 +104,7 @@ cdio_read (const CdIo_t *p_cdio, void *p_buf, size_t size)
/*! /*!
Reads an audio sector from cd device into data starting Reads an audio sector from cd device into data starting
from lsn. Returns 0 if no error. from lsn. Returns DRIVER_OP_SUCCESS if no error.
*/ */
driver_return_code_t driver_return_code_t
cdio_read_audio_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn) cdio_read_audio_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn)
@@ -117,7 +117,7 @@ cdio_read_audio_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn)
/*! /*!
Reads audio sectors from cd device into data starting Reads audio sectors from cd device into data starting
from lsn. Returns 0 if no error. from lsn. Returns DRIVER_OP_SUCCESS if no error.
*/ */
driver_return_code_t driver_return_code_t
cdio_read_audio_sectors (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, cdio_read_audio_sectors (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn,
@@ -135,7 +135,7 @@ cdio_read_audio_sectors (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn,
/*! /*!
Reads a single mode1 form1 or form2 sector from cd device Reads a single mode1 form1 or form2 sector from cd device
into data starting from lsn. Returns 0 if no error. into data starting from lsn. Returns DRIVER_OP_SUCCESS if no error.
*/ */
driver_return_code_t driver_return_code_t
cdio_read_mode1_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, cdio_read_mode1_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn,

View File

@@ -1,7 +1,7 @@
/* /*
$Id: sector.c,v 1.1 2004/12/18 17:29:32 rocky Exp $ $Id: sector.c,v 1.2 2005/02/05 04:25:14 rocky Exp $
Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> Copyright (C) 2004, 2005 Rocky Bernstein <rocky@panix.com>
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
@@ -35,8 +35,13 @@
#include <ctype.h> #include <ctype.h>
static const char _rcsid[] = "$Id: sector.c,v 1.1 2004/12/18 17:29:32 rocky Exp $"; static const char _rcsid[] = "$Id: sector.c,v 1.2 2005/02/05 04:25:14 rocky Exp $";
/*! String of bytes used to identify the beginning of a Mode 1 or
Mode 2 sector. */
const uint8_t CDIO_SECTOR_SYNC_HEADER[CDIO_CD_SYNC_SIZE] =
{0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0};
lba_t lba_t
cdio_lba_to_lsn (lba_t lba) cdio_lba_to_lsn (lba_t lba)
{ {

View File

@@ -1,8 +1,8 @@
/* /*
$Id: iso9660_fs.c,v 1.5 2005/02/04 02:18:12 rocky Exp $ $Id: iso9660_fs.c,v 1.6 2005/02/05 04:25:14 rocky Exp $
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -51,20 +51,127 @@
#include <stdio.h> #include <stdio.h>
static const char _rcsid[] = "$Id: iso9660_fs.c,v 1.5 2005/02/04 02:18:12 rocky Exp $"; static const char _rcsid[] = "$Id: iso9660_fs.c,v 1.6 2005/02/05 04:25:14 rocky Exp $";
/* Implementation of iso9660_t type */ /* Implementation of iso9660_t type */
struct _iso9660 { struct _iso9660 {
CdioDataSource_t *stream; /* Stream pointer */ CdioDataSource_t *stream; /* Stream pointer */
bool b_xa; /* true if has XA attributes. */ bool b_xa; /* true if has XA attributes. */
uint8_t i_joliet_level;/* 0 = no Joliet extensions. uint8_t i_joliet_level; /* 0 = no Joliet extensions.
1-3: Joliet level. */ 1-3: Joliet level. */
iso9660_pvd_t pvd; iso9660_pvd_t pvd;
iso9660_svd_t svd; iso9660_svd_t svd;
iso_extension_mask_t iso_extension_mask; /* What extensions we iso_extension_mask_t iso_extension_mask; /* What extensions we
tolerate. */ tolerate. */
uint32_t i_datastart; /* Usually 0 when i_framesize is ISO_BLOCKSIZE.
This is the normal condition. But in a fuzzy
read we may be reading a CD-image
and not a true ISO 9660 image this might be
CDIO_CD_SYNC_SIZE
*/
uint32_t i_framesize; /* Usually ISO_BLOCKSIZE (2048), but in a
fuzzy read, we may be reading a CD-image
and not a true ISO 9660 image this might
be CDIO_CD_FRAMESIZE_RAW (2352) or
M2RAW_SECTOR_SIZE (2336).
*/
int i_fuzzy_offset; /* Adjustment in bytes to make ISO_STANDARD_ID
("CD001") come out as ISO_PVD_SECTOR
(frame 16). Normally this should be 0
for an ISO 9660 image, but if one is
say reading a BIN/CUE or cdrdao BIN/TOC
without having the CUE or TOC and
trying to extract an ISO-9660
filesystem inside that it may be
different.
*/
}; };
static long int iso9660_seek_read_framesize (const iso9660_t *p_iso,
void *ptr, lsn_t start,
long int size,
uint16_t i_framesize);
/* Adjust the p_iso's i_datastart, i_byte_offset and i_framesize
based on whether we find a frame header or not.
*/
static void
adjust_fuzzy_pvd( iso9660_t *p_iso )
{
long int i_byte_offset;
if (!p_iso) return;
i_byte_offset = (ISO_PVD_SECTOR * p_iso->i_framesize)
+ p_iso->i_fuzzy_offset + p_iso->i_datastart;
/* If we have a raw 2352-byte frame then we should expect to see a sync
frame and a header.
*/
if (CDIO_CD_FRAMESIZE_RAW == p_iso->i_framesize) {
const int pre_user_data=CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE
+ CDIO_CD_SUBHEADER_SIZE;
char buf[pre_user_data];
i_byte_offset -= pre_user_data;
if ( DRIVER_OP_SUCCESS != cdio_stream_seek (p_iso->stream, i_byte_offset,
SEEK_SET) )
return;
if (sizeof(buf) == cdio_stream_read (p_iso->stream, buf, sizeof(buf), 1)) {
if (memcmp(CDIO_SECTOR_SYNC_HEADER, buf, CDIO_CD_SYNC_SIZE) &&
memcmp(CDIO_SECTOR_SYNC_HEADER, buf+CDIO_CD_SUBHEADER_SIZE,
CDIO_CD_SYNC_SIZE)) {
/* Has no frame header */
p_iso->i_framesize = M2RAW_SECTOR_SIZE;
p_iso->i_fuzzy_offset = (CDIO_CD_FRAMESIZE_RAW - M2RAW_SECTOR_SIZE)
* ISO_PVD_SECTOR + p_iso->i_fuzzy_offset + p_iso->i_datastart;
p_iso->i_datastart = 0;
}
}
}
}
/*!
Open an ISO 9660 image for reading in either fuzzy mode or not.
*/
static iso9660_t *
iso9660_open_ext_private (const char *pathname,
iso_extension_mask_t iso_extension_mask,
uint16_t i_fuzz, bool b_fuzzy)
{
iso9660_t *p_iso = (iso9660_t *) calloc(1, sizeof(struct _iso9660)) ;
bool b_have_superblock;
if (!p_iso) return NULL;
p_iso->stream = cdio_stdio_new( pathname );
if (NULL == p_iso->stream)
goto error;
p_iso->i_framesize = ISO_BLOCKSIZE;
b_have_superblock = (b_fuzzy)
? iso9660_ifs_fuzzy_read_superblock(p_iso, iso_extension_mask, i_fuzz)
: iso9660_ifs_read_superblock(p_iso, iso_extension_mask) ;
if ( ! b_have_superblock ) goto error;
/* Determine if image has XA attributes. */
p_iso->b_xa = !strncmp ((char *) &(p_iso->pvd) + ISO_XA_MARKER_OFFSET,
ISO_XA_MARKER_STRING,
strlen (ISO_XA_MARKER_STRING));
p_iso->iso_extension_mask = iso_extension_mask;
return p_iso;
error:
free(p_iso);
return NULL;
}
/*! /*!
Open an ISO 9660 image for reading. Maybe in the future we will have Open an ISO 9660 image for reading. Maybe in the future we will have
a mode. NULL is returned on error. a mode. NULL is returned on error.
@@ -80,34 +187,35 @@ iso9660_open (const char *pathname /*, mode*/)
a mode. NULL is returned on error. a mode. NULL is returned on error.
*/ */
iso9660_t * iso9660_t *
iso9660_open_ext (const char *pathname, iso9660_open_ext (const char *psz_path,
iso_extension_mask_t iso_extension_mask) iso_extension_mask_t iso_extension_mask)
{ {
iso9660_t *p_iso = (iso9660_t *) calloc(1, sizeof(struct _iso9660)) ; return iso9660_open_ext_private(psz_path, iso_extension_mask, 0, false);
if (NULL == p_iso) return NULL;
p_iso->stream = cdio_stdio_new( pathname );
if (NULL == p_iso->stream)
goto error;
if ( !iso9660_ifs_read_superblock(p_iso, iso_extension_mask) )
goto error;
/* Determine if image has XA attributes. */
p_iso->b_xa = !strncmp ((char *) &(p_iso->pvd) + ISO_XA_MARKER_OFFSET,
ISO_XA_MARKER_STRING,
strlen (ISO_XA_MARKER_STRING));
p_iso->iso_extension_mask = iso_extension_mask;
return p_iso;
error:
free(p_iso);
return NULL;
} }
/*!
Open an ISO 9660 image for reading. Maybe in the future we will have
a mode. NULL is returned on error.
*/
iso9660_t *
iso9660_open_fuzzy (const char *psz_path, uint16_t i_fuzz /*, mode*/)
{
return iso9660_open_fuzzy_ext(psz_path, ISO_EXTENSION_NONE, i_fuzz);
}
/*!
Open an ISO 9660 image for reading. Maybe in the future we will have
a mode. NULL is returned on error.
*/
iso9660_t *
iso9660_open_fuzzy_ext (const char *psz_path,
iso_extension_mask_t iso_extension_mask,
uint16_t i_fuzz)
{
return iso9660_open_ext_private(psz_path, iso_extension_mask, i_fuzz,
true);
}
/*! /*!
Close previously opened ISO 9660 image. Close previously opened ISO 9660 image.
@@ -125,16 +233,16 @@ iso9660_close (iso9660_t *p_iso)
} }
static bool static bool
check_pvd (const iso9660_pvd_t *p_pvd) check_pvd (const iso9660_pvd_t *p_pvd, cdio_log_level_t log_level)
{ {
if ( ISO_VD_PRIMARY != from_711(p_pvd->type) ) { if ( ISO_VD_PRIMARY != from_711(p_pvd->type) ) {
cdio_warn ("unexpected PVD type %d", p_pvd->type); cdio_log (log_level, "unexpected PVD type %d", p_pvd->type);
return false; return false;
} }
if (strncmp (p_pvd->id, ISO_STANDARD_ID, strlen (ISO_STANDARD_ID))) if (strncmp (p_pvd->id, ISO_STANDARD_ID, strlen (ISO_STANDARD_ID)))
{ {
cdio_warn ("unexpected ID encountered (expected `" cdio_log (log_level, "unexpected ID encountered (expected `"
ISO_STANDARD_ID "', got `%.5s'", p_pvd->id); ISO_STANDARD_ID "', got `%.5s'", p_pvd->id);
return false; return false;
} }
@@ -386,6 +494,22 @@ bool iso9660_ifs_get_volumeset_id(iso9660_t *p_iso,
} }
/*!
Read the Primary Volume Descriptor for an ISO 9660 image.
True is returned if read, and false if there was an error.
*/
static bool
iso9660_ifs_read_pvd_loglevel (const iso9660_t *p_iso,
/*out*/ iso9660_pvd_t *p_pvd,
cdio_log_level_t log_level)
{
if (0 == iso9660_iso_seek_read (p_iso, p_pvd, ISO_PVD_SECTOR, 1)) {
cdio_log ( log_level, "error reading PVD sector (%d)", ISO_PVD_SECTOR );
return false;
}
return check_pvd(p_pvd, log_level);
}
/*! /*!
Read the Primary Volume Descriptor for an ISO 9660 image. Read the Primary Volume Descriptor for an ISO 9660 image.
True is returned if read, and false if there was an error. True is returned if read, and false if there was an error.
@@ -393,11 +517,7 @@ bool iso9660_ifs_get_volumeset_id(iso9660_t *p_iso,
bool bool
iso9660_ifs_read_pvd (const iso9660_t *p_iso, /*out*/ iso9660_pvd_t *p_pvd) iso9660_ifs_read_pvd (const iso9660_t *p_iso, /*out*/ iso9660_pvd_t *p_pvd)
{ {
if (0 == iso9660_iso_seek_read (p_iso, p_pvd, ISO_PVD_SECTOR, 1)) { return iso9660_ifs_read_pvd_loglevel(p_iso, p_pvd, CDIO_LOG_WARN);
cdio_warn ("error reading PVD sector (%d)", ISO_PVD_SECTOR);
return false;
}
return check_pvd(p_pvd);
} }
@@ -448,7 +568,74 @@ iso9660_ifs_read_superblock (iso9660_t *p_iso,
return true; return true;
} }
/*!
Read the Super block of an ISO 9660 image but determine framesize
and datastart and a possible additional offset. Generally here we are
not reading an ISO 9660 image but a CD-Image which contains an ISO 9660
filesystem.
*/
bool
iso9660_ifs_fuzzy_read_superblock (iso9660_t *p_iso,
iso_extension_mask_t iso_extension_mask,
uint16_t i_fuzz)
{
/* Got some work to do to find ISO_STANDARD_ID ("CD001") */
unsigned int i;
for (i=0; i<i_fuzz; i++) {
unsigned int j;
char *pvd = NULL;
for (j = 0; j <= 1; j++ ) {
lsn_t lsn;
uint16_t k;
const uint16_t framesizes[] = { ISO_BLOCKSIZE, CDIO_CD_FRAMESIZE_RAW,
M2RAW_SECTOR_SIZE } ;
/* We don't need to loop over a zero offset twice*/
if (0==i && j)
continue;
lsn = (j) ? ISO_PVD_SECTOR - i : ISO_PVD_SECTOR + i;
for (k=0; k < 3; k++) {
char *p, *q;
char frame[CDIO_CD_FRAMESIZE_RAW] = {'\0',};
p_iso->i_framesize = framesizes[k];
p_iso->i_datastart = (ISO_BLOCKSIZE == framesizes[k]) ?
0 : CDIO_CD_SYNC_SIZE;
p_iso->i_fuzzy_offset = 0;
if (0 == iso9660_seek_read_framesize (p_iso, frame, lsn, 1,
p_iso->i_framesize)) {
return false;
}
q = memchr(frame, 'C', p_iso->i_framesize);
for ( p=q; p && p < frame + p_iso->i_framesize ; p=q+1 ) {
q = memchr(p, 'C', p_iso->i_framesize - (p - frame));
if ( !q || (pvd = strstr(q, ISO_STANDARD_ID)) )
break;
}
if (pvd) {
/* Yay! Found something */
p_iso->i_fuzzy_offset = (pvd - frame - 1) -
((ISO_PVD_SECTOR-lsn)*p_iso->i_framesize) ;
/* But is it *really* a PVD? */
if ( iso9660_ifs_read_pvd_loglevel(p_iso, &(p_iso->pvd),
CDIO_LOG_DEBUG) ) {
adjust_fuzzy_pvd(p_iso);
return true;
}
}
}
}
}
return false;
}
/*! /*!
Read the Primary Volume Descriptor for of CD. Read the Primary Volume Descriptor for of CD.
*/ */
@@ -491,7 +678,7 @@ iso9660_fs_read_pvd(const CdIo_t *p_cdio, /*out*/ iso9660_pvd_t *p_pvd)
cdio_assert (sizeof(buf) >= sizeof (iso9660_pvd_t)); cdio_assert (sizeof(buf) >= sizeof (iso9660_pvd_t));
memcpy(p_pvd, buf, sizeof(iso9660_pvd_t)); memcpy(p_pvd, buf, sizeof(iso9660_pvd_t));
return check_pvd(p_pvd); return check_pvd(p_pvd, CDIO_LOG_WARN);
} }
@@ -578,6 +765,26 @@ iso9660_fs_read_superblock (CdIo_t *p_cdio,
return true; return true;
} }
/*!
Seek to a position and then read n blocks. Size read is returned.
*/
static long int
iso9660_seek_read_framesize (const iso9660_t *p_iso, void *ptr,
lsn_t start, long int size,
uint16_t i_framesize)
{
long int ret;
long int i_byte_offset;
if (!p_iso) return 0;
i_byte_offset = (start * p_iso->i_framesize) + p_iso->i_fuzzy_offset
+ p_iso->i_datastart;
ret = cdio_stream_seek (p_iso->stream, i_byte_offset, SEEK_SET);
if (ret!=0) return 0;
return cdio_stream_read (p_iso->stream, ptr, i_framesize, size);
}
/*! /*!
Seek to a position and then read n blocks. Size read is returned. Seek to a position and then read n blocks. Size read is returned.
*/ */
@@ -585,14 +792,11 @@ long int
iso9660_iso_seek_read (const iso9660_t *p_iso, void *ptr, lsn_t start, iso9660_iso_seek_read (const iso9660_t *p_iso, void *ptr, lsn_t start,
long int size) long int size)
{ {
long int ret; return iso9660_seek_read_framesize(p_iso, ptr, start, size, ISO_BLOCKSIZE);
if (NULL == p_iso) return 0;
ret = cdio_stream_seek (p_iso->stream, start * ISO_BLOCKSIZE, SEEK_SET);
if (ret!=0) return 0;
return cdio_stream_read (p_iso->stream, ptr, ISO_BLOCKSIZE, size);
} }
static iso9660_stat_t * static iso9660_stat_t *
_iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir, _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir,
bool b_mode2, uint8_t i_joliet_level) bool b_mode2, uint8_t i_joliet_level)
@@ -639,7 +843,11 @@ _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir,
iso9660_get_dtime(&(p_iso9660_dir->recording_time), true, &(stat->tm)); iso9660_get_dtime(&(p_iso9660_dir->recording_time), true, &(stat->tm));
cdio_assert (dir_len >= sizeof (iso9660_dir_t)); if (dir_len < sizeof (iso9660_dir_t)) {
free(stat);
return NULL;
}
if (b_mode2) { if (b_mode2) {
int su_length = iso9660_get_dir_len(p_iso9660_dir) int su_length = iso9660_get_dir_len(p_iso9660_dir)
@@ -944,7 +1152,7 @@ _fs_iso_stat_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root,
Get file status for pathname into stat. NULL is returned on error. Get file status for pathname into stat. NULL is returned on error.
*/ */
iso9660_stat_t * iso9660_stat_t *
iso9660_fs_stat (CdIo_t *p_cdio, const char pathname[]) iso9660_fs_stat (CdIo_t *p_cdio, const char psz_path[])
{ {
iso9660_stat_t *p_root; iso9660_stat_t *p_root;
char **p_psz_splitpath; char **p_psz_splitpath;
@@ -953,13 +1161,13 @@ iso9660_fs_stat (CdIo_t *p_cdio, const char pathname[])
bool b_mode2; bool b_mode2;
if (!p_cdio) return NULL; if (!p_cdio) return NULL;
if (!pathname) return NULL; if (!psz_path) return NULL;
p_root = _fs_stat_root (p_cdio); p_root = _fs_stat_root (p_cdio);
if (!p_root) return NULL; if (!p_root) return NULL;
b_mode2 = cdio_get_track_green(p_cdio, 1); b_mode2 = cdio_get_track_green(p_cdio, 1);
p_psz_splitpath = _cdio_strsplit (pathname, '/'); p_psz_splitpath = _cdio_strsplit (psz_path, '/');
p_stat = _fs_stat_traverse (p_cdio, p_root, p_psz_splitpath, b_mode2, false); p_stat = _fs_stat_traverse (p_cdio, p_root, p_psz_splitpath, b_mode2, false);
free(p_root); free(p_root);
_cdio_strfreev (p_psz_splitpath); _cdio_strfreev (p_psz_splitpath);
@@ -974,7 +1182,7 @@ iso9660_fs_stat (CdIo_t *p_cdio, const char pathname[])
are lowercased. are lowercased.
*/ */
iso9660_stat_t * iso9660_stat_t *
iso9660_fs_stat_translate (CdIo_t *p_cdio, const char pathname[], iso9660_fs_stat_translate (CdIo_t *p_cdio, const char psz_path[],
bool b_mode2) bool b_mode2)
{ {
iso9660_stat_t *p_root; iso9660_stat_t *p_root;
@@ -982,12 +1190,12 @@ iso9660_fs_stat_translate (CdIo_t *p_cdio, const char pathname[],
iso9660_stat_t *p_stat; iso9660_stat_t *p_stat;
if (!p_cdio) return NULL; if (!p_cdio) return NULL;
if (pathname) return NULL; if (psz_path) return NULL;
p_root = _fs_stat_root (p_cdio); p_root = _fs_stat_root (p_cdio);
if (!p_root) return NULL; if (!p_root) return NULL;
p_psz_splitpath = _cdio_strsplit (pathname, '/'); p_psz_splitpath = _cdio_strsplit (psz_path, '/');
p_stat = _fs_stat_traverse (p_cdio, p_root, p_psz_splitpath, b_mode2, true); p_stat = _fs_stat_traverse (p_cdio, p_root, p_psz_splitpath, b_mode2, true);
free(p_root); free(p_root);
_cdio_strfreev (p_psz_splitpath); _cdio_strfreev (p_psz_splitpath);
@@ -999,19 +1207,19 @@ iso9660_fs_stat_translate (CdIo_t *p_cdio, const char pathname[],
Get file status for pathname into stat. NULL is returned on error. Get file status for pathname into stat. NULL is returned on error.
*/ */
iso9660_stat_t * iso9660_stat_t *
iso9660_ifs_stat (iso9660_t *p_iso, const char pathname[]) iso9660_ifs_stat (iso9660_t *p_iso, const char psz_path[])
{ {
iso9660_stat_t *p_root; iso9660_stat_t *p_root;
char **splitpath; char **splitpath;
iso9660_stat_t *stat; iso9660_stat_t *stat;
if (!p_iso) return NULL; if (!p_iso) return NULL;
if (!pathname) return NULL; if (!psz_path) return NULL;
p_root = _fs_stat_iso_root (p_iso); p_root = _fs_stat_iso_root (p_iso);
if (!p_root) return NULL; if (!p_root) return NULL;
splitpath = _cdio_strsplit (pathname, '/'); splitpath = _cdio_strsplit (psz_path, '/');
stat = _fs_iso_stat_traverse (p_iso, p_root, splitpath, false); stat = _fs_iso_stat_traverse (p_iso, p_root, splitpath, false);
free(p_root); free(p_root);
/*** FIXME _cdio_strfreev (splitpath); ***/ /*** FIXME _cdio_strfreev (splitpath); ***/
@@ -1026,19 +1234,19 @@ iso9660_ifs_stat (iso9660_t *p_iso, const char pathname[])
are lowercased. are lowercased.
*/ */
iso9660_stat_t * iso9660_stat_t *
iso9660_ifs_stat_translate (iso9660_t *p_iso, const char pathname[]) iso9660_ifs_stat_translate (iso9660_t *p_iso, const char psz_path[])
{ {
iso9660_stat_t *p_root; iso9660_stat_t *p_root;
char **p_psz_splitpath; char **p_psz_splitpath;
iso9660_stat_t *p_stat; iso9660_stat_t *p_stat;
if (!p_iso) return NULL; if (!p_iso) return NULL;
if (!pathname) return NULL; if (!psz_path) return NULL;
p_root = _fs_stat_iso_root (p_iso); p_root = _fs_stat_iso_root (p_iso);
if (NULL == p_root) return NULL; if (NULL == p_root) return NULL;
p_psz_splitpath = _cdio_strsplit (pathname, '/'); p_psz_splitpath = _cdio_strsplit (psz_path, '/');
p_stat = _fs_iso_stat_traverse (p_iso, p_root, p_psz_splitpath, true); p_stat = _fs_iso_stat_traverse (p_iso, p_root, p_psz_splitpath, true);
free(p_root); free(p_root);
_cdio_strfreev (p_psz_splitpath); _cdio_strfreev (p_psz_splitpath);
@@ -1051,15 +1259,15 @@ iso9660_ifs_stat_translate (iso9660_t *p_iso, const char pathname[])
of the files inside that. The caller must free the returned result. of the files inside that. The caller must free the returned result.
*/ */
CdioList_t * CdioList_t *
iso9660_fs_readdir (CdIo_t *p_cdio, const char pathname[], bool b_mode2) iso9660_fs_readdir (CdIo_t *p_cdio, const char psz_path[], bool b_mode2)
{ {
iso9660_stat_t *p_stat; iso9660_stat_t *p_stat;
generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env; generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env;
if (!p_cdio) return NULL; if (!p_cdio) return NULL;
if (!pathname) return NULL; if (!psz_path) return NULL;
p_stat = iso9660_fs_stat (p_cdio, pathname); p_stat = iso9660_fs_stat (p_cdio, psz_path);
if (!p_stat) return NULL; if (!p_stat) return NULL;
if (p_stat->type != _STAT_DIR) { if (p_stat->type != _STAT_DIR) {
@@ -1122,14 +1330,14 @@ iso9660_fs_readdir (CdIo_t *p_cdio, const char pathname[], bool b_mode2)
of the files inside that. The caller must free the returned result. of the files inside that. The caller must free the returned result.
*/ */
CdioList_t * CdioList_t *
iso9660_ifs_readdir (iso9660_t *p_iso, const char pathname[]) iso9660_ifs_readdir (iso9660_t *p_iso, const char psz_path[])
{ {
iso9660_stat_t *p_stat; iso9660_stat_t *p_stat;
if (!p_iso) return NULL; if (!p_iso) return NULL;
if (!pathname) return NULL; if (!psz_path) return NULL;
p_stat = iso9660_ifs_stat (p_iso, pathname); p_stat = iso9660_ifs_stat (p_iso, psz_path);
if (!p_stat) return NULL; if (!p_stat) return NULL;
if (p_stat->type != _STAT_DIR) { if (p_stat->type != _STAT_DIR) {
@@ -1168,14 +1376,21 @@ iso9660_ifs_readdir (iso9660_t *p_iso, const char pathname[])
p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, true, p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, true,
p_iso->i_joliet_level); p_iso->i_joliet_level);
_cdio_list_append (retval, p_iso9660_stat);
if (p_iso9660_stat)
_cdio_list_append (retval, p_iso9660_stat);
offset += iso9660_get_dir_len(p_iso9660_dir); offset += iso9660_get_dir_len(p_iso9660_dir);
} }
cdio_assert (offset == (p_stat->secsize * ISO_BLOCKSIZE));
free (_dirbuf); free (_dirbuf);
if (offset != (p_stat->secsize * ISO_BLOCKSIZE)) {
free (p_stat);
_cdio_list_free (retval, true);
return NULL;
}
free (p_stat); free (p_stat);
return retval; return retval;
} }

View File

@@ -1,5 +1,5 @@
/* /*
$Id: iso9660_private.h,v 1.1 2004/12/18 17:29:32 rocky Exp $ $Id: iso9660_private.h,v 1.2 2005/02/05 04:25:14 rocky Exp $
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
@@ -39,7 +39,7 @@ PRAGMA_BEGIN_PACKED
struct iso_volume_descriptor { struct iso_volume_descriptor {
uint8_t type; /* 711 */ uint8_t type; /* 711 */
char id[5]; char id[5]; /* "CD001" (ISO_STANDARD_ID) */
uint8_t version; /* 711 */ uint8_t version; /* 711 */
char data[2041]; char data[2041];
} GNUC_PACKED; } GNUC_PACKED;

View File

@@ -26,6 +26,7 @@ iso9660_get_system_id
iso9660_get_volume_id iso9660_get_volume_id
iso9660_get_volumeset_id iso9660_get_volumeset_id
iso9660_get_xa_attr_str iso9660_get_xa_attr_str
iso9660_ifs_fuzzy_read_superblock
iso9660_ifs_get_application_id iso9660_ifs_get_application_id
iso9660_ifs_get_joliet_level iso9660_ifs_get_joliet_level
iso9660_ifs_get_preparer_id iso9660_ifs_get_preparer_id
@@ -46,6 +47,8 @@ iso9660_name_translate
iso9660_name_translate_ext iso9660_name_translate_ext
iso9660_open iso9660_open
iso9660_open_ext iso9660_open_ext
iso9660_open_fuzzy
iso9660_open_fuzzy_ext
iso9660_pathname_isofy iso9660_pathname_isofy
iso9660_pathname_valid_p iso9660_pathname_valid_p
iso9660_pathtable_get_size iso9660_pathtable_get_size

View File

@@ -1,5 +1,5 @@
/* /*
$Id: util.c,v 1.31 2005/01/09 16:33:18 rocky Exp $ $Id: util.c,v 1.32 2005/02/05 04:25:14 rocky Exp $
Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com> Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
@@ -164,7 +164,7 @@ fillout_device_name(const char *device_name)
if (0 == strncmp(device_name, DEV_PREFIX, prefix_len)) if (0 == strncmp(device_name, DEV_PREFIX, prefix_len))
return strdup(device_name); return strdup(device_name);
else { else {
char *full_device_name = (char*) malloc(strlen(device_name)+prefix_len); char *full_device_name = (char*) calloc(1, strlen(device_name)+prefix_len);
report( stdout, full_device_name, DEV_PREFIX "%s", device_name); report( stdout, full_device_name, DEV_PREFIX "%s", device_name);
return full_device_name; return full_device_name;
} }