First inkling of code for UDF support.

This commit is contained in:
rocky
2005-10-24 03:12:30 +00:00
parent c521b4eefd
commit e9be12e7e5
8 changed files with 365 additions and 143 deletions

View File

@@ -19,7 +19,7 @@ define(RELEASE_NUM, 77)
define(CDIO_VERSION_STR, 0.$1cvs)
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_CONFIG_SRCDIR(src/cd-info.c)
@@ -601,6 +601,7 @@ AC_CONFIG_FILES([ \
lib/driver/Makefile \
lib/iso9660/Makefile \
lib/paranoia/Makefile \
lib/udf/Makefile \
libcdio.pc \
libcdio_cdda.pc \
libcdio_paranoia.pc \

View File

@@ -17,3 +17,5 @@ paranoia
paranoia2
sample?
tracks
udf1

View File

@@ -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>
#
@@ -28,7 +28,7 @@ paranoia_progs = paranoia paranoia2
endif
noinst_PROGRAMS = audio cdtext device drives iso1 iso2 iso3 isofuzzy \
mmc1 mmc2 $(paranoia_progs) tracks \
sample3 sample4
sample3 sample4 udf1
INCLUDES = -I$(top_srcdir) $(LIBCDIO_CFLAGS)
@@ -58,5 +58,9 @@ sample4_LDADD = $(LIBCDIO_LIBS)
tracks_LDADD = $(LIBCDIO_LIBS)
udf1_DEPENDENCIES = $(LIBUDF_LIBS) $(LIBCDIO_LIBS)
udf1_LDADD = $(LIBUDF_LIBS) $(LIBCDIO_LIBS)
# iso programs create file "copying"
MOSTLYCLEANFILES = copying

111
example/udf1.c Normal file
View 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;
}

View File

@@ -925,7 +925,7 @@ PRAGMA_END_PACKED
/** The below variables are trickery to force the above enum symbol
values to be recorded in debug symbol tables. They are used to
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 tag_id_t debug_tagid;

View File

@@ -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>
This program is free software; you can redistribute it and/or modify
@@ -30,22 +30,24 @@
#include <cdio/ecma_167.h>
typedef uint16_t partition_num_t;
/* FIXME: these probably don't go here. */
typedef uint16_t unicode16_t;
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. */
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;
uint32_t i_part_start;
uint32_t dir_lba, dir_end_lba;
uint64_t dir_left;
uint8_t *sector;
udf_fileid_desc_t *fid;
} 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_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.
@@ -93,7 +120,7 @@ bool udf_close (udf_t *p_udf);
/*!
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*/

View File

@@ -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>
#
@@ -21,7 +21,7 @@
########################################################
if BUILD_CD_PARANOIA
SUBDIRS = driver iso9660 cdda_interface paranoia
SUBDIRS = driver iso9660 cdda_interface paranoia udf
else
SUBDIRS = driver iso9660
SUBDIRS = driver iso9660 udf
endif

View File

@@ -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>
@@ -134,13 +134,11 @@ struct udf_s {
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 */
uint16_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 */
udf_long_ad_t root_icb;
udf_file_t *p_root;
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 */
};
/**
@@ -216,6 +214,57 @@ udf_get_lba(const udf_file_entry_t *p_fe,
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.
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,
const char *psz_name, bool b_dir, bool b_parent)
{
udf_file_t *p_fid = (udf_file_t *) calloc(1, sizeof(udf_file_t));
if (!p_fid) return NULL;
p_fid->psz_name = strdup(psz_name);
p_fid->b_dir = b_dir;
p_fid->b_parent = b_parent;
p_fid->i_part_start = i_part_start;
p_fid->dir_left = uint64_from_le(p_fe->info_len);
udf_file_t *p_udf_file = (udf_file_t *) calloc(1, sizeof(udf_file_t));
if (!p_udf_file) return NULL;
p_udf_file->psz_name = strdup(psz_name);
p_udf_file->b_dir = b_dir;
p_udf_file->b_parent = b_parent;
p_udf_file->i_part_start = i_part_start;
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) );
return p_fid;
udf_get_lba( p_fe, &(p_udf_file->dir_lba), &(p_udf_file->dir_end_lba) );
return p_udf_file;
}
/*!
@@ -290,13 +339,16 @@ udf_open (const char *psz_path)
if (!p_udf) return NULL;
/* FIXME:
Some magic should be put here to figure out if we mean a UDF file
image or a CD-ROM or DVD. For now we'll go with stream. */
p_udf->b_stream = true;
p_udf->stream = cdio_stdio_new( psz_path );
if (NULL == p_udf->stream)
goto error;
p_udf->b_stream = !cdio_is_device(psz_path, DRIVER_UNKNOWN);
if (p_udf->b_stream) {
p_udf->stream = cdio_stdio_new( psz_path );
if (!p_udf->stream)
goto error;
} else {
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.
@@ -340,67 +392,6 @@ udf_open (const char *psz_path)
*/
if (i_lba == mvds_end)
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;
@@ -410,6 +401,91 @@ udf_open (const char *psz_path)
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.
*/
@@ -423,8 +499,6 @@ udf_close (udf_t *p_udf)
cdio_destroy(p_udf->cdio);
}
udf_file_free(p_udf->p_root);
/* Get rid of root directory if allocated. */
free(p_udf);
@@ -432,21 +506,22 @@ udf_close (udf_t *p_udf)
}
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];
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
+ 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 (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,
p_file->psz_name, true, true);
return p_file_new;
udf_file_t *p_udf_file_new = udf_new_file(p_fe, p_udf->i_part_start,
p_udf_file->psz_name,
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_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) {
p_file->fid = NULL;
if (p_udf_file->dir_left <= 0) {
p_udf_file->fid = NULL;
return NULL;
}
if (p_file->fid) {
if (p_udf_file->fid) {
/* advance to next File Identifier Descriptor */
uint32_t ofs = 4 *
((sizeof *(p_file->fid) + p_file->fid->i_imp_use + p_file->fid->i_file_id + 3)
/ 4);
((sizeof(*(p_udf_file->fid)) + p_udf_file->fid->i_imp_use
+ 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) {
uint32_t i_sectors = (p_file->dir_end_lba - p_file->dir_lba + 1);
if (!p_udf_file->fid) {
uint32_t i_sectors = (p_udf_file->dir_end_lba - p_udf_file->dir_lba + 1);
uint32_t size = UDF_BLOCKSIZE * i_sectors;
int i_read;
if (!p_file->sector)
p_file->sector = (uint8_t*) malloc(size);
i_read = udf_read_sectors(p_udf, p_file->sector,
p_file->i_part_start + p_file->dir_lba,
if (!p_udf_file->sector)
p_udf_file->sector = (uint8_t*) malloc(size);
i_read = udf_read_sectors(p_udf, p_udf_file->sector,
p_udf_file->i_part_start + p_udf_file->dir_lba,
i_sectors);
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
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_file->b_dir =
(p_file->fid->file_characteristics & UDF_FILE_DIRECTORY) != 0;
p_file->b_parent =
(p_file->fid->file_characteristics & UDF_FILE_PARENT) != 0;
unicode16_decode(p_file->fid->imp_use + p_file->fid->i_imp_use,
p_file->fid->i_file_id, p_file->psz_name);
return p_file;
p_udf_file->dir_left -= ofs;
p_udf_file->b_dir =
(p_udf_file->fid->file_characteristics & UDF_FILE_DIRECTORY) != 0;
p_udf_file->b_parent =
(p_udf_file->fid->file_characteristics & UDF_FILE_PARENT) != 0;
unicode16_decode(p_udf_file->fid->imp_use + p_udf_file->fid->i_imp_use,
p_udf_file->fid->i_file_id, p_udf_file->psz_name);
return p_udf_file;
}
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.
*/
bool
udf_file_free(udf_file_t * p_fe)
udf_file_free(udf_file_t *p_udf_file)
{
if (p_fe) {
free(p_fe->psz_name);
free(p_fe->sector);
free(p_fe);
if (p_udf_file) {
free(p_udf_file->psz_name);
free(p_udf_file->sector);
free(p_udf_file);
}
return true;
}