iso9600_stat now has filename inside it.

iso9660_fs_readdir now returns a list of iso9660_stat_t's rather than
filenames.

This should reduce by a small amount the number of CD reads since we store
more information in the iso9660_fs_readdir return.

However all of this is in preparation for greatly reducing the number of
CD reads when picking out segment lsn information.
This commit is contained in:
rocky
2003-11-16 19:30:45 +00:00
parent 734ebfdebd
commit ff736f6bae
4 changed files with 154 additions and 116 deletions

View File

@@ -1,3 +1,22 @@
# $Id: Makefile.am,v 1.3 2003/11/16 19:30:45 rocky Exp $
#
# Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
#
# 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
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
EXTRA_DIST = doxygen/Doxyfile doxygen/run_doxygen
info_TEXINFOS = libcdio.texi
pdf: libcdio.pdf

View File

@@ -1,5 +1,5 @@
/*
$Id: iso9660.h,v 1.30 2003/11/10 04:01:16 rocky Exp $
$Id: iso9660.h,v 1.31 2003/11/16 19:30:45 rocky Exp $
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
@@ -194,7 +194,8 @@ typedef struct iso9660_stat iso9660_stat_t;
#endif
/*
* XXX JS: The next structure may have an odd length!
* XXX JS: The next structure may have an odd length depending on how
* many characters there are in the filename!
* Some compilers (e.g. on Sun3/mc68020) padd the structures to even length.
* For this reason, we cannot use sizeof (struct iso_path_table) or
* sizeof (struct iso_directory_record) to compute on disk sizes.
@@ -229,7 +230,8 @@ struct iso9660_stat { /* big endian!! */
uint32_t secsize; /**< number of sectors allocated */
iso9660_xa_t xa; /**< XA attributes */
struct tm tm; /**< time on entry */
} ;
char filename[EMPTY_ARRAY_SIZE]; /**< filename */
} GNUC_PACKED;
PRAGMA_END_PACKED
@@ -367,22 +369,22 @@ 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.
lsn and return information about it.
Returns true if we found an entry with the lsn and false if not.
Returns stat_t of entry if we found lsn, or NULL otherwise.
*/
bool iso9660_find_fs_lsn(const CdIo *cdio, lsn_t lsn,
/*out*/ iso9660_stat_t *stat);
iso9660_stat_t *iso9660_find_fs_lsn(const CdIo *cdio, lsn_t lsn);
/*!
Get file status for pathname into stat. As with libc's stat, 0 is returned
if no error and -1 on error.
Get file status for pathname into stat. NULL is returned on error.
*/
int iso9660_fs_stat (const CdIo *obj, const char pathname[],
/*out*/ iso9660_stat_t *stat, bool is_mode2);
iso9660_stat_t *iso9660_fs_stat (const CdIo *obj, const char pathname[],
bool is_mode2);
/*! Read pathname (a directory) and return a list of of the files
inside that (char *). The caller must free the returned result.
/*!
Read pathname (a directory) and return a list of iso9660_stat_t
of the files inside that. The caller must free the returned result.
*/
void * iso9660_fs_readdir (const CdIo *obj, const char pathname[], bool mode2);

View File

@@ -1,5 +1,5 @@
/*
$Id: iso9660_fs.c,v 1.12 2003/11/10 04:01:16 rocky Exp $
$Id: iso9660_fs.c,v 1.13 2003/11/16 19:30:45 rocky Exp $
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
@@ -38,38 +38,51 @@
#include <stdio.h>
static const char _rcsid[] = "$Id: iso9660_fs.c,v 1.12 2003/11/10 04:01:16 rocky Exp $";
static const char _rcsid[] = "$Id: iso9660_fs.c,v 1.13 2003/11/16 19:30:45 rocky Exp $";
static void
_iso9660_dir_to_statbuf (const iso9660_dir_t *iso9660_dir,
iso9660_stat_t *stat, bool is_mode2)
static iso9660_stat_t *
_iso9660_dir_to_statbuf (const iso9660_dir_t *iso9660_dir, bool is_mode2)
{
iso9660_xa_t *xa_data = NULL;
uint8_t dir_len= iso9660_get_dir_len(iso9660_dir);
unsigned int filename_len;
unsigned int stat_len;
iso9660_stat_t *stat;
memset ((void *) stat, 0, sizeof (iso9660_stat_t));
if (!dir_len) return NULL;
if (!dir_len) return;
filename_len = from_711(iso9660_dir->filename_len);
/* .. string in statbuf is one longer than in iso9660_dir's listing '\1' */
stat_len = sizeof(iso9660_stat_t)+filename_len+2;
stat = _cdio_malloc(stat_len);
stat->type = (iso9660_dir->file_flags & ISO_DIRECTORY)
? _STAT_DIR : _STAT_FILE;
stat->lsn = from_733 (iso9660_dir->extent);
stat->size = from_733 (iso9660_dir->size);
stat->secsize = _cdio_len2blocks (stat->size, ISO_BLOCKSIZE);
if (iso9660_dir->filename[0] == '\0')
strcpy (stat->filename, ".");
else if (iso9660_dir->filename[0] == '\1')
strcpy (stat->filename, "..");
else
strncpy (stat->filename, iso9660_dir->filename, filename_len);
iso9660_get_dtime(&(iso9660_dir->recording_time), true, &(stat->tm));
cdio_assert (dir_len >= sizeof (iso9660_dir_t));
if (is_mode2) {
int su_length = iso9660_get_dir_len(iso9660_dir) - sizeof (iso9660_dir_t);
su_length -= iso9660_dir->filename_len;
su_length -= filename_len;
if (su_length % 2)
su_length--;
if (su_length < 0 || su_length < sizeof (iso9660_xa_t))
return;
return stat;
xa_data = (void *) (((char *) iso9660_dir)
+ (iso9660_get_dir_len(iso9660_dir) - su_length));
@@ -81,14 +94,15 @@ _iso9660_dir_to_statbuf (const iso9660_dir_t *iso9660_dir,
" ignoring XA attributes for this file entry.");
cdio_debug ("%d %d %d, '%c%c' (%d, %d)",
iso9660_get_dir_len(iso9660_dir),
iso9660_dir->filename_len,
filename_len,
su_length,
xa_data->signature[0], xa_data->signature[1],
xa_data->signature[0], xa_data->signature[1]);
return;
return stat;
}
stat->xa = *xa_data;
}
return stat;
}
@@ -120,12 +134,13 @@ iso9660_dir_to_name (const iso9660_dir_t *iso9660_dir)
}
static void
_fs_stat_root (const CdIo *cdio, iso9660_stat_t *stat, bool is_mode2)
static iso9660_stat_t *
_fs_stat_root (const CdIo *cdio, bool is_mode2)
{
char block[ISO_BLOCKSIZE] = { 0, };
const iso9660_pvd_t *pvd = (void *) &block;
const iso9660_dir_t *iso9660_dir = (void *) pvd->root_directory_record;
iso9660_stat_t *stat;
if (is_mode2) {
if (cdio_read_mode2_sector (cdio, &block, ISO_PVD_SECTOR, false))
@@ -135,25 +150,28 @@ _fs_stat_root (const CdIo *cdio, iso9660_stat_t *stat, bool is_mode2)
cdio_assert_not_reached ();
}
_iso9660_dir_to_statbuf (iso9660_dir, stat, is_mode2);
stat = _iso9660_dir_to_statbuf (iso9660_dir, is_mode2);
return stat;
}
static int
static iso9660_stat_t *
_fs_stat_traverse (const CdIo *cdio, const iso9660_stat_t *_root,
char **splitpath, /*out*/ iso9660_stat_t *buf,
bool is_mode2)
char **splitpath, bool is_mode2)
{
unsigned offset = 0;
uint8_t *_dirbuf = NULL;
iso9660_stat_t *stat;
if (!splitpath[0])
{
*buf = *_root;
return 0;
unsigned int len=sizeof(iso9660_stat_t) + strlen(_root->filename)+1;
stat = _cdio_malloc(len);
memcpy(stat, _root, len);
return stat;
}
if (_root->type == _STAT_FILE)
return -1;
return NULL;
cdio_assert (_root->type == _STAT_DIR);
@@ -179,8 +197,7 @@ _fs_stat_traverse (const CdIo *cdio, const iso9660_stat_t *_root,
while (offset < (_root->secsize * ISO_BLOCKSIZE))
{
const iso9660_dir_t *iso9660_dir = (void *) &_dirbuf[offset];
iso9660_stat_t stat;
char *name;
iso9660_stat_t *stat;
if (!iso9660_get_dir_len(iso9660_dir))
{
@@ -188,20 +205,19 @@ _fs_stat_traverse (const CdIo *cdio, const iso9660_stat_t *_root,
continue;
}
name = iso9660_dir_to_name (iso9660_dir);
_iso9660_dir_to_statbuf (iso9660_dir, &stat, is_mode2);
stat = _iso9660_dir_to_statbuf (iso9660_dir, is_mode2);
if (!strcmp (splitpath[0], name))
if (!strcmp (splitpath[0], stat->filename))
{
int retval = _fs_stat_traverse (cdio, &stat, &splitpath[1], buf,
is_mode2);
free (name);
iso9660_stat_t *ret_stat
= _fs_stat_traverse (cdio, stat, &splitpath[1], is_mode2);
free(stat);
free (_dirbuf);
return retval;
return ret_stat;
}
free (name);
free(stat);
offset += iso9660_get_dir_len(iso9660_dir);
}
@@ -209,101 +225,106 @@ _fs_stat_traverse (const CdIo *cdio, const iso9660_stat_t *_root,
/* not found */
free (_dirbuf);
return -1;
return NULL;
}
/*!
Get file status for pathname into stat. As with libc's stat, 0 is returned
if no error and -1 on error.
Get file status for pathname into stat. NULL is returned on error.
*/
int
iso9660_fs_stat (const CdIo *cdio, const char pathname[],
/*out*/ iso9660_stat_t *stat, bool is_mode2)
iso9660_stat_t *
iso9660_fs_stat (const CdIo *cdio, const char pathname[], bool is_mode2)
{
iso9660_stat_t _root;
int retval;
iso9660_stat_t *root;
char **splitpath;
iso9660_stat_t *stat;
cdio_assert (cdio != NULL);
cdio_assert (pathname != NULL);
cdio_assert (stat != NULL);
_fs_stat_root (cdio, &_root, is_mode2);
root = _fs_stat_root (cdio, is_mode2);
if (NULL == root) return NULL;
splitpath = _cdio_strsplit (pathname, '/');
retval = _fs_stat_traverse (cdio, &_root, splitpath, stat, is_mode2);
stat = _fs_stat_traverse (cdio, root, splitpath, is_mode2);
free(root);
_cdio_strfreev (splitpath);
return retval;
return stat;
}
/*! Read pathname (a directory) and return a list of of the files
inside that (char *). The caller must free the returned result.
/*!
Read pathname (a directory) and return a list of iso9660_stat_t
of the files inside that. The caller must free the returned result.
*/
void *
iso9660_fs_readdir (const CdIo *cdio, const char pathname[], bool is_mode2)
{
iso9660_stat_t stat;
iso9660_stat_t *stat;
cdio_assert (cdio != NULL);
cdio_assert (pathname != NULL);
if (iso9660_fs_stat (cdio, pathname, &stat, is_mode2))
stat = iso9660_fs_stat (cdio, pathname, is_mode2);
if (NULL == stat)
return NULL;
if (stat.type != _STAT_DIR)
if (stat->type != _STAT_DIR) {
free(stat);
return NULL;
}
{
unsigned offset = 0;
uint8_t *_dirbuf = NULL;
CdioList *retval = _cdio_list_new ();
if (stat.size != ISO_BLOCKSIZE * stat.secsize)
if (stat->size != ISO_BLOCKSIZE * stat->secsize)
{
cdio_warn ("bad size for ISO9660 directory (%ud) should be (%lu)!",
(unsigned) stat.size,
(unsigned long int) ISO_BLOCKSIZE * stat.secsize);
(unsigned) stat->size,
(unsigned long int) ISO_BLOCKSIZE * stat->secsize);
}
_dirbuf = _cdio_malloc (stat.secsize * ISO_BLOCKSIZE);
_dirbuf = _cdio_malloc (stat->secsize * ISO_BLOCKSIZE);
if (is_mode2) {
if (cdio_read_mode2_sectors (cdio, _dirbuf, stat.lsn, false,
stat.secsize))
if (cdio_read_mode2_sectors (cdio, _dirbuf, stat->lsn, false,
stat->secsize))
cdio_assert_not_reached ();
} else {
if (cdio_read_mode1_sectors (cdio, _dirbuf, stat.lsn, false,
stat.secsize))
if (cdio_read_mode1_sectors (cdio, _dirbuf, stat->lsn, false,
stat->secsize))
cdio_assert_not_reached ();
}
while (offset < (stat.secsize * ISO_BLOCKSIZE))
while (offset < (stat->secsize * ISO_BLOCKSIZE))
{
const iso9660_dir_t *idr = (void *) &_dirbuf[offset];
if (!iso9660_get_dir_len(idr))
const iso9660_dir_t *iso9660_dir = (void *) &_dirbuf[offset];
iso9660_stat_t *iso9660_stat;
if (!iso9660_get_dir_len(iso9660_dir))
{
offset++;
continue;
}
_cdio_list_append (retval, iso9660_dir_to_name (idr));
iso9660_stat = _iso9660_dir_to_statbuf(iso9660_dir, is_mode2);
_cdio_list_append (retval, iso9660_stat);
offset += iso9660_get_dir_len(idr);
offset += iso9660_get_dir_len(iso9660_dir);
}
cdio_assert (offset == (stat.secsize * ISO_BLOCKSIZE));
cdio_assert (offset == (stat->secsize * ISO_BLOCKSIZE));
free (_dirbuf);
free (stat);
return retval;
}
}
static bool
find_fs_lsn_recurse (const CdIo *cdio, const char pathname[],
/*out*/ iso9660_stat_t *statbuf, lsn_t lsn)
static iso9660_stat_t *
find_fs_lsn_recurse (const CdIo *cdio, const char pathname[], lsn_t lsn)
{
CdioList *entlist = iso9660_fs_readdir (cdio, pathname, true);
CdioList *dirlist = _cdio_list_new ();
@@ -315,25 +336,26 @@ find_fs_lsn_recurse (const CdIo *cdio, const char pathname[],
_CDIO_LIST_FOREACH (entnode, entlist)
{
char *name = _cdio_list_node_data (entnode);
iso9660_stat_t *statbuf = _cdio_list_node_data (entnode);
char _fullname[4096] = { 0, };
char *filename = (char *) statbuf->filename;
snprintf (_fullname, sizeof (_fullname), "%s%s", pathname, name);
snprintf (_fullname, sizeof (_fullname), "%s%s", pathname, filename);
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, ".."))
&& strcmp ((char *) statbuf->filename, ".")
&& strcmp ((char *) statbuf->filename, ".."))
_cdio_list_append (dirlist, strdup (_fullname));
if (statbuf->lsn == lsn) {
unsigned int len=sizeof(iso9660_stat_t)+strlen(statbuf->filename)+1;
iso9660_stat_t *ret_stat = _cdio_malloc(len);
memcpy(ret_stat, statbuf, len);
_cdio_list_free (entlist, true);
_cdio_list_free (dirlist, true);
return true;
return ret_stat;
}
}
@@ -345,26 +367,27 @@ find_fs_lsn_recurse (const CdIo *cdio, const char pathname[],
_CDIO_LIST_FOREACH (entnode, dirlist)
{
char *_fullname = _cdio_list_node_data (entnode);
iso9660_stat_t *ret_stat = find_fs_lsn_recurse (cdio, _fullname, lsn);
if (find_fs_lsn_recurse (cdio, _fullname, statbuf, lsn)) {
if (NULL != ret_stat) {
_cdio_list_free (dirlist, true);
return true;
return ret_stat;
}
}
_cdio_list_free (dirlist, true);
return false;
return NULL;
}
/*!
Given a directory pointer, find the filesystem entry that contains
lsn and return information about it in stat.
lsn and return information about it.
Returns true if we found an entry with the lsn and false if not.
Returns stat_t of entry if we found lsn, or NULL otherwise.
*/
bool
iso9660_find_fs_lsn(const CdIo *cdio, lsn_t lsn, /*out*/ iso9660_stat_t *stat)
iso9660_stat_t *
iso9660_find_fs_lsn(const CdIo *cdio, lsn_t lsn)
{
return find_fs_lsn_recurse (cdio, "/", stat, lsn);
return find_fs_lsn_recurse (cdio, "/", lsn);
}

View File

@@ -1,5 +1,5 @@
/*
$Id: cd-info.c,v 1.46 2003/11/09 15:51:43 rocky Exp $
$Id: cd-info.c,v 1.47 2003/11/16 19:30:45 rocky Exp $
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
Copyright (C) 1996,1997,1998 Gerd Knorr <kraxel@bytesex.org>
@@ -493,9 +493,9 @@ print_iso9660_recurse (CdIo *cdio, const char pathname[], cdio_fs_anal_t fs,
_CDIO_LIST_FOREACH (entnode, entlist)
{
char *iso_name = _cdio_list_node_data (entnode);
iso9660_stat_t *statbuf = _cdio_list_node_data (entnode);
char *iso_name = statbuf->filename;
char _fullname[4096] = { 0, };
iso9660_stat_t statbuf;
char translated_name[MAX_ISONAME+1];
#define DATESTR_SIZE 30
char date_str[DATESTR_SIZE];
@@ -505,37 +505,31 @@ print_iso9660_recurse (CdIo *cdio, const char pathname[], cdio_fs_anal_t fs,
snprintf (_fullname, sizeof (_fullname), "%s%s", pathname,
iso_name);
if (iso9660_fs_stat (cdio, _fullname, &statbuf, is_mode2)) {
fprintf(stderr, "Error getting file info for directory %s/\n",
_fullname);
continue;
}
strncat (_fullname, "/", sizeof (_fullname));
if (statbuf.type == _STAT_DIR
if (statbuf->type == _STAT_DIR
&& strcmp (iso_name, ".")
&& strcmp (iso_name, ".."))
_cdio_list_append (dirlist, strdup (_fullname));
if (fs & CDIO_FS_ANAL_XA) {
printf ( " %c %s %d %d [fn %.2d] [LSN %6lu] ",
(statbuf.type == _STAT_DIR) ? 'd' : '-',
iso9660_get_xa_attr_str (statbuf.xa.attributes),
uint16_from_be (statbuf.xa.user_id),
uint16_from_be (statbuf.xa.group_id),
statbuf.xa.filenum,
(long unsigned int) statbuf.lsn);
(statbuf->type == _STAT_DIR) ? 'd' : '-',
iso9660_get_xa_attr_str (statbuf->xa.attributes),
uint16_from_be (statbuf->xa.user_id),
uint16_from_be (statbuf->xa.group_id),
statbuf->xa.filenum,
(long unsigned int) statbuf->lsn);
if (uint16_from_be(statbuf.xa.attributes) & XA_ATTR_MODE2FORM2) {
if (uint16_from_be(statbuf->xa.attributes) & XA_ATTR_MODE2FORM2) {
printf ("%9u (%9u)",
(unsigned int) statbuf.secsize * M2F2_SECTOR_SIZE,
(unsigned int) statbuf.size);
(unsigned int) statbuf->secsize * M2F2_SECTOR_SIZE,
(unsigned int) statbuf->size);
} else {
printf ("%9u", (unsigned int) statbuf.size);
printf ("%9u", (unsigned int) statbuf->size);
}
}
strftime(date_str, DATESTR_SIZE, "%b %e %Y %H:%M ", &statbuf.tm);
strftime(date_str, DATESTR_SIZE, "%b %e %Y %H:%M ", &statbuf->tm);
printf (" %s %s\n", date_str, translated_name);
}