UDF file is now opaque. Access routines then added.

Note: there are valgrind and free() errors that need going over.
This commit is contained in:
rocky
2005-10-24 10:14:57 +00:00
parent 63402ba0c9
commit b0306c811e
7 changed files with 166 additions and 87 deletions

View File

@@ -1,5 +1,5 @@
/* /*
$Id: udf1.c,v 1.1 2005/10/24 03:12:30 rocky Exp $ $Id: udf1.c,v 1.2 2005/10/24 10:14:57 rocky Exp $
Copyright (C) 2005 Rocky Bernstein <rocky@panix.com> Copyright (C) 2005 Rocky Bernstein <rocky@panix.com>
@@ -52,15 +52,16 @@
static static
udf_file_t * udf_file_t *
list_directory(udf_t *p_udf, udf_file_t *p_udf_file, char *psz_token) list_directory(const udf_t *p_udf, udf_file_t *p_udf_file,
const char *psz_token)
{ {
if (!p_udf_file) return NULL; if (!p_udf_file) return NULL;
while (udf_get_next(p_udf, p_udf_file)) { while (udf_get_next(p_udf, p_udf_file)) {
printf("%s\n", psz_token); printf("%s\n", psz_token);
if (strcmp(psz_token, p_udf_file->psz_name) == 0) { if (strcmp(psz_token, udf_get_name(p_udf_file)) == 0) {
char *next_tok = strtok(NULL, udf_PATH_DELIMITERS); const char *next_tok = strtok(NULL, udf_PATH_DELIMITERS);
if (p_udf_file->b_dir) { if (udf_is_dir(p_udf_file)) {
udf_file_t * p_udf_file2 = udf_get_sub(p_udf, p_udf_file); udf_file_t * p_udf_file2 = udf_get_sub(p_udf, p_udf_file);
if (p_udf_file2) { if (p_udf_file2) {
@@ -101,7 +102,7 @@ main(int argc, const char *argv[])
return 1; return 1;
} }
list_directory(p_udf, p_udf_file, p_udf_file->psz_name); list_directory(p_udf, p_udf_file, udf_get_name(p_udf_file));
/* Go over: udf_file_free(p_udf_file);*/ /* Go over: udf_file_free(p_udf_file);*/
} }

View File

@@ -1,5 +1,5 @@
/* /*
$Id: udf.h,v 1.6 2005/10/24 03:12:30 rocky Exp $ $Id: udf.h,v 1.7 2005/10/24 10:14:58 rocky Exp $
Copyright (C) 2005 Rocky Bernstein <rocky@panix.com> Copyright (C) 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
@@ -28,6 +28,7 @@
#ifndef UDF_H #ifndef UDF_H
#define UDF_H #define UDF_H
#include <cdio/cdio.h>
#include <cdio/ecma_167.h> #include <cdio/ecma_167.h>
typedef uint16_t partition_num_t; typedef uint16_t partition_num_t;
@@ -36,23 +37,10 @@ typedef uint16_t partition_num_t;
typedef uint16_t unicode16_t; typedef uint16_t unicode16_t;
typedef uint8_t ubyte; typedef uint8_t ubyte;
typedef struct
{
char *psz_name;
bool b_dir; /* true if this entry is a directory. */
bool b_parent; /* True if has parent directory (e.g. not root
directory). If not set b_dir will probably
be true. */
uint32_t i_part_start; /** Opaque structures. */
uint32_t dir_lba, dir_end_lba;
uint64_t dir_left;
uint8_t *sector;
udf_fileid_desc_t *fid;
} udf_file_t;
/** This is an opaque structure. */
typedef struct udf_s udf_t; typedef struct udf_s udf_t;
typedef struct udf_file_s udf_file_t;
/** /**
Imagine the below a #define'd value rather than distinct values of Imagine the below a #define'd value rather than distinct values of
@@ -72,8 +60,8 @@ extern udf_enum1_t debug_udf_enums1;
Seek to a position i_start and then read i_blocks. Number of blocks read is Seek to a position i_start and then read i_blocks. Number of blocks read is
returned. One normally expects the return to be equal to i_blocks. returned. One normally expects the return to be equal to i_blocks.
*/ */
long int udf_read_sectors (const udf_t *p_udf, void *ptr, lsn_t i_start, driver_return_code_t udf_read_sectors (const udf_t *p_udf, void *ptr,
long int i_blocks); lsn_t i_start, long int i_blocks);
/*! /*!
Open an UDF for reading. Maybe in the future we will have Open an UDF for reading. Maybe in the future we will have
@@ -91,26 +79,31 @@ udf_t *udf_open (const char *psz_path);
Caller must free result - use udf_file_free for that. Caller must free result - use udf_file_free for that.
*/ */
udf_file_t *udf_get_root (udf_t *p_udf, const bool b_any_partition, udf_file_t *udf_get_root (udf_t *p_udf, bool b_any_partition,
const partition_num_t i_partition); partition_num_t i_partition);
/*! /*!
Return a file pointer matching pzz_name. If b_any_partition is false then Return a file pointer matching pzz_name. If b_any_partition is false then
the root must be in the given partition. the root must be in the given partition.
*/ */
udf_file_t *udf_find_file(udf_t *p_udf, const char *psz_name, udf_file_t *udf_find_file(udf_t *p_udf, const char *psz_name,
const bool b_any_partition, bool b_any_partition,
const partition_num_t i_partition); partition_num_t i_partition);
/*! /*!
Return the next subdirectory. Return the next subdirectory.
*/ */
udf_file_t *udf_get_sub(udf_t *p_udf, udf_file_t *p_udf_file); udf_file_t *udf_get_sub(const udf_t *p_udf, const udf_file_t *p_udf_file);
/*!
Return the name of the file
*/
const char *udf_get_name(const udf_file_t *p_udf_file);
/*! /*!
Return the next file. Return the next file.
*/ */
udf_file_t *udf_get_next(udf_t *p_udf, udf_file_t *p_udf_file); udf_file_t *udf_get_next(const udf_t *p_udf, udf_file_t *p_udf_file);
/*! /*!
Close UDF and free resources associated with p_udf. Close UDF and free resources associated with p_udf.
@@ -122,5 +115,10 @@ bool udf_close (udf_t *p_udf);
*/ */
bool udf_file_free(udf_file_t *p_udf_file); bool udf_file_free(udf_file_t *p_udf_file);
/*!
Return true if the file is a directory.
*/
bool udf_is_dir(const udf_file_t *p_udf_file);
#endif /*UDF_H*/ #endif /*UDF_H*/

View File

@@ -30,12 +30,11 @@ libudf_la_AGE := 0
EXTRA_DIST = libudf.sym EXTRA_DIST = libudf.sym
# noinst_HEADERS = crc.h osta.h noinst_HEADERS = udf_private.h
lib_LTLIBRARIES = libudf.la lib_LTLIBRARIES = libudf.la
#libudf_la_SOURCES = crc.c osta.c udf_fs.c libudf_la_SOURCES = udf.c udf_fs.c
libudf_la_SOURCES = udf_fs.c
libudf_la_LIBADD = @LIBCDIO_LIBS@ libudf_la_LIBADD = @LIBCDIO_LIBS@

View File

@@ -9,7 +9,9 @@ VSD_STD_ID_NSR03
VSD_STD_ID_TEA01 VSD_STD_ID_TEA01
udf_close udf_close
udf_file_free udf_file_free
udf_get_name
udf_get_next udf_get_next
udf_get_sub udf_get_sub
udf_is_dir
udf_open udf_open
udf_read_sectors udf_read_sectors

36
lib/udf/udf.c Normal file
View File

@@ -0,0 +1,36 @@
/*
$Id: udf.c,v 1.1 2005/10/24 10:14:58 rocky Exp $
Copyright (C) 2005 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
*/
/* Access routines */
#include "udf_private.h"
const char *
udf_get_name(const udf_file_t *p_udf_file)
{
return p_udf_file->psz_name;
}
bool
udf_is_dir(const udf_file_t *p_udf_file)
{
return p_udf_file->b_dir;
}

View File

@@ -1,5 +1,5 @@
/* /*
$Id: udf_fs.c,v 1.2 2005/10/24 03:12:30 rocky Exp $ $Id: udf_fs.c,v 1.3 2005/10/24 10:14:58 rocky Exp $
Copyright (C) 2005 Rocky Bernstein <rocky@panix.com> Copyright (C) 2005 Rocky Bernstein <rocky@panix.com>
@@ -67,9 +67,8 @@ const char VSD_STD_ID_CDW01[] = {'C', 'D', 'W', '0', '2'};
const char VSD_STD_ID_NSR03[] = {'N', 'S', 'R', '0', '3'}; const char VSD_STD_ID_NSR03[] = {'N', 'S', 'R', '0', '3'};
const char VSD_STD_ID_TEA01[] = {'T', 'E', 'A', '0', '1'}; const char VSD_STD_ID_TEA01[] = {'T', 'E', 'A', '0', '1'};
#include <cdio/udf.h>
#include <cdio/ecma_167.h>
#include <cdio/bytesex.h> #include <cdio/bytesex.h>
#include "udf_private.h"
/** The below variables are trickery to force enum symbol values to be /** The below variables are trickery to force enum symbol values to be
recorded in debug symbol tables. They are used to allow one to refer recorded in debug symbol tables. They are used to allow one to refer
@@ -80,8 +79,6 @@ tag_id_t debug_tagid;
file_characteristics_t debug_file_characteristics; file_characteristics_t debug_file_characteristics;
udf_enum1_t debug_udf_enums1; udf_enum1_t debug_udf_enums1;
/* Private headers */
#include "_cdio_stdio.h"
/* /*
* The UDF specs are pretty clear on how each data structure is made * The UDF specs are pretty clear on how each data structure is made
@@ -126,21 +123,6 @@ udf_enum1_t debug_udf_enums1;
* |-->File data * |-->File data
*/ */
/* Implementation of udf_t type */
struct udf_s {
bool b_stream; /* Use stream pointer, else use
p_cdio.
*/
CdioDataSource_t *stream; /* Stream pointer if stream */
CdIo_t *cdio; /* Cdio pointer if read device */
anchor_vol_desc_ptr_t anchor_vol_desc_ptr;
uint32_t pvd_lba; /* sector of Primary Volume Descriptor */
partition_num_t i_partition; /* partition number */
uint32_t i_part_start; /* start of Partition Descriptor */
uint32_t lvd_lba; /* sector of Logical Volume Descriptor */
uint32_t fsd_offset; /* lba of fileset descriptor */
};
/** /**
* Check the descriptor tag for both the correct id and correct checksum. * Check the descriptor tag for both the correct id and correct checksum.
* Return zero if all is good, -1 if not. * Return zero if all is good, -1 if not.
@@ -246,8 +228,8 @@ udf_ff_traverse(udf_t *p_udf, udf_file_t *p_udf_file, char *psz_token)
#define udf_MAX_PATHLEN 2048 #define udf_MAX_PATHLEN 2048
udf_file_t * udf_file_t *
udf_find_file(udf_t *p_udf, const char *psz_name, const bool b_any_partition, udf_find_file(udf_t *p_udf, const char *psz_name, bool b_any_partition,
const partition_num_t i_partition) partition_num_t i_partition)
{ {
udf_file_t *p_udf_file = udf_get_root(p_udf, b_any_partition, i_partition); udf_file_t *p_udf_file = udf_get_root(p_udf, b_any_partition, i_partition);
udf_file_t *p_udf_file2 = NULL; udf_file_t *p_udf_file2 = NULL;
@@ -305,11 +287,12 @@ udf_new_file(udf_file_entry_t *p_fe, uint32_t i_part_start,
Seek to a position i_start and then read i_blocks. Number of blocks read is Seek to a position i_start and then read i_blocks. Number of blocks read is
returned. One normally expects the return to be equal to i_blocks. returned. One normally expects the return to be equal to i_blocks.
*/ */
long int driver_return_code_t
udf_read_sectors (const udf_t *p_udf, void *ptr, lsn_t i_start, udf_read_sectors (const udf_t *p_udf, void *ptr, lsn_t i_start,
long int i_blocks) long int i_blocks)
{ {
long int ret; driver_return_code_t ret;
long int i_read;
long int i_byte_offset; long int i_byte_offset;
if (!p_udf) return 0; if (!p_udf) return 0;
@@ -317,8 +300,10 @@ udf_read_sectors (const udf_t *p_udf, void *ptr, lsn_t i_start,
if (p_udf->b_stream) { if (p_udf->b_stream) {
ret = cdio_stream_seek (p_udf->stream, i_byte_offset, SEEK_SET); ret = cdio_stream_seek (p_udf->stream, i_byte_offset, SEEK_SET);
if (ret!=0) return 0; if (DRIVER_OP_SUCCESS != ret) return ret;
return cdio_stream_read (p_udf->stream, ptr, UDF_BLOCKSIZE, i_blocks); i_read = cdio_stream_read (p_udf->stream, ptr, UDF_BLOCKSIZE, i_blocks);
if (i_read) return DRIVER_OP_SUCCESS;
return DRIVER_OP_ERROR;
} else { } else {
return cdio_read_data_sectors(p_udf->cdio, ptr, i_start, UDF_BLOCKSIZE, return cdio_read_data_sectors(p_udf->cdio, ptr, i_start, UDF_BLOCKSIZE,
i_blocks); i_blocks);
@@ -339,21 +324,21 @@ udf_open (const char *psz_path)
if (!p_udf) return NULL; if (!p_udf) return NULL;
p_udf->b_stream = !cdio_is_device(psz_path, DRIVER_UNKNOWN); p_udf->cdio = cdio_open(psz_path, DRIVER_UNKNOWN);
if (p_udf->b_stream) { if (!p_udf->cdio) {
/* Not a CD-ROM drive or CD Image. Maybe it's a UDF file not
encapsulated as a CD-ROM Image (e.g. often .UDF or (sic) .ISO)
*/
p_udf->stream = cdio_stdio_new( psz_path ); p_udf->stream = cdio_stdio_new( psz_path );
if (!p_udf->stream) if (!p_udf->stream)
goto error; goto error;
} else { p_udf->b_stream = true;
p_udf->cdio = cdio_open(psz_path, DRIVER_UNKNOWN);
if (!p_udf->cdio)
goto error;
} }
/* /*
* Look for an Anchor Volume Descriptor Pointer at sector 256. * Look for an Anchor Volume Descriptor Pointer at sector 256.
*/ */
if (! udf_read_sectors (p_udf, &data, 256, 1) ) if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, &data, 256, 1) )
goto error; goto error;
memcpy(&(p_udf->anchor_vol_desc_ptr), &data, sizeof(anchor_vol_desc_ptr_t)); memcpy(&(p_udf->anchor_vol_desc_ptr), &data, sizeof(anchor_vol_desc_ptr_t));
@@ -377,7 +362,7 @@ udf_open (const char *psz_path)
udf_pvd_t *p_pvd = (udf_pvd_t *) &data; udf_pvd_t *p_pvd = (udf_pvd_t *) &data;
if (! udf_read_sectors (p_udf, p_pvd, i_lba, 1) ) if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, p_pvd, i_lba, 1) )
goto error; goto error;
if (!udf_checktag(&p_pvd->tag, TAGID_PRI_VOL)) { if (!udf_checktag(&p_pvd->tag, TAGID_PRI_VOL)) {
@@ -410,8 +395,7 @@ udf_open (const char *psz_path)
Caller must free result - use udf_file_free for that. Caller must free result - use udf_file_free for that.
*/ */
udf_file_t * udf_file_t *
udf_get_root (udf_t *p_udf, const bool b_any_partition, udf_get_root (udf_t *p_udf, bool b_any_partition, partition_num_t i_partition)
const partition_num_t i_partition)
{ {
const anchor_vol_desc_ptr_t *p_avdp = &p_udf->anchor_vol_desc_ptr; const anchor_vol_desc_ptr_t *p_avdp = &p_udf->anchor_vol_desc_ptr;
const uint32_t mvds_start = const uint32_t mvds_start =
@@ -433,7 +417,7 @@ udf_get_root (udf_t *p_udf, const bool b_any_partition,
partition_desc_t *p_partition = (partition_desc_t *) &data; partition_desc_t *p_partition = (partition_desc_t *) &data;
if (! udf_read_sectors (p_udf, p_partition, i_lba, 1) ) if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, p_partition, i_lba, 1) )
return NULL; return NULL;
if (!udf_checktag(&p_partition->tag, TAGID_PARTITION)) { if (!udf_checktag(&p_partition->tag, TAGID_PARTITION)) {
@@ -462,18 +446,19 @@ udf_get_root (udf_t *p_udf, const bool b_any_partition,
if (p_udf->lvd_lba && p_udf->i_part_start) { if (p_udf->lvd_lba && p_udf->i_part_start) {
udf_fsd_t *p_fsd = (udf_fsd_t *) &data; udf_fsd_t *p_fsd = (udf_fsd_t *) &data;
int i_sectors = udf_read_sectors(p_udf, p_fsd, driver_return_code_t ret =
p_udf->i_part_start + p_udf->fsd_offset, udf_read_sectors(p_udf, p_fsd, p_udf->i_part_start + p_udf->fsd_offset,
1); 1);
if (i_sectors > 0 && !udf_checktag(&p_fsd->tag, TAGID_FSD)) { if (DRIVER_OP_SUCCESS == ret && !udf_checktag(&p_fsd->tag, TAGID_FSD)) {
udf_file_entry_t *p_fe = (udf_file_entry_t *) &data; udf_file_entry_t *p_fe = (udf_file_entry_t *) &data;
const uint32_t parent_icb = uint32_from_le(p_fsd->root_icb.loc.lba); const uint32_t parent_icb = uint32_from_le(p_fsd->root_icb.loc.lba);
/* Check partition numbers match of last-read block? */ /* Check partition numbers match of last-read block? */
udf_read_sectors(p_udf, p_fe, p_udf->i_part_start + parent_icb, 1); ret = udf_read_sectors(p_udf, p_fe, p_udf->i_part_start + parent_icb, 1);
if (!udf_checktag(&p_fe->tag, TAGID_FILE_ENTRY)) { if (ret == DRIVER_OP_SUCCESS &&
!udf_checktag(&p_fe->tag, TAGID_FILE_ENTRY)) {
/* Check partition numbers match of last-read block? */ /* Check partition numbers match of last-read block? */
@@ -506,16 +491,18 @@ udf_close (udf_t *p_udf)
} }
udf_file_t * udf_file_t *
udf_get_sub(udf_t *p_udf, udf_file_t *p_udf_file) udf_get_sub(const udf_t *p_udf, const udf_file_t *p_udf_file)
{ {
if (p_udf_file->b_dir && !p_udf_file->b_parent && p_udf_file->fid) { if (p_udf_file->b_dir && p_udf_file->fid) {
uint8_t data[UDF_BLOCKSIZE]; uint8_t data[UDF_BLOCKSIZE];
udf_file_entry_t *p_fe = (udf_file_entry_t *) &data; udf_file_entry_t *p_fe = (udf_file_entry_t *) &data;
int i_sectors = udf_read_sectors(p_udf, p_fe, p_udf->i_part_start driver_return_code_t i_ret =
+ p_udf_file->fid->icb.loc.lba, 1); udf_read_sectors(p_udf, p_fe, p_udf->i_part_start
+ p_udf_file->fid->icb.loc.lba, 1);
if (i_sectors && !udf_checktag(&p_fe->tag, TAGID_FILE_ENTRY)) { if (DRIVER_OP_SUCCESS == i_ret
&& !udf_checktag(&p_fe->tag, TAGID_FILE_ENTRY)) {
if (ICBTAG_FILE_TYPE_DIRECTORY == p_fe->icb_tag.file_type) { if (ICBTAG_FILE_TYPE_DIRECTORY == p_fe->icb_tag.file_type) {
udf_file_t *p_udf_file_new = udf_new_file(p_fe, p_udf->i_part_start, udf_file_t *p_udf_file_new = udf_new_file(p_fe, p_udf->i_part_start,
@@ -529,7 +516,7 @@ udf_get_sub(udf_t *p_udf, udf_file_t *p_udf_file)
} }
udf_file_t * udf_file_t *
udf_get_next(udf_t *p_udf, udf_file_t *p_udf_file) udf_get_next(const udf_t *p_udf, udf_file_t *p_udf_file)
{ {
if (p_udf_file->dir_left <= 0) { if (p_udf_file->dir_left <= 0) {
@@ -549,14 +536,14 @@ udf_get_next(udf_t *p_udf, udf_file_t *p_udf_file)
if (!p_udf_file->fid) { if (!p_udf_file->fid) {
uint32_t i_sectors = (p_udf_file->dir_end_lba - p_udf_file->dir_lba + 1); uint32_t i_sectors = (p_udf_file->dir_end_lba - p_udf_file->dir_lba + 1);
uint32_t size = UDF_BLOCKSIZE * i_sectors; uint32_t size = UDF_BLOCKSIZE * i_sectors;
int i_read; driver_return_code_t i_ret;
if (!p_udf_file->sector) if (!p_udf_file->sector)
p_udf_file->sector = (uint8_t*) malloc(size); p_udf_file->sector = (uint8_t*) malloc(size);
i_read = udf_read_sectors(p_udf, p_udf_file->sector, i_ret = udf_read_sectors(p_udf, p_udf_file->sector,
p_udf_file->i_part_start + p_udf_file->dir_lba, p_udf_file->i_part_start + p_udf_file->dir_lba,
i_sectors); i_sectors);
if (i_read) if (DRIVER_OP_SUCCESS == i_ret)
p_udf_file->fid = (udf_fileid_desc_t *) p_udf_file->sector; p_udf_file->fid = (udf_fileid_desc_t *) p_udf_file->sector;
else else
p_udf_file->fid = NULL; p_udf_file->fid = NULL;

56
lib/udf/udf_private.h Normal file
View File

@@ -0,0 +1,56 @@
/*
$Id: udf_private.h,v 1.1 2005/10/24 10:14:58 rocky Exp $
Copyright (C) 2005 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
*/
#include <cdio/types.h>
#include <cdio/ecma_167.h>
#include <cdio/udf.h>
#include "_cdio_stdio.h"
/* Implementation of opaque types */
struct udf_s {
bool b_stream; /* Use stream pointer, else use
p_cdio.
*/
CdioDataSource_t *stream; /* Stream pointer if stream */
CdIo_t *cdio; /* Cdio pointer if read device */
anchor_vol_desc_ptr_t anchor_vol_desc_ptr;
uint32_t pvd_lba; /* sector of Primary Volume Descriptor */
partition_num_t i_partition; /* partition number */
uint32_t i_part_start; /* start of Partition Descriptor */
uint32_t lvd_lba; /* sector of Logical Volume Descriptor */
uint32_t fsd_offset; /* lba of fileset descriptor */
};
struct udf_file_s
{
char *psz_name;
bool b_dir; /* true if this entry is a directory. */
bool b_parent; /* True if has parent directory (e.g. not root
directory). If not set b_dir will probably
be true. */
uint32_t i_part_start;
uint32_t dir_lba, dir_end_lba;
uint64_t dir_left;
uint8_t *sector;
udf_fileid_desc_t *fid;
};