First inkling of code for UDF support.
This commit is contained in:
@@ -19,7 +19,7 @@ define(RELEASE_NUM, 77)
|
|||||||
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.175 2005/10/23 12:56:40 rocky Exp $])dnl
|
AC_REVISION([$Id: configure.ac,v 1.176 2005/10/24 03:12:30 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)
|
||||||
|
|
||||||
@@ -601,6 +601,7 @@ AC_CONFIG_FILES([ \
|
|||||||
lib/driver/Makefile \
|
lib/driver/Makefile \
|
||||||
lib/iso9660/Makefile \
|
lib/iso9660/Makefile \
|
||||||
lib/paranoia/Makefile \
|
lib/paranoia/Makefile \
|
||||||
|
lib/udf/Makefile \
|
||||||
libcdio.pc \
|
libcdio.pc \
|
||||||
libcdio_cdda.pc \
|
libcdio_cdda.pc \
|
||||||
libcdio_paranoia.pc \
|
libcdio_paranoia.pc \
|
||||||
|
|||||||
@@ -17,3 +17,5 @@ paranoia
|
|||||||
paranoia2
|
paranoia2
|
||||||
sample?
|
sample?
|
||||||
tracks
|
tracks
|
||||||
|
udf1
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# $Id: Makefile.am,v 1.25 2005/09/16 09:31:39 rocky Exp $
|
# $Id: Makefile.am,v 1.26 2005/10/24 03:12:30 rocky Exp $
|
||||||
#
|
#
|
||||||
# Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
|
# Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
|
||||||
#
|
#
|
||||||
@@ -28,7 +28,7 @@ paranoia_progs = paranoia paranoia2
|
|||||||
endif
|
endif
|
||||||
noinst_PROGRAMS = audio cdtext device drives iso1 iso2 iso3 isofuzzy \
|
noinst_PROGRAMS = audio cdtext device drives iso1 iso2 iso3 isofuzzy \
|
||||||
mmc1 mmc2 $(paranoia_progs) tracks \
|
mmc1 mmc2 $(paranoia_progs) tracks \
|
||||||
sample3 sample4
|
sample3 sample4 udf1
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir) $(LIBCDIO_CFLAGS)
|
INCLUDES = -I$(top_srcdir) $(LIBCDIO_CFLAGS)
|
||||||
|
|
||||||
@@ -58,5 +58,9 @@ sample4_LDADD = $(LIBCDIO_LIBS)
|
|||||||
|
|
||||||
tracks_LDADD = $(LIBCDIO_LIBS)
|
tracks_LDADD = $(LIBCDIO_LIBS)
|
||||||
|
|
||||||
|
udf1_DEPENDENCIES = $(LIBUDF_LIBS) $(LIBCDIO_LIBS)
|
||||||
|
udf1_LDADD = $(LIBUDF_LIBS) $(LIBCDIO_LIBS)
|
||||||
|
|
||||||
|
|
||||||
# iso programs create file "copying"
|
# iso programs create file "copying"
|
||||||
MOSTLYCLEANFILES = copying
|
MOSTLYCLEANFILES = copying
|
||||||
|
|||||||
111
example/udf1.c
Normal file
111
example/udf1.c
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
$Id: udf1.c,v 1.1 2005/10/24 03:12:30 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Simple program to show using libiso9660 to list files in a directory of
|
||||||
|
an ISO-9660 image.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This is the UDF image. */
|
||||||
|
#define UDF_IMAGE_PATH "../"
|
||||||
|
#define UDF_IMAGE "/src2/cd-images/udf/UDF102ISO.iso"
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <cdio/cdio.h>
|
||||||
|
#include <cdio/udf.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define udf_PATH_DELIMITERS "/\\"
|
||||||
|
|
||||||
|
static
|
||||||
|
udf_file_t *
|
||||||
|
list_directory(udf_t *p_udf, udf_file_t *p_udf_file, char *psz_token)
|
||||||
|
{
|
||||||
|
if (!p_udf_file) return NULL;
|
||||||
|
while (udf_get_next(p_udf, p_udf_file)) {
|
||||||
|
printf("%s\n", psz_token);
|
||||||
|
if (strcmp(psz_token, p_udf_file->psz_name) == 0) {
|
||||||
|
char *next_tok = strtok(NULL, udf_PATH_DELIMITERS);
|
||||||
|
|
||||||
|
if (p_udf_file->b_dir) {
|
||||||
|
udf_file_t * p_udf_file2 = udf_get_sub(p_udf, p_udf_file);
|
||||||
|
|
||||||
|
if (p_udf_file2) {
|
||||||
|
udf_file_t *p_udf_file3 =
|
||||||
|
list_directory(p_udf, p_udf_file2, next_tok);
|
||||||
|
|
||||||
|
if (!p_udf_file3) udf_file_free(p_udf_file2);
|
||||||
|
return p_udf_file3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p_udf_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
udf_t *p_udf;
|
||||||
|
char const *psz_fname;
|
||||||
|
|
||||||
|
if (argc > 1)
|
||||||
|
psz_fname = argv[1];
|
||||||
|
else
|
||||||
|
psz_fname = UDF_IMAGE;
|
||||||
|
|
||||||
|
p_udf = udf_open (psz_fname);
|
||||||
|
|
||||||
|
if (NULL == p_udf) {
|
||||||
|
fprintf(stderr, "Sorry, couldn't open %s as something using UDF\n",
|
||||||
|
psz_fname);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
udf_file_t *p_udf_file = udf_get_root(p_udf, true, 0);
|
||||||
|
if (NULL == p_udf_file) {
|
||||||
|
fprintf(stderr, "Sorry, couldn't find / in %s\n",
|
||||||
|
psz_fname);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_directory(p_udf, p_udf_file, p_udf_file->psz_name);
|
||||||
|
/* Go over: udf_file_free(p_udf_file);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
udf_close(p_udf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -925,7 +925,7 @@ PRAGMA_END_PACKED
|
|||||||
/** The below variables are trickery to force the above enum symbol
|
/** The below variables are trickery to force the above enum symbol
|
||||||
values to be recorded in debug symbol tables. They are used to
|
values to be recorded in debug symbol tables. They are used to
|
||||||
allow one refer to the enumeration value names in the typedefs
|
allow one refer to the enumeration value names in the typedefs
|
||||||
above in a debugger and debugger expressions
|
above in a debugger and in debugger expressions.
|
||||||
*/
|
*/
|
||||||
extern file_characteristics_t debug_file_characteristics;
|
extern file_characteristics_t debug_file_characteristics;
|
||||||
extern tag_id_t debug_tagid;
|
extern tag_id_t debug_tagid;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
$Id: udf.h,v 1.5 2005/10/21 12:33:46 rocky Exp $
|
$Id: udf.h,v 1.6 2005/10/24 03:12:30 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
|
||||||
@@ -30,22 +30,24 @@
|
|||||||
|
|
||||||
#include <cdio/ecma_167.h>
|
#include <cdio/ecma_167.h>
|
||||||
|
|
||||||
|
typedef uint16_t partition_num_t;
|
||||||
|
|
||||||
/* FIXME: these probably don't go here. */
|
/* FIXME: these probably don't go here. */
|
||||||
typedef uint16_t unicode16_t;
|
typedef uint16_t unicode16_t;
|
||||||
typedef uint8_t ubyte;
|
typedef uint8_t ubyte;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char *psz_name;
|
char *psz_name;
|
||||||
bool b_dir; /* true if this entry is a directory. */
|
bool b_dir; /* true if this entry is a directory. */
|
||||||
bool b_parent; /* True if has parent directory (e.g. not root
|
bool b_parent; /* True if has parent directory (e.g. not root
|
||||||
directory). If not set b_dir will probably
|
directory). If not set b_dir will probably
|
||||||
be true. */
|
be true. */
|
||||||
|
|
||||||
uint32_t i_part_start;
|
uint32_t i_part_start;
|
||||||
uint32_t dir_lba, dir_end_lba;
|
uint32_t dir_lba, dir_end_lba;
|
||||||
uint64_t dir_left;
|
uint64_t dir_left;
|
||||||
uint8_t *sector;
|
uint8_t *sector;
|
||||||
udf_fileid_desc_t *fid;
|
udf_fileid_desc_t *fid;
|
||||||
} udf_file_t;
|
} udf_file_t;
|
||||||
|
|
||||||
@@ -81,9 +83,34 @@ long int udf_read_sectors (const udf_t *p_udf, void *ptr, lsn_t i_start,
|
|||||||
*/
|
*/
|
||||||
udf_t *udf_open (const char *psz_path);
|
udf_t *udf_open (const char *psz_path);
|
||||||
|
|
||||||
udf_file_t *udf_get_sub(udf_t *p_udf, udf_file_t *p_file);
|
/*!
|
||||||
|
Get the root in p_udf. If b_any_partition is false then
|
||||||
|
the root must be in the given partition.
|
||||||
|
NULL is returned if the partition is not found or a root is not found or
|
||||||
|
there is on error.
|
||||||
|
|
||||||
udf_file_t *udf_get_next(udf_t *p_udf, udf_file_t * p_file);
|
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,
|
||||||
|
const partition_num_t i_partition);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Return a file pointer matching pzz_name. If b_any_partition is false then
|
||||||
|
the root must be in the given partition.
|
||||||
|
*/
|
||||||
|
udf_file_t *udf_find_file(udf_t *p_udf, const char *psz_name,
|
||||||
|
const bool b_any_partition,
|
||||||
|
const partition_num_t i_partition);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Return the next subdirectory.
|
||||||
|
*/
|
||||||
|
udf_file_t *udf_get_sub(udf_t *p_udf, udf_file_t *p_udf_file);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Return the next file.
|
||||||
|
*/
|
||||||
|
udf_file_t *udf_get_next(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.
|
||||||
@@ -93,7 +120,7 @@ bool udf_close (udf_t *p_udf);
|
|||||||
/*!
|
/*!
|
||||||
free free resources associated with p_fe.
|
free free resources associated with p_fe.
|
||||||
*/
|
*/
|
||||||
bool udf_file_free(udf_file_t * p_fe);
|
bool udf_file_free(udf_file_t *p_udf_file);
|
||||||
|
|
||||||
|
|
||||||
#endif /*UDF_H*/
|
#endif /*UDF_H*/
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# $Id: Makefile.am,v 1.66 2004/12/22 10:04:46 rocky Exp $
|
# $Id: Makefile.am,v 1.67 2005/10/24 03:12:30 rocky Exp $
|
||||||
#
|
#
|
||||||
# Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
# Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
||||||
#
|
#
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
########################################################
|
########################################################
|
||||||
|
|
||||||
if BUILD_CD_PARANOIA
|
if BUILD_CD_PARANOIA
|
||||||
SUBDIRS = driver iso9660 cdda_interface paranoia
|
SUBDIRS = driver iso9660 cdda_interface paranoia udf
|
||||||
else
|
else
|
||||||
SUBDIRS = driver iso9660
|
SUBDIRS = driver iso9660 udf
|
||||||
endif
|
endif
|
||||||
|
|||||||
323
lib/udf/udf_fs.c
323
lib/udf/udf_fs.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
$Id: udf_fs.c,v 1.1 2005/10/21 12:31:02 rocky Exp $
|
$Id: udf_fs.c,v 1.2 2005/10/24 03:12:30 rocky Exp $
|
||||||
|
|
||||||
Copyright (C) 2005 Rocky Bernstein <rocky@panix.com>
|
Copyright (C) 2005 Rocky Bernstein <rocky@panix.com>
|
||||||
|
|
||||||
@@ -134,13 +134,11 @@ struct udf_s {
|
|||||||
CdioDataSource_t *stream; /* Stream pointer if stream */
|
CdioDataSource_t *stream; /* Stream pointer if stream */
|
||||||
CdIo_t *cdio; /* Cdio pointer if read device */
|
CdIo_t *cdio; /* Cdio pointer if read device */
|
||||||
anchor_vol_desc_ptr_t anchor_vol_desc_ptr;
|
anchor_vol_desc_ptr_t anchor_vol_desc_ptr;
|
||||||
uint32_t pvd_lba; /* sector of Primary Volume Descriptor */
|
uint32_t pvd_lba; /* sector of Primary Volume Descriptor */
|
||||||
uint16_t i_partition; /* partition number */
|
partition_num_t i_partition; /* partition number */
|
||||||
uint32_t i_part_start; /* start of Partition Descriptor */
|
uint32_t i_part_start; /* start of Partition Descriptor */
|
||||||
uint32_t lvd_lba; /* sector of Logical Volume Descriptor */
|
uint32_t lvd_lba; /* sector of Logical Volume Descriptor */
|
||||||
uint32_t fsd_offset; /* lba of fileset descriptor */
|
uint32_t fsd_offset; /* lba of fileset descriptor */
|
||||||
udf_long_ad_t root_icb;
|
|
||||||
udf_file_t *p_root;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -216,6 +214,57 @@ udf_get_lba(const udf_file_entry_t *p_fe,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define udf_PATH_DELIMITERS "/\\"
|
||||||
|
|
||||||
|
static
|
||||||
|
udf_file_t *
|
||||||
|
udf_ff_traverse(udf_t *p_udf, udf_file_t *p_udf_file, char *psz_token)
|
||||||
|
{
|
||||||
|
while (udf_get_next(p_udf, p_udf_file)) {
|
||||||
|
if (strcmp(psz_token, p_udf_file->psz_name) == 0) {
|
||||||
|
char *next_tok = strtok(NULL, udf_PATH_DELIMITERS);
|
||||||
|
|
||||||
|
if (!next_tok)
|
||||||
|
return p_udf_file; /* found */
|
||||||
|
else if (p_udf_file->b_dir) {
|
||||||
|
udf_file_t * p_udf_file2 = udf_get_sub(p_udf, p_udf_file);
|
||||||
|
|
||||||
|
if (p_udf_file2) {
|
||||||
|
udf_file_t * p_udf_file3 =
|
||||||
|
udf_ff_traverse(p_udf, p_udf_file2, next_tok);
|
||||||
|
|
||||||
|
if (!p_udf_file3) udf_file_free(p_udf_file2);
|
||||||
|
return p_udf_file3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME! */
|
||||||
|
#define udf_MAX_PATHLEN 2048
|
||||||
|
|
||||||
|
udf_file_t *
|
||||||
|
udf_find_file(udf_t *p_udf, const char *psz_name, const bool b_any_partition,
|
||||||
|
const 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_file2 = NULL;
|
||||||
|
|
||||||
|
if (p_udf_file) {
|
||||||
|
char tokenline[udf_MAX_PATHLEN];
|
||||||
|
char *psz_token;
|
||||||
|
|
||||||
|
strcpy(tokenline, psz_name);
|
||||||
|
psz_token = strtok(tokenline, udf_PATH_DELIMITERS);
|
||||||
|
if (psz_token)
|
||||||
|
p_udf_file2 = udf_ff_traverse(p_udf, p_udf_file, psz_token);
|
||||||
|
udf_file_free(p_udf_file);
|
||||||
|
}
|
||||||
|
return p_udf_file2;
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert unicode16 to 8-bit char by dripping MSB.
|
/* Convert unicode16 to 8-bit char by dripping MSB.
|
||||||
Wonder if iconv can be used here
|
Wonder if iconv can be used here
|
||||||
*/
|
*/
|
||||||
@@ -240,16 +289,16 @@ static udf_file_t *
|
|||||||
udf_new_file(udf_file_entry_t *p_fe, uint32_t i_part_start,
|
udf_new_file(udf_file_entry_t *p_fe, uint32_t i_part_start,
|
||||||
const char *psz_name, bool b_dir, bool b_parent)
|
const char *psz_name, bool b_dir, bool b_parent)
|
||||||
{
|
{
|
||||||
udf_file_t *p_fid = (udf_file_t *) calloc(1, sizeof(udf_file_t));
|
udf_file_t *p_udf_file = (udf_file_t *) calloc(1, sizeof(udf_file_t));
|
||||||
if (!p_fid) return NULL;
|
if (!p_udf_file) return NULL;
|
||||||
p_fid->psz_name = strdup(psz_name);
|
p_udf_file->psz_name = strdup(psz_name);
|
||||||
p_fid->b_dir = b_dir;
|
p_udf_file->b_dir = b_dir;
|
||||||
p_fid->b_parent = b_parent;
|
p_udf_file->b_parent = b_parent;
|
||||||
p_fid->i_part_start = i_part_start;
|
p_udf_file->i_part_start = i_part_start;
|
||||||
p_fid->dir_left = uint64_from_le(p_fe->info_len);
|
p_udf_file->dir_left = uint64_from_le(p_fe->info_len);
|
||||||
|
|
||||||
udf_get_lba( p_fe, &(p_fid->dir_lba), &(p_fid->dir_end_lba) );
|
udf_get_lba( p_fe, &(p_udf_file->dir_lba), &(p_udf_file->dir_end_lba) );
|
||||||
return p_fid;
|
return p_udf_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -290,13 +339,16 @@ udf_open (const char *psz_path)
|
|||||||
|
|
||||||
if (!p_udf) return NULL;
|
if (!p_udf) return NULL;
|
||||||
|
|
||||||
/* FIXME:
|
p_udf->b_stream = !cdio_is_device(psz_path, DRIVER_UNKNOWN);
|
||||||
Some magic should be put here to figure out if we mean a UDF file
|
if (p_udf->b_stream) {
|
||||||
image or a CD-ROM or DVD. For now we'll go with stream. */
|
p_udf->stream = cdio_stdio_new( psz_path );
|
||||||
p_udf->b_stream = true;
|
if (!p_udf->stream)
|
||||||
p_udf->stream = cdio_stdio_new( psz_path );
|
goto error;
|
||||||
if (NULL == p_udf->stream)
|
} else {
|
||||||
goto error;
|
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.
|
||||||
@@ -340,67 +392,6 @@ udf_open (const char *psz_path)
|
|||||||
*/
|
*/
|
||||||
if (i_lba == mvds_end)
|
if (i_lba == mvds_end)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/*
|
|
||||||
Now we have the joy of finding the Partition Descriptor and the
|
|
||||||
Logical Volume Descriptor for the Main Volume Descriptor
|
|
||||||
Sequence. Once we've got that, we use the Logical Volume
|
|
||||||
Descriptor to get a Fileset Descriptor and that has the Root
|
|
||||||
Directory File Entry.
|
|
||||||
*/
|
|
||||||
for (i_lba = mvds_start; i_lba < mvds_end; i_lba++) {
|
|
||||||
|
|
||||||
partition_desc_t *p_partition = (partition_desc_t *) &data;
|
|
||||||
|
|
||||||
if (! udf_read_sectors (p_udf, p_partition, i_lba, 1) )
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (!udf_checktag(&p_partition->tag, TAGID_PARTITION)) {
|
|
||||||
/* Squirrel away some data regarding partition */
|
|
||||||
p_udf->i_partition = uint16_from_le(p_partition->number);
|
|
||||||
p_udf->i_part_start = uint32_from_le(p_partition->start_loc);
|
|
||||||
if (p_udf->lvd_lba) break;
|
|
||||||
} else if (!udf_checktag(&p_partition->tag, TAGID_LOGVOL)) {
|
|
||||||
/* Get fileset descriptor */
|
|
||||||
logical_vol_desc_t *p_logvol = (logical_vol_desc_t *) &data;
|
|
||||||
bool b_valid =
|
|
||||||
UDF_BLOCKSIZE == uint32_from_le(p_logvol->logical_blocksize);
|
|
||||||
|
|
||||||
if (b_valid) {
|
|
||||||
p_udf->lvd_lba = i_lba;
|
|
||||||
p_udf->fsd_offset =
|
|
||||||
uint32_from_le(p_logvol->lvd_use.fsd_loc.loc.lba);
|
|
||||||
if (p_udf->i_part_start) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p_udf->lvd_lba && p_udf->i_part_start) {
|
|
||||||
udf_fsd_t *p_fsd = (udf_fsd_t *) &data;
|
|
||||||
|
|
||||||
int i_sectors = udf_read_sectors(p_udf, p_fsd,
|
|
||||||
p_udf->i_part_start + p_udf->fsd_offset,
|
|
||||||
1);
|
|
||||||
|
|
||||||
if (i_sectors > 0 && !udf_checktag(&p_fsd->tag, TAGID_FSD)) {
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* Check partition numbers match of last-read block? */
|
|
||||||
|
|
||||||
memcpy(&p_udf->root_icb, &p_fsd->root_icb, sizeof(udf_long_ad_t));
|
|
||||||
udf_read_sectors(p_udf, p_fe, p_udf->i_part_start + parent_icb, 1);
|
|
||||||
if (!udf_checktag(&p_fe->tag, TAGID_FILE_ENTRY)) {
|
|
||||||
|
|
||||||
/* Check partition numbers match of last-read block? */
|
|
||||||
|
|
||||||
/* We win! - Save root directory information. */
|
|
||||||
p_udf->p_root = udf_new_file(p_fe, p_udf->i_part_start, "/",
|
|
||||||
true, false );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return p_udf;
|
return p_udf;
|
||||||
@@ -410,6 +401,91 @@ udf_open (const char *psz_path)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Get the root in p_udf. If b_any_partition is false then
|
||||||
|
the root must be in the given partition.
|
||||||
|
NULL is returned if the partition is not found or a root is not found or
|
||||||
|
there is on error.
|
||||||
|
|
||||||
|
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,
|
||||||
|
const partition_num_t i_partition)
|
||||||
|
{
|
||||||
|
const anchor_vol_desc_ptr_t *p_avdp = &p_udf->anchor_vol_desc_ptr;
|
||||||
|
const uint32_t mvds_start =
|
||||||
|
uint32_from_le(p_avdp->main_vol_desc_seq_ext.loc);
|
||||||
|
const uint32_t mvds_end = mvds_start +
|
||||||
|
(uint32_from_le(p_avdp->main_vol_desc_seq_ext.len) - 1) / UDF_BLOCKSIZE;
|
||||||
|
uint32_t i_lba;
|
||||||
|
uint8_t data[UDF_BLOCKSIZE];
|
||||||
|
|
||||||
|
/*
|
||||||
|
Now we have the joy of finding the Partition Descriptor and the
|
||||||
|
Logical Volume Descriptor for the Main Volume Descriptor
|
||||||
|
Sequence. Once we've got that, we use the Logical Volume
|
||||||
|
Descriptor to get a Fileset Descriptor and that has the Root
|
||||||
|
Directory File Entry.
|
||||||
|
*/
|
||||||
|
for (i_lba = mvds_start; i_lba < mvds_end; i_lba++) {
|
||||||
|
uint8_t data[UDF_BLOCKSIZE];
|
||||||
|
|
||||||
|
partition_desc_t *p_partition = (partition_desc_t *) &data;
|
||||||
|
|
||||||
|
if (! udf_read_sectors (p_udf, p_partition, i_lba, 1) )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!udf_checktag(&p_partition->tag, TAGID_PARTITION)) {
|
||||||
|
const partition_num_t i_partition_check
|
||||||
|
= uint16_from_le(p_partition->number);
|
||||||
|
if (b_any_partition || i_partition_check == i_partition) {
|
||||||
|
/* Squirrel away some data regarding partition */
|
||||||
|
p_udf->i_partition = uint16_from_le(p_partition->number);
|
||||||
|
p_udf->i_part_start = uint32_from_le(p_partition->start_loc);
|
||||||
|
if (p_udf->lvd_lba) break;
|
||||||
|
}
|
||||||
|
} else if (!udf_checktag(&p_partition->tag, TAGID_LOGVOL)) {
|
||||||
|
/* Get fileset descriptor */
|
||||||
|
logical_vol_desc_t *p_logvol = (logical_vol_desc_t *) &data;
|
||||||
|
bool b_valid =
|
||||||
|
UDF_BLOCKSIZE == uint32_from_le(p_logvol->logical_blocksize);
|
||||||
|
|
||||||
|
if (b_valid) {
|
||||||
|
p_udf->lvd_lba = i_lba;
|
||||||
|
p_udf->fsd_offset =
|
||||||
|
uint32_from_le(p_logvol->lvd_use.fsd_loc.loc.lba);
|
||||||
|
if (p_udf->i_part_start) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p_udf->lvd_lba && p_udf->i_part_start) {
|
||||||
|
udf_fsd_t *p_fsd = (udf_fsd_t *) &data;
|
||||||
|
|
||||||
|
int i_sectors = udf_read_sectors(p_udf, p_fsd,
|
||||||
|
p_udf->i_part_start + p_udf->fsd_offset,
|
||||||
|
1);
|
||||||
|
|
||||||
|
if (i_sectors > 0 && !udf_checktag(&p_fsd->tag, TAGID_FSD)) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Check partition numbers match of last-read block? */
|
||||||
|
|
||||||
|
udf_read_sectors(p_udf, p_fe, p_udf->i_part_start + parent_icb, 1);
|
||||||
|
if (!udf_checktag(&p_fe->tag, TAGID_FILE_ENTRY)) {
|
||||||
|
|
||||||
|
/* Check partition numbers match of last-read block? */
|
||||||
|
|
||||||
|
/* We win! - Save root directory information. */
|
||||||
|
return udf_new_file(p_fe, p_udf->i_part_start, "/", true, false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Close UDF and free resources associated with p_udf.
|
Close UDF and free resources associated with p_udf.
|
||||||
*/
|
*/
|
||||||
@@ -423,8 +499,6 @@ udf_close (udf_t *p_udf)
|
|||||||
cdio_destroy(p_udf->cdio);
|
cdio_destroy(p_udf->cdio);
|
||||||
}
|
}
|
||||||
|
|
||||||
udf_file_free(p_udf->p_root);
|
|
||||||
|
|
||||||
/* Get rid of root directory if allocated. */
|
/* Get rid of root directory if allocated. */
|
||||||
|
|
||||||
free(p_udf);
|
free(p_udf);
|
||||||
@@ -432,21 +506,22 @@ udf_close (udf_t *p_udf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
udf_file_t *
|
udf_file_t *
|
||||||
udf_get_sub(udf_t *p_udf, udf_file_t *p_file)
|
udf_get_sub(udf_t *p_udf, udf_file_t *p_udf_file)
|
||||||
{
|
{
|
||||||
if (p_file->b_dir && !p_file->b_parent && p_file->fid) {
|
if (p_udf_file->b_dir && !p_udf_file->b_parent && 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
|
int i_sectors = udf_read_sectors(p_udf, p_fe, p_udf->i_part_start
|
||||||
+ p_file->fid->icb.loc.lba, 1);
|
+ p_udf_file->fid->icb.loc.lba, 1);
|
||||||
|
|
||||||
if (i_sectors && !udf_checktag(&p_fe->tag, TAGID_FILE_ENTRY)) {
|
if (i_sectors && !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_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,
|
||||||
p_file->psz_name, true, true);
|
p_udf_file->psz_name,
|
||||||
return p_file_new;
|
true, true);
|
||||||
|
return p_udf_file_new;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -454,51 +529,53 @@ udf_get_sub(udf_t *p_udf, udf_file_t *p_file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
udf_file_t *
|
udf_file_t *
|
||||||
udf_get_next(udf_t *p_udf, udf_file_t *p_file)
|
udf_get_next(udf_t *p_udf, udf_file_t *p_udf_file)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (p_file->dir_left <= 0) {
|
if (p_udf_file->dir_left <= 0) {
|
||||||
p_file->fid = NULL;
|
p_udf_file->fid = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_file->fid) {
|
if (p_udf_file->fid) {
|
||||||
/* advance to next File Identifier Descriptor */
|
/* advance to next File Identifier Descriptor */
|
||||||
uint32_t ofs = 4 *
|
uint32_t ofs = 4 *
|
||||||
((sizeof *(p_file->fid) + p_file->fid->i_imp_use + p_file->fid->i_file_id + 3)
|
((sizeof(*(p_udf_file->fid)) + p_udf_file->fid->i_imp_use
|
||||||
/ 4);
|
+ p_udf_file->fid->i_file_id + 3) / 4);
|
||||||
|
|
||||||
p_file->fid = (udf_fileid_desc_t *)((uint8_t *)p_file->fid + ofs);
|
p_udf_file->fid = (udf_fileid_desc_t *)((uint8_t *)p_udf_file->fid + ofs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p_file->fid) {
|
if (!p_udf_file->fid) {
|
||||||
uint32_t i_sectors = (p_file->dir_end_lba - p_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;
|
int i_read;
|
||||||
|
|
||||||
if (!p_file->sector)
|
if (!p_udf_file->sector)
|
||||||
p_file->sector = (uint8_t*) malloc(size);
|
p_udf_file->sector = (uint8_t*) malloc(size);
|
||||||
i_read = udf_read_sectors(p_udf, p_file->sector,
|
i_read = udf_read_sectors(p_udf, p_udf_file->sector,
|
||||||
p_file->i_part_start + p_file->dir_lba,
|
p_udf_file->i_part_start + p_udf_file->dir_lba,
|
||||||
i_sectors);
|
i_sectors);
|
||||||
if (i_read)
|
if (i_read)
|
||||||
p_file->fid = (udf_fileid_desc_t *) p_file->sector;
|
p_udf_file->fid = (udf_fileid_desc_t *) p_udf_file->sector;
|
||||||
else
|
else
|
||||||
p_file->fid = NULL;
|
p_udf_file->fid = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_file->fid && udf_checktag(&(p_file->fid->tag), TAGID_FID))
|
if (p_udf_file->fid && !udf_checktag(&(p_udf_file->fid->tag), TAGID_FID))
|
||||||
{
|
{
|
||||||
uint32_t ofs = 4 * ((sizeof *p_file->fid + p_file->fid->i_imp_use + p_file->fid->i_file_id + 3) / 4);
|
uint32_t ofs =
|
||||||
|
4 * ((sizeof(*p_udf_file->fid) + p_udf_file->fid->i_imp_use
|
||||||
|
+ p_udf_file->fid->i_file_id + 3) / 4);
|
||||||
|
|
||||||
p_file->dir_left -= ofs;
|
p_udf_file->dir_left -= ofs;
|
||||||
p_file->b_dir =
|
p_udf_file->b_dir =
|
||||||
(p_file->fid->file_characteristics & UDF_FILE_DIRECTORY) != 0;
|
(p_udf_file->fid->file_characteristics & UDF_FILE_DIRECTORY) != 0;
|
||||||
p_file->b_parent =
|
p_udf_file->b_parent =
|
||||||
(p_file->fid->file_characteristics & UDF_FILE_PARENT) != 0;
|
(p_udf_file->fid->file_characteristics & UDF_FILE_PARENT) != 0;
|
||||||
unicode16_decode(p_file->fid->imp_use + p_file->fid->i_imp_use,
|
unicode16_decode(p_udf_file->fid->imp_use + p_udf_file->fid->i_imp_use,
|
||||||
p_file->fid->i_file_id, p_file->psz_name);
|
p_udf_file->fid->i_file_id, p_udf_file->psz_name);
|
||||||
return p_file;
|
return p_udf_file;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -507,12 +584,12 @@ udf_get_next(udf_t *p_udf, udf_file_t *p_file)
|
|||||||
free free resources associated with p_fe.
|
free free resources associated with p_fe.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
udf_file_free(udf_file_t * p_fe)
|
udf_file_free(udf_file_t *p_udf_file)
|
||||||
{
|
{
|
||||||
if (p_fe) {
|
if (p_udf_file) {
|
||||||
free(p_fe->psz_name);
|
free(p_udf_file->psz_name);
|
||||||
free(p_fe->sector);
|
free(p_udf_file->sector);
|
||||||
free(p_fe);
|
free(p_udf_file);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user