diff --git a/include/cdio/cdio.h b/include/cdio/cdio.h index 49617f4e..1729f862 100644 --- a/include/cdio/cdio.h +++ b/include/cdio/cdio.h @@ -1,5 +1,5 @@ /* -*- c -*- - $Id: cdio.h,v 1.17 2003/08/31 14:26:06 rocky Exp $ + $Id: cdio.h,v 1.18 2003/09/05 22:48:16 rocky Exp $ Copyright (C) 2001 Herbert Valerio Riedel Copyright (C) 2003 Rocky Bernstein @@ -203,47 +203,49 @@ extern "C" { Returns (off_t) -1 on error. Similar to (if not the same as) libc's lseek() */ - off_t cdio_lseek(CdIo *obj, off_t offset, int whence); + off_t cdio_lseek(const CdIo *obj, off_t offset, int whence); /*! Reads into buf the next size bytes. Returns -1 on error. Similar to (if not the same as) libc's read() */ - ssize_t cdio_read(CdIo *obj, void *buf, size_t size); + ssize_t cdio_read(const CdIo *obj, void *buf, size_t size); /*! Reads a audio sector from cd device into data starting from lsn. Returns 0 if no error. */ - int cdio_read_audio_sector (CdIo *obj, void *buf, lsn_t lsn); + int cdio_read_audio_sector (const CdIo *obj, void *buf, lsn_t lsn); /*! Reads a single mode1 sector from cd device into data starting from lsn. Returns 0 if no error. */ - int cdio_read_mode1_sector (CdIo *obj, void *buf, lsn_t lsn, bool is_form2); + int cdio_read_mode1_sector (const CdIo *obj, void *buf, lsn_t lsn, + bool is_form2); /*! Reads nblocks of mode1 sectors from cd device into data starting from lsn. Returns 0 if no error. */ - int cdio_read_mode1_sectors (CdIo *obj, void *buf, lsn_t lsn, bool is_form2, - unsigned int num_sectors); + int cdio_read_mode1_sectors (const CdIo *obj, void *buf, lsn_t lsn, + bool is_form2, unsigned int num_sectors); /*! Reads a single mode2 sector from cd device into data starting from lsn. Returns 0 if no error. */ - int cdio_read_mode2_sector (CdIo *obj, void *buf, lsn_t lsn, bool is_form2); + int cdio_read_mode2_sector (const CdIo *obj, void *buf, lsn_t lsn, + bool is_form2); /*! Reads nblocks of mode2 sectors from cd device into data starting from lsn. Returns 0 if no error. */ - int cdio_read_mode2_sectors (CdIo *obj, void *buf, lsn_t lsn, bool is_form2, - unsigned int num_sectors); + int cdio_read_mode2_sectors (const CdIo *obj, void *buf, lsn_t lsn, + bool is_form2, unsigned int num_sectors); /*! Set the arg "key" with "value" in the source device. @@ -253,7 +255,7 @@ extern "C" { /*! Return the size of the CD in logical block address (LBA) units. */ - uint32_t cdio_stat_size (CdIo *obj); + uint32_t cdio_stat_size (const CdIo *obj); /*! Initialize CD Reading and control routines. Should be called first. diff --git a/include/cdio/iso9660.h b/include/cdio/iso9660.h index 9ef50585..c2cc3eb0 100644 --- a/include/cdio/iso9660.h +++ b/include/cdio/iso9660.h @@ -1,5 +1,5 @@ /* - $Id: iso9660.h,v 1.16 2003/09/01 16:02:13 rocky Exp $ + $Id: iso9660.h,v 1.17 2003/09/05 22:48:16 rocky Exp $ Copyright (C) 2000 Herbert Valerio Riedel Copyright (C) 2003 Rocky Bernstein @@ -257,12 +257,22 @@ iso9660_dir_add_entry_su (void *dir, const char name[], uint32_t extent, unsigned int iso9660_dir_calc_record_size (unsigned int namelen, unsigned int su_len); +/*! + Given a directory pointer, find the filesystem entry that contains + lsn and return information about it in stat. + + Returns true if we found an entry with the lsn and false if not. + */ +bool +iso9660_find_fs_lsn(const CdIo *cdio, lsn_t lsn, /*out*/ iso9660_stat_t *stat); + + int -iso9660_fs_stat (CdIo *obj,const char pathname[], iso9660_stat_t *buf, +iso9660_fs_stat (const CdIo *obj, const char pathname[], iso9660_stat_t *buf, bool is_mode2); void * /* list of char* -- caller must free it */ -iso9660_fs_readdir (CdIo *obj, const char pathname[], bool mode2); +iso9660_fs_readdir (const CdIo *obj, const char pathname[], bool mode2); uint8_t iso9660_get_dir_len(const iso9660_dir_t *idr); diff --git a/lib/cdio.c b/lib/cdio.c index b5d974f3..a8dde6c6 100644 --- a/lib/cdio.c +++ b/lib/cdio.c @@ -1,5 +1,5 @@ /* - $Id: cdio.c,v 1.22 2003/08/31 14:26:06 rocky Exp $ + $Id: cdio.c,v 1.23 2003/09/05 22:48:16 rocky Exp $ Copyright (C) 2003 Rocky Bernstein Copyright (C) 2001 Herbert Valerio Riedel @@ -35,7 +35,7 @@ #include #include "cdio_private.h" -static const char _rcsid[] = "$Id: cdio.c,v 1.22 2003/08/31 14:26:06 rocky Exp $"; +static const char _rcsid[] = "$Id: cdio.c,v 1.23 2003/09/05 22:48:16 rocky Exp $"; const char *track_format2str[6] = @@ -459,7 +459,7 @@ cdio_destroy (CdIo *obj) Similar to (if not the same as) libc's lseek() */ off_t -cdio_lseek (CdIo *obj, off_t offset, int whence) +cdio_lseek (const CdIo *obj, off_t offset, int whence) { if (obj == NULL) return -1; @@ -474,7 +474,7 @@ cdio_lseek (CdIo *obj, off_t offset, int whence) Similar to (if not the same as) libc's read() */ ssize_t -cdio_read (CdIo *obj, void *buf, size_t size) +cdio_read (const CdIo *obj, void *buf, size_t size) { if (obj == NULL) return -1; @@ -484,7 +484,7 @@ cdio_read (CdIo *obj, void *buf, size_t size) } int -cdio_read_audio_sector (CdIo *obj, void *buf, lsn_t lsn) +cdio_read_audio_sector (const CdIo *obj, void *buf, lsn_t lsn) { cdio_assert (obj != NULL); cdio_assert (buf != NULL); @@ -499,7 +499,7 @@ cdio_read_audio_sector (CdIo *obj, void *buf, lsn_t lsn) into data starting from lsn. Returns 0 if no error. */ int -cdio_read_mode1_sector (CdIo *obj, void *data, lsn_t lsn, bool is_form2) +cdio_read_mode1_sector (const CdIo *obj, void *data, lsn_t lsn, bool is_form2) { uint32_t size = is_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE ; char buf[M2RAW_SECTOR_SIZE] = { 0, }; @@ -525,8 +525,8 @@ cdio_read_mode1_sector (CdIo *obj, void *data, lsn_t lsn, bool is_form2) } int -cdio_read_mode1_sectors (CdIo *obj, void *data, lsn_t lsn, bool is_form2, - unsigned int num_sectors) +cdio_read_mode1_sectors (const CdIo *obj, void *data, lsn_t lsn, + bool is_form2, unsigned int num_sectors) { uint32_t size = is_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE ; int retval; @@ -548,7 +548,8 @@ cdio_read_mode1_sectors (CdIo *obj, void *data, lsn_t lsn, bool is_form2, from lsn. Returns 0 if no error. */ int -cdio_read_mode2_sector (CdIo *obj, void *buf, uint32_t lsn, bool is_form2) +cdio_read_mode2_sector (const CdIo *obj, void *buf, lsn_t lsn, + bool is_form2) { cdio_assert (obj != NULL); cdio_assert (buf != NULL); @@ -565,7 +566,7 @@ cdio_read_mode2_sector (CdIo *obj, void *buf, uint32_t lsn, bool is_form2) } int -cdio_read_mode2_sectors (CdIo *obj, void *buf, lsn_t lsn, bool mode2raw, +cdio_read_mode2_sectors (const CdIo *obj, void *buf, lsn_t lsn, bool mode2raw, unsigned num_sectors) { cdio_assert (obj != NULL); @@ -577,7 +578,7 @@ cdio_read_mode2_sectors (CdIo *obj, void *buf, lsn_t lsn, bool mode2raw, } uint32_t -cdio_stat_size (CdIo *obj) +cdio_stat_size (const CdIo *obj) { cdio_assert (obj != NULL); diff --git a/lib/iso9660_fs.c b/lib/iso9660_fs.c index f521185c..f7d8174f 100644 --- a/lib/iso9660_fs.c +++ b/lib/iso9660_fs.c @@ -1,5 +1,5 @@ /* - $Id: iso9660_fs.c,v 1.5 2003/08/31 15:52:56 rocky Exp $ + $Id: iso9660_fs.c,v 1.6 2003/09/05 22:48:16 rocky Exp $ Copyright (C) 2001 Herbert Valerio Riedel Copyright (C) 2003 Rocky Bernstein @@ -36,7 +36,9 @@ #include "bytesex.h" #include "ds.h" -static const char _rcsid[] = "$Id: iso9660_fs.c,v 1.5 2003/08/31 15:52:56 rocky Exp $"; +#include + +static const char _rcsid[] = "$Id: iso9660_fs.c,v 1.6 2003/09/05 22:48:16 rocky Exp $"; static void _idr2statbuf (const iso9660_dir_t *idr, iso9660_stat_t *buf, bool is_mode2) @@ -108,17 +110,17 @@ _idr2name (const iso9660_dir_t *idr) static void -_fs_stat_root (CdIo *obj, iso9660_stat_t *buf, bool is_mode2) +_fs_stat_root (const CdIo *cdio, iso9660_stat_t *buf, bool is_mode2) { char block[ISO_BLOCKSIZE] = { 0, }; const iso9660_pvd_t *pvd = (void *) █ const iso9660_dir_t *idr = (void *) pvd->root_directory_record; if (is_mode2) { - if (cdio_read_mode2_sector (obj, &block, ISO_PVD_SECTOR, false)) + if (cdio_read_mode2_sector (cdio, &block, ISO_PVD_SECTOR, false)) cdio_assert_not_reached (); } else { - if (cdio_read_mode1_sector (obj, &block, ISO_PVD_SECTOR, false)) + if (cdio_read_mode1_sector (cdio, &block, ISO_PVD_SECTOR, false)) cdio_assert_not_reached (); } @@ -126,8 +128,8 @@ _fs_stat_root (CdIo *obj, iso9660_stat_t *buf, bool is_mode2) } static int -_fs_stat_traverse (CdIo *obj, const iso9660_stat_t *_root, char **splitpath, - iso9660_stat_t *buf, bool is_mode2) +_fs_stat_traverse (const CdIo *cdio, const iso9660_stat_t *_root, + char **splitpath, iso9660_stat_t *buf, bool is_mode2) { unsigned offset = 0; uint8_t *_dirbuf = NULL; @@ -152,11 +154,11 @@ _fs_stat_traverse (CdIo *obj, const iso9660_stat_t *_root, char **splitpath, _dirbuf = _cdio_malloc (_root->secsize * ISO_BLOCKSIZE); if (is_mode2) { - if (cdio_read_mode2_sectors (obj, _dirbuf, _root->lsn, false, + if (cdio_read_mode2_sectors (cdio, _dirbuf, _root->lsn, false, _root->secsize)) cdio_assert_not_reached (); } else { - if (cdio_read_mode1_sectors (obj, _dirbuf, _root->lsn, false, + if (cdio_read_mode1_sectors (cdio, _dirbuf, _root->lsn, false, _root->secsize)) cdio_assert_not_reached (); } @@ -180,7 +182,7 @@ _fs_stat_traverse (CdIo *obj, const iso9660_stat_t *_root, char **splitpath, if (!strcmp (splitpath[0], _name)) { - int retval = _fs_stat_traverse (obj, &_stat, &splitpath[1], buf, + int retval = _fs_stat_traverse (cdio, &_stat, &splitpath[1], buf, is_mode2); free (_name); free (_dirbuf); @@ -200,35 +202,35 @@ _fs_stat_traverse (CdIo *obj, const iso9660_stat_t *_root, char **splitpath, } int -iso9660_fs_stat (CdIo *obj, const char pathname[], iso9660_stat_t *buf, +iso9660_fs_stat (const CdIo *cdio, const char pathname[], iso9660_stat_t *buf, bool is_mode2) { iso9660_stat_t _root; int retval; char **splitpath; - cdio_assert (obj != NULL); + cdio_assert (cdio != NULL); cdio_assert (pathname != NULL); cdio_assert (buf != NULL); - _fs_stat_root (obj, &_root, is_mode2); + _fs_stat_root (cdio, &_root, is_mode2); splitpath = _cdio_strsplit (pathname, '/'); - retval = _fs_stat_traverse (obj, &_root, splitpath, buf, is_mode2); + retval = _fs_stat_traverse (cdio, &_root, splitpath, buf, is_mode2); _cdio_strfreev (splitpath); return retval; } void * /* list of char* -- caller must free it */ -iso9660_fs_readdir (CdIo *obj, const char pathname[], bool is_mode2) +iso9660_fs_readdir (const CdIo *cdio, const char pathname[], bool is_mode2) { iso9660_stat_t _stat; - cdio_assert (obj != NULL); + cdio_assert (cdio != NULL); cdio_assert (pathname != NULL); - if (iso9660_fs_stat (obj, pathname, &_stat, is_mode2)) + if (iso9660_fs_stat (cdio, pathname, &_stat, is_mode2)) return NULL; if (_stat.type != _STAT_DIR) @@ -248,11 +250,11 @@ iso9660_fs_readdir (CdIo *obj, const char pathname[], bool is_mode2) _dirbuf = _cdio_malloc (_stat.secsize * ISO_BLOCKSIZE); if (is_mode2) { - if (cdio_read_mode2_sectors (obj, _dirbuf, _stat.lsn, false, + if (cdio_read_mode2_sectors (cdio, _dirbuf, _stat.lsn, false, _stat.secsize)) cdio_assert_not_reached (); } else { - if (cdio_read_mode1_sectors (obj, _dirbuf, _stat.lsn, false, + if (cdio_read_mode1_sectors (cdio, _dirbuf, _stat.lsn, false, _stat.secsize)) cdio_assert_not_reached (); } @@ -279,3 +281,70 @@ iso9660_fs_readdir (CdIo *obj, const char pathname[], bool is_mode2) } } +static bool +find_fs_lsn_recurse (const CdIo *cdio, const char pathname[], + /*out*/ iso9660_stat_t *statbuf, lsn_t lsn) +{ + CdioList *entlist = iso9660_fs_readdir (cdio, pathname, true); + CdioList *dirlist = _cdio_list_new (); + CdioListNode *entnode; + + cdio_assert (entlist != NULL); + + /* iterate over each entry in the directory */ + + _CDIO_LIST_FOREACH (entnode, entlist) + { + char *_name = _cdio_list_node_data (entnode); + char _fullname[4096] = { 0, }; + + snprintf (_fullname, sizeof (_fullname), "%s%s", pathname, _name); + + if (iso9660_fs_stat (cdio, _fullname, statbuf, true)) + cdio_assert_not_reached (); + + strncat (_fullname, "/", sizeof (_fullname)); + + if (statbuf->type == _STAT_DIR + && strcmp (_name, ".") + && strcmp (_name, "..")) + _cdio_list_append (dirlist, strdup (_fullname)); + + if (statbuf->lsn == lsn) { + _cdio_list_free (entlist, true); + _cdio_list_free (dirlist, true); + return true; + } + + } + + _cdio_list_free (entlist, true); + + /* now recurse/descend over directories encountered */ + + _CDIO_LIST_FOREACH (entnode, dirlist) + { + char *_fullname = _cdio_list_node_data (entnode); + + if (find_fs_lsn_recurse (cdio, _fullname, statbuf, lsn)) { + _cdio_list_free (dirlist, true); + return true; + } + } + + _cdio_list_free (dirlist, true); + return false; +} + +/*! + Given a directory pointer, find the filesystem entry that contains + lsn and return information about it in stat. + + Returns true if we found an entry with the lsn and false if not. + */ +bool +iso9660_find_fs_lsn(const CdIo *cdio, lsn_t lsn, /*out*/ iso9660_stat_t *stat) +{ + return find_fs_lsn_recurse (cdio, "/", stat, lsn); +} +