Commit e73add92 authored by Petri Hintukainen's avatar Petri Hintukainen

disc: add UDF support

NOTE: BD-J menus still require mounted directory tree.
parent 6e53d5fc
......@@ -1204,7 +1204,12 @@ static int _start_bdj(BLURAY *bd, unsigned title)
{
#ifdef USING_BDJAVA
if (bd->bdjava == NULL) {
bd->bdjava = bdj_open(disc_root(bd->disc), bd, bd->disc_info.bdj_disc_id, &bd->bdjstorage);
const char *root = disc_root(bd->disc);
if (!root) {
BD_DEBUG(DBG_BLURAY | DBG_CRIT, "Title %d: BD-J with disc images is not supported yet\n", title);
return 0;
}
bd->bdjava = bdj_open(root, bd, bd->disc_info.bdj_disc_id, &bd->bdjstorage);
if (!bd->bdjava) {
return 0;
}
......
......@@ -34,6 +34,10 @@
#include <string.h>
#ifdef ENABLE_UDF
#include "udf_fs.h"
#endif
struct bd_disc {
BD_MUTEX ovl_mutex; /* protect access to overlay root */
......@@ -42,6 +46,11 @@ struct bd_disc {
char *overlay_root; /* overlay filesystem root (if set) */
BD_DEC *dec;
void *fs_handle;
BD_FILE_H * (*pf_file_open_bdrom)(void *, const char *);
BD_DIR_H * (*pf_dir_open_bdrom)(void *, const char *);
void (*pf_fs_close)(void *);
};
/*
......@@ -61,12 +70,13 @@ static BD_FILE_H *_bdrom_open_path(void *p, const char *rel_path)
return fp;
}
static BD_DIR_H *_bdrom_open_dir(BD_DISC *p, const char *dir)
static BD_DIR_H *_bdrom_open_dir(void *p, const char *dir)
{
BD_DISC *disc = (BD_DISC *)p;
BD_DIR_H *dp;
char *path;
path = str_printf("%s%s", p->disc_root, dir);
path = str_printf("%s%s", disc->disc_root, dir);
dp = dir_open(path);
X_FREE(path);
......@@ -213,7 +223,34 @@ BD_DISC *disc_open(const char *device_path,
bd_mutex_init(&p->ovl_mutex);
struct dec_dev dev = { p, _bdrom_open_path, (file_openFp)disc_open_path, p->disc_root, p->disc_device };
/* default file access functions */
p->fs_handle = (void*)p;
p->pf_file_open_bdrom = _bdrom_open_path;
p->pf_dir_open_bdrom = _bdrom_open_dir;
#ifdef ENABLE_UDF
/* check if disc root directory can be opened. If not, treat it as device/image file. */
BD_DIR_H *dp_img = dir_open(device_path);
if (!dp_img) {
void *udf = udf_image_open(device_path);
if (!udf) {
BD_DEBUG(DBG_FILE | DBG_CRIT, "failed opening UDF image %s\n", device_path);
} else {
p->fs_handle = udf;
p->pf_fs_close = udf_image_close;
p->pf_file_open_bdrom = udf_file_open;
p->pf_dir_open_bdrom = udf_dir_open;
/* root not accessible with stdio */
X_FREE(p->disc_root);
}
} else {
dir_close(dp_img);
BD_DEBUG(DBG_FILE | DBG_CRIT, "%s does not seem to be image file or device node\n", device_path);
}
#endif
struct dec_dev dev = { p, p->pf_file_open_bdrom, (file_openFp)disc_open_path, p->disc_root, p->disc_device };
p->dec = dec_init(&dev, enc_info, keyfile_path, regs, psr_read, psr_write);
}
......@@ -227,6 +264,10 @@ void disc_close(BD_DISC **pp)
dec_close(&p->dec);
if (p->pf_fs_close) {
p->pf_fs_close(p->fs_handle);
}
bd_mutex_destroy(&p->ovl_mutex);
X_FREE(p->disc_root);
......@@ -257,7 +298,7 @@ BD_FILE_H *disc_open_path(BD_DISC *p, const char *rel_path)
/* if not found, try BD-ROM */
if (!fp) {
fp = _bdrom_open_path((void *)p, rel_path);
fp = p->pf_file_open_bdrom(p->fs_handle, rel_path);
if (!fp) {
BD_DEBUG(DBG_FILE | DBG_CRIT, "error opening file %s\n", rel_path);
......@@ -284,7 +325,7 @@ BD_DIR_H *disc_open_dir(BD_DISC *p, const char *dir)
BD_DIR_H *dp_rom;
BD_DIR_H *dp_ovl;
dp_rom = _bdrom_open_dir(p, dir);
dp_rom = p->pf_dir_open_bdrom(p->fs_handle, dir);
dp_ovl = _overlay_open_dir(p, dir);
if (!dp_ovl) {
......
/*
* This file is part of libbluray
* Copyright (C) 2015 Petri Hintukainen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include "udf_fs.h"
#include "file/file.h"
#include "util/macro.h"
#include "util/mutex.h"
#include "util/logging.h"
#include "udfread.h"
#include "blockinput.h"
#include <stdlib.h>
#include <stdio.h> // SEEK_SET
#include <string.h>
#include <inttypes.h>
/*
* file access
*/
static void _file_close(BD_FILE_H *file)
{
if (file) {
udfread_file_close(file->internal);
BD_DEBUG(DBG_FILE, "Closed UDF file (%p)\n", (void*)file);
X_FREE(file);
}
}
static int64_t _file_seek(BD_FILE_H *file, int64_t offset, int32_t origin)
{
return udfread_file_seek(file->internal, offset, origin);
}
static int64_t _file_tell(BD_FILE_H *file)
{
return udfread_file_tell(file->internal);
}
static int64_t _file_read(BD_FILE_H *file, uint8_t *buf, int64_t size)
{
return udfread_file_read(file->internal, buf, size);
}
BD_FILE_H *udf_file_open(void *udf, const char *filename)
{
BD_FILE_H *file = calloc(1, sizeof(BD_FILE_H));
BD_DEBUG(DBG_FILE, "Opening UDF file %s... (%p)\n", filename, (void*)file);
file->close = _file_close;
file->seek = _file_seek;
file->read = _file_read;
file->write = NULL;
file->tell = _file_tell;
file->eof = NULL;
file->internal = udfread_file_open(udf, filename);
if (!file->internal) {
BD_DEBUG(DBG_FILE, "Error opening file %s!\n", filename);
X_FREE(file);
}
return file;
}
/*
* directory access
*/
static void _dir_close(BD_DIR_H *dir)
{
if (dir) {
udfread_closedir(dir->internal);
BD_DEBUG(DBG_DIR, "Closed UDF dir (%p)\n", (void*)dir);
X_FREE(dir);
}
}
static int _dir_read(BD_DIR_H *dir, BD_DIRENT *entry)
{
struct udfread_dirent e;
if (!udfread_readdir(dir->internal, &e)) {
return -1;
}
strncpy(entry->d_name, e.d_name, sizeof(entry->d_name));
entry->d_name[sizeof(entry->d_name) - 1] = 0;
return 0;
}
BD_DIR_H *udf_dir_open(void *udf, const char* dirname)
{
BD_DIR_H *dir = calloc(1, sizeof(BD_DIR_H));
BD_DEBUG(DBG_DIR, "Opening UDF dir %s... (%p)\n", dirname, (void*)dir);
dir->close = _dir_close;
dir->read = _dir_read;
dir->internal = udfread_opendir(udf, dirname);
if (!dir->internal) {
BD_DEBUG(DBG_DIR, "Error opening %s\n", dirname);
X_FREE(dir);
}
return dir;
}
/*
* UDF image access
*/
typedef struct {
struct udfread_block_input i;
BD_FILE_H *fp;
BD_MUTEX mutex;
} UDF_BI;
static int _bi_close(struct udfread_block_input *bi_gen)
{
UDF_BI *bi = (UDF_BI *)bi_gen;
file_close(bi->fp);
bd_mutex_destroy(&bi->mutex);
X_FREE(bi);
return 0;
}
static uint32_t _bi_size(struct udfread_block_input *bi_gen)
{
UDF_BI *bi = (UDF_BI *)bi_gen;
return file_size(bi->fp) / 2048;
}
static int _bi_read(struct udfread_block_input *bi_gen, uint32_t lba, void *buf, uint32_t nblocks, int flags)
{
(void)flags;
UDF_BI *bi = (UDF_BI *)bi_gen;
int got = -1;
/* seek + read must be atomic */
bd_mutex_lock(&bi->mutex);
if (file_seek(bi->fp, SEEK_SET, (int64_t)lba * 2048) >= 0) {
int64_t bytes = file_read(bi->fp, buf, (int64_t)nblocks * 2048);
if (bytes >= 2048) {
got = bytes / 2048;
}
}
bd_mutex_unlock(&bi->mutex);
return got;
}
static struct udfread_block_input *_block_input(const char *img)
{
BD_FILE_H *fp = file_open(img, "rb");
if (fp) {
UDF_BI *bi = calloc(1, sizeof(*bi));
if (bi) {
bi->fp = fp;
bi->i.close = _bi_close;
bi->i.read = _bi_read;
bi->i.size = _bi_size;
bd_mutex_init(&bi->mutex);
return &bi->i;
}
file_close(fp);
}
return NULL;
}
void *udf_image_open(const char *img_path)
{
udfread *udf = NULL;
/* app handles file I/O ? */
if (file_open != file_open_default()) {
struct udfread_block_input *bi = _block_input(img_path);
if (bi) {
udf = udfread_open_input(bi);
if (!udf) {
bi->close(bi);
}
}
}
if (!udf) {
udf = (void*)udfread_open(img_path);
}
return (void*)udf;
}
void udf_image_close(void *udf)
{
udfread_close(udf);
}
/*
* This file is part of libbluray
* Copyright (C) 2015 Petri Hintukainen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef _BD_UDF_FS_H_
#define _BD_UDF_FS_H_
#include "util/attributes.h"
struct bd_file_s;
struct bd_dir_s;
BD_PRIVATE void *udf_image_open(const char *img_path);
BD_PRIVATE void udf_image_close(void *udf);
BD_PRIVATE struct bd_file_s *udf_file_open(void *udf, const char *filename);
BD_PRIVATE struct bd_dir_s *udf_dir_open(void *udf, const char* dirname);
#endif /* _BD_UDF_FS_H_ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment