Skip to content

Commit

Permalink
Update libudfread to match commit 34d762c0 (v1.1.1) from https://code…
Browse files Browse the repository at this point in the history
  • Loading branch information
peper03 committed Dec 30, 2020
1 parent d2422df commit 17c2cd2
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 46 deletions.
15 changes: 8 additions & 7 deletions mythtv/external/libudfread/ecma167.c
Expand Up @@ -92,7 +92,7 @@ enum tag_identifier decode_descriptor_tag(const uint8_t *buf)
}

if (checksum != buf[4]) {
return ECMA_TAG_NONE;
return ECMA_TAG_INVALID;
}

return (enum tag_identifier)id;
Expand Down Expand Up @@ -174,7 +174,7 @@ size_t decode_file_identifier(const uint8_t *p, size_t size, struct file_identif
size_t l_iu; /* length of implementation use field */

if (size < 38) {
ecma_error("not enough data\n");
ecma_error("decode_file_identifier: not enough data\n");
return 0;
}

Expand All @@ -185,7 +185,7 @@ size_t decode_file_identifier(const uint8_t *p, size_t size, struct file_identif
l_iu = _get_u16(p + 36);

if (size < 38 + l_iu + fi->filename_len) {
ecma_error("not enough data\n");
ecma_error("decode_file_identifier: not enough data\n");
return 0;
}

Expand Down Expand Up @@ -285,14 +285,15 @@ static struct file_entry *_decode_file_entry(const uint8_t *p, size_t size,
int content_inline = 0;

if (p_ad + l_ad > size) {
ecma_error("not enough data in file entry\n");
ecma_error("decode_file_entry: not enough data\n");
return NULL;
}

_decode_icb_tag(p + 16, &tag);
if (tag.strategy_type != 4) {
/* UDF (2.): only ICB strategy types 4 and 4096 shall be recorded */
ecma_error("unsupported icb strategy type %d\n", tag.strategy_type);
ecma_error("decode_file_entry: unsupported icb strategy type %d\n",
tag.strategy_type);
return NULL;
}

Expand All @@ -305,7 +306,7 @@ static struct file_entry *_decode_file_entry(const uint8_t *p, size_t size,
content_inline = 1;
break;
default:
ecma_error("unsupported icb flags: 0x%x\n", tag.flags);
ecma_error("decode_file_entry: unsupported icb flags: 0x%x\n", tag.flags);
return NULL;
}

Expand Down Expand Up @@ -401,7 +402,7 @@ struct file_entry *decode_ext_file_entry(const uint8_t *p, size_t size, uint16_t

/* check for integer overflow */
if ((uint64_t)l_ea + (uint64_t)l_ad + (uint64_t)216 >= (uint64_t)1<<32) {
ecma_error("invalid file entry\n");
ecma_error("invalid extended file entry\n");
return NULL;
}

Expand Down
2 changes: 1 addition & 1 deletion mythtv/external/libudfread/ecma167.h
Expand Up @@ -99,7 +99,7 @@ enum tag_identifier {
ECMA_FileEntry = 261,
ECMA_ExtendedFileEntry = 266,

ECMA_TAG_NONE = -1,
ECMA_TAG_INVALID = -1, /* checksum failed */
};

enum tag_identifier decode_descriptor_tag(const uint8_t *buf);
Expand Down
4 changes: 2 additions & 2 deletions mythtv/external/libudfread/udfread-version.h
Expand Up @@ -28,8 +28,8 @@
((micro) * 1))

#define UDFREAD_VERSION_MAJOR 1
#define UDFREAD_VERSION_MINOR 0
#define UDFREAD_VERSION_MICRO 0
#define UDFREAD_VERSION_MINOR 1
#define UDFREAD_VERSION_MICRO 1

#define UDFREAD_VERSION_STRING "@UDFREAD_VERSION_MAJOR@.@UDFREAD_VERSION_MINOR@.@UDFREAD_VERSION_MICRO@"

Expand Down
120 changes: 89 additions & 31 deletions mythtv/external/libudfread/udfread.c
Expand Up @@ -140,9 +140,16 @@ static void *_safe_realloc(void *p, size_t s)
* Decoding
*/

#define utf16lo_to_utf8(out, out_pos, out_size, ch) \
/*
* outputs Modified UTF-8 (MUTF-8).
* The null character (U+0000) uses the two-byte overlong encoding 11000000 10000000 (hexadecimal C0 80), instead of 00000000 (hexadecimal 00).
*
* - not strictly UTF-8 compilant, but works with C str*() functions and Java, while \0 bytes in middle of strings won't.
*/

#define utf16lo_to_mutf8(out, out_pos, out_size, ch) \
do { \
if (ch < 0x80) { \
if (ch != 0 && ch < 0x80) { \
out[out_pos++] = (uint8_t)ch; \
} else { \
out_size++; \
Expand All @@ -154,10 +161,10 @@ static void *_safe_realloc(void *p, size_t s)
} \
} while (0)

#define utf16_to_utf8(out, out_pos, out_size, ch) \
#define utf16_to_mutf8(out, out_pos, out_size, ch) \
do { \
if (ch < 0x7ff) { \
utf16lo_to_utf8(out, out_pos, out_size, ch); \
utf16lo_to_mutf8(out, out_pos, out_size, ch); \
} else { \
out_size += 2; \
out = (uint8_t *)_safe_realloc(out, out_size); \
Expand All @@ -171,7 +178,7 @@ static void *_safe_realloc(void *p, size_t s)
} while (0)

/* Strings, CS0 (UDF 2.1.1) */
static char *_cs0_to_utf8(const uint8_t *cs0, size_t size)
static char *_cs0_to_mutf8(const uint8_t *cs0, size_t size)
{
size_t out_pos = 0;
size_t out_size = size;
Expand All @@ -193,13 +200,13 @@ static char *_cs0_to_utf8(const uint8_t *cs0, size_t size)
case 8:
/*udf_trace("string in utf-8\n");*/
for (i = 1; i < size; i++) {
utf16lo_to_utf8(out, out_pos, out_size, cs0[i]);
utf16lo_to_mutf8(out, out_pos, out_size, cs0[i]);
}
break;
case 16:
for (i = 1; i < size - 1; i+=2) {
uint16_t ch = cs0[i + 1] | (cs0[i] << 8);
utf16_to_utf8(out, out_pos, out_size, ch);
utf16_to_mutf8(out, out_pos, out_size, ch);
}
break;
default:
Expand Down Expand Up @@ -666,8 +673,8 @@ static int _parse_udf_partition_maps(udfread_block_input *input,
*/

struct udf_file_identifier {
char *filename;
struct long_ad icb;
char *filename; /* MUTF-8 */
struct long_ad icb; /* location of file entry */
uint8_t characteristic; /* CHAR_FLAG_* */
};

Expand Down Expand Up @@ -954,7 +961,7 @@ static int _parse_dir(const uint8_t *data, uint32_t length, struct udf_dir *dir)

dir->files[dir->num_entries].characteristic = fid.characteristic;
dir->files[dir->num_entries].icb = fid.icb;
dir->files[dir->num_entries].filename = _cs0_to_utf8(fid.filename, fid.filename_len);
dir->files[dir->num_entries].filename = _cs0_to_mutf8(fid.filename, fid.filename_len);

if (!dir->files[dir->num_entries].filename) {
continue;
Expand Down Expand Up @@ -1128,7 +1135,7 @@ static int _scan_dir(const struct udf_dir *dir, const char *filename, uint32_t *
}

static int _find_file(udfread *udf, const char *path,
const struct udf_dir **p_dir,
struct udf_dir **p_dir,
const struct udf_file_identifier **p_fid)
{
const struct udf_file_identifier *fid = NULL;
Expand Down Expand Up @@ -1222,10 +1229,12 @@ int udfread_open_input(udfread *udf, udfread_block_input *input/*, int partition
}

/* Volume Identifier. CS0, UDF 2.1.1 */
udf->volume_identifier = _cs0_to_utf8(vds.pvd.volume_identifier, vds.pvd.volume_identifier_length);
udf->volume_identifier = _cs0_to_mutf8(vds.pvd.volume_identifier, vds.pvd.volume_identifier_length);
if (udf->volume_identifier) {
udf_log("Volume Identifier: %s\n", udf->volume_identifier);
}

memcpy(udf->volume_set_identifier, vds.pvd.volume_set_identifier, 128);
udf_log("Volume Identifier: %s\n", udf->volume_identifier);

/* map partitions */
if (_parse_udf_partition_maps(input, &udf->part, &vds) < 0) {
Expand Down Expand Up @@ -1307,15 +1316,32 @@ size_t udfread_get_volume_set_id (udfread *udf, void *buffer, size_t size)
*/

struct udfread_dir {
const struct udf_dir *dir;
udfread *udf;
struct udf_dir *dir;
uint32_t current_file;
};

UDFDIR *udfread_opendir(udfread *udf, const char *path)
static UDFDIR *_new_udfdir(udfread *udf, struct udf_dir *dir)
{
const struct udf_dir *dir = NULL;
UDFDIR *result;

if (!dir) {
return NULL;
}

result = (UDFDIR *)calloc(1, sizeof(UDFDIR));
if (result) {
result->dir = dir;
result->udf = udf;
}

return result;
}

UDFDIR *udfread_opendir(udfread *udf, const char *path)
{
struct udf_dir *dir = NULL;

if (!udf || !udf->input || !path) {
return NULL;
}
Expand All @@ -1324,16 +1350,26 @@ UDFDIR *udfread_opendir(udfread *udf, const char *path)
return NULL;
}

if (!dir) {
return _new_udfdir(udf, dir);
}

UDFDIR *udfread_opendir_at(UDFDIR *p, const char *name)
{
struct udf_dir *dir = NULL;
uint32_t index;

if (!p || !name) {
return NULL;
}

result = (UDFDIR *)calloc(1, sizeof(UDFDIR));
if (result) {
result->dir = dir;
if (_scan_dir(p->dir, name, &index) < 0) {
udf_log("udfread_opendir_at: entry %s not found\n", name);
return NULL;
}

return result;
dir = _read_subdir(p->udf, p->dir, index);

return _new_udfdir(p->udf, dir);
}

struct udfread_dirent *udfread_readdir(UDFDIR *p, struct udfread_dirent *entry)
Expand Down Expand Up @@ -1395,20 +1431,11 @@ struct udfread_file {
void *block_mem;
};

UDFFILE *udfread_file_open(udfread *udf, const char *path)
static UDFFILE *_file_open(udfread *udf, const char *path, const struct udf_file_identifier *fi)
{
const struct udf_file_identifier *fi = NULL;
struct file_entry *fe;
UDFFILE *result;

if (!udf || !udf->input || !path) {
return NULL;
}

if (_find_file(udf, path, NULL, &fi) < 0) {
return NULL;
}

if (fi->characteristic & CHAR_FLAG_DIR) {
udf_log("error opening file %s (is directory)\n", path);
return NULL;
Expand All @@ -1432,6 +1459,37 @@ UDFFILE *udfread_file_open(udfread *udf, const char *path)
return result;
}

UDFFILE *udfread_file_open(udfread *udf, const char *path)
{
const struct udf_file_identifier *fi = NULL;

if (!udf || !udf->input || !path) {
return NULL;
}

if (_find_file(udf, path, NULL, &fi) < 0) {
return NULL;
}

return _file_open(udf, path, fi);
}

UDFFILE *udfread_file_openat(UDFDIR *dir, const char *name)
{
uint32_t index;

if (!dir || !name) {
return NULL;
}

if (_scan_dir(dir->dir, name, &index) < 0) {
udf_log("udfread_file_openat: entry %s not found\n", name);
return NULL;
}

return _file_open(dir->udf, name, &dir->dir->files[index]);
}

int64_t udfread_file_size(UDFFILE *p)
{
if (p) {
Expand Down
41 changes: 36 additions & 5 deletions mythtv/external/libudfread/udfread.h
Expand Up @@ -34,6 +34,15 @@ extern "C" {
* external API header
*/

/*
* NOTE:
*
* UDF filesystem file identifiers may contain nul bytes (0x00).
*
* In libudfread API file and directory names are encoded as Modified UTF-8 (MUTF-8).
* The null character (U+0000) uses two-byte overlong encoding 11000000 10000000
* (hexadecimal C0 80) instead of 00000000 (hexadecimal 00).
*/

/*
* UDF volume access
Expand Down Expand Up @@ -80,7 +89,7 @@ void udfread_close (udfread *);
* Get UDF Volume Identifier
*
* @param p udfread object
* @return Volume ID as null-terminated UTF-8 string, NULL if error
* @return Volume ID as null-terminated MUTF-8 string, NULL if error. Returned pointer is valid until udfread_close().
*/
const char *udfread_get_volume_id (udfread *);

Expand Down Expand Up @@ -109,7 +118,7 @@ enum {
/* Directory stream entry */
struct udfread_dirent {
unsigned int d_type; /* UDF_DT_* */
const char *d_name; /* UTF-8 */
const char *d_name; /* MUTF-8 */
};

/* opaque handle for directory stream */
Expand All @@ -119,11 +128,22 @@ typedef struct udfread_dir UDFDIR;
* Open directory stream
*
* @param p udfread object
* @param path path to the directory
* @return directory stream on the directory, or NULL if it could not be opened.
* @param path path to the directory (MUTF-8)
* @return directory stream handle on the directory, or NULL if it could not be opened.
*/
UDFDIR *udfread_opendir (udfread *, const char *path);

/**
* Open directory stream
*
* Directory name may contain special chars (/, \, ...).
*
* @param dir parent directory stream handle
* @param name name of the directory to open from dir (MUTF-8)
* @return directory stream handle on the directory, or NULL if it could not be opened.
*/
UDFDIR *udfread_opendir_at(UDFDIR *dir, const char *name);

/**
* Read directory stream
*
Expand Down Expand Up @@ -177,11 +197,22 @@ typedef struct udfread_file UDFFILE;
* Path may not contain "." or ".." directory components.
*
* @param p udfread object
* @param path path to the file
* @param path path to the file (MUTF-8)
* @return file object, or NULL if it could not be opened.
*/
UDFFILE *udfread_file_open (udfread *, const char *path);

/**
* Open a file from directory
*
* File name may contain special chars (/, \, ...).
*
* @param dir parent directory stream handle
* @param name name of the file (MUTF-8)
* @return file object, or NULL if it could not be opened.
*/
UDFFILE *udfread_file_openat (UDFDIR *dir, const char *name);

/**
* Close file object
*
Expand Down

0 comments on commit 17c2cd2

Please sign in to comment.