First cut at Joliet support for ISO 9660 images. More work is needed

to integrate this into CD reading.
This commit is contained in:
rocky
2004-10-23 20:55:08 +00:00
parent 8cca2f6709
commit a492bb4ab6
8 changed files with 649 additions and 220 deletions

6
NEWS
View File

@@ -13,7 +13,9 @@
- Add iso9660_ifs_is_xa() a routine to determine if an iso image has - Add iso9660_ifs_is_xa() a routine to determine if an iso image has
XA attributes. XA attributes.
- iso-info now shows XA attributes what that is available. - iso-info now shows XA attributes if that is available.
- Some Joliet support.
0.70 0.70
@@ -153,4 +155,4 @@
0.1 0.1
Routines split off from VCDImager. Routines split off from VCDImager.
$Id: NEWS,v 1.53 2004/10/22 01:14:08 rocky Exp $ $Id: NEWS,v 1.54 2004/10/23 20:55:08 rocky Exp $

View File

@@ -19,10 +19,11 @@ define(RELEASE_NUM, 71)
define(CDIO_VERSION_STR, 0.$1cvs) define(CDIO_VERSION_STR, 0.$1cvs)
AC_PREREQ(2.52) AC_PREREQ(2.52)
AC_REVISION([$Id: configure.ac,v 1.94 2004/09/03 23:20:11 rocky Exp $])dnl AC_REVISION([$Id: configure.ac,v 1.95 2004/10/23 20:55:08 rocky Exp $])dnl
AC_INIT(libcdio, CDIO_VERSION_STR(RELEASE_NUM)) AC_INIT(libcdio, CDIO_VERSION_STR(RELEASE_NUM))
AC_CONFIG_SRCDIR(src/cd-info.c) AC_CONFIG_SRCDIR(src/cd-info.c)
AM_INIT_AUTOMAKE AM_INIT_AUTOMAKE
AC_CANONICAL_HOST AC_CANONICAL_HOST
AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(config.h)
@@ -47,6 +48,11 @@ AC_ARG_WITH(versioned_libs,
[ --without-versioned-libs build versioned library symbols (enabled by default if you have GNU ld)], [ --without-versioned-libs build versioned library symbols (enabled by default if you have GNU ld)],
enable_versioned_libs="${withval}", enable_versioned_libs=yes) enable_versioned_libs="${withval}", enable_versioned_libs=yes)
AC_ARG_WITH([iconv],
AC_HELP_STRING([--without-iconv],
[do not include character set conversion support using ]
[the iconv library (default = enabled if found)]))
dnl Checks for programs. dnl Checks for programs.
AC_PROG_CC AC_PROG_CC
@@ -77,6 +83,14 @@ else
unset warning_flags unset warning_flags
fi fi
dnl Check for iconv
if test x$with_iconv != xno; then
AC_CHECK_HEADERS([iconv.h], [with_iconv=1], [with_iconv=0])
else
with_iconv=0
fi
AC_SUBST(with_iconv)
# We use Perl for documentation and regression tests # We use Perl for documentation and regression tests
AC_PATH_PROG(PERL, perl, no) AC_PATH_PROG(PERL, perl, no)
AC_SUBST(PERL) AC_SUBST(PERL)

View File

@@ -124,6 +124,9 @@ This standard was developed for Windows 95 and Windows NT by Microsoft
as an extension of ISO 9600 which allows the use of Unicode characters as an extension of ISO 9600 which allows the use of Unicode characters
and supports file names up to 64 characters. and supports file names up to 64 characters.
See @uref{http://bmrc.berkeley.edu/people/chaffee/jolspec.html} for
the Joliet Specification.
@item LBA @item LBA
Logical Block Addressing. Mapped integer numbers from CD Red Book Logical Block Addressing. Mapped integer numbers from CD Red Book

View File

@@ -1,5 +1,5 @@
/* /*
$Id: iso9660.h,v 1.50 2004/10/22 01:13:38 rocky Exp $ $Id: iso9660.h,v 1.51 2004/10/23 20:55:09 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>
@@ -334,15 +334,41 @@ struct iso9660_stat { /* big endian!! */
}; };
/** A mask used in iso9660_ifs_read_vd which allows what kinds
of extensions we allow, eg. Joliet, Rock Ridge, etc. */
typedef uint8_t iso_extension_mask_t;
#define ISO_EXTENSION_JOLIET_LEVEL1 0x01
#define ISO_EXTENSION_JOLIET_LEVEL2 0x02
#define ISO_EXTENSION_JOLIET_LEVEL3 0x04
#define ISO_EXTENSION_ROCK_RIDGE 0x08
#define ISO_EXTENSION_HIGH_SIERRA 0x10
#define ISO_EXTENSION_ALL 0xFF
#define ISO_EXTENSION_NONE 0x00
#define ISO_EXTENSION_JOLIET \
(ISO_EXTENSION_JOLIET_LEVEL1 | \
ISO_EXTENSION_JOLIET_LEVEL2 | \
ISO_EXTENSION_JOLIET_LEVEL3 )
/** This is an opaque structure. */ /** This is an opaque structure. */
typedef struct _iso9660 iso9660_t; typedef struct _iso9660 iso9660_t;
/*! /*!
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
flags and mode. NULL is returned on error. a mode. NULL is returned on error.
*/ */
iso9660_t *iso9660_open (const char *psz_pathname /*flags, mode */); iso9660_t *iso9660_open (const char *psz_pathname /*flags, mode */);
/*!
Open an ISO 9660 image for reading allowing various ISO 9660
extensions. Maybe in the future we will have a mode. NULL is
returned on error.
*/
iso9660_t *iso9660_open_ext (const char *psz_pathname,
iso_extension_mask_t iso_extension_mask);
/*! /*!
Close previously opened ISO 9660 image. Close previously opened ISO 9660 image.
True is unconditionally returned. If there was an error false would True is unconditionally returned. If there was an error false would
@@ -364,6 +390,14 @@ typedef struct _iso9660 iso9660_t;
bool iso9660_ifs_read_pvd (const iso9660_t *p_iso, bool iso9660_ifs_read_pvd (const iso9660_t *p_iso,
/*out*/ iso9660_pvd_t *p_pvd); /*out*/ iso9660_pvd_t *p_pvd);
/*!
Read the Supper block of an ISO 9660 image. This is either the
Primvary Volume Descriptor (PVD) or perhaps a Supplimental Volume
Descriptor if (Joliet) extensions are acceptable.
*/
bool iso9660_ifs_read_super (iso9660_t *p_iso, /*out*/ iso9660_pvd_t *p_vd,
iso_extension_mask_t iso_extension_mask);
/*! /*!
Read the Primary Volume Descriptor for a CD. Read the Primary Volume Descriptor for a CD.
True is returned if read, and false if there was an error. True is returned if read, and false if there was an error.
@@ -420,13 +454,24 @@ bool iso9660_isachar (int c);
/*! /*!
Convert ISO-9660 file name that stored in a directory entry into Convert ISO-9660 file name that stored in a directory entry into
what's usually listed as the file name in a listing. what's usually listed as the file name in a listing.
Lowercase name, and drop deal with trailing ;1's or .;1's or Lowercase name, and remove trailing ;1's or .;1's and
; version numbers. turn the other ;'s into version numbers.
The length of the translated string is returned. The length of the translated string is returned.
*/ */
int iso9660_name_translate(const char *psz_oldname, char *psz_newname); int iso9660_name_translate(const char *psz_oldname, char *psz_newname);
/*!
Convert ISO-9660 file name that stored in a directory entry into
what's usually listed as the file name in a listing. Lowercase
name if not using Joliet extension. Remove trailing ;1's or .;1's and
turn the other ;'s into version numbers.
The length of the translated string is returned.
*/
int iso9660_name_translate_ext(const char *old, char *new,
uint8_t i_joliet_level);
/*! /*!
Pad string src with spaces to size len and copy this to dst. If Pad string src with spaces to size len and copy this to dst. If
len is less than the length of src, dst will be truncated to the len is less than the length of src, dst will be truncated to the
@@ -568,9 +613,20 @@ CdioList * iso9660_ifs_readdir (iso9660_t *p_iso, const char pathname[]);
/*! /*!
Return the PVD's application ID. Return the PVD's application ID.
NULL is returned if there is some problem in getting this. NULL is returned if there is some problem in getting this.
*/ */
const char * iso9660_get_application_id(const iso9660_pvd_t *p_pvd); char * iso9660_get_application_id(iso9660_pvd_t *p_pvd);
/*!
Get the application ID. psz_app_id is set to NULL if there
is some problem in getting this and false is returned.
*/
bool iso9660_ifs_get_application_id(iso9660_t *p_iso,
/*out*/ char **p_psz_app_id);
/*!
Return the Joliet level recognaized for p_iso.
*/
uint8_t iso9660_ifs_get_joliet_level(iso9660_t *p_iso);
uint8_t iso9660_get_dir_len(const iso9660_dir_t *p_idr); uint8_t iso9660_get_dir_len(const iso9660_dir_t *p_idr);
@@ -591,13 +647,27 @@ char * iso9660_dir_to_name (const iso9660_dir_t *p_iso9660_dir);
Return a string containing the preparer id with trailing Return a string containing the preparer id with trailing
blanks removed. blanks removed.
*/ */
const char *iso9660_get_preparer_id(const iso9660_pvd_t *pvd); char *iso9660_get_preparer_id(const iso9660_pvd_t *p_pvd);
/*!
Get the preparer ID. psz_preparer_id is set to NULL if there
is some problem in getting this and false is returned.
*/
bool iso9660_ifs_get_preparer_id(iso9660_t *p_iso,
/*out*/ char **p_psz_preparer_id);
/*! /*!
Return a string containing the PVD's publisher id with trailing Return a string containing the PVD's publisher id with trailing
blanks removed. blanks removed.
*/ */
const char *iso9660_get_publisher_id(const iso9660_pvd_t *p_pvd); char *iso9660_get_publisher_id(const iso9660_pvd_t *p_pvd);
/*!
Get the publisher ID. psz_publisher_id is set to NULL if there
is some problem in getting this and false is returned.
*/
bool iso9660_ifs_get_publisher_id(iso9660_t *p_iso,
/*out*/ char **p_psz_publisher_id);
uint8_t iso9660_get_pvd_type(const iso9660_pvd_t *p_pvd); uint8_t iso9660_get_pvd_type(const iso9660_pvd_t *p_pvd);
@@ -616,8 +686,15 @@ int iso9660_get_pvd_version(const iso9660_pvd_t *pvd) ;
Return a string containing the PVD's system id with trailing Return a string containing the PVD's system id with trailing
blanks removed. blanks removed.
*/ */
const char *iso9660_get_system_id(const iso9660_pvd_t *pvd); char *iso9660_get_system_id(const iso9660_pvd_t *p_pvd);
/*!
Get the system ID. psz_system_id is set to NULL if there
is some problem in getting this and false is returned.
*/
bool iso9660_ifs_get_system_id(iso9660_t *p_iso,
/*out*/ char **p_psz_system_id);
/*! Return the LSN of the root directory for pvd. /*! Return the LSN of the root directory for pvd.
If there is an error CDIO_INVALID_LSN is returned. If there is an error CDIO_INVALID_LSN is returned.
@@ -627,13 +704,27 @@ lsn_t iso9660_get_root_lsn(const iso9660_pvd_t *p_pvd);
/*! /*!
Return the PVD's volume ID. Return the PVD's volume ID.
*/ */
const char *iso9660_get_volume_id(const iso9660_pvd_t *p_pvd); char *iso9660_get_volume_id(const iso9660_pvd_t *p_pvd);
/*!
Get the system ID. psz_system_id is set to NULL if there
is some problem in getting this and false is returned.
*/
bool iso9660_ifs_get_volume_id(iso9660_t *p_iso,
/*out*/ char **p_psz_volume_id);
/*! /*!
Return the PVD's volumeset ID. Return the PVD's volumeset ID.
NULL is returned if there is some problem in getting this. NULL is returned if there is some problem in getting this.
*/ */
const char *iso9660_get_volumeset_id(const iso9660_pvd_t *p_pvd); char *iso9660_get_volumeset_id(const iso9660_pvd_t *p_pvd);
/*!
Get the systemset ID. psz_systemset_id is set to NULL if there
is some problem in getting this and false is returned.
*/
bool iso9660_ifs_get_volumeset_id(iso9660_t *p_iso,
/*out*/ char **p_psz_volumeset_id);
/* pathtable */ /* pathtable */

View File

@@ -1,8 +1,8 @@
/* /*
$Id: iso9660.c,v 1.17 2004/10/22 01:13:38 rocky Exp $ $Id: iso9660.c,v 1.18 2004/10/23 20:55:09 rocky Exp $
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com> Copyright (C) 2003, 2004 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
@@ -37,7 +37,7 @@
#include <stdio.h> #include <stdio.h>
#endif #endif
static const char _rcsid[] = "$Id: iso9660.c,v 1.17 2004/10/22 01:13:38 rocky Exp $"; static const char _rcsid[] = "$Id: iso9660.c,v 1.18 2004/10/23 20:55:09 rocky Exp $";
/* some parameters... */ /* some parameters... */
#define SYSTEM_ID "CD-RTOS CD-BRIDGE" #define SYSTEM_ID "CD-RTOS CD-BRIDGE"
@@ -47,7 +47,7 @@ static const char _rcsid[] = "$Id: iso9660.c,v 1.17 2004/10/22 01:13:38 rocky Ex
Change trailing blanks in str to nulls. Str has a maximum size of Change trailing blanks in str to nulls. Str has a maximum size of
n characters. n characters.
*/ */
static const char * static char *
strip_trail (const char str[], size_t n) strip_trail (const char str[], size_t n)
{ {
static char buf[1024]; static char buf[1024];
@@ -78,72 +78,72 @@ pathtable_get_size_and_entries(const void *pt, unsigned int *size,
record. Even though tm_wday and tm_yday fields are not explicitly in record. Even though tm_wday and tm_yday fields are not explicitly in
idr_date, the are calculated from the other fields. idr_date, the are calculated from the other fields.
If tm is to reflect the localtime set use_localtime true, otherwise If tm is to reflect the localtime set b_localtime true, otherwise
tm will reported in GMT. tm will reported in GMT.
*/ */
void void
iso9660_get_dtime (const iso9660_dtime_t *idr_date, bool use_localtime, iso9660_get_dtime (const iso9660_dtime_t *idr_date, bool b_localtime,
/*out*/ struct tm *tm) /*out*/ struct tm *p_tm)
{ {
time_t t; time_t t;
struct tm *temp_tm; struct tm *p_temp_tm;
if (!idr_date) return; if (!idr_date) return;
tm->tm_year = idr_date->dt_year; p_tm->tm_year = idr_date->dt_year;
tm->tm_mon = idr_date->dt_month - 1; p_tm->tm_mon = idr_date->dt_month - 1;
tm->tm_mday = idr_date->dt_day; p_tm->tm_mday = idr_date->dt_day;
tm->tm_hour = idr_date->dt_hour; p_tm->tm_hour = idr_date->dt_hour;
tm->tm_min = idr_date->dt_minute; p_tm->tm_min = idr_date->dt_minute;
tm->tm_sec = idr_date->dt_second; p_tm->tm_sec = idr_date->dt_second;
/* Recompute tm_wday and tm_yday via mktime. */ /* Recompute tm_wday and tm_yday via mktime. */
t = mktime(tm); t = mktime(p_tm);
if (use_localtime) if (b_localtime)
temp_tm = localtime(&t); p_temp_tm = localtime(&t);
else else
temp_tm = gmtime(&t); p_temp_tm = gmtime(&t);
memcpy(tm, temp_tm, sizeof(struct tm)); memcpy(p_tm, p_temp_tm, sizeof(struct tm));
} }
/*! /*!
Set time in format used in ISO 9660 directory index record Set time in format used in ISO 9660 directory index record
from a Unix time structure. */ from a Unix time structure. */
void void
iso9660_set_dtime (const struct tm *tm, /*out*/ iso9660_dtime_t *idr_date) iso9660_set_dtime (const struct tm *p_tm, /*out*/ iso9660_dtime_t *p_idr_date)
{ {
memset (idr_date, 0, 7); memset (p_idr_date, 0, 7);
if (!tm) return; if (!p_tm) return;
idr_date->dt_year = tm->tm_year; p_idr_date->dt_year = p_tm->tm_year;
idr_date->dt_month = tm->tm_mon + 1; p_idr_date->dt_month = p_tm->tm_mon + 1;
idr_date->dt_day = tm->tm_mday; p_idr_date->dt_day = p_tm->tm_mday;
idr_date->dt_hour = tm->tm_hour; p_idr_date->dt_hour = p_tm->tm_hour;
idr_date->dt_minute = tm->tm_min; p_idr_date->dt_minute = p_tm->tm_min;
idr_date->dt_second = tm->tm_sec; p_idr_date->dt_second = p_tm->tm_sec;
#ifdef HAVE_TM_GMTOFF #ifdef HAVE_TM_GMTOFF
/* The ISO 9660 timezone is in the range -48..+52 and each unit /* The ISO 9660 timezone is in the range -48..+52 and each unit
represents a 15-minute interval. */ represents a 15-minute interval. */
idr_date->dt_gmtoff = tm->tm_gmtoff / (15 * 60); p_idr_date->dt_gmtoff = p_tm->tm_gmtoff / (15 * 60);
if (tm->tm_isdst) idr_date->dt_gmtoff -= 4; if (p_tm->tm_isdst) p_idr_date->dt_gmtoff -= 4;
if (idr_date->dt_gmtoff < -48 ) { if (p_idr_date->dt_gmtoff < -48 ) {
cdio_warn ("Converted ISO 9660 timezone %d is less than -48. Adjusted", cdio_warn ("Converted ISO 9660 timezone %d is less than -48. Adjusted",
idr_date->dt_gmtoff); p_idr_date->dt_gmtoff);
idr_date->dt_gmtoff = -48; p_idr_date->dt_gmtoff = -48;
} else if (idr_date->dt_gmtoff > 52) { } else if (p_idr_date->dt_gmtoff > 52) {
cdio_warn ("Converted ISO 9660 timezone %d is over 52. Adjusted", cdio_warn ("Converted ISO 9660 timezone %d is over 52. Adjusted",
idr_date->dt_gmtoff); p_idr_date->dt_gmtoff);
idr_date->dt_gmtoff = 52; p_idr_date->dt_gmtoff = 52;
} }
#else #else
idr_date->dt_gmtoff = 0; p_idr_date->dt_gmtoff = 0;
#endif #endif
} }
@@ -172,13 +172,27 @@ iso9660_set_ltime (const struct tm *_tm, /*out*/ iso9660_ltime_t *pvd_date)
/*! /*!
Convert ISO-9660 file name that stored in a directory entry into Convert ISO-9660 file name that stored in a directory entry into
what's usually listed as the file name in a listing. what's usually listed as the file name in a listing.
Lowercase name, and trailing ;1's or .;1's and turn the Lowercase name, and remove trailing ;1's or .;1's and
other ;'s into version numbers. turn the other ;'s into version numbers.
The length of the translated string is returned. The length of the translated string is returned.
*/ */
int int
iso9660_name_translate(const char *old, char *new) iso9660_name_translate(const char *old, char *new)
{
return iso9660_name_translate_ext(old, new, 0);
}
/*!
Convert ISO-9660 file name that stored in a directory entry into
what's usually listed as the file name in a listing. Lowercase
name if not using Joliet extension. Remove trailing ;1's or .;1's and
turn the other ;'s into version numbers.
The length of the translated string is returned.
*/
int
iso9660_name_translate_ext(const char *old, char *new, uint8_t i_joliet_level)
{ {
int len = strlen(old); int len = strlen(old);
int i; int i;
@@ -188,8 +202,8 @@ iso9660_name_translate(const char *old, char *new)
if (!c) if (!c)
break; break;
/* lower case */ /* Lower case, unless we have Joliet extensions. */
if (isupper(c)) c = tolower(c); if (!i_joliet_level && isupper(c)) c = tolower(c);
/* Drop trailing '.;1' (ISO 9660:1988 7.5.1 requires period) */ /* Drop trailing '.;1' (ISO 9660:1988 7.5.1 requires period) */
if (c == '.' && i == len - 3 && old[i + 1] == ';' && old[i + 2] == '1') if (c == '.' && i == len - 3 && old[i + 1] == ';' && old[i + 2] == '1')
@@ -827,11 +841,11 @@ iso9660_pathname_isofy (const char pathname[], uint16_t version)
Return the PVD's application ID. Return the PVD's application ID.
NULL is returned if there is some problem in getting this. NULL is returned if there is some problem in getting this.
*/ */
const char * char *
iso9660_get_application_id(const iso9660_pvd_t *pvd) iso9660_get_application_id(iso9660_pvd_t *p_pvd)
{ {
if (NULL==pvd) return NULL; if (NULL==p_pvd) return NULL;
return(strip_trail(pvd->application_id, ISO_MAX_APPLICATION_ID)); return strdup(strip_trail(p_pvd->application_id, ISO_MAX_APPLICATION_ID));
} }
#if FIXME #if FIXME
@@ -916,54 +930,54 @@ iso9660_get_root_lsn(const iso9660_pvd_t *pvd)
Return a string containing the preparer id with trailing Return a string containing the preparer id with trailing
blanks removed. blanks removed.
*/ */
const char * char *
iso9660_get_preparer_id(const iso9660_pvd_t *pvd) iso9660_get_preparer_id(const iso9660_pvd_t *pvd)
{ {
if (NULL==pvd) return NULL; if (NULL==pvd) return NULL;
return(strip_trail(pvd->preparer_id, ISO_MAX_PREPARER_ID)); return strdup(strip_trail(pvd->preparer_id, ISO_MAX_PREPARER_ID));
} }
/*! /*!
Return a string containing the publisher id with trailing Return a string containing the publisher id with trailing
blanks removed. blanks removed.
*/ */
const char * char *
iso9660_get_publisher_id(const iso9660_pvd_t *pvd) iso9660_get_publisher_id(const iso9660_pvd_t *pvd)
{ {
if (NULL==pvd) return NULL; if (NULL==pvd) return NULL;
return(strip_trail(pvd->publisher_id, ISO_MAX_PUBLISHER_ID)); return strdup(strip_trail(pvd->publisher_id, ISO_MAX_PUBLISHER_ID));
} }
/*! /*!
Return a string containing the PVD's system id with trailing Return a string containing the PVD's system id with trailing
blanks removed. blanks removed.
*/ */
const char * char *
iso9660_get_system_id(const iso9660_pvd_t *pvd) iso9660_get_system_id(const iso9660_pvd_t *pvd)
{ {
if (NULL==pvd) return NULL; if (NULL==pvd) return NULL;
return(strip_trail(pvd->system_id, ISO_MAX_SYSTEM_ID)); return strdup(strip_trail(pvd->system_id, ISO_MAX_SYSTEM_ID));
} }
/*! /*!
Return the PVD's volume ID. Return the PVD's volume ID.
*/ */
const char * char *
iso9660_get_volume_id(const iso9660_pvd_t *pvd) iso9660_get_volume_id(const iso9660_pvd_t *pvd)
{ {
if (NULL == pvd) return NULL; if (NULL == pvd) return NULL;
return(strip_trail(pvd->volume_id, ISO_MAX_VOLUME_ID)); return strdup(strip_trail(pvd->volume_id, ISO_MAX_VOLUME_ID));
} }
/*! /*!
Return the PVD's volumeset ID. Return the PVD's volumeset ID.
NULL is returned if there is some problem in getting this. NULL is returned if there is some problem in getting this.
*/ */
const char * char *
iso9660_get_volumeset_id(const iso9660_pvd_t *pvd) iso9660_get_volumeset_id(const iso9660_pvd_t *pvd)
{ {
if ( NULL == pvd ) return NULL; if ( NULL == pvd ) return NULL;
return strip_trail(pvd->volume_set_id, ISO_MAX_VOLUMESET_ID); return strdup(strip_trail(pvd->volume_set_id, ISO_MAX_VOLUMESET_ID));
} }

View File

@@ -1,5 +1,5 @@
/* /*
$Id: iso9660_fs.c,v 1.26 2004/10/22 01:13:38 rocky Exp $ $Id: iso9660_fs.c,v 1.27 2004/10/23 20:55:09 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 Rocky Bernstein <rocky@panix.com>
@@ -24,9 +24,19 @@
#endif #endif
#ifdef HAVE_STRING_H #ifdef HAVE_STRING_H
#include <string.h> # include <string.h>
#endif #endif
#ifdef HAVE_ERRNO_H
# include <errno.h>
#endif
#ifdef HAVE_ICONV_H
# include <iconv.h>
#endif
#include <langinfo.h>
#include <cdio/cdio.h> #include <cdio/cdio.h>
#include <cdio/bytesex.h> #include <cdio/bytesex.h>
#include <cdio/iso9660.h> #include <cdio/iso9660.h>
@@ -39,23 +49,39 @@
#include <stdio.h> #include <stdio.h>
static const char _rcsid[] = "$Id: iso9660_fs.c,v 1.26 2004/10/22 01:13:38 rocky Exp $"; static const char _rcsid[] = "$Id: iso9660_fs.c,v 1.27 2004/10/23 20:55:09 rocky Exp $";
/* Implementation of iso9660_t type */ /* Implementation of iso9660_t type */
struct _iso9660 { struct _iso9660 {
CdioDataSource *stream; /* Stream pointer */ CdioDataSource *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.
1-3: Joliet level. */
iso9660_pvd_t vd; /* Either a PVD or a SVD, but rather than
use union we'll cast when necessary */
iso_extension_mask_t iso_extension_mask; /* What extensions we
tolerate. */
}; };
/*! /*!
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
flags and mode. NULL is returned on error. a mode. NULL is returned on error.
*/ */
iso9660_t * iso9660_t *
iso9660_open (const char *pathname /*flags, mode */) iso9660_open (const char *pathname /*, mode*/)
{
return iso9660_open_ext(pathname, ISO_EXTENSION_NONE);
}
/*!
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_ext (const char *pathname,
iso_extension_mask_t iso_extension_mask)
{ {
iso9660_t *p_iso = (iso9660_t *) _cdio_malloc(sizeof(struct _iso9660)) ; iso9660_t *p_iso = (iso9660_t *) _cdio_malloc(sizeof(struct _iso9660)) ;
iso9660_pvd_t pvd;
if (NULL == p_iso) return NULL; if (NULL == p_iso) return NULL;
@@ -63,14 +89,15 @@ iso9660_open (const char *pathname /*flags, mode */)
if (NULL == p_iso->stream) if (NULL == p_iso->stream)
goto error; goto error;
if (!iso9660_ifs_read_pvd(p_iso, &pvd)) if ( !iso9660_ifs_read_super(p_iso, &(p_iso->vd), iso_extension_mask) )
goto error; goto error;
/* Determine if image has XA attributes. */ /* Determine if image has XA attributes. */
p_iso->b_xa = !strncmp ((char *) &pvd + ISO_XA_MARKER_OFFSET, p_iso->b_xa = !strncmp ((char *) &(p_iso->vd) + ISO_XA_MARKER_OFFSET,
ISO_XA_MARKER_STRING, ISO_XA_MARKER_STRING,
strlen (ISO_XA_MARKER_STRING)); strlen (ISO_XA_MARKER_STRING));
p_iso->iso_extension_mask = iso_extension_mask;
return p_iso; return p_iso;
error: error:
@@ -98,7 +125,7 @@ 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)
{ {
if (p_pvd->type != ISO_VD_PRIMARY) { if ( ISO_VD_PRIMARY != from_711(p_pvd->type) ) {
cdio_warn ("unexpected PVD type %d", p_pvd->type); cdio_warn ("unexpected PVD type %d", p_pvd->type);
return false; return false;
} }
@@ -112,8 +139,218 @@ check_pvd (const iso9660_pvd_t *p_pvd)
return true; return true;
} }
static bool
ucs2be_to_locale(char *psz_ucs2be, size_t i_inlen,
char **p_psz_out, size_t i_outlen)
{
iconv_t ic = iconv_open(nl_langinfo(CODESET), "UCS-2BE");
int rc;
char *psz_buf = NULL;
char *psz_buf2;
int i_outlen_save = i_outlen;
psz_buf = (char *) realloc(psz_buf, i_outlen);
psz_buf2 = psz_buf;
if (!psz_buf) {
/* XXX: report out of memory error */
goto error;
}
rc = iconv(ic, &psz_ucs2be, &i_inlen, &psz_buf2, &i_outlen);
iconv_close(ic);
if ((rc == -1) && (errno != E2BIG)) {
/* conversion failed */
goto error;
}
*p_psz_out = malloc(i_outlen_save + 1);
memcpy(*p_psz_out, psz_buf, i_outlen_save);
*(*p_psz_out + i_outlen_save) = '\0';
free(psz_buf);
return true;
error:
free(psz_buf);
*p_psz_out = NULL;
return false;
}
/*!
Return the application ID. NULL is returned in psz_app_id if there
is some problem in getting this.
*/
bool
iso9660_ifs_get_application_id(iso9660_t *p_iso,
/*out*/ char **p_psz_app_id)
{
if (!p_iso) {
*p_psz_app_id = NULL;
return false;
}
if (p_iso->i_joliet_level) {
/* TODO: check that we haven't reached the maximum size.
If we have, perhaps we've truncated and if we can get
longer results *and* have the same character using
the PVD, do that.
*/
return ucs2be_to_locale(p_iso->vd.application_id,
ISO_MAX_APPLICATION_ID,
p_psz_app_id,
ISO_MAX_APPLICATION_ID);
} else {
*p_psz_app_id = iso9660_get_application_id( &(p_iso->vd) );
return *p_psz_app_id != NULL && strlen(*p_psz_app_id);
}
}
/*!
Return the Joliet level recognaized for p_iso.
*/
uint8_t iso9660_ifs_get_joliet_level(iso9660_t *p_iso)
{
if (!p_iso) return 0;
return p_iso->i_joliet_level;
}
/*!
Return a string containing the preparer id with trailing
blanks removed.
*/
bool
iso9660_ifs_get_preparer_id(iso9660_t *p_iso,
/*out*/ char **p_psz_preparer_id)
{
if (!p_iso) {
*p_psz_preparer_id = NULL;
return false;
}
if (p_iso->i_joliet_level) {
/* TODO: check that we haven't reached the maximum size.
If we have, perhaps we've truncated and if we can get
longer results *and* have the same character using
the PVD, do that.
*/
return ucs2be_to_locale(p_iso->vd.preparer_id, ISO_MAX_PREPARER_ID,
p_psz_preparer_id, ISO_MAX_PREPARER_ID);
} else {
*p_psz_preparer_id = iso9660_get_preparer_id( &(p_iso->vd) );
return *p_psz_preparer_id != NULL && strlen(*p_psz_preparer_id);
}
}
/*!
Return a string containing the PVD's publisher id with trailing
blanks removed.
*/
bool iso9660_ifs_get_publisher_id(iso9660_t *p_iso,
/*out*/ char **p_psz_publisher_id)
{
if (!p_iso) {
*p_psz_publisher_id = NULL;
return false;
}
if (p_iso->i_joliet_level) {
/* TODO: check that we haven't reached the maximum size.
If we have, perhaps we've truncated and if we can get
longer results *and* have the same character using
the PVD, do that.
*/
return ucs2be_to_locale(p_iso->vd.publisher_id, ISO_MAX_PUBLISHER_ID,
p_psz_publisher_id, ISO_MAX_PUBLISHER_ID);
} else {
*p_psz_publisher_id = iso9660_get_publisher_id( &(p_iso->vd) );
return *p_psz_publisher_id != NULL && strlen(*p_psz_publisher_id);
}
}
/*!
Return a string containing the PVD's publisher id with trailing
blanks removed.
*/
bool iso9660_ifs_get_system_id(iso9660_t *p_iso,
/*out*/ char **p_psz_system_id)
{
if (!p_iso) {
*p_psz_system_id = NULL;
return false;
}
if (p_iso->i_joliet_level) {
/* TODO: check that we haven't reached the maximum size.
If we have, perhaps we've truncated and if we can get
longer results *and* have the same character using
the PVD, do that.
*/
return ucs2be_to_locale(p_iso->vd.system_id, ISO_MAX_SYSTEM_ID,
p_psz_system_id, ISO_MAX_SYSTEM_ID);
} else {
*p_psz_system_id = iso9660_get_system_id( &(p_iso->vd) );
return *p_psz_system_id != NULL && strlen(*p_psz_system_id);
}
}
/*!
Return a string containing the PVD's publisher id with trailing
blanks removed.
*/
bool iso9660_ifs_get_volume_id(iso9660_t *p_iso,
/*out*/ char **p_psz_volume_id)
{
if (!p_iso) {
*p_psz_volume_id = NULL;
return false;
}
if (p_iso->i_joliet_level) {
/* TODO: check that we haven't reached the maximum size.
If we have, perhaps we've truncated and if we can get
longer results *and* have the same character using
the PVD, do that.
*/
return ucs2be_to_locale(p_iso->vd.volume_id, ISO_MAX_VOLUME_ID,
p_psz_volume_id, ISO_MAX_VOLUME_ID);
} else {
*p_psz_volume_id = iso9660_get_volume_id( &(p_iso->vd) );
return *p_psz_volume_id != NULL && strlen(*p_psz_volume_id);
}
}
/*!
Return a string containing the PVD's publisher id with trailing
blanks removed.
*/
bool iso9660_ifs_get_volumeset_id(iso9660_t *p_iso,
/*out*/ char **p_psz_volumeset_id)
{
if (!p_iso) {
*p_psz_volumeset_id = NULL;
return false;
}
if (p_iso->i_joliet_level) {
/* TODO: check that we haven't reached the maximum size.
If we have, perhaps we've truncated and if we can get
longer results *and* have the same character using
the PVD, do that.
*/
return ucs2be_to_locale(p_iso->vd.volume_set_id,
ISO_MAX_VOLUMESET_ID,
p_psz_volumeset_id,
ISO_MAX_VOLUMESET_ID);
} else {
*p_psz_volumeset_id = iso9660_get_volume_id( &(p_iso->vd) );
return *p_psz_volumeset_id != NULL && strlen(*p_psz_volumeset_id);
}
}
/*! /*!
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.
*/ */
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)
@@ -126,6 +363,53 @@ iso9660_ifs_read_pvd (const iso9660_t *p_iso, /*out*/ iso9660_pvd_t *p_pvd)
} }
/*!
Read the Supper block of an ISO 9660 image. This is either the
Primvary Volume Descriptor (PVD) or perhaps a Supplimental Volume
Descriptor if (Joliet) extensions are acceptable.
*/
bool
iso9660_ifs_read_super (iso9660_t *p_iso, /*out*/ iso9660_pvd_t *p_pvd,
iso_extension_mask_t iso_extension_mask)
{
iso9660_svd_t svd; /* Secondary volume descriptor. */
if (!iso9660_ifs_read_pvd(p_iso, p_pvd))
return false;
p_iso->i_joliet_level = 0;
if (0 != iso9660_iso_seek_read (p_iso, &svd, ISO_PVD_SECTOR+1, 1)) {
if ( ISO_VD_SUPPLEMENTARY == from_711(svd.type) ) {
if (svd.escape_sequences[0] == 0x25 && svd.escape_sequences[1] == 0x2f) {
switch (svd.escape_sequences[2]) {
case 0x40:
if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL1)
p_iso->i_joliet_level = 1;
break;
case 0x43:
if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL2)
p_iso->i_joliet_level = 2;
break;
case 0x45:
if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL3)
p_iso->i_joliet_level = 3;
break;
default:
cdio_info("Supplementary Volume Descriptor found, but not Joliet");
}
if (p_iso->i_joliet_level > 0) {
cdio_info("Found Extension: Joliet Level %d", p_iso->i_joliet_level);
memcpy(p_pvd, &svd, sizeof(iso9660_pvd_t));
}
}
}
}
return true;
}
/*! /*!
Read the Primary Volume Descriptor for of CD. Read the Primary Volume Descriptor for of CD.
*/ */
@@ -158,41 +442,54 @@ iso9660_iso_seek_read (const iso9660_t *p_iso, void *ptr, lsn_t start,
static iso9660_stat_t * static iso9660_stat_t *
_iso9660_dir_to_statbuf (const iso9660_dir_t *iso9660_dir, bool is_mode2) _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir,
bool b_mode2, uint8_t i_joliet_level)
{ {
iso9660_xa_t *xa_data = NULL; iso9660_xa_t *xa_data = NULL;
uint8_t dir_len= iso9660_get_dir_len(iso9660_dir); uint8_t dir_len= iso9660_get_dir_len(p_iso9660_dir);
unsigned int filename_len; unsigned int filename_len;
unsigned int stat_len; unsigned int stat_len;
iso9660_stat_t *stat; iso9660_stat_t *stat;
if (!dir_len) return NULL; if (!dir_len) return NULL;
filename_len = from_711(iso9660_dir->filename_len); filename_len = from_711(p_iso9660_dir->filename_len);
/* .. string in statbuf is one longer than in iso9660_dir's listing '\1' */ /* .. string in statbuf is one longer than in p_iso9660_dir's listing '\1' */
stat_len = sizeof(iso9660_stat_t)+filename_len+2; stat_len = sizeof(iso9660_stat_t)+filename_len+2;
stat = _cdio_malloc(stat_len); stat = _cdio_malloc(stat_len);
stat->type = (iso9660_dir->file_flags & ISO_DIRECTORY) stat->type = (p_iso9660_dir->file_flags & ISO_DIRECTORY)
? _STAT_DIR : _STAT_FILE; ? _STAT_DIR : _STAT_FILE;
stat->lsn = from_733 (iso9660_dir->extent); stat->lsn = from_733 (p_iso9660_dir->extent);
stat->size = from_733 (iso9660_dir->size); stat->size = from_733 (p_iso9660_dir->size);
stat->secsize = _cdio_len2blocks (stat->size, ISO_BLOCKSIZE); stat->secsize = _cdio_len2blocks (stat->size, ISO_BLOCKSIZE);
if (iso9660_dir->filename[0] == '\0') if ('\0' == p_iso9660_dir->filename[0] && 1 == filename_len)
strcpy (stat->filename, "."); strcpy (stat->filename, ".");
else if (iso9660_dir->filename[0] == '\1') else if ('\1' == p_iso9660_dir->filename[0] && 1 == filename_len)
strcpy (stat->filename, ".."); strcpy (stat->filename, "..");
else else {
strncpy (stat->filename, iso9660_dir->filename, filename_len); if (i_joliet_level) {
int i_inlen = filename_len;
int i_outlen = (i_inlen / 2);
char *p_psz_out = NULL;
ucs2be_to_locale(p_iso9660_dir->filename, i_inlen,
&p_psz_out, i_outlen);
strncpy(stat->filename, p_psz_out, filename_len);
free(p_psz_out);
} else
strncpy (stat->filename, p_iso9660_dir->filename, filename_len);
}
iso9660_get_dtime(&(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)); cdio_assert (dir_len >= sizeof (iso9660_dir_t));
if (is_mode2) { if (b_mode2) {
int su_length = iso9660_get_dir_len(iso9660_dir) - sizeof (iso9660_dir_t); int su_length = iso9660_get_dir_len(p_iso9660_dir)
- sizeof (iso9660_dir_t);
su_length -= filename_len; su_length -= filename_len;
if (su_length % 2) if (su_length % 2)
@@ -201,8 +498,8 @@ _iso9660_dir_to_statbuf (const iso9660_dir_t *iso9660_dir, bool is_mode2)
if (su_length < 0 || su_length < sizeof (iso9660_xa_t)) if (su_length < 0 || su_length < sizeof (iso9660_xa_t))
return stat; return stat;
xa_data = (void *) (((char *) iso9660_dir) xa_data = (void *) (((char *) p_iso9660_dir)
+ (iso9660_get_dir_len(iso9660_dir) - su_length)); + (iso9660_get_dir_len(p_iso9660_dir) - su_length));
if (xa_data->signature[0] != 'X' if (xa_data->signature[0] != 'X'
|| xa_data->signature[1] != 'A') || xa_data->signature[1] != 'A')
@@ -210,7 +507,7 @@ _iso9660_dir_to_statbuf (const iso9660_dir_t *iso9660_dir, bool is_mode2)
cdio_warn ("XA signature not found in ISO9660's system use area;" cdio_warn ("XA signature not found in ISO9660's system use area;"
" ignoring XA attributes for this file entry."); " ignoring XA attributes for this file entry.");
cdio_debug ("%d %d %d, '%c%c' (%d, %d)", cdio_debug ("%d %d %d, '%c%c' (%d, %d)",
iso9660_get_dir_len(iso9660_dir), iso9660_get_dir_len(p_iso9660_dir),
filename_len, filename_len,
su_length, su_length,
xa_data->signature[0], xa_data->signature[1], xa_data->signature[0], xa_data->signature[1],
@@ -254,14 +551,14 @@ iso9660_dir_to_name (const iso9660_dir_t *iso9660_dir)
Return a pointer to a ISO 9660 stat buffer or NULL if there's an error Return a pointer to a ISO 9660 stat buffer or NULL if there's an error
*/ */
static iso9660_stat_t * static iso9660_stat_t *
_fs_stat_root (const CdIo *cdio, bool is_mode2) _fs_stat_root (const CdIo *cdio, bool b_mode2)
{ {
char block[ISO_BLOCKSIZE] = { 0, }; char block[ISO_BLOCKSIZE] = { 0, };
const iso9660_pvd_t *pvd = (void *) &block; const iso9660_pvd_t *pvd = (void *) &block;
const iso9660_dir_t *iso9660_dir = (void *) pvd->root_directory_record; iso9660_dir_t *iso9660_dir = (void *) pvd->root_directory_record;
iso9660_stat_t *stat; iso9660_stat_t *stat;
if (is_mode2) { if (b_mode2) {
if (cdio_read_mode2_sector (cdio, &block, ISO_PVD_SECTOR, false)) { if (cdio_read_mode2_sector (cdio, &block, ISO_PVD_SECTOR, false)) {
cdio_warn("Could not read Primary Volume descriptor (PVD)."); cdio_warn("Could not read Primary Volume descriptor (PVD).");
return NULL; return NULL;
@@ -273,29 +570,35 @@ _fs_stat_root (const CdIo *cdio, bool is_mode2)
} }
} }
stat = _iso9660_dir_to_statbuf (iso9660_dir, is_mode2); stat = _iso9660_dir_to_statbuf (iso9660_dir, b_mode2, 0);
return stat; return stat;
} }
static iso9660_stat_t * static iso9660_stat_t *
_fs_stat_iso_root (iso9660_t *iso) _fs_stat_iso_root (iso9660_t *p_iso)
{ {
char block[ISO_BLOCKSIZE] = { 0, }; iso9660_stat_t *p_stat;
const iso9660_pvd_t *pvd = (void *) &block; #if 1
const iso9660_dir_t *iso9660_dir = (void *) pvd->root_directory_record; iso9660_dir_t *p_iso9660_dir =
iso9660_stat_t *stat; (iso9660_dir_t *) p_iso->vd.root_directory_record;
#else
int ret; int ret;
char block[ISO_BLOCKSIZE] = { 0, };
const iso9660_pvd_t *p_pvd = (void *) &block;
iso9660_dir_t *iso9660_dir = (void *) p_pvd->root_directory_record;
ret = iso9660_iso_seek_read (iso, block, ISO_PVD_SECTOR, 1); ret = iso9660_iso_seek_read (p_iso, block, ISO_PVD_SECTOR, 1);
if (ret!=ISO_BLOCKSIZE) return NULL; if (ret!=ISO_BLOCKSIZE) return NULL;
#endif
stat = _iso9660_dir_to_statbuf (iso9660_dir, true); p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, true,
return stat; p_iso->i_joliet_level);
return p_stat;
} }
static iso9660_stat_t * static iso9660_stat_t *
_fs_stat_traverse (const CdIo *cdio, const iso9660_stat_t *_root, _fs_stat_traverse (const CdIo *cdio, const iso9660_stat_t *_root,
char **splitpath, bool is_mode2, bool translate) char **splitpath, bool b_mode2, bool translate)
{ {
unsigned offset = 0; unsigned offset = 0;
uint8_t *_dirbuf = NULL; uint8_t *_dirbuf = NULL;
@@ -323,7 +626,7 @@ _fs_stat_traverse (const CdIo *cdio, const iso9660_stat_t *_root,
_dirbuf = _cdio_malloc (_root->secsize * ISO_BLOCKSIZE); _dirbuf = _cdio_malloc (_root->secsize * ISO_BLOCKSIZE);
if (is_mode2) { if (b_mode2) {
if (cdio_read_mode2_sectors (cdio, _dirbuf, _root->lsn, false, if (cdio_read_mode2_sectors (cdio, _dirbuf, _root->lsn, false,
_root->secsize)) _root->secsize))
return NULL; return NULL;
@@ -335,17 +638,17 @@ _fs_stat_traverse (const CdIo *cdio, const iso9660_stat_t *_root,
while (offset < (_root->secsize * ISO_BLOCKSIZE)) while (offset < (_root->secsize * ISO_BLOCKSIZE))
{ {
const iso9660_dir_t *iso9660_dir = (void *) &_dirbuf[offset]; iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset];
iso9660_stat_t *stat; iso9660_stat_t *stat;
int cmp; int cmp;
if (!iso9660_get_dir_len(iso9660_dir)) if (!iso9660_get_dir_len(p_iso9660_dir))
{ {
offset++; offset++;
continue; continue;
} }
stat = _iso9660_dir_to_statbuf (iso9660_dir, is_mode2); stat = _iso9660_dir_to_statbuf (p_iso9660_dir, b_mode2, 0);
if (translate) { if (translate) {
char *trans_fname = malloc(strlen(stat->filename)); char *trans_fname = malloc(strlen(stat->filename));
@@ -365,7 +668,7 @@ _fs_stat_traverse (const CdIo *cdio, const iso9660_stat_t *_root,
if (!cmp) { if (!cmp) {
iso9660_stat_t *ret_stat iso9660_stat_t *ret_stat
= _fs_stat_traverse (cdio, stat, &splitpath[1], is_mode2, = _fs_stat_traverse (cdio, stat, &splitpath[1], b_mode2,
translate); translate);
free(stat); free(stat);
free (_dirbuf); free (_dirbuf);
@@ -374,7 +677,7 @@ _fs_stat_traverse (const CdIo *cdio, const iso9660_stat_t *_root,
free(stat); free(stat);
offset += iso9660_get_dir_len(iso9660_dir); offset += iso9660_get_dir_len(p_iso9660_dir);
} }
cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE)); cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE));
@@ -385,20 +688,20 @@ _fs_stat_traverse (const CdIo *cdio, const iso9660_stat_t *_root,
} }
static iso9660_stat_t * static iso9660_stat_t *
_fs_iso_stat_traverse (iso9660_t *iso, const iso9660_stat_t *_root, _fs_iso_stat_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root,
char **splitpath, bool translate) char **splitpath, bool translate)
{ {
unsigned offset = 0; unsigned offset = 0;
uint8_t *_dirbuf = NULL; uint8_t *_dirbuf = NULL;
iso9660_stat_t *stat;
int ret; int ret;
if (!splitpath[0]) if (!splitpath[0])
{ {
iso9660_stat_t *p_stat;
unsigned int len=sizeof(iso9660_stat_t) + strlen(_root->filename)+1; unsigned int len=sizeof(iso9660_stat_t) + strlen(_root->filename)+1;
stat = _cdio_malloc(len); p_stat = _cdio_malloc(len);
memcpy(stat, _root, len); memcpy(p_stat, _root, len);
return stat; return p_stat;
} }
if (_root->type == _STAT_FILE) if (_root->type == _STAT_FILE)
@@ -415,50 +718,52 @@ _fs_iso_stat_traverse (iso9660_t *iso, const iso9660_stat_t *_root,
_dirbuf = _cdio_malloc (_root->secsize * ISO_BLOCKSIZE); _dirbuf = _cdio_malloc (_root->secsize * ISO_BLOCKSIZE);
ret = iso9660_iso_seek_read (iso, _dirbuf, _root->lsn, _root->secsize); ret = iso9660_iso_seek_read (p_iso, _dirbuf, _root->lsn, _root->secsize);
if (ret!=ISO_BLOCKSIZE*_root->secsize) return NULL; if (ret!=ISO_BLOCKSIZE*_root->secsize) return NULL;
while (offset < (_root->secsize * ISO_BLOCKSIZE)) while (offset < (_root->secsize * ISO_BLOCKSIZE))
{ {
const iso9660_dir_t *iso9660_dir = (void *) &_dirbuf[offset]; iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset];
iso9660_stat_t *stat; iso9660_stat_t *p_stat;
int cmp; int cmp;
if (!iso9660_get_dir_len(iso9660_dir)) if (!iso9660_get_dir_len(p_iso9660_dir))
{ {
offset++; offset++;
continue; continue;
} }
stat = _iso9660_dir_to_statbuf (iso9660_dir, true); p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, true,
p_iso->i_joliet_level);
if (translate) { if (translate) {
char *trans_fname = malloc(strlen(stat->filename)+1); char *trans_fname = malloc(strlen(p_stat->filename)+1);
int trans_len; int trans_len;
if (trans_fname == NULL) { if (trans_fname == NULL) {
cdio_warn("can't allocate %lu bytes", cdio_warn("can't allocate %lu bytes",
(long unsigned int) strlen(stat->filename)); (long unsigned int) strlen(p_stat->filename));
return NULL; return NULL;
} }
trans_len = iso9660_name_translate(stat->filename, trans_fname); trans_len = iso9660_name_translate_ext(p_stat->filename, trans_fname,
p_iso->i_joliet_level);
cmp = strcmp(splitpath[0], trans_fname); cmp = strcmp(splitpath[0], trans_fname);
free(trans_fname); free(trans_fname);
} else { } else {
cmp = strcmp(splitpath[0], stat->filename); cmp = strcmp(splitpath[0], p_stat->filename);
} }
if (!cmp) { if (!cmp) {
iso9660_stat_t *ret_stat iso9660_stat_t *ret_stat
= _fs_iso_stat_traverse (iso, stat, &splitpath[1], translate); = _fs_iso_stat_traverse (p_iso, p_stat, &splitpath[1], translate);
free(stat); free(p_stat);
free (_dirbuf); free (_dirbuf);
return ret_stat; return ret_stat;
} }
free(stat); free(p_stat);
offset += iso9660_get_dir_len(iso9660_dir); offset += iso9660_get_dir_len(p_iso9660_dir);
} }
cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE)); cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE));
@@ -472,7 +777,7 @@ _fs_iso_stat_traverse (iso9660_t *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 (const CdIo *cdio, const char pathname[], bool is_mode2) iso9660_fs_stat (const CdIo *cdio, const char pathname[], bool b_mode2)
{ {
iso9660_stat_t *root; iso9660_stat_t *root;
char **splitpath; char **splitpath;
@@ -481,11 +786,11 @@ iso9660_fs_stat (const CdIo *cdio, const char pathname[], bool is_mode2)
if (cdio == NULL) return NULL; if (cdio == NULL) return NULL;
if (pathname == NULL) return NULL; if (pathname == NULL) return NULL;
root = _fs_stat_root (cdio, is_mode2); root = _fs_stat_root (cdio, b_mode2);
if (NULL == root) return NULL; if (NULL == root) return NULL;
splitpath = _cdio_strsplit (pathname, '/'); splitpath = _cdio_strsplit (pathname, '/');
stat = _fs_stat_traverse (cdio, root, splitpath, is_mode2, false); stat = _fs_stat_traverse (cdio, root, splitpath, b_mode2, false);
free(root); free(root);
_cdio_strfreev (splitpath); _cdio_strfreev (splitpath);
@@ -500,7 +805,7 @@ iso9660_fs_stat (const CdIo *cdio, const char pathname[], bool is_mode2)
*/ */
iso9660_stat_t * iso9660_stat_t *
iso9660_fs_stat_translate (const CdIo *cdio, const char pathname[], iso9660_fs_stat_translate (const CdIo *cdio, const char pathname[],
bool is_mode2) bool b_mode2)
{ {
iso9660_stat_t *root; iso9660_stat_t *root;
char **splitpath; char **splitpath;
@@ -509,11 +814,11 @@ iso9660_fs_stat_translate (const CdIo *cdio, const char pathname[],
if (cdio == NULL) return NULL; if (cdio == NULL) return NULL;
if (pathname == NULL) return NULL; if (pathname == NULL) return NULL;
root = _fs_stat_root (cdio, is_mode2); root = _fs_stat_root (cdio, b_mode2);
if (NULL == root) return NULL; if (NULL == root) return NULL;
splitpath = _cdio_strsplit (pathname, '/'); splitpath = _cdio_strsplit (pathname, '/');
stat = _fs_stat_traverse (cdio, root, splitpath, is_mode2, true); stat = _fs_stat_traverse (cdio, root, splitpath, b_mode2, true);
free(root); free(root);
_cdio_strfreev (splitpath); _cdio_strfreev (splitpath);
@@ -524,22 +829,22 @@ iso9660_fs_stat_translate (const CdIo *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 *iso, const char pathname[]) iso9660_ifs_stat (iso9660_t *p_iso, const char pathname[])
{ {
iso9660_stat_t *root; iso9660_stat_t *p_root;
char **splitpath; char **splitpath;
iso9660_stat_t *stat; iso9660_stat_t *stat;
if (iso == NULL) return NULL; if (!p_iso) return NULL;
if (pathname == NULL) return NULL; if (!pathname) return NULL;
root = _fs_stat_iso_root (iso); p_root = _fs_stat_iso_root (p_iso);
if (NULL == root) return NULL; if (!p_root) return NULL;
splitpath = _cdio_strsplit (pathname, '/'); splitpath = _cdio_strsplit (pathname, '/');
stat = _fs_iso_stat_traverse (iso, root, splitpath, false); stat = _fs_iso_stat_traverse (p_iso, p_root, splitpath, false);
free(root); free(p_root);
_cdio_strfreev (splitpath); /*** FIXME _cdio_strfreev (splitpath); ***/
return stat; return stat;
} }
@@ -553,19 +858,19 @@ iso9660_ifs_stat (iso9660_t *iso, const char pathname[])
iso9660_stat_t * iso9660_stat_t *
iso9660_ifs_stat_translate (iso9660_t *iso, const char pathname[]) iso9660_ifs_stat_translate (iso9660_t *iso, const char pathname[])
{ {
iso9660_stat_t *root; iso9660_stat_t *p_root;
char **splitpath; char **splitpath;
iso9660_stat_t *stat; iso9660_stat_t *stat;
if (iso == NULL) return NULL; if (iso == NULL) return NULL;
if (pathname == NULL) return NULL; if (pathname == NULL) return NULL;
root = _fs_stat_iso_root (iso); p_root = _fs_stat_iso_root (iso);
if (NULL == root) return NULL; if (NULL == p_root) return NULL;
splitpath = _cdio_strsplit (pathname, '/'); splitpath = _cdio_strsplit (pathname, '/');
stat = _fs_iso_stat_traverse (iso, root, splitpath, true); stat = _fs_iso_stat_traverse (iso, p_root, splitpath, true);
free(root); free(p_root);
_cdio_strfreev (splitpath); _cdio_strfreev (splitpath);
return stat; return stat;
@@ -576,19 +881,18 @@ iso9660_ifs_stat_translate (iso9660_t *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 * CdioList *
iso9660_fs_readdir (const CdIo *cdio, const char pathname[], bool is_mode2) iso9660_fs_readdir (const CdIo *cdio, const char pathname[], bool b_mode2)
{ {
iso9660_stat_t *stat; iso9660_stat_t *p_stat;
if (NULL == cdio) return NULL; if (NULL == cdio) return NULL;
if (NULL == pathname) return NULL; if (NULL == pathname) return NULL;
stat = iso9660_fs_stat (cdio, pathname, is_mode2); p_stat = iso9660_fs_stat (cdio, pathname, b_mode2);
if (NULL == stat) if (!p_stat) return NULL;
return NULL;
if (stat->type != _STAT_DIR) { if (p_stat->type != _STAT_DIR) {
free(stat); free(p_stat);
return NULL; return NULL;
} }
@@ -597,46 +901,46 @@ iso9660_fs_readdir (const CdIo *cdio, const char pathname[], bool is_mode2)
uint8_t *_dirbuf = NULL; uint8_t *_dirbuf = NULL;
CdioList *retval = _cdio_list_new (); CdioList *retval = _cdio_list_new ();
if (stat->size != ISO_BLOCKSIZE * stat->secsize) if (p_stat->size != ISO_BLOCKSIZE * p_stat->secsize)
{ {
cdio_warn ("bad size for ISO9660 directory (%ud) should be (%lu)!", cdio_warn ("bad size for ISO9660 directory (%ud) should be (%lu)!",
(unsigned) stat->size, (unsigned) p_stat->size,
(unsigned long int) ISO_BLOCKSIZE * stat->secsize); (unsigned long int) ISO_BLOCKSIZE * p_stat->secsize);
} }
_dirbuf = _cdio_malloc (stat->secsize * ISO_BLOCKSIZE); _dirbuf = _cdio_malloc (p_stat->secsize * ISO_BLOCKSIZE);
if (is_mode2) { if (b_mode2) {
if (cdio_read_mode2_sectors (cdio, _dirbuf, stat->lsn, false, if (cdio_read_mode2_sectors (cdio, _dirbuf, p_stat->lsn, false,
stat->secsize)) p_stat->secsize))
cdio_assert_not_reached (); cdio_assert_not_reached ();
} else { } else {
if (cdio_read_mode1_sectors (cdio, _dirbuf, stat->lsn, false, if (cdio_read_mode1_sectors (cdio, _dirbuf, p_stat->lsn, false,
stat->secsize)) p_stat->secsize))
cdio_assert_not_reached (); cdio_assert_not_reached ();
} }
while (offset < (stat->secsize * ISO_BLOCKSIZE)) while (offset < (p_stat->secsize * ISO_BLOCKSIZE))
{ {
const iso9660_dir_t *iso9660_dir = (void *) &_dirbuf[offset]; iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset];
iso9660_stat_t *iso9660_stat; iso9660_stat_t *p_iso9660_stat;
if (!iso9660_get_dir_len(iso9660_dir)) if (!iso9660_get_dir_len(p_iso9660_dir))
{ {
offset++; offset++;
continue; continue;
} }
iso9660_stat = _iso9660_dir_to_statbuf(iso9660_dir, is_mode2); p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, b_mode2, 0);
_cdio_list_append (retval, iso9660_stat); _cdio_list_append (retval, p_iso9660_stat);
offset += iso9660_get_dir_len(iso9660_dir); offset += iso9660_get_dir_len(p_iso9660_dir);
} }
cdio_assert (offset == (stat->secsize * ISO_BLOCKSIZE)); cdio_assert (offset == (p_stat->secsize * ISO_BLOCKSIZE));
free (_dirbuf); free (_dirbuf);
free (stat); free (p_stat);
return retval; return retval;
} }
} }
@@ -646,18 +950,18 @@ iso9660_fs_readdir (const CdIo *cdio, const char pathname[], bool is_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 * CdioList *
iso9660_ifs_readdir (iso9660_t *iso, const char pathname[]) iso9660_ifs_readdir (iso9660_t *p_iso, const char pathname[])
{ {
iso9660_stat_t *stat; iso9660_stat_t *p_stat;
if (NULL == iso) return NULL; if (!p_iso) return NULL;
if (NULL == pathname) return NULL; if (!pathname) return NULL;
stat = iso9660_ifs_stat (iso, pathname); p_stat = iso9660_ifs_stat (p_iso, pathname);
if (NULL == stat) return NULL; if (!p_stat) return NULL;
if (stat->type != _STAT_DIR) { if (p_stat->type != _STAT_DIR) {
free(stat); free(p_stat);
return NULL; return NULL;
} }
@@ -667,39 +971,40 @@ iso9660_ifs_readdir (iso9660_t *iso, const char pathname[])
uint8_t *_dirbuf = NULL; uint8_t *_dirbuf = NULL;
CdioList *retval = _cdio_list_new (); CdioList *retval = _cdio_list_new ();
if (stat->size != ISO_BLOCKSIZE * stat->secsize) if (p_stat->size != ISO_BLOCKSIZE * p_stat->secsize)
{ {
cdio_warn ("bad size for ISO9660 directory (%ud) should be (%lu)!", cdio_warn ("bad size for ISO9660 directory (%ud) should be (%lu)!",
(unsigned) stat->size, (unsigned int) p_stat->size,
(unsigned long int) ISO_BLOCKSIZE * stat->secsize); (unsigned long int) ISO_BLOCKSIZE * p_stat->secsize);
} }
_dirbuf = _cdio_malloc (stat->secsize * ISO_BLOCKSIZE); _dirbuf = _cdio_malloc (p_stat->secsize * ISO_BLOCKSIZE);
ret = iso9660_iso_seek_read (iso, _dirbuf, stat->lsn, stat->secsize); ret = iso9660_iso_seek_read (p_iso, _dirbuf, p_stat->lsn, p_stat->secsize);
if (ret != ISO_BLOCKSIZE*stat->secsize) return NULL; if (ret != ISO_BLOCKSIZE*p_stat->secsize) return NULL;
while (offset < (stat->secsize * ISO_BLOCKSIZE)) while (offset < (p_stat->secsize * ISO_BLOCKSIZE))
{ {
const iso9660_dir_t *iso9660_dir = (void *) &_dirbuf[offset]; iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset];
iso9660_stat_t *iso9660_stat; iso9660_stat_t *p_iso9660_stat;
if (!iso9660_get_dir_len(iso9660_dir)) if (!iso9660_get_dir_len(p_iso9660_dir))
{ {
offset++; offset++;
continue; continue;
} }
iso9660_stat = _iso9660_dir_to_statbuf(iso9660_dir, true); p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, true,
_cdio_list_append (retval, iso9660_stat); p_iso->i_joliet_level);
_cdio_list_append (retval, p_iso9660_stat);
offset += iso9660_get_dir_len(iso9660_dir); offset += iso9660_get_dir_len(p_iso9660_dir);
} }
cdio_assert (offset == (stat->secsize * ISO_BLOCKSIZE)); cdio_assert (offset == (p_stat->secsize * ISO_BLOCKSIZE));
free (_dirbuf); free (_dirbuf);
free (stat); free (p_stat);
return retval; return retval;
} }
} }
@@ -781,5 +1086,3 @@ iso9660_ifs_is_xa (const iso9660_t * p_iso)
if (!p_iso) return false; if (!p_iso) return false;
return p_iso->b_xa; return p_iso->b_xa;
} }

View File

@@ -1,5 +1,5 @@
/* /*
$Id: iso-info.c,v 1.12 2004/10/22 09:51:40 rocky Exp $ $Id: iso-info.c,v 1.13 2004/10/23 20:55:09 rocky Exp $
Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> Copyright (C) 2004 Rocky Bernstein <rocky@panix.com>
@@ -157,6 +157,7 @@ print_iso9660_recurse (iso9660_t *p_iso, const char pathname[])
CdioList *entlist; CdioList *entlist;
CdioList *dirlist = _cdio_list_new (); CdioList *dirlist = _cdio_list_new ();
CdioListNode *entnode; CdioListNode *entnode;
uint8_t i_joliet_level = iso9660_ifs_get_joliet_level(p_iso);
entlist = iso9660_ifs_readdir (p_iso, pathname); entlist = iso9660_ifs_readdir (p_iso, pathname);
@@ -178,7 +179,7 @@ print_iso9660_recurse (iso9660_t *p_iso, const char pathname[])
#define DATESTR_SIZE 30 #define DATESTR_SIZE 30
char date_str[DATESTR_SIZE]; char date_str[DATESTR_SIZE];
iso9660_name_translate(iso_name, translated_name); iso9660_name_translate_ext(iso_name, translated_name, i_joliet_level);
snprintf (_fullname, sizeof (_fullname), "%s%s", pathname, snprintf (_fullname, sizeof (_fullname), "%s%s", pathname,
iso_name); iso_name);
@@ -249,6 +250,13 @@ init(void)
opts.print_iso9660 = 0; opts.print_iso9660 = 0;
} }
#define print_vd_info(title, fn) \
if (fn(p_iso, &psz_str)) { \
printf(title ": %s\n", psz_str); \
free(psz_str); \
psz_str = NULL; \
}
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
int int
@@ -275,7 +283,7 @@ main(int argc, const char *argv[])
err_exit("No input device given/found\n"); err_exit("No input device given/found\n");
} }
p_iso = iso9660_open (source_name); p_iso = iso9660_open_ext (source_name, ISO_EXTENSION_ALL);
if (p_iso==NULL) { if (p_iso==NULL) {
free(source_name); free(source_name);
@@ -283,18 +291,15 @@ main(int argc, const char *argv[])
} }
if (opts.silent == 0) { if (opts.silent == 0) {
iso9660_pvd_t pvd; char *psz_str = NULL;
printf(STRONG "ISO 9660 image: %s\n", source_name); printf(STRONG "ISO 9660 image: %s\n", source_name);
print_vd_info("Application", iso9660_ifs_get_application_id);
if (iso9660_ifs_read_pvd(p_iso, &pvd)) { print_vd_info("Preparer ", iso9660_ifs_get_preparer_id);
printf("Application: %s\n", iso9660_get_application_id(&pvd)); print_vd_info("Publisher ", iso9660_ifs_get_publisher_id);
printf("Preparer : %s\n", iso9660_get_preparer_id(&pvd)); print_vd_info("System ", iso9660_ifs_get_system_id);
printf("Publisher : %s\n", iso9660_get_publisher_id(&pvd)); print_vd_info("Volume ", iso9660_ifs_get_volume_id);
printf("System : %s\n", iso9660_get_system_id(&pvd)); print_vd_info("Volume Set ", iso9660_ifs_get_volumeset_id);
printf("Volume : %s\n", iso9660_get_volume_id(&pvd));
printf("Volume Set : %s\n", iso9660_get_volumeset_id(&pvd));
}
} }
if (!opts.no_analysis) { if (!opts.no_analysis) {

View File

@@ -1,5 +1,5 @@
/* /*
$Id: testbincue.c,v 1.3 2004/09/05 13:03:46 rocky Exp $ $Id: testbincue.c,v 1.4 2004/10/23 20:55:09 rocky Exp $
Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> Copyright (C) 2004 Rocky Bernstein <rocky@panix.com>
@@ -79,7 +79,6 @@ main(int argc, const char *argv[])
printf("Correct: %s parses as a CDRWin CUE file.\n", printf("Correct: %s parses as a CDRWin CUE file.\n",
cue_file[i]); cue_file[i]);
} }
free(psz_cuefile);
} }
for (i=0; i<NUM_BAD_CUES; i++) { for (i=0; i<NUM_BAD_CUES; i++) {
@@ -89,12 +88,10 @@ main(int argc, const char *argv[])
if (!cdio_is_cuefile(psz_cuefile)) { if (!cdio_is_cuefile(psz_cuefile)) {
printf("Correct: %s doesn't parse as a CDRWin CUE file.\n", printf("Correct: %s doesn't parse as a CDRWin CUE file.\n",
badcue_file[i]); badcue_file[i]);
free(psz_cuefile);
} else { } else {
printf("Incorrect: %s parses as a CDRWin CUE file.\n", printf("Incorrect: %s parses as a CDRWin CUE file.\n",
badcue_file[i]); badcue_file[i]);
ret+=50*i+1; ret+=50*i+1;
free(psz_cuefile);
break; break;
} }
} }