mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[iso] fix UDF UNICODE support
* libcdio's unicode16_decode() was not decoding labels at all, but simply stripping the MSB of the UDF USC-16 sequences * use an actual conversion to UTF-8 * also update the rest of udf_fs.c to latest libcdio version * closes #285
This commit is contained in:
parent
167a877e9f
commit
60b68258dc
3 changed files with 180 additions and 146 deletions
|
@ -113,7 +113,6 @@ FILE* fopen_utf8(const char* filename, const char* mode)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_JOLIET
|
|
||||||
#ifdef HAVE_ICONV
|
#ifdef HAVE_ICONV
|
||||||
#include <iconv.h>
|
#include <iconv.h>
|
||||||
struct cdio_charset_coverter_s
|
struct cdio_charset_coverter_s
|
||||||
|
@ -344,5 +343,3 @@ bool cdio_charset_to_utf8(const char *src, size_t src_len, cdio_utf8_t **dst,
|
||||||
return (*dst != NULL);
|
return (*dst != NULL);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_ICONV */
|
#endif /* HAVE_ICONV */
|
||||||
|
|
||||||
#endif /* HAVE_JOLIET */
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2005, 2006, 2008, 2011 Rocky Bernstein <rocky@gnu.org>
|
Copyright (C) 2005-2006, 2008, 2011, 2013 Rocky Bernstein <rocky@gnu.org>
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* These definitions are also to make debugging easy. Note that they
|
/* These definitions are also to make debugging easy. Note that they
|
||||||
have to come *before* #include <cdio/ecma_167.h> which sets
|
have to come *before* #include <cdio/ecma_167.h> which sets
|
||||||
#defines for these.
|
#defines for these.
|
||||||
*/
|
*/
|
||||||
const char VSD_STD_ID_BEA01[] = {'B', 'E', 'A', '0', '1'};
|
const char VSD_STD_ID_BEA01[] = {'B', 'E', 'A', '0', '1'};
|
||||||
|
@ -70,6 +70,9 @@ 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/bytesex.h>
|
#include <cdio/bytesex.h>
|
||||||
|
#include <cdio/utf8.h>
|
||||||
|
#include <cdio/util.h>
|
||||||
|
|
||||||
#include "udf_private.h"
|
#include "udf_private.h"
|
||||||
#include "udf_fs.h"
|
#include "udf_fs.h"
|
||||||
#include "cdio_assert.h"
|
#include "cdio_assert.h"
|
||||||
|
@ -131,24 +134,28 @@ udf_checktag(const udf_tag_t *p_tag, udf_Uint16_t tag_id)
|
||||||
uint8_t *itag;
|
uint8_t *itag;
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
uint8_t cksum = 0;
|
uint8_t cksum = 0;
|
||||||
|
|
||||||
itag = (uint8_t *)p_tag;
|
itag = (uint8_t *)p_tag;
|
||||||
|
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
tag_id = UINT16_SWAP_LE_BE(tag_id);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (p_tag->id != tag_id)
|
if (p_tag->id != tag_id)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for (i = 0; i < 15; i++)
|
for (i = 0; i < 15; i++)
|
||||||
cksum = cksum + itag[i];
|
cksum = cksum + itag[i];
|
||||||
cksum = cksum - itag[4];
|
cksum = cksum - itag[4];
|
||||||
|
|
||||||
if (cksum == p_tag->cksum)
|
if (cksum == p_tag->cksum)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
udf_get_lba(const udf_file_entry_t *p_udf_fe,
|
udf_get_lba(const udf_file_entry_t *p_udf_fe,
|
||||||
/*out*/ uint32_t *start, /*out*/ uint32_t *end)
|
/*out*/ uint32_t *start, /*out*/ uint32_t *end)
|
||||||
{
|
{
|
||||||
if (! p_udf_fe->i_alloc_descs)
|
if (! p_udf_fe->i_alloc_descs)
|
||||||
|
@ -158,11 +165,11 @@ udf_get_lba(const udf_file_entry_t *p_udf_fe,
|
||||||
case ICBTAG_FLAG_AD_SHORT:
|
case ICBTAG_FLAG_AD_SHORT:
|
||||||
{
|
{
|
||||||
/* The allocation descriptor field is filled with short_ad's. */
|
/* The allocation descriptor field is filled with short_ad's. */
|
||||||
udf_short_ad_t *p_ad = (udf_short_ad_t *)
|
udf_short_ad_t *p_ad = (udf_short_ad_t *)
|
||||||
(p_udf_fe->u.ext_attr + p_udf_fe->i_extended_attr);
|
(p_udf_fe->u.ext_attr + p_udf_fe->i_extended_attr);
|
||||||
|
|
||||||
*start = uint32_from_le(p_ad->pos);
|
*start = uint32_from_le(p_ad->pos);
|
||||||
*end = *start +
|
*end = *start +
|
||||||
((uint32_from_le(p_ad->len) & UDF_LENGTH_MASK) - 1) / UDF_BLOCKSIZE;
|
((uint32_from_le(p_ad->len) & UDF_LENGTH_MASK) - 1) / UDF_BLOCKSIZE;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -170,11 +177,11 @@ udf_get_lba(const udf_file_entry_t *p_udf_fe,
|
||||||
case ICBTAG_FLAG_AD_LONG:
|
case ICBTAG_FLAG_AD_LONG:
|
||||||
{
|
{
|
||||||
/* The allocation descriptor field is filled with long_ad's */
|
/* The allocation descriptor field is filled with long_ad's */
|
||||||
udf_long_ad_t *p_ad = (udf_long_ad_t *)
|
udf_long_ad_t *p_ad = (udf_long_ad_t *)
|
||||||
(p_udf_fe->u.ext_attr + p_udf_fe->i_extended_attr);
|
(p_udf_fe->u.ext_attr + p_udf_fe->i_extended_attr);
|
||||||
|
|
||||||
*start = uint32_from_le(p_ad->loc.lba); /* ignore partition number */
|
*start = uint32_from_le(p_ad->loc.lba); /* ignore partition number */
|
||||||
*end = *start +
|
*end = *start +
|
||||||
((uint32_from_le(p_ad->len) & UDF_LENGTH_MASK) - 1) / UDF_BLOCKSIZE;
|
((uint32_from_le(p_ad->len) & UDF_LENGTH_MASK) - 1) / UDF_BLOCKSIZE;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -183,9 +190,9 @@ udf_get_lba(const udf_file_entry_t *p_udf_fe,
|
||||||
{
|
{
|
||||||
udf_ext_ad_t *p_ad = (udf_ext_ad_t *)
|
udf_ext_ad_t *p_ad = (udf_ext_ad_t *)
|
||||||
(p_udf_fe->u.ext_attr + p_udf_fe->i_extended_attr);
|
(p_udf_fe->u.ext_attr + p_udf_fe->i_extended_attr);
|
||||||
|
|
||||||
*start = uint32_from_le(p_ad->ext_loc.lba); /* ignore partition number */
|
*start = uint32_from_le(p_ad->ext_loc.lba); /* ignore partition number */
|
||||||
*end = *start +
|
*end = *start +
|
||||||
((uint32_from_le(p_ad->len) & UDF_LENGTH_MASK) - 1) / UDF_BLOCKSIZE;
|
((uint32_from_le(p_ad->len) & UDF_LENGTH_MASK) - 1) / UDF_BLOCKSIZE;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -203,21 +210,21 @@ udf_get_lba(const udf_file_entry_t *p_udf_fe,
|
||||||
not found p_udf_dirent is useless and thus the caller should
|
not found p_udf_dirent is useless and thus the caller should
|
||||||
not use it afterwards.
|
not use it afterwards.
|
||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
udf_dirent_t *
|
udf_dirent_t *
|
||||||
udf_ff_traverse(udf_dirent_t *p_udf_dirent, char *psz_token)
|
udf_ff_traverse(udf_dirent_t *p_udf_dirent, char *psz_token)
|
||||||
{
|
{
|
||||||
while ((p_udf_dirent = udf_readdir(p_udf_dirent))) {
|
while ((p_udf_dirent = udf_readdir(p_udf_dirent))) {
|
||||||
if (strcmp(psz_token, p_udf_dirent->psz_name) == 0) {
|
if (strcmp(psz_token, p_udf_dirent->psz_name) == 0) {
|
||||||
char *next_tok = strtok(NULL, udf_PATH_DELIMITERS);
|
char *next_tok = strtok(NULL, udf_PATH_DELIMITERS);
|
||||||
|
|
||||||
if (!next_tok)
|
if (!next_tok)
|
||||||
return p_udf_dirent; /* found */
|
return p_udf_dirent; /* found */
|
||||||
else if (p_udf_dirent->b_dir) {
|
else if (p_udf_dirent->b_dir) {
|
||||||
udf_dirent_t * p_udf_dirent2 = udf_opendir(p_udf_dirent);
|
udf_dirent_t * p_udf_dirent2 = udf_opendir(p_udf_dirent);
|
||||||
|
|
||||||
if (p_udf_dirent2) {
|
if (p_udf_dirent2) {
|
||||||
udf_dirent_t * p_udf_dirent3 =
|
udf_dirent_t * p_udf_dirent3 =
|
||||||
udf_ff_traverse(p_udf_dirent2, next_tok);
|
udf_ff_traverse(p_udf_dirent2, next_tok);
|
||||||
|
|
||||||
/* if p_udf_dirent3 is null p_udf_dirent2 is free'd. */
|
/* if p_udf_dirent3 is null p_udf_dirent2 is free'd. */
|
||||||
|
@ -234,11 +241,11 @@ udf_ff_traverse(udf_dirent_t *p_udf_dirent, char *psz_token)
|
||||||
/* FIXME! */
|
/* FIXME! */
|
||||||
#define udf_MAX_PATHLEN 2048
|
#define udf_MAX_PATHLEN 2048
|
||||||
|
|
||||||
udf_dirent_t *
|
udf_dirent_t *
|
||||||
udf_fopen(udf_dirent_t *p_udf_root, const char *psz_name)
|
udf_fopen(udf_dirent_t *p_udf_root, const char *psz_name)
|
||||||
{
|
{
|
||||||
udf_dirent_t *p_udf_file = NULL;
|
udf_dirent_t *p_udf_file = NULL;
|
||||||
|
|
||||||
if (p_udf_root) {
|
if (p_udf_root) {
|
||||||
char tokenline[udf_MAX_PATHLEN];
|
char tokenline[udf_MAX_PATHLEN];
|
||||||
char *psz_token;
|
char *psz_token;
|
||||||
|
@ -251,11 +258,11 @@ udf_fopen(udf_dirent_t *p_udf_root, const char *psz_name)
|
||||||
if (psz_token) {
|
if (psz_token) {
|
||||||
/*** FIXME??? udf_dirent can be variable size due to the
|
/*** FIXME??? udf_dirent can be variable size due to the
|
||||||
extended attributes and descriptors. Given that, is this
|
extended attributes and descriptors. Given that, is this
|
||||||
correct?
|
correct?
|
||||||
*/
|
*/
|
||||||
udf_dirent_t *p_udf_dirent =
|
udf_dirent_t *p_udf_dirent =
|
||||||
udf_new_dirent(&p_udf_root->fe, p_udf_root->p_udf,
|
udf_new_dirent(&p_udf_root->fe, p_udf_root->p_udf,
|
||||||
p_udf_root->psz_name, p_udf_root->b_dir,
|
p_udf_root->psz_name, p_udf_root->b_dir,
|
||||||
p_udf_root->b_parent);
|
p_udf_root->b_parent);
|
||||||
p_udf_file = udf_ff_traverse(p_udf_dirent, psz_token);
|
p_udf_file = udf_ff_traverse(p_udf_dirent, psz_token);
|
||||||
if (p_udf_file != p_udf_dirent)
|
if (p_udf_file != p_udf_dirent)
|
||||||
|
@ -263,67 +270,75 @@ udf_fopen(udf_dirent_t *p_udf_root, const char *psz_name)
|
||||||
}
|
}
|
||||||
else if ( 0 == strncmp("/", psz_name, sizeof("/")) ) {
|
else if ( 0 == strncmp("/", psz_name, sizeof("/")) ) {
|
||||||
return udf_new_dirent(&p_udf_root->fe, p_udf_root->p_udf,
|
return udf_new_dirent(&p_udf_root->fe, p_udf_root->p_udf,
|
||||||
p_udf_root->psz_name, p_udf_root->b_dir,
|
p_udf_root->psz_name, p_udf_root->b_dir,
|
||||||
p_udf_root->b_parent);
|
p_udf_root->b_parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p_udf_file;
|
return p_udf_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert unicode16 to 8-bit char by dripping MSB.
|
/* Convert unicode16 to UTF-8.
|
||||||
Wonder if iconv can be used here
|
The returned string is allocated and must be freed by the caller
|
||||||
*/
|
*/
|
||||||
static int
|
static char*
|
||||||
unicode16_decode( const uint8_t *data, int i_len, char *target )
|
unicode16_decode(const uint8_t *data, int i_len)
|
||||||
{
|
{
|
||||||
int p = 1, i = 0;
|
int i;
|
||||||
|
char* r = NULL;
|
||||||
if( ( data[ 0 ] == 8 ) || ( data[ 0 ] == 16 ) ) do {
|
|
||||||
if( data[ 0 ] == 16 ) p++; /* Ignore MSB of unicode16 */
|
switch (data[0])
|
||||||
if( p < i_len ) {
|
{
|
||||||
target[ i++ ] = data[ p++ ];
|
case 8:
|
||||||
}
|
r = (char*)malloc(i_len);
|
||||||
} while( p < i_len );
|
if (r == NULL)
|
||||||
|
return r;
|
||||||
target[ i ] = '\0';
|
for (i=0; i<i_len-1; i++)
|
||||||
return 0;
|
r[i] = data[i+1];
|
||||||
|
r[i] = 0;
|
||||||
|
return r;
|
||||||
|
case 16:
|
||||||
|
cdio_charset_to_utf8((char*)&data[1], i_len-1, &r, "UCS-2BE");
|
||||||
|
return r;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static udf_dirent_t *
|
static udf_dirent_t *
|
||||||
udf_new_dirent(udf_file_entry_t *p_udf_fe, udf_t *p_udf,
|
udf_new_dirent(udf_file_entry_t *p_udf_fe, udf_t *p_udf,
|
||||||
const char *psz_name, bool b_dir, bool b_parent)
|
const char *psz_name, bool b_dir, bool b_parent)
|
||||||
{
|
{
|
||||||
udf_dirent_t *p_udf_dirent = (udf_dirent_t *)
|
udf_dirent_t *p_udf_dirent = (udf_dirent_t *)
|
||||||
calloc(1, sizeof(udf_dirent_t));
|
calloc(1, sizeof(udf_dirent_t));
|
||||||
if (!p_udf_dirent) return NULL;
|
if (!p_udf_dirent) return NULL;
|
||||||
|
|
||||||
p_udf_dirent->psz_name = strdup(psz_name);
|
p_udf_dirent->psz_name = strdup(psz_name);
|
||||||
p_udf_dirent->b_dir = b_dir;
|
p_udf_dirent->b_dir = b_dir;
|
||||||
p_udf_dirent->b_parent = b_parent;
|
p_udf_dirent->b_parent = b_parent;
|
||||||
p_udf_dirent->p_udf = p_udf;
|
p_udf_dirent->p_udf = p_udf;
|
||||||
p_udf_dirent->i_part_start = p_udf->i_part_start;
|
p_udf_dirent->i_part_start = p_udf->i_part_start;
|
||||||
p_udf_dirent->dir_left = uint64_from_le(p_udf_fe->info_len);
|
p_udf_dirent->dir_left = uint64_from_le(p_udf_fe->info_len);
|
||||||
|
|
||||||
memcpy(&(p_udf_dirent->fe), p_udf_fe,
|
memcpy(&(p_udf_dirent->fe), p_udf_fe,
|
||||||
sizeof(udf_file_entry_t));
|
sizeof(udf_file_entry_t));
|
||||||
udf_get_lba( p_udf_fe, &(p_udf_dirent->i_loc),
|
udf_get_lba( p_udf_fe, &(p_udf_dirent->i_loc),
|
||||||
&(p_udf_dirent->i_loc_end) );
|
&(p_udf_dirent->i_loc_end) );
|
||||||
return p_udf_dirent;
|
return p_udf_dirent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
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.
|
||||||
*/
|
*/
|
||||||
driver_return_code_t
|
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 i_blocks)
|
long i_blocks)
|
||||||
{
|
{
|
||||||
driver_return_code_t ret;
|
driver_return_code_t ret;
|
||||||
long i_read;
|
long i_read;
|
||||||
off_t i_byte_offset;
|
off_t i_byte_offset;
|
||||||
|
|
||||||
if (!p_udf) return 0;
|
if (!p_udf) return 0;
|
||||||
/* Without the cast, i_start * UDF_BLOCKSIZE may be evaluated as 32 bit */
|
/* Without the cast, i_start * UDF_BLOCKSIZE may be evaluated as 32 bit */
|
||||||
i_byte_offset = ((off_t)i_start) * UDF_BLOCKSIZE;
|
i_byte_offset = ((off_t)i_start) * UDF_BLOCKSIZE;
|
||||||
|
@ -369,7 +384,7 @@ udf_open (const char *psz_path)
|
||||||
encapsulated as a CD-ROM Image (e.g. often .UDF or (sic) .ISO)
|
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;
|
||||||
p_udf->b_stream = true;
|
p_udf->b_stream = true;
|
||||||
}
|
}
|
||||||
|
@ -379,36 +394,36 @@ udf_open (const char *psz_path)
|
||||||
*/
|
*/
|
||||||
if (DRIVER_OP_SUCCESS != 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));
|
||||||
|
|
||||||
if (udf_checktag((udf_tag_t *)&(p_udf->anchor_vol_desc_ptr), TAGID_ANCHOR))
|
if (udf_checktag((udf_tag_t *)&(p_udf->anchor_vol_desc_ptr), TAGID_ANCHOR))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Then try to find a reference to a Primary Volume Descriptor.
|
* Then try to find a reference to a Primary Volume Descriptor.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
const anchor_vol_desc_ptr_t *p_avdp = &p_udf->anchor_vol_desc_ptr;
|
anchor_vol_desc_ptr_t *p_avdp = &p_udf->anchor_vol_desc_ptr;
|
||||||
const uint32_t mvds_start =
|
|
||||||
|
const uint32_t mvds_start =
|
||||||
uint32_from_le(p_avdp->main_vol_desc_seq_ext.loc);
|
uint32_from_le(p_avdp->main_vol_desc_seq_ext.loc);
|
||||||
const uint32_t mvds_end = mvds_start +
|
const uint32_t mvds_end = mvds_start +
|
||||||
(uint32_from_le(p_avdp->main_vol_desc_seq_ext.len) - 1) / UDF_BLOCKSIZE;
|
(uint32_from_le(p_avdp->main_vol_desc_seq_ext.len) - 1) / UDF_BLOCKSIZE;
|
||||||
|
|
||||||
uint32_t i_lba;
|
uint32_t i_lba;
|
||||||
|
|
||||||
for (i_lba = mvds_start; i_lba < mvds_end; i_lba++) {
|
for (i_lba = mvds_start; i_lba < mvds_end; i_lba++) {
|
||||||
|
|
||||||
udf_pvd_t *p_pvd = (udf_pvd_t *) &data;
|
udf_pvd_t *p_pvd = (udf_pvd_t *) &data;
|
||||||
|
|
||||||
if (DRIVER_OP_SUCCESS != 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)) {
|
||||||
p_udf->pvd_lba = i_lba;
|
p_udf->pvd_lba = i_lba;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -427,18 +442,24 @@ udf_open (const char *psz_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the Volume Identifier string, in 8bit unicode (latin-1)
|
* Gets the Volume Identifier, as an UTF-8 string
|
||||||
* psz_volid, place to put the string
|
* psz_volid, place to put the string
|
||||||
* i_volid, size of the buffer psz_volid points to
|
* i_volid, size of the buffer psz_volid points to
|
||||||
* returns the size of buffer needed for all data
|
* returns the size of buffer needed for all data
|
||||||
|
* Note: this call accepts a NULL psz_volid, to retrieve the length required.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
udf_get_volume_id(udf_t *p_udf, /*out*/ char *psz_volid, unsigned int i_volid)
|
udf_get_volume_id(udf_t *p_udf, /*out*/ char *psz_volid, unsigned int i_volid)
|
||||||
{
|
{
|
||||||
uint8_t data[UDF_BLOCKSIZE];
|
uint8_t data[UDF_BLOCKSIZE];
|
||||||
const udf_pvd_t *p_pvd = (udf_pvd_t *) &data;
|
const udf_pvd_t *p_pvd = (udf_pvd_t *) &data;
|
||||||
|
char* r;
|
||||||
unsigned int volid_len;
|
unsigned int volid_len;
|
||||||
|
|
||||||
|
/* clear the output to empty string */
|
||||||
|
if (psz_volid != NULL)
|
||||||
|
psz_volid[0] = 0;
|
||||||
|
|
||||||
/* get primary volume descriptor */
|
/* get primary volume descriptor */
|
||||||
if ( DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, &data, p_udf->pvd_lba, 1) )
|
if ( DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, &data, p_udf->pvd_lba, 1) )
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -448,11 +469,18 @@ udf_get_volume_id(udf_t *p_udf, /*out*/ char *psz_volid, unsigned int i_volid)
|
||||||
/* this field is only UDF_VOLID_SIZE bytes something is wrong */
|
/* this field is only UDF_VOLID_SIZE bytes something is wrong */
|
||||||
volid_len = UDF_VOLID_SIZE-1;
|
volid_len = UDF_VOLID_SIZE-1;
|
||||||
}
|
}
|
||||||
if(i_volid > volid_len) {
|
|
||||||
i_volid = volid_len;
|
r = unicode16_decode((uint8_t *) p_pvd->vol_ident, volid_len);
|
||||||
|
if (r == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
volid_len = strlen(r)+1; /* +1 for NUL terminator */
|
||||||
|
if (psz_volid != NULL) {
|
||||||
|
strncpy(psz_volid, r, MIN(volid_len, i_volid));
|
||||||
|
psz_volid[i_volid-1] = 0; /* strncpy does not always terminate the dest */
|
||||||
}
|
}
|
||||||
unicode16_decode((uint8_t *) p_pvd->vol_ident, i_volid, psz_volid);
|
free(r);
|
||||||
|
|
||||||
return volid_len;
|
return volid_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,12 +488,12 @@ udf_get_volume_id(udf_t *p_udf, /*out*/ char *psz_volid, unsigned int i_volid)
|
||||||
* Gets the Volume Set Identifier, as a 128-byte dstring (not decoded)
|
* Gets the Volume Set Identifier, as a 128-byte dstring (not decoded)
|
||||||
* WARNING This is not a null terminated string
|
* WARNING This is not a null terminated string
|
||||||
* volsetid, place to put the data
|
* volsetid, place to put the data
|
||||||
* i_volsetid, size of the buffer psz_volsetid points to
|
* i_volsetid, size of the buffer psz_volsetid points to
|
||||||
* the buffer should be >=128 bytes to store the whole volumesetidentifier
|
* the buffer should be >=128 bytes to store the whole volumesetidentifier
|
||||||
* returns the size of the available volsetid information (128)
|
* returns the size of the available volsetid information (128)
|
||||||
* or 0 on error
|
* or 0 on error
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
udf_get_volumeset_id(udf_t *p_udf, /*out*/ uint8_t *volsetid,
|
udf_get_volumeset_id(udf_t *p_udf, /*out*/ uint8_t *volsetid,
|
||||||
unsigned int i_volsetid)
|
unsigned int i_volsetid)
|
||||||
{
|
{
|
||||||
|
@ -479,34 +507,46 @@ udf_get_volumeset_id(udf_t *p_udf, /*out*/ uint8_t *volsetid,
|
||||||
if (i_volsetid > UDF_VOLSET_ID_SIZE) {
|
if (i_volsetid > UDF_VOLSET_ID_SIZE) {
|
||||||
i_volsetid = UDF_VOLSET_ID_SIZE;
|
i_volsetid = UDF_VOLSET_ID_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(volsetid, p_pvd->volset_id, i_volsetid);
|
memcpy(volsetid, p_pvd->volset_id, i_volsetid);
|
||||||
|
|
||||||
return UDF_VOLSET_ID_SIZE;
|
return UDF_VOLSET_ID_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the Logical Volume Identifier string, in 8bit unicode (latin-1)
|
* Gets the Logical Volume Identifier string, as an UTF-8 string
|
||||||
* psz_logvolid, place to put the string (should be at least 64 bytes)
|
* psz_logvolid, place to put the string (should be at least 64 bytes)
|
||||||
* i_logvolid, size of the buffer psz_logvolid points to
|
* i_logvolid, size of the buffer psz_logvolid points to
|
||||||
* returns the size of buffer needed for all data
|
* returns the size of buffer needed for all data, including NUL terminator
|
||||||
* A call to udf_get_root() should have been issued before this call
|
* A call to udf_get_root() should have been issued before this call
|
||||||
|
* Note: this call accepts a NULL psz_volid, to retrieve the length required.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
udf_get_logical_volume_id(udf_t *p_udf, /*out*/ char *psz_logvolid, unsigned int i_logvolid)
|
udf_get_logical_volume_id(udf_t *p_udf, /*out*/ char *psz_logvolid, unsigned int i_logvolid)
|
||||||
{
|
{
|
||||||
uint8_t data[UDF_BLOCKSIZE];
|
uint8_t data[UDF_BLOCKSIZE];
|
||||||
logical_vol_desc_t *p_logvol = (logical_vol_desc_t *) &data;
|
logical_vol_desc_t *p_logvol = (logical_vol_desc_t *) &data;
|
||||||
|
char* r;
|
||||||
int logvolid_len;
|
int logvolid_len;
|
||||||
|
|
||||||
|
/* clear the output to empty string */
|
||||||
|
if (psz_logvolid != NULL)
|
||||||
|
psz_logvolid[0] = 0;
|
||||||
|
|
||||||
if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, p_logvol, p_udf->lvd_lba, 1) )
|
if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, p_logvol, p_udf->lvd_lba, 1) )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
logvolid_len = (p_logvol->logvol_id[127]+1)/2;
|
r = unicode16_decode((uint8_t *) p_logvol->logvol_id, p_logvol->logvol_id[127]);
|
||||||
if (i_logvolid > logvolid_len)
|
if (r == NULL)
|
||||||
i_logvolid = logvolid_len;
|
return 0;
|
||||||
|
|
||||||
|
logvolid_len = strlen(r)+1; /* +1 for NUL terminator */
|
||||||
|
if (psz_logvolid != NULL) {
|
||||||
|
strncpy(psz_logvolid, r, MIN(logvolid_len, i_logvolid));
|
||||||
|
psz_logvolid[i_logvolid-1] = 0; /* strncpy does not always terminate the dest */
|
||||||
|
}
|
||||||
|
free(r);
|
||||||
|
|
||||||
unicode16_decode((uint8_t *) p_logvol->logvol_id, 2*i_logvolid, psz_logvolid);
|
|
||||||
return logvolid_len;
|
return logvolid_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,14 +562,14 @@ udf_dirent_t *
|
||||||
udf_get_root (udf_t *p_udf, bool b_any_partition, partition_num_t i_partition)
|
udf_get_root (udf_t *p_udf, bool b_any_partition, 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 =
|
||||||
uint32_from_le(p_avdp->main_vol_desc_seq_ext.loc);
|
uint32_from_le(p_avdp->main_vol_desc_seq_ext.loc);
|
||||||
const uint32_t mvds_end = mvds_start +
|
const uint32_t mvds_end = mvds_start +
|
||||||
(uint32_from_le(p_avdp->main_vol_desc_seq_ext.len) - 1) / UDF_BLOCKSIZE;
|
(uint32_from_le(p_avdp->main_vol_desc_seq_ext.len) - 1) / UDF_BLOCKSIZE;
|
||||||
uint32_t i_lba;
|
uint32_t i_lba;
|
||||||
uint8_t data[UDF_BLOCKSIZE];
|
uint8_t data[UDF_BLOCKSIZE];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Now we have the joy of finding the Partition Descriptor and the
|
Now we have the joy of finding the Partition Descriptor and the
|
||||||
Logical Volume Descriptor for the Main Volume Descriptor
|
Logical Volume Descriptor for the Main Volume Descriptor
|
||||||
Sequence. Once we've got that, we use the Logical Volume
|
Sequence. Once we've got that, we use the Logical Volume
|
||||||
|
@ -538,14 +578,14 @@ udf_get_root (udf_t *p_udf, bool b_any_partition, partition_num_t i_partition)
|
||||||
*/
|
*/
|
||||||
for (i_lba = mvds_start; i_lba < mvds_end; i_lba++) {
|
for (i_lba = mvds_start; i_lba < mvds_end; i_lba++) {
|
||||||
uint8_t data2[UDF_BLOCKSIZE];
|
uint8_t data2[UDF_BLOCKSIZE];
|
||||||
|
|
||||||
partition_desc_t *p_partition = (partition_desc_t *) &data2;
|
partition_desc_t *p_partition = (partition_desc_t *) &data2;
|
||||||
|
|
||||||
if (DRIVER_OP_SUCCESS != 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)) {
|
||||||
const partition_num_t i_partition_check
|
const partition_num_t i_partition_check
|
||||||
= uint16_from_le(p_partition->number);
|
= uint16_from_le(p_partition->number);
|
||||||
if (b_any_partition || i_partition_check == i_partition) {
|
if (b_any_partition || i_partition_check == i_partition) {
|
||||||
/* Squirrel away some data regarding partition */
|
/* Squirrel away some data regarding partition */
|
||||||
|
@ -556,37 +596,37 @@ udf_get_root (udf_t *p_udf, bool b_any_partition, partition_num_t i_partition)
|
||||||
} else if (!udf_checktag(&p_partition->tag, TAGID_LOGVOL)) {
|
} else if (!udf_checktag(&p_partition->tag, TAGID_LOGVOL)) {
|
||||||
/* Get fileset descriptor */
|
/* Get fileset descriptor */
|
||||||
logical_vol_desc_t *p_logvol = (logical_vol_desc_t *) &data2;
|
logical_vol_desc_t *p_logvol = (logical_vol_desc_t *) &data2;
|
||||||
bool b_valid =
|
bool b_valid =
|
||||||
UDF_BLOCKSIZE == uint32_from_le(p_logvol->logical_blocksize);
|
UDF_BLOCKSIZE == uint32_from_le(p_logvol->logical_blocksize);
|
||||||
|
|
||||||
if (b_valid) {
|
if (b_valid) {
|
||||||
p_udf->lvd_lba = i_lba;
|
p_udf->lvd_lba = i_lba;
|
||||||
p_udf->fsd_offset =
|
p_udf->fsd_offset =
|
||||||
uint32_from_le(p_logvol->lvd_use.fsd_loc.loc.lba);
|
uint32_from_le(p_logvol->lvd_use.fsd_loc.loc.lba);
|
||||||
if (p_udf->i_part_start) break;
|
if (p_udf->i_part_start) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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;
|
||||||
|
|
||||||
driver_return_code_t ret =
|
driver_return_code_t ret =
|
||||||
udf_read_sectors(p_udf, p_fsd, 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 (DRIVER_OP_SUCCESS == ret && !udf_checktag(&p_fsd->tag, TAGID_FSD)) {
|
if (DRIVER_OP_SUCCESS == ret && !udf_checktag(&p_fsd->tag, TAGID_FSD)) {
|
||||||
udf_file_entry_t *p_udf_fe = (udf_file_entry_t *) &data;
|
udf_file_entry_t *p_udf_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? */
|
||||||
|
|
||||||
ret = udf_read_sectors(p_udf, p_udf_fe,
|
ret = udf_read_sectors(p_udf, p_udf_fe,
|
||||||
p_udf->i_part_start + parent_icb, 1);
|
p_udf->i_part_start + parent_icb, 1);
|
||||||
if (ret == DRIVER_OP_SUCCESS &&
|
if (ret == DRIVER_OP_SUCCESS &&
|
||||||
!udf_checktag(&p_udf_fe->tag, TAGID_FILE_ENTRY)) {
|
!udf_checktag(&p_udf_fe->tag, TAGID_FILE_ENTRY)) {
|
||||||
|
|
||||||
/* Check partition numbers match of last-read block? */
|
/* Check partition numbers match of last-read block? */
|
||||||
|
|
||||||
/* We win! - Save root directory information. */
|
/* We win! - Save root directory information. */
|
||||||
return udf_new_dirent(p_udf_fe, p_udf, "/", true, false );
|
return udf_new_dirent(p_udf_fe, p_udf, "/", true, false );
|
||||||
}
|
}
|
||||||
|
@ -598,13 +638,13 @@ udf_get_root (udf_t *p_udf, bool b_any_partition, partition_num_t i_partition)
|
||||||
|
|
||||||
#define free_and_null(x) \
|
#define free_and_null(x) \
|
||||||
free(x); \
|
free(x); \
|
||||||
x=NULL
|
x=NULL
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Close UDF and free resources associated with p_udf.
|
Close UDF and free resources associated with p_udf.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
udf_close (udf_t *p_udf)
|
udf_close (udf_t *p_udf)
|
||||||
{
|
{
|
||||||
if (!p_udf) return true;
|
if (!p_udf) return true;
|
||||||
if (p_udf->b_stream) {
|
if (p_udf->b_stream) {
|
||||||
|
@ -619,22 +659,22 @@ udf_close (udf_t *p_udf)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
udf_dirent_t *
|
udf_dirent_t *
|
||||||
udf_opendir(const udf_dirent_t *p_udf_dirent)
|
udf_opendir(const udf_dirent_t *p_udf_dirent)
|
||||||
{
|
{
|
||||||
if (p_udf_dirent->b_dir && !p_udf_dirent->b_parent && p_udf_dirent->fid) {
|
if (p_udf_dirent->b_dir && !p_udf_dirent->b_parent && p_udf_dirent->fid) {
|
||||||
udf_t *p_udf = p_udf_dirent->p_udf;
|
udf_t *p_udf = p_udf_dirent->p_udf;
|
||||||
udf_file_entry_t udf_fe;
|
udf_file_entry_t udf_fe;
|
||||||
|
|
||||||
driver_return_code_t i_ret =
|
driver_return_code_t i_ret =
|
||||||
udf_read_sectors(p_udf, &udf_fe, p_udf->i_part_start
|
udf_read_sectors(p_udf, &udf_fe, p_udf->i_part_start
|
||||||
+ p_udf_dirent->fid->icb.loc.lba, 1);
|
+ p_udf_dirent->fid->icb.loc.lba, 1);
|
||||||
|
|
||||||
if (DRIVER_OP_SUCCESS == i_ret
|
if (DRIVER_OP_SUCCESS == i_ret
|
||||||
&& !udf_checktag(&udf_fe.tag, TAGID_FILE_ENTRY)) {
|
&& !udf_checktag(&udf_fe.tag, TAGID_FILE_ENTRY)) {
|
||||||
|
|
||||||
if (ICBTAG_FILE_TYPE_DIRECTORY == udf_fe.icb_tag.file_type) {
|
if (ICBTAG_FILE_TYPE_DIRECTORY == udf_fe.icb_tag.file_type) {
|
||||||
udf_dirent_t *p_udf_dirent_new =
|
udf_dirent_t *p_udf_dirent_new =
|
||||||
udf_new_dirent(&udf_fe, p_udf, p_udf_dirent->psz_name, true, true);
|
udf_new_dirent(&udf_fe, p_udf, p_udf_dirent->psz_name, true, true);
|
||||||
return p_udf_dirent_new;
|
return p_udf_dirent_new;
|
||||||
}
|
}
|
||||||
|
@ -647,7 +687,8 @@ udf_dirent_t *
|
||||||
udf_readdir(udf_dirent_t *p_udf_dirent)
|
udf_readdir(udf_dirent_t *p_udf_dirent)
|
||||||
{
|
{
|
||||||
udf_t *p_udf;
|
udf_t *p_udf;
|
||||||
|
uint8_t* p;
|
||||||
|
|
||||||
if (p_udf_dirent->dir_left <= 0) {
|
if (p_udf_dirent->dir_left <= 0) {
|
||||||
udf_dirent_free(p_udf_dirent);
|
udf_dirent_free(p_udf_dirent);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -657,62 +698,58 @@ udf_readdir(udf_dirent_t *p_udf_dirent)
|
||||||
p_udf = p_udf_dirent->p_udf;
|
p_udf = p_udf_dirent->p_udf;
|
||||||
p_udf->i_position = 0;
|
p_udf->i_position = 0;
|
||||||
|
|
||||||
if (p_udf_dirent->fid) {
|
if (p_udf_dirent->fid) {
|
||||||
/* advance to next File Identifier Descriptor */
|
/* advance to next File Identifier Descriptor */
|
||||||
/* FIXME: need to advance file entry (fe) as well. */
|
/* FIXME: need to advance file entry (fe) as well. */
|
||||||
uint32_t ofs = 4 *
|
uint32_t ofs = 4 *
|
||||||
((sizeof(*(p_udf_dirent->fid)) + p_udf_dirent->fid->u.i_imp_use
|
((sizeof(*(p_udf_dirent->fid)) + p_udf_dirent->fid->u.i_imp_use
|
||||||
+ p_udf_dirent->fid->i_file_id + 3) / 4);
|
+ p_udf_dirent->fid->i_file_id + 3) / 4);
|
||||||
|
|
||||||
p_udf_dirent->fid =
|
p_udf_dirent->fid =
|
||||||
(udf_fileid_desc_t *)((uint8_t *)p_udf_dirent->fid + ofs);
|
(udf_fileid_desc_t *)((uint8_t *)p_udf_dirent->fid + ofs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p_udf_dirent->fid) {
|
if (!p_udf_dirent->fid) {
|
||||||
uint32_t i_sectors =
|
uint32_t i_sectors =
|
||||||
(p_udf_dirent->i_loc_end - p_udf_dirent->i_loc + 1);
|
(p_udf_dirent->i_loc_end - p_udf_dirent->i_loc + 1);
|
||||||
uint32_t size = UDF_BLOCKSIZE * i_sectors;
|
uint32_t size = UDF_BLOCKSIZE * i_sectors;
|
||||||
driver_return_code_t i_ret;
|
driver_return_code_t i_ret;
|
||||||
|
|
||||||
if (!p_udf_dirent->sector)
|
if (!p_udf_dirent->sector)
|
||||||
p_udf_dirent->sector = (uint8_t*) malloc(size);
|
p_udf_dirent->sector = (uint8_t*) malloc(size);
|
||||||
i_ret = udf_read_sectors(p_udf, p_udf_dirent->sector,
|
i_ret = udf_read_sectors(p_udf, p_udf_dirent->sector,
|
||||||
p_udf_dirent->i_part_start+p_udf_dirent->i_loc,
|
p_udf_dirent->i_part_start+p_udf_dirent->i_loc,
|
||||||
i_sectors);
|
i_sectors);
|
||||||
if (DRIVER_OP_SUCCESS == i_ret)
|
if (DRIVER_OP_SUCCESS == i_ret)
|
||||||
p_udf_dirent->fid = (udf_fileid_desc_t *) p_udf_dirent->sector;
|
p_udf_dirent->fid = (udf_fileid_desc_t *) p_udf_dirent->sector;
|
||||||
else
|
else
|
||||||
p_udf_dirent->fid = NULL;
|
p_udf_dirent->fid = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_udf_dirent->fid && !udf_checktag(&(p_udf_dirent->fid->tag), TAGID_FID))
|
if (p_udf_dirent->fid && !udf_checktag(&(p_udf_dirent->fid->tag), TAGID_FID))
|
||||||
{
|
{
|
||||||
uint32_t ofs =
|
uint32_t ofs =
|
||||||
4 * ((sizeof(*p_udf_dirent->fid) + p_udf_dirent->fid->u.i_imp_use
|
4 * ((sizeof(*p_udf_dirent->fid) + p_udf_dirent->fid->u.i_imp_use
|
||||||
+ p_udf_dirent->fid->i_file_id + 3) / 4);
|
+ p_udf_dirent->fid->i_file_id + 3) / 4);
|
||||||
|
|
||||||
p_udf_dirent->dir_left -= ofs;
|
p_udf_dirent->dir_left -= ofs;
|
||||||
p_udf_dirent->b_dir =
|
p_udf_dirent->b_dir =
|
||||||
(p_udf_dirent->fid->file_characteristics & UDF_FILE_DIRECTORY) != 0;
|
(p_udf_dirent->fid->file_characteristics & UDF_FILE_DIRECTORY) != 0;
|
||||||
p_udf_dirent->b_parent =
|
p_udf_dirent->b_parent =
|
||||||
(p_udf_dirent->fid->file_characteristics & UDF_FILE_PARENT) != 0;
|
(p_udf_dirent->fid->file_characteristics & UDF_FILE_PARENT) != 0;
|
||||||
|
|
||||||
{
|
{
|
||||||
const unsigned int i_len = p_udf_dirent->fid->i_file_id;
|
const unsigned int i_len = p_udf_dirent->fid->i_file_id;
|
||||||
|
|
||||||
if (DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, &p_udf_dirent->fe, p_udf->i_part_start
|
if (DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, &p_udf_dirent->fe, p_udf->i_part_start
|
||||||
+ p_udf_dirent->fid->icb.loc.lba, 1)) {
|
+ p_udf_dirent->fid->icb.loc.lba, 1)) {
|
||||||
udf_dirent_free(p_udf_dirent);
|
udf_dirent_free(p_udf_dirent);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(p_udf_dirent->psz_name) < i_len)
|
free_and_null(p_udf_dirent->psz_name);
|
||||||
p_udf_dirent->psz_name = (char *)
|
p = (uint8_t*)p_udf_dirent->fid->u.imp_use.data + p_udf_dirent->fid->u.i_imp_use;
|
||||||
realloc(p_udf_dirent->psz_name, sizeof(char)*i_len+1);
|
p_udf_dirent->psz_name = unicode16_decode(p, i_len);
|
||||||
|
|
||||||
unicode16_decode(p_udf_dirent->fid->u.imp_use.data
|
|
||||||
+ p_udf_dirent->fid->u.i_imp_use,
|
|
||||||
i_len, p_udf_dirent->psz_name);
|
|
||||||
}
|
}
|
||||||
return p_udf_dirent;
|
return p_udf_dirent;
|
||||||
}
|
}
|
||||||
|
@ -723,8 +760,8 @@ udf_readdir(udf_dirent_t *p_udf_dirent)
|
||||||
/*!
|
/*!
|
||||||
free free resources associated with p_udf_dirent.
|
free free resources associated with p_udf_dirent.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
udf_dirent_free(udf_dirent_t *p_udf_dirent)
|
udf_dirent_free(udf_dirent_t *p_udf_dirent)
|
||||||
{
|
{
|
||||||
if (p_udf_dirent) {
|
if (p_udf_dirent) {
|
||||||
p_udf_dirent->fid = NULL;
|
p_udf_dirent->fid = NULL;
|
||||||
|
|
12
src/rufus.rc
12
src/rufus.rc
|
@ -32,7 +32,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
|
|
||||||
IDD_DIALOG DIALOGEX 12, 12, 206, 329
|
IDD_DIALOG DIALOGEX 12, 12, 206, 329
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
CAPTION "Rufus 1.4.4.412"
|
CAPTION "Rufus 1.4.4.413"
|
||||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||||
BEGIN
|
BEGIN
|
||||||
DEFPUSHBUTTON "Start",IDC_START,94,291,50,14
|
DEFPUSHBUTTON "Start",IDC_START,94,291,50,14
|
||||||
|
@ -165,7 +165,7 @@ END
|
||||||
RTL_IDD_DIALOG DIALOGEX 12, 12, 206, 329
|
RTL_IDD_DIALOG DIALOGEX 12, 12, 206, 329
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL
|
EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL
|
||||||
CAPTION "Rufus 1.4.4.412"
|
CAPTION "Rufus 1.4.4.413"
|
||||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||||
BEGIN
|
BEGIN
|
||||||
DEFPUSHBUTTON "Start",IDC_START,94,291,50,14
|
DEFPUSHBUTTON "Start",IDC_START,94,291,50,14
|
||||||
|
@ -427,8 +427,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,4,4,412
|
FILEVERSION 1,4,4,413
|
||||||
PRODUCTVERSION 1,4,4,412
|
PRODUCTVERSION 1,4,4,413
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -445,13 +445,13 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
|
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
|
||||||
VALUE "FileDescription", "Rufus"
|
VALUE "FileDescription", "Rufus"
|
||||||
VALUE "FileVersion", "1.4.4.412"
|
VALUE "FileVersion", "1.4.4.413"
|
||||||
VALUE "InternalName", "Rufus"
|
VALUE "InternalName", "Rufus"
|
||||||
VALUE "LegalCopyright", "© 2011-2014 Pete Batard (GPL v3)"
|
VALUE "LegalCopyright", "© 2011-2014 Pete Batard (GPL v3)"
|
||||||
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
|
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
|
||||||
VALUE "OriginalFilename", "rufus.exe"
|
VALUE "OriginalFilename", "rufus.exe"
|
||||||
VALUE "ProductName", "Rufus"
|
VALUE "ProductName", "Rufus"
|
||||||
VALUE "ProductVersion", "1.4.4.412"
|
VALUE "ProductVersion", "1.4.4.413"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
Loading…
Reference in a new issue