diff options
Diffstat (limited to 'debian/patches/libdvdread/0001-libdvdread-PR40-enen92.patch')
-rw-r--r-- | debian/patches/libdvdread/0001-libdvdread-PR40-enen92.patch | 1694 |
1 files changed, 1694 insertions, 0 deletions
diff --git a/debian/patches/libdvdread/0001-libdvdread-PR40-enen92.patch b/debian/patches/libdvdread/0001-libdvdread-PR40-enen92.patch new file mode 100644 index 0000000..f512696 --- /dev/null +++ b/debian/patches/libdvdread/0001-libdvdread-PR40-enen92.patch @@ -0,0 +1,1694 @@ +From 4510e2ab7f85f87f781b59cafb0ad278c9edeb61 Mon Sep 17 00:00:00 2001 +From: Miguel Borges de Freitas <enen92@kodi.tv> +Date: Fri, 17 Jun 2022 09:43:49 +0100 +Subject: [PATCH 1/3] Split filesystem implementation into platform based code + +--- + libdvdread-embedded/Makefile.am | 17 ++- + libdvdread-embedded/configure.ac | 4 + + libdvdread-embedded/src/dvd_input.c | 58 +++------- + libdvdread-embedded/src/dvd_input.h | 23 +--- + libdvdread-embedded/src/dvd_reader.c | 216 ++++++++++------------------------- + libdvdread-embedded/src/dvdread/dvd_filesystem.h | 124 ++++++++++++++++++++ + libdvdread-embedded/src/dvdread/dvd_reader.h | 13 +-- + libdvdread-embedded/src/dvdread_internal.h | 1 + + libdvdread-embedded/src/file/dir_posix.c | 98 ++++++++++++++++ + libdvdread-embedded/src/file/dir_win32.c | 108 ++++++++++++++++++ + libdvdread-embedded/src/file/file_posix.c | 113 ++++++++++++++++++ + libdvdread-embedded/src/file/file_win32.c | 98 ++++++++++++++++ + libdvdread-embedded/src/file/filesystem.c | 37 ++++++ + libdvdread-embedded/src/file/filesystem.h | 46 ++++++++ + libdvdread-embedded/src/file/stat_posix.c | 36 ++++++ + libdvdread-embedded/src/file/stat_win32.c | 53 +++++++++ + 16 files changed, 821 insertions(+), 224 deletions(-) + create mode 100644 libdvdread-embedded/src/dvdread/dvd_filesystem.h + create mode 100644 libdvdread-embedded/src/file/dir_posix.c + create mode 100644 libdvdread-embedded/src/file/dir_win32.c + create mode 100644 libdvdread-embedded/src/file/file_posix.c + create mode 100644 libdvdread-embedded/src/file/file_win32.c + create mode 100644 libdvdread-embedded/src/file/filesystem.c + create mode 100644 libdvdread-embedded/src/file/filesystem.h + create mode 100644 libdvdread-embedded/src/file/stat_posix.c + create mode 100644 libdvdread-embedded/src/file/stat_win32.c + +diff --git a/libdvdread-embedded/Makefile.am b/libdvdread-embedded/Makefile.am +index f2849b8..29dca92 100644 +--- a/libdvdread-embedded/Makefile.am ++++ b/libdvdread-embedded/Makefile.am +@@ -32,7 +32,21 @@ libdvdread_la_SOURCES = \ + src/md5.h \ + src/nav_print.c \ + src/nav_read.c \ +- msvc/contrib/win32_cs.h ++ msvc/contrib/win32_cs.h \ ++ src/file/filesystem.c \ ++ src/file/filesystem.h ++ ++if HAVE_WIN32 ++libdvdread_la_SOURCES+= \ ++ src/file/dir_win32.c \ ++ src/file/file_win32.c \ ++ src/file/stat_win32.c ++else ++libdvdread_la_SOURCES+= \ ++ src/file/dir_posix.c \ ++ src/file/file_posix.c \ ++ src/file/stat_posix.c ++endif + + libdvdread_la_LIBADD = $(CSS_LIBS) + +@@ -42,6 +56,7 @@ libdvdread_la_LDFLAGS = -version-info $(DVDREAD_LTVERSION) \ + pkgincludedir = $(includedir)/dvdread + pkginclude_HEADERS = \ + src/dvdread/bitreader.h \ ++ src/dvdread/dvd_filesystem.h \ + src/dvdread/dvd_reader.h \ + src/dvdread/dvd_udf.h \ + src/dvdread/ifo_print.h \ +diff --git a/libdvdread-embedded/configure.ac b/libdvdread-embedded/configure.ac +index a60ef0c..e3cb5ac 100644 +--- a/libdvdread-embedded/configure.ac ++++ b/libdvdread-embedded/configure.ac +@@ -77,6 +77,9 @@ AC_ARG_ENABLE([dlfcn], + [use_builtin_dlfcn=$enableval], + [use_builtin_dlfcn=no]) + ++# for filesystem/dir access ++AC_CHECK_HEADERS([dirent.h]) ++ + AS_IF([test x"$with_libdvdcss" = "xyes"], [ + CSS_REQUIRES="libdvdcss >= 1.2" + PKG_CHECK_MODULES([CSS], [$CSS_REQUIRES]) +@@ -108,6 +111,7 @@ AS_IF([test "x$DOXYGEN" = "x"], [ + ]) + ]) + AM_CONDITIONAL([APIDOC], [test "x$DOXYGEN" != "x" && test "x$enable_apidoc" = "xyes"]) ++AM_CONDITIONAL(HAVE_WIN32, expr $host : '.*-mingw' >/dev/null 2>&1) + + AS_IF([test "x$ac_cv_c_compiler_gnu" = "xyes"], [ + AC_DEFINE([UNUSED], [__attribute__((unused))], [Unused parameter annotation]) +diff --git a/libdvdread-embedded/src/dvd_input.c b/libdvdread-embedded/src/dvd_input.c +index 17f0d36..1baf8f7 100644 +--- a/libdvdread-embedded/src/dvd_input.c ++++ b/libdvdread-embedded/src/dvd_input.c +@@ -22,16 +22,9 @@ + #include "config.h" /* Required for HAVE_DVDCSS_DVDCSS_H */ + #include <stdio.h> /* fprintf */ + #include <stdlib.h> /* free */ +-#include <fcntl.h> /* open */ +-#include <unistd.h> /* lseek */ + #include <string.h> /* strerror */ + #include <errno.h> + +-#ifdef _WIN32 +-#include <windows.h> +-#include "../msvc/contrib/win32_cs.h" +-#endif +- + #include "dvdread/dvd_reader.h" /* DVD_VIDEO_LB_LEN */ + #include "dvdread_internal.h" + #include "dvd_input.h" +@@ -40,7 +33,8 @@ + + /* The function pointers that is the exported interface of this file. */ + dvd_input_t (*dvdinput_open) (void *, dvd_logger_cb *, +- const char *,dvd_reader_stream_cb *); ++ const char *, dvd_reader_stream_cb *, ++ dvd_reader_filesystem_h *); + int (*dvdinput_close) (dvd_input_t); + int (*dvdinput_seek) (dvd_input_t, int); + int (*dvdinput_title) (dvd_input_t, int); +@@ -77,22 +71,6 @@ static int (*DVDcss_read) (dvdcss_t, void *, int, int); + #define DVDCSS_SEEK_KEY (1 << 1) + #endif + +-#ifdef _WIN32 +-static int open_win32(const char *path, int flags) +-{ +- wchar_t *wpath; +- int fd; +- +- wpath = _utf8_to_wchar(path); +- if (!wpath) { +- return -1; +- } +- fd = _wopen(wpath, flags); +- free(wpath); +- return fd; +-} +-#endif +- + /* The DVDinput handle, add stuff here for new input methods. + * NOTE: All members of this structure must be initialized in dvd_input_New + */ +@@ -104,8 +82,8 @@ struct dvd_input_s { + dvd_logger_cb *logcb; + off_t ipos; + +- /* dummy file input */ +- int fd; ++ /* file input */ ++ dvd_file_h* file; + /* stream input */ + dvd_reader_stream_cb *stream_cb; + }; +@@ -121,7 +99,7 @@ static dvd_input_t dvd_input_New(void *priv, dvd_logger_cb *logcb) + + /* Initialize all inputs to safe defaults */ + dev->dvdcss = NULL; +- dev->fd = -1; ++ dev->file = NULL; + dev->stream_cb = NULL; + } + return dev; +@@ -132,7 +110,8 @@ static dvd_input_t dvd_input_New(void *priv, dvd_logger_cb *logcb) + */ + static dvd_input_t css_open(void *priv, dvd_logger_cb *logcb, + const char *target, +- dvd_reader_stream_cb *stream_cb) ++ dvd_reader_stream_cb *stream_cb, ++ dvd_reader_filesystem_h *fs UNUSED) + { + dvd_input_t dev; + +@@ -210,7 +189,8 @@ static int css_close(dvd_input_t dev) + */ + static dvd_input_t file_open(void *priv, dvd_logger_cb *logcb, + const char *target, +- dvd_reader_stream_cb *stream_cb) ++ dvd_reader_stream_cb *stream_cb, ++ dvd_reader_filesystem_h *fs) + { + dvd_input_t dev; + +@@ -239,14 +219,8 @@ static dvd_input_t file_open(void *priv, dvd_logger_cb *logcb, + free(dev); + return NULL; + } +-#if defined(_WIN32) +- dev->fd = open_win32(target, O_RDONLY | O_BINARY); +-#elif defined(__OS2__) +- dev->fd = open(target, O_RDONLY | O_BINARY); +-#else +- dev->fd = open(target, O_RDONLY); +-#endif +- if(dev->fd < 0) { ++ dev->file = fs->file_open(fs, target); ++ if(!dev->file) { + char buf[256]; + #if defined(HAVE_STRERROR_R) && defined(HAVE_DECL_STRERROR_R) + #ifdef STRERROR_R_CHAR_P +@@ -279,7 +253,7 @@ static dvd_input_t file_open(void *priv, dvd_logger_cb *logcb, + */ + static int file_seek(dvd_input_t dev, int blocks) + { +- off_t pos = -1; ++ int64_t pos = -1; + + if(dev->ipos == blocks) + { +@@ -298,7 +272,7 @@ static int file_seek(dvd_input_t dev, int blocks) + /* Returns position as the number of bytes from beginning of file + * or -1 on error + */ +- pos = lseek(dev->fd, (off_t)blocks * (off_t)DVD_VIDEO_LB_LEN, SEEK_SET); ++ pos = dev->file->seek(dev->file, (int64_t)blocks * (int64_t)DVD_VIDEO_LB_LEN, SEEK_SET); + + if (pos >= 0) { + dev->ipos = pos / DVD_VIDEO_LB_LEN; +@@ -342,7 +316,7 @@ static int file_read(dvd_input_t dev, void *buffer, int blocks, + ret = dev->stream_cb->pf_read(dev->priv, ((char*)buffer) + bytes, len); + } else { + /* Returns the number of bytes read or -1 on error */ +- ret = read(dev->fd, ((char*)buffer) + bytes, len); ++ ret = dev->file->read(dev->file, ((char*)buffer) + bytes, len); + } + + if(ret < 0) { +@@ -381,8 +355,8 @@ static int file_close(dvd_input_t dev) + + /* close file if it was open */ + +- if (dev->fd >= 0) { +- ret = close(dev->fd); ++ if (dev->file) { ++ ret = dev->file->close(dev->file); + } + + free(dev); +diff --git a/libdvdread-embedded/src/dvd_input.h b/libdvdread-embedded/src/dvd_input.h +index 470cfa4..56fe170 100644 +--- a/libdvdread-embedded/src/dvd_input.h ++++ b/libdvdread-embedded/src/dvd_input.h +@@ -31,33 +31,14 @@ + + typedef struct dvd_input_s *dvd_input_t; + +-#if defined( __MINGW32__ ) +-# undef lseek +-# define lseek _lseeki64 +-# undef off_t +-# define off_t off64_t +-# undef stat +-# define stat _stati64 +-# undef fstat +-# define fstat _fstati64 +-# undef wstat +-# define wstat _wstati64 +-#endif +- +-#ifdef __ANDROID__ +-# undef lseek +-# define lseek lseek64 +-# undef off_t +-# define off_t off64_t +-#endif +- + /** + * Function pointers that will be filled in by the input implementation. + * These functions provide the main API. + */ + extern dvd_input_t (*dvdinput_open) (void *, dvd_logger_cb *, + const char *, +- dvd_reader_stream_cb *); ++ dvd_reader_stream_cb *, ++ dvd_reader_filesystem_h *); + extern int (*dvdinput_close) (dvd_input_t); + extern int (*dvdinput_seek) (dvd_input_t, int); + extern int (*dvdinput_title) (dvd_input_t, int); +diff --git a/libdvdread-embedded/src/dvd_reader.c b/libdvdread-embedded/src/dvd_reader.c +index c4d9641..5a21056 100644 +--- a/libdvdread-embedded/src/dvd_reader.c ++++ b/libdvdread-embedded/src/dvd_reader.c +@@ -21,17 +21,13 @@ + */ + + #include "config.h" +-#include <sys/types.h> /* off_t */ +-#include <sys/stat.h> /* stat */ + #include <sys/time.h> /* For the timing of dvdcss_title crack. */ +-#include <fcntl.h> /* open */ + #include <stdlib.h> /* free */ + #include <stdio.h> /* fprintf */ + #include <errno.h> /* errno, EIN* */ + #include <string.h> /* memcpy, strlen */ + #include <unistd.h> /* pclose */ + #include <limits.h> /* PATH_MAX */ +-#include <dirent.h> /* opendir, readdir */ + #include <ctype.h> /* isalpha */ + + #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__) || defined(__APPLE__) +@@ -57,11 +53,8 @@ + #include "dvdread_internal.h" + #include "md5.h" + #include "dvdread/ifo_read.h" ++#include "file/filesystem.h" + +-#if defined(_WIN32) +-# include <windows.h> +-# include "msvc/contrib/win32_cs.h" +-#endif + + /* misc win32 helpers */ + +@@ -81,107 +74,6 @@ static inline int _private_gettimeofday( struct timeval *tv, void *tz ) + # endif + #endif /* _WIN32 */ + +-/* Compat wrapper for stat() */ +- +-#if defined(_WIN32) +-/* can't re-define stat (used in both function name and struct name) */ +-typedef struct _stat64 dvdstat_t; +-static inline int dvdstat(const char *path, dvdstat_t *st) +-{ +- wchar_t *wpath, *it; +- int ret; +- +- wpath = _utf8_to_wchar(path); +- if (!wpath) { +- return -1; +- } +- +- /* need to strip possible trailing \\ */ +- for (it = wpath; *it; it++) +- if ((*it == '\\' || *it == '/') && *(it+1) == 0) +- *it = 0; +- +- ret = _wstat64(wpath, st); +- free(wpath); +- return ret; +-} +-#else +-typedef struct stat dvdstat_t; +-static inline int dvdstat(const char *file, dvdstat_t *st) { +- return stat(file, st); +-} +-#endif +- +-#if defined(_WIN32) +-/* UTF-8 aware version of opendir()/readdir() */ +- +-#include <io.h> +- +-typedef struct { +- intptr_t handle; +- struct _wfinddata_t went; +- struct dirent ent; +-} win32_dir_t; +- +-win32_dir_t *win32_opendir(const char *path) +-{ +- char *filespec; +- wchar_t *wfilespec; +- win32_dir_t *d; +- +- d = calloc(1, sizeof(*d)); +- if (!d) +- return NULL; +- +- filespec = malloc(strlen(path) + 3); +- if (!filespec) { +- goto fail; +- } +- sprintf(filespec, "%s\\*", path); +- +- wfilespec = _utf8_to_wchar(filespec); +- free(filespec); +- if (!wfilespec) { +- goto fail; +- } +- +- d->handle = _wfindfirst(wfilespec, &d->went); +- free(wfilespec); +- if (d->handle != -1) { +- return d; +- } +- +- fail: +- free(d); +- return NULL; +-} +- +-static struct dirent *win32_readdir(win32_dir_t *dir) +-{ +- if (dir->went.name[0]) { +- if (!WideCharToMultiByte(CP_UTF8, 0, dir->went.name, -1, dir->ent.d_name, sizeof(dir->ent.d_name), NULL, NULL)) +- dir->ent.d_name[0] = 0; /* allow reading next */ +- dir->went.name[0] = 0; +- _wfindnext(dir->handle, &dir->went); +- return &dir->ent; +- } +- +- return NULL; +-} +- +-static void win32_closedir(win32_dir_t *dir) +-{ +- _findclose(dir->handle); +- free(dir); +-} +- +-#define DIR win32_dir_t +-#define opendir win32_opendir +-#define readdir win32_readdir +-#define closedir win32_closedir +- +-#endif /* _WIN32 */ +- + #define DEFAULT_UDF_CACHE_LEVEL 1 + + struct dvd_reader_device_s { +@@ -338,7 +230,7 @@ static dvd_reader_device_t *DVDOpenImageFile( dvd_reader_t *ctx, + dvd_reader_device_t *dvd; + dvd_input_t dev; + +- dev = dvdinput_open( ctx->priv, &ctx->logcb, location, stream_cb ); ++ dev = dvdinput_open( ctx->priv, &ctx->logcb, location, stream_cb, ctx->fs ); + if( !dev ) { + Log0(ctx,"Can't open %s for reading", location ); + return NULL; +@@ -452,6 +344,13 @@ static dvd_reader_t *DVDOpenCommon( void *priv, + if(logcb) + ctx->logcb = *logcb; + ++ ctx->fs = InitInternalFilesystem(); ++ if (!ctx->fs) ++ { ++ free(ctx); ++ return NULL; ++ } ++ + #if defined(_WIN32) || defined(__OS2__) + int len; + #endif +@@ -490,7 +389,7 @@ static dvd_reader_t *DVDOpenCommon( void *priv, + } + #endif + +- ret = dvdstat( path, &fileinfo ); ++ ret = ctx->fs->stat(ctx->fs, path, &fileinfo); + + if( ret < 0 ) { + +@@ -513,9 +412,9 @@ static dvd_reader_t *DVDOpenCommon( void *priv, + } + + /* First check if this is a block/char device or a file*/ +- if( S_ISBLK( fileinfo.st_mode ) || +- S_ISCHR( fileinfo.st_mode ) || +- S_ISREG( fileinfo.st_mode ) ) { ++ if( (fileinfo.st_mode & DVD_S_IFMT) == DVD_S_IFBLK || ++ (fileinfo.st_mode & DVD_S_IFMT) == DVD_S_IFCHR || ++ (fileinfo.st_mode & DVD_S_IFMT) == DVD_S_IFREG ) { + + /** + * Block devices and regular files are assumed to be DVD-Video images. +@@ -538,7 +437,7 @@ static dvd_reader_t *DVDOpenCommon( void *priv, + return NULL; + } + return ctx; +- } else if( S_ISDIR( fileinfo.st_mode ) ) { ++ } else if ((fileinfo.st_mode & DVD_S_IFMT) == DVD_S_IFDIR ) { + #if defined(SYS_BSD) + struct fstab* fe; + #elif defined(__sun) || defined(__linux__) +@@ -758,6 +657,9 @@ void DVDClose( dvd_reader_t *dvd ) + if( dvd->rd->path_root ) free( dvd->rd->path_root ); + if( dvd->rd->udfcache ) FreeUDFCache( dvd->rd->udfcache ); + free( dvd->rd ); ++ if (dvd->fs) { ++ dvd->fs->close(dvd->fs); ++ } + free( dvd ); + } + } +@@ -813,24 +715,33 @@ static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *ctx, const char *filename, + * or -1 on file not found. + * or -2 on path not found. + */ +-static int findDirFile( const char *path, const char *file, char *filename ) ++static int findDirFile(dvd_reader_t *ctx, const char *path, const char *file, char *filename ) + { +- DIR *dir; +- struct dirent *ent; +- +- dir = opendir( path ); +- if( !dir ) return -2; ++ dvd_dirent_t entry; ++ dvd_dir_h *dir = ctx->fs->dir_open(ctx->fs, path); ++ if( !dir ) { ++ Log0(ctx, "findDirFile: Could not open dir %s ", path); ++ return -2; ++ } + +- while( ( ent = readdir( dir ) ) != NULL ) { +- if( !strcasecmp( ent->d_name, file ) ) { ++ int result = 0; ++ do ++ { ++ result = dir->read(dir, &entry); ++ if (result < 0) { ++ Log0(ctx, "findDirFile: Error reading dir %s (errorno: %d)", path, result); ++ return -1; ++ } ++ if( !strcasecmp( entry.d_name, file ) ) { + sprintf( filename, "%s%s%s", path, + ( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ), +- ent->d_name ); +- closedir(dir); ++ entry.d_name ); ++ dir->close(dir); + return 0; + } +- } +- closedir(dir); ++ } while (result == 0); ++ ++ dir->close(dir); + return -1; + } + +@@ -846,17 +757,17 @@ static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filename ) + nodirfile = file; + } + +- ret = findDirFile( dvd->rd->path_root, nodirfile, filename ); ++ ret = findDirFile(dvd, dvd->rd->path_root, nodirfile, filename ); + if( ret < 0 ) { + char video_path[ PATH_MAX + 1 ]; + + /* Try also with adding the path, just in case. */ + sprintf( video_path, "%s/VIDEO_TS/", dvd->rd->path_root ); +- ret = findDirFile( video_path, nodirfile, filename ); ++ ret = findDirFile(dvd, video_path, nodirfile, filename ); + if( ret < 0 ) { + /* Try with the path, but in lower case. */ + sprintf( video_path, "%s/video_ts/", dvd->rd->path_root ); +- ret = findDirFile( video_path, nodirfile, filename ); ++ ret = findDirFile(dvd, video_path, nodirfile, filename ); + if( ret < 0 ) { + return 0; + } +@@ -882,7 +793,7 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *ctx, const char *filename ) + return NULL; + } + +- dev = dvdinput_open( ctx->priv, &ctx->logcb, full_path, NULL ); ++ dev = dvdinput_open( ctx->priv, &ctx->logcb, full_path, NULL, ctx->fs ); + if( !dev ) { + Log0(ctx, "DVDOpenFilePath:dvdinput_open %s failed", full_path ); + return NULL; +@@ -896,13 +807,13 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *ctx, const char *filename ) + } + dvd_file->ctx = ctx; + +- if( dvdstat( full_path, &fileinfo ) < 0 ) { ++ if (ctx->fs->stat(ctx->fs, full_path, &fileinfo) < 0) { + Log0(ctx, "Can't stat() %s.", filename ); + free( dvd_file ); + dvdinput_close( dev ); + return NULL; + } +- dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; ++ dvd_file->title_sizes[ 0 ] = fileinfo.size / DVD_VIDEO_LB_LEN; + dvd_file->title_devs[ 0 ] = dev; + dvd_file->filesize = dvd_file->title_sizes[ 0 ]; + +@@ -979,23 +890,22 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *ctx, int title, int menu ) + return NULL; + } + +- dev = dvdinput_open( ctx->priv, &ctx->logcb, full_path, NULL ); ++ dev = dvdinput_open( ctx->priv, &ctx->logcb, full_path, NULL, ctx->fs ); + if( dev == NULL ) { + free( dvd_file ); + return NULL; + } + +- if( dvdstat( full_path, &fileinfo ) < 0 ) { ++ if (ctx->fs->stat(ctx->fs, full_path, &fileinfo) > 0) { + Log0(ctx, "Can't stat() %s.", filename ); + dvdinput_close(dev); + free( dvd_file ); + return NULL; + } +- dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; ++ dvd_file->title_sizes[ 0 ] = fileinfo.size / DVD_VIDEO_LB_LEN; + dvd_file->title_devs[ 0 ] = dev; + dvdinput_title( dvd_file->title_devs[0], 0); + dvd_file->filesize = dvd_file->title_sizes[ 0 ]; +- + } else { + int i; + +@@ -1006,13 +916,13 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *ctx, int title, int menu ) + break; + } + +- if( dvdstat( full_path, &fileinfo ) < 0 ) { ++ if (ctx->fs->stat(ctx->fs, full_path, &fileinfo) < 0) { + Log0(ctx, "Can't stat() %s.", filename ); + break; + } + +- dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; +- dvd_file->title_devs[ i ] = dvdinput_open( ctx->priv, &ctx->logcb, full_path, NULL ); ++ dvd_file->title_sizes[ i ] = fileinfo.size / DVD_VIDEO_LB_LEN; ++ dvd_file->title_devs[ i ] = dvdinput_open( ctx->priv, &ctx->logcb, full_path, NULL, ctx->fs ); + dvdinput_title( dvd_file->title_devs[ i ], 0 ); + dvd_file->filesize += dvd_file->title_sizes[ i ]; + } +@@ -1105,8 +1015,8 @@ static int DVDFileStatVOBUDF( dvd_reader_t *dvd, int title, + { + char filename[ MAX_UDF_FILE_NAME_LEN ]; + uint32_t size; +- off_t tot_size; +- off_t parts_size[ 9 ]; ++ int64_t tot_size; ++ int64_t parts_size[ 9 ]; + int nr_parts = 0; + int n; + +@@ -1151,8 +1061,8 @@ static int DVDFileStatVOBPath( dvd_reader_t *dvd, int title, + char filename[ MAX_UDF_FILE_NAME_LEN ]; + char full_path[ PATH_MAX + 1 ]; + dvdstat_t fileinfo; +- off_t tot_size; +- off_t parts_size[ 9 ]; ++ int64_t tot_size; ++ int64_t parts_size[ 9 ]; + int nr_parts = 0; + int n; + +@@ -1164,14 +1074,14 @@ static int DVDFileStatVOBPath( dvd_reader_t *dvd, int title, + if( !findDVDFile( dvd, filename, full_path ) ) + return -1; + +- if( dvdstat( full_path, &fileinfo ) < 0 ) { ++ if (dvd->fs->stat(dvd->fs, full_path, &fileinfo) < 0) { + Log1(dvd, "Can't stat() %s.", filename ); + return -1; + } + +- tot_size = fileinfo.st_size; ++ tot_size = fileinfo.size; + nr_parts = 1; +- parts_size[ 0 ] = fileinfo.st_size; ++ parts_size[ 0 ] = fileinfo.size; + + if( !menu ) { + int cur; +@@ -1180,12 +1090,12 @@ static int DVDFileStatVOBPath( dvd_reader_t *dvd, int title, + if( !findDVDFile( dvd, filename, full_path ) ) + break; + +- if( dvdstat( full_path, &fileinfo ) < 0 ) { ++ if (dvd->fs->stat(dvd->fs, full_path, &fileinfo) < 0) { + Log1(dvd, "Can't stat() %s.", filename ); + break; + } + +- parts_size[ nr_parts ] = fileinfo.st_size; ++ parts_size[ nr_parts ] = fileinfo.size; + tot_size += parts_size[ nr_parts ]; + nr_parts++; + } +@@ -1263,10 +1173,10 @@ int DVDFileStat( dvd_reader_t *reader, int titlenum, + char full_path[ PATH_MAX + 1 ]; + + if( findDVDFile( reader, filename, full_path ) ) { +- if( dvdstat( full_path, &fileinfo ) < 0 ) ++ if (reader->fs->stat(reader->fs, full_path, &fileinfo) < 0) + Log1(reader, "Can't stat() %s.", filename ); + else { +- statbuf->size = fileinfo.st_size; ++ statbuf->size = fileinfo.size; + statbuf->nr_parts = 1; + statbuf->parts_size[ 0 ] = statbuf->size; + return 0; +@@ -1318,8 +1228,8 @@ static int DVDReadBlocksUDF( const dvd_file_t *dvd_file, uint32_t offset, + + /* Copy the cache at a specified offset into data. offset and block_count + * must be converted into bytes */ +- memcpy( data, dvd_file->cache + (off_t)offset * (off_t)DVD_VIDEO_LB_LEN, +- (off_t)block_count * (off_t)DVD_VIDEO_LB_LEN ); ++ memcpy( data, dvd_file->cache + (int64_t)offset * (int64_t)DVD_VIDEO_LB_LEN, ++ (int64_t)block_count * (int64_t)DVD_VIDEO_LB_LEN ); + + /* return the amount of blocks copied */ + return block_count; +diff --git a/libdvdread-embedded/src/dvdread/dvd_filesystem.h b/libdvdread-embedded/src/dvdread/dvd_filesystem.h +new file mode 100644 +index 0000000..291f4d9 +--- /dev/null ++++ b/libdvdread-embedded/src/dvdread/dvd_filesystem.h +@@ -0,0 +1,124 @@ ++/* ++ * This file is part of libdvdread ++ * Copyright (C) 2022 VideoLAN ++ * ++ * This file 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 file 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 DVDREAD_FILESYSTEM_H_ ++#define DVDREAD_FILESYSTEM_H_ ++ ++#include <stdint.h> ++#include <sys/types.h> ++ ++/* ++ * directory access ++ */ ++ ++/** ++ * The dvd_dirent_t struct abstracts dirent usage from the respective platform implementation. ++ * For this reason, it only includes the parts the lib cares about (in this case d_name - the directory name) ++ */ ++typedef struct ++{ ++ char d_name[256]; ++} dvd_dirent_t; ++ ++typedef struct dvd_filesystem_dir_s dvd_dir_h; ++/** ++ * Abstraction for directory access ++ * internal - opaque handler internal to the specific implementation used to store the data type of directory stream objects. ++ * This is tipically a dir handler (e.g. a DIR* in posix) ++ * close(dvd_dir_h *dir) - called to close the directory and cleanup any alloc'd dir structures ++ * read(dvd_dir_h *dir, dvd_dirent_t *entry) - provided the dvd_dirent_t, reads the respective directory and returns -1 if the ++ * directory could not be read, 0 if successfully read. ++ */ ++struct dvd_filesystem_dir_s ++{ ++ void *internal; ++ void (*close)(dvd_dir_h *dir); ++ int (*read)(dvd_dir_h *dir, dvd_dirent_t *entry); ++}; ++ ++/* ++ * Stat access ++ */ ++ ++#define DVD_S_IFMT 0170000 /* These bits determine file type. */ ++ ++#define DVD_S_IFCHR 0020000 /* character special */ ++#define DVD_S_IFDIR 0040000 /* directory */ ++#define DVD_S_IFBLK 0060000 /* block special */ ++#define DVD_S_IFREG 0100000 /* regular */ ++ ++/** ++ * Abstraction for stat buffer structure ++ * size - size of the stat'd file ++ * st_mode - file mode ++ */ ++typedef struct ++{ ++ off_t size; ++ unsigned int st_mode; ++} dvdstat_t; ++ ++ ++/* ++ * file access ++ */ ++ ++/** ++ * Abstraction for file access ++ * internal - opaque handler internal to the specific implementation used to store the data type of the file object. ++ * This is tipically a file reference (e.g. the file descriptor/fd) ++ * close(dvd_file_h *file) - called to close the file and cleanup any alloc'd file structs ++ * seek(dvd_file_h *file, int64_t offset, int32_t origin) - used to seek into the given file (provided the offset and the origin). Returns ++ * the position on the file after seek. ++ * read(dvd_file_h *file, char *buf, int64_t size) - used to read the file into the passed buffer, given the read size. Returns the read ++ * read from the file ++ */ ++typedef struct dvd_filesystem_file_s dvd_file_h; ++struct dvd_filesystem_file_s ++{ ++ void *internal; ++ int (*close) (dvd_file_h *file); ++ int64_t (*seek) (dvd_file_h *file, int64_t offset, int32_t origin); ++ ssize_t (*read) (dvd_file_h *file, char *buf, size_t size); ++}; ++ ++/* ++ * Filesystem implementation ++ */ ++ ++/** ++ * Groups all filesystem operations into a common struct. This is the struct external applications should override to ++ * provide custom filesystem implementations: ++ * internal - opaque data pointer to user data (used to convey custom data within the filesystem struct) ++ * close(dvd_reader_filesystem_h *fs) - called to destroy the filesystem implementation (free any alloc'd structs) ++ * stat(dvd_reader_filesystem_h *fs, const char *path, dvdstat_t* statbuf) - stat a file/dir provided the statbuf, initializes the dvdstat_t. ++ * dir_open(dvd_reader_filesystem_h *fs, const char* dirname) - open the provided dir, initializes dvd_dir_h ++ * file_open(dvd_reader_filesystem_h *fs, const char* filename, const char *mode) - open a file, initializes dvd_file_h ++ */ ++typedef struct dvd_reader_filesystem_s dvd_reader_filesystem_h; ++struct dvd_reader_filesystem_s ++{ ++ void *internal; ++ void (*close) (dvd_reader_filesystem_h *fs); ++ int (*stat) (dvd_reader_filesystem_h *fs, const char *path, dvdstat_t *statbuf); ++ dvd_dir_h* (*dir_open) (dvd_reader_filesystem_h *fs, const char *dirname); ++ dvd_file_h* (*file_open) (dvd_reader_filesystem_h *fs, const char *filename); ++}; ++ ++#endif /* DVDREAD_FILESYSTEM_H_ */ +diff --git a/libdvdread-embedded/src/dvdread/dvd_reader.h b/libdvdread-embedded/src/dvdread/dvd_reader.h +index 54ef5dd..5b15704 100644 +--- a/libdvdread-embedded/src/dvdread/dvd_reader.h ++++ b/libdvdread-embedded/src/dvdread/dvd_reader.h +@@ -23,13 +23,6 @@ + #ifndef LIBDVDREAD_DVD_READER_H + #define LIBDVDREAD_DVD_READER_H + +-#ifdef _MSC_VER +-#include <config.h> +- +-#include <stdio.h> +-#include <stdlib.h> +-#endif +- + #include <sys/types.h> + #include <inttypes.h> + #include <stdarg.h> +@@ -46,6 +39,12 @@ + */ + #include "version.h" + ++/** ++ * Filesystem types ++ */ ++#include "dvd_filesystem.h" ++ ++ + /** + * The length of one Logical Block of a DVD. + */ +diff --git a/libdvdread-embedded/src/dvdread_internal.h b/libdvdread-embedded/src/dvdread_internal.h +index bf4e2e1..1a35059 100644 +--- a/libdvdread-embedded/src/dvdread_internal.h ++++ b/libdvdread-embedded/src/dvdread_internal.h +@@ -39,6 +39,7 @@ struct dvd_reader_s + dvd_reader_device_t *rd; + void *priv; /* User provided context */ + dvd_logger_cb logcb; ++ dvd_reader_filesystem_h* fs; + /* Set 100 flags for BUP fallback, most signifiant left + [0] for upper remaining VTS, [1] for the first Main + 63 VTS */ + uint64_t ifoBUPflags[2]; +diff --git a/libdvdread-embedded/src/file/dir_posix.c b/libdvdread-embedded/src/file/dir_posix.c +new file mode 100644 +index 0000000..f55e62a +--- /dev/null ++++ b/libdvdread-embedded/src/file/dir_posix.c +@@ -0,0 +1,98 @@ ++/* ++ * This file is part of libdvdread ++ * Copyright (C) 2022 VideoLAN ++ * ++ * This file 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 file 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/>. ++ */ ++ ++#include "config.h" ++ ++#include <stdlib.h> ++#include <string.h> ++#if HAVE_DIRENT_H ++#include <dirent.h> ++#endif ++ ++#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) ++# if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 24) ++# define USE_READDIR ++# include <errno.h> ++# endif ++#endif ++ ++#include <dvdread/dvd_filesystem.h> ++#include "filesystem.h" ++ ++void _dir_close_posix(dvd_dir_h *dir) ++{ ++ if (dir) { ++ closedir((DIR *)dir->internal); ++ free(dir); ++ dir = NULL; ++ } ++} ++ ++int _dir_read_posix(dvd_dir_h *dir, dvd_dirent_t *entry) ++{ ++ struct dirent *p_e; ++ ++#ifdef USE_READDIR ++ errno = 0; ++ p_e = readdir((DIR*)dir->internal); ++ if (!p_e && errno) { ++ return -errno; ++ } ++#else /* USE_READDIR */ ++ int result; ++ struct dirent e; ++ ++ result = readdir_r((DIR*)dir->internal, &e, &p_e); ++ if (result) { ++ return -result; ++ } ++#endif /* USE_READDIR */ ++ ++ if (p_e == NULL) { ++ return 1; ++ } ++ strncpy(entry->d_name, p_e->d_name, sizeof(entry->d_name)); ++ entry->d_name[sizeof(entry->d_name) - 1] = 0; ++ ++ return 0; ++} ++ ++dvd_dir_h *dir_open_default(dvd_reader_filesystem_h *fs, const char* dirname) ++{ ++ if (!fs) ++ return NULL; ++ ++ dvd_dir_h *dir = calloc(1, sizeof(dvd_dir_h)); ++ ++ if (!dir) { ++ return NULL; ++ } ++ ++ dir->close = _dir_close_posix; ++ dir->read = _dir_read_posix; ++ ++ if ((dir->internal = opendir(dirname))) { ++ return dir; ++ } ++ ++ free(dir); ++ dir = NULL; ++ ++ return NULL; ++} +diff --git a/libdvdread-embedded/src/file/dir_win32.c b/libdvdread-embedded/src/file/dir_win32.c +new file mode 100644 +index 0000000..cb89728 +--- /dev/null ++++ b/libdvdread-embedded/src/file/dir_win32.c +@@ -0,0 +1,108 @@ ++/* ++ * This file is part of libdvdread ++ * Copyright (C) 2022 VideoLAN ++ * ++ * This file 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 file 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/>. ++ */ ++ ++#include <io.h> ++#include <stdlib.h> ++#include <string.h> ++#include <stdio.h> ++ ++#include <windows.h> ++#include "../msvc/contrib/win32_cs.h" ++ ++ ++#include <dvdread/dvd_filesystem.h> ++#include "filesystem.h" ++ ++ ++typedef struct { ++ intptr_t handle; ++ struct _wfinddata_t went; ++} win32_dir_t; ++ ++ ++void _dir_close_win32(dvd_dir_h *dir) ++{ ++ if (dir) { ++ _findclose(((win32_dir_t*)dir->internal)->handle); ++ free((win32_dir_t*)dir->internal); ++ free(dir); ++ dir = NULL; ++ } ++} ++ ++int _dir_read_win32(dvd_dir_h *dir, dvd_dirent_t *entry) ++{ ++ win32_dir_t *wdir = (win32_dir_t*)dir->internal; ++ if (wdir->went.name[0]) { ++ if (!WideCharToMultiByte(CP_UTF8, 0, wdir->went.name, -1, entry->d_name, sizeof(entry->d_name), NULL, NULL)) ++ entry->d_name[0] = 0; /* allow reading next */ ++ wdir->went.name[0] = 0; ++ _wfindnext(wdir->handle, &wdir->went); ++ return 0; ++ } ++ return -1; ++} ++ ++dvd_dir_h *dir_open_default(dvd_reader_filesystem_h *fs, const char* dirname) ++{ ++ if (!fs) ++ return NULL; ++ ++ char *filespec; ++ wchar_t *wfilespec; ++ win32_dir_t *d; ++ dvd_dir_h *dir = calloc(1, sizeof(dvd_dir_h)); ++ ++ if (!dir) { ++ return NULL; ++ } ++ ++ d = calloc(1, sizeof(*d)); ++ if (!d) ++ { ++ free(dir); ++ return NULL; ++ } ++ ++ filespec = malloc(strlen(dirname) + 3); ++ if (!filespec) { ++ goto fail; ++ } ++ sprintf(filespec, "%s\\*", dirname); ++ ++ wfilespec = _utf8_to_wchar(filespec); ++ free(filespec); ++ if (!wfilespec) { ++ goto fail; ++ } ++ ++ d->handle = _wfindfirst(wfilespec, &d->went); ++ free(wfilespec); ++ if (d->handle != -1) { ++ dir->internal = (void*)d; ++ dir->close = _dir_close_win32; ++ dir->read = _dir_read_win32; ++ return dir; ++ } ++ ++ fail: ++ free(d); ++ free(dir); ++ return NULL; ++} +diff --git a/libdvdread-embedded/src/file/file_posix.c b/libdvdread-embedded/src/file/file_posix.c +new file mode 100644 +index 0000000..cbdbd58 +--- /dev/null ++++ b/libdvdread-embedded/src/file/file_posix.c +@@ -0,0 +1,113 @@ ++/* ++ * This file is part of libdvdread ++ * Copyright (C) 2022 VideoLAN ++ * ++ * This file 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 file 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/>. ++ */ ++ ++ ++#include <stdlib.h> ++#include <unistd.h> ++#include <stdio.h> ++#include <errno.h> ++ ++ ++#include <sys/stat.h> ++#include <fcntl.h> ++ ++#include <dvdread/dvd_filesystem.h> ++ ++#include "filesystem.h" ++ ++#ifdef __ANDROID__ ++# undef lseek ++# define lseek lseek64 ++# undef off_t ++# define off_t off64_t ++#endif ++ ++ ++int _file_close(dvd_file_h *file) ++{ ++ if (file) { ++ int ret = close((int)(intptr_t)file->internal); ++ free(file); ++ return ret; ++ } ++ return 0; ++} ++ ++int64_t _file_seek(dvd_file_h *file, int64_t offset, int32_t origin) ++{ ++ off_t result = lseek((int)(intptr_t)file->internal, offset, origin); ++ if (result == (off_t)-1) { ++ return -1; ++ } ++ return (int64_t)result; ++} ++ ++ssize_t _file_read(dvd_file_h *file, char *buf, size_t size) ++{ ++ ssize_t result; ++ ++ if (size <= 0) { ++ return 0; ++ } ++ ++ result = read((int)(intptr_t)file->internal, buf, size); ++ return result; ++} ++ ++ ++dvd_file_h* file_open_default(dvd_reader_filesystem_h *fs, const char* filename) ++{ ++ if (!fs) ++ return NULL; ++ ++ dvd_file_h *file; ++ int fd = -1; ++ int flags = 0; ++ int mode = 0; ++ ++ #if defined(__OS2__) // not posix but kept here for legacy compatibility reasons ++ flags = O_RDONLY | O_BINARY; ++ #else ++ flags = O_RDONLY; ++ #endif ++ ++#ifdef O_CLOEXEC ++ flags |= O_CLOEXEC; ++#endif ++#ifdef O_BINARY ++ flags |= O_BINARY; ++#endif ++ ++ if ((fd = open(filename, flags, mode)) < 0) { ++ return NULL; ++ } ++ ++ file = calloc(1, sizeof(dvd_file_h)); ++ if (!file) { ++ close(fd); ++ return NULL; ++ } ++ ++ file->close = _file_close; ++ file->read = _file_read; ++ file->seek = _file_seek; ++ file->internal = (void*)(intptr_t)fd; ++ ++ return file; ++} +diff --git a/libdvdread-embedded/src/file/file_win32.c b/libdvdread-embedded/src/file/file_win32.c +new file mode 100644 +index 0000000..9787076 +--- /dev/null ++++ b/libdvdread-embedded/src/file/file_win32.c +@@ -0,0 +1,98 @@ ++/* ++ * This file is part of libdvdread ++ * Copyright (C) 2022 VideoLAN ++ * ++ * This file 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 file 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/>. ++ */ ++ ++#include <stdlib.h> ++#include <unistd.h> ++#include <stdio.h> ++#include <errno.h> ++ ++#include <sys/stat.h> ++#include <fcntl.h> ++ ++#include <windows.h> ++#include "../msvc/contrib/win32_cs.h" ++ ++#include <dvdread/dvd_filesystem.h> ++#include "filesystem.h" ++ ++ ++int _file_close_win32(dvd_file_h *file) ++{ ++ if (file) { ++ int ret = close((int)(intptr_t)file->internal); ++ free(file); ++ return ret; ++ } ++ return 0; ++} ++ ++int64_t _file_seek_win32(dvd_file_h *file, int64_t offset, int32_t origin) ++{ ++ off64_t result = _lseeki64((int)(intptr_t)file->internal, offset, origin); ++ if (result == (off64_t)-1) { ++ return -1; ++ } ++ return (int64_t)result; ++} ++ ++ssize_t _file_read_win32(dvd_file_h *file, char *buf, size_t size) ++{ ++ ssize_t result; ++ ++ if (size <= 0) { ++ return 0; ++ } ++ ++ result = read((int)(intptr_t)file->internal, buf, size); ++ return result; ++} ++ ++ ++dvd_file_h* file_open_default(dvd_reader_filesystem_h *fs, const char* filename) ++{ ++ if (!fs) ++ return NULL; ++ ++ dvd_file_h *file; ++ int fd = -1; ++ wchar_t *wpath; ++ ++ wpath = _utf8_to_wchar(filename); ++ if (!wpath) { ++ return NULL; ++ } ++ ++ if ((fd = _wopen(wpath, O_RDONLY | O_BINARY)) < 0) { ++ free(wpath); ++ return NULL; ++ } ++ ++ file = calloc(1, sizeof(dvd_file_h)); ++ if (!file) { ++ close(fd); ++ return NULL; ++ } ++ ++ file->close = _file_close_win32; ++ file->read = _file_read_win32; ++ file->seek = _file_seek_win32; ++ file->internal = (void*)(intptr_t)fd; ++ ++ return file; ++} +diff --git a/libdvdread-embedded/src/file/filesystem.c b/libdvdread-embedded/src/file/filesystem.c +new file mode 100644 +index 0000000..b79edae +--- /dev/null ++++ b/libdvdread-embedded/src/file/filesystem.c +@@ -0,0 +1,37 @@ ++/* ++ * This file is part of libdvdread. ++ * ++ * This program 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 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 Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this program; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. ++ */ ++ ++#include "filesystem.h" ++ ++#include <stdlib.h> ++ ++static void default_filesystem_close(dvd_reader_filesystem_h *fs) { ++ free(fs); ++} ++ ++dvd_reader_filesystem_h* InitInternalFilesystem() { ++ dvd_reader_filesystem_h* fs = calloc( 1, sizeof(dvd_reader_filesystem_h)); ++ if (!fs) { ++ return NULL; ++ } ++ fs->dir_open = dir_open_default; ++ fs->stat = stat_default; ++ fs->file_open = file_open_default; ++ fs->close = default_filesystem_close; ++ return fs; ++} +diff --git a/libdvdread-embedded/src/file/filesystem.h b/libdvdread-embedded/src/file/filesystem.h +new file mode 100644 +index 0000000..1b8a014 +--- /dev/null ++++ b/libdvdread-embedded/src/file/filesystem.h +@@ -0,0 +1,46 @@ ++/* ++ * This file is part of libdvdread. ++ * ++ * This program 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 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 Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this program; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. ++ */ ++ ++#ifndef LIBDVDREAD_FILESYSTEM_H ++#define LIBDVDREAD_FILESYSTEM_H ++ ++#include "dvdread/dvd_filesystem.h" ++ ++/** ++ * Prototype definition for default file open function (implemented by each platform) ++ */ ++dvd_file_h* file_open_default(dvd_reader_filesystem_h *fs, const char* filename); ++ ++/** ++ * Prototype definition for default dir open function (implemented by each platform) ++ */ ++dvd_dir_h* dir_open_default(dvd_reader_filesystem_h *fs, const char* dirname); ++ ++/** ++ * Prototype definition for default stat function (implemented by each platform) ++ */ ++int stat_default(dvd_reader_filesystem_h *fs, const char *path, dvdstat_t* statbuf); ++ ++/** ++ * Inits the internal (platform specific) filesystem implementation ++ * bundled with libdvdread. This includes initializing the default internal ++ * implmentations of file_open, dir_open, stat, etc. ++ */ ++dvd_reader_filesystem_h* InitInternalFilesystem(); ++ ++#endif +diff --git a/libdvdread-embedded/src/file/stat_posix.c b/libdvdread-embedded/src/file/stat_posix.c +new file mode 100644 +index 0000000..61670fc +--- /dev/null ++++ b/libdvdread-embedded/src/file/stat_posix.c +@@ -0,0 +1,36 @@ ++/* ++ * This file is part of libdvdread ++ * Copyright (C) 2022 VideoLAN ++ * ++ * This file 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 file 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/>. ++ */ ++ ++#include <stdlib.h> ++#include <sys/stat.h> ++ ++#include <dvdread/dvd_filesystem.h> ++#include "filesystem.h" ++ ++int stat_default(dvd_reader_filesystem_h *fs, const char *path, dvdstat_t* statbuf) ++{ ++ if (!fs) ++ return -1; ++ ++ struct stat posixstatbuf; ++ int ret = stat(path, &posixstatbuf); ++ statbuf->size = posixstatbuf.st_size; ++ statbuf->st_mode = posixstatbuf.st_mode; ++ return ret; ++} +diff --git a/libdvdread-embedded/src/file/stat_win32.c b/libdvdread-embedded/src/file/stat_win32.c +new file mode 100644 +index 0000000..0b8245d +--- /dev/null ++++ b/libdvdread-embedded/src/file/stat_win32.c +@@ -0,0 +1,53 @@ ++/* ++ * This file is part of libdvdread ++ * Copyright (C) 2022 VideoLAN ++ * ++ * This file 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 file 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/>. ++ */ ++ ++#include <stdlib.h> ++#include <sys/stat.h> ++ ++#include <windows.h> ++#include "../msvc/contrib/win32_cs.h" ++ ++#include <dvdread/dvd_filesystem.h> ++#include "filesystem.h" ++ ++ ++int stat_default(dvd_reader_filesystem_h *fs, const char *path, dvdstat_t* statbuf) ++{ ++ if (!fs) ++ return -1; ++ ++ struct _stat64 win32statbuf; ++ ++ wchar_t *wpath, *it; ++ ++ wpath = _utf8_to_wchar(path); ++ if (!wpath) { ++ return -1; ++ } ++ ++ /* need to strip possible trailing \\ */ ++ for (it = wpath; *it; it++) ++ if ((*it == '\\' || *it == '/') && *(it+1) == 0) ++ *it = 0; ++ ++ int ret = _wstat64(wpath, &win32statbuf); ++ statbuf->size = win32statbuf.st_size; ++ statbuf->st_mode = win32statbuf.st_mode; ++ return ret; ++} +-- +2.35.1 + + +From 7215ed052b632be49c4f1ed444c7c9447e2d4c61 Mon Sep 17 00:00:00 2001 +From: Miguel Borges de Freitas <enen92@kodi.tv> +Date: Fri, 29 Jul 2022 12:50:24 +0100 +Subject: [PATCH 2/3] Decouple dvdinput_setup providing dvdinput_setup_builtin + for minimal/internal fs access + +--- + libdvdread-embedded/src/dvd_input.c | 23 +++++++++++++++++------ + libdvdread-embedded/src/dvd_input.h | 8 ++++++++ + 2 files changed, 25 insertions(+), 6 deletions(-) + +diff --git a/libdvdread-embedded/src/dvd_input.c b/libdvdread-embedded/src/dvd_input.c +index 1baf8f7..70f31b3 100644 +--- a/libdvdread-embedded/src/dvd_input.c ++++ b/libdvdread-embedded/src/dvd_input.c +@@ -446,12 +446,23 @@ int dvdinput_setup(void *priv, dvd_logger_cb *logcb) + DVDReadLog(priv, logcb, DVD_LOGGER_LEVEL_WARN, + "Encrypted DVD support unavailable."); + +- /* libdvdcss replacement functions */ +- dvdinput_open = file_open; +- dvdinput_close = file_close; +- dvdinput_seek = file_seek; +- dvdinput_title = file_title; +- dvdinput_read = file_read; ++ dvdinput_setup_builtin(priv, logcb); + return 0; + } + } ++ ++/** ++ * Setup read functions with the builtin libdvdread implementation (minimal DVD access without css). ++ */ ++void dvdinput_setup_builtin(void *priv, dvd_logger_cb *logcb) ++{ ++ DVDReadLog(priv, logcb, DVD_LOGGER_LEVEL_INFO, ++ "Setting up builtin libdvdread implementation"); ++ ++ /* libdvdcss replacement functions */ ++ dvdinput_open = file_open; ++ dvdinput_close = file_close; ++ dvdinput_seek = file_seek; ++ dvdinput_title = file_title; ++ dvdinput_read = file_read; ++} +diff --git a/libdvdread-embedded/src/dvd_input.h b/libdvdread-embedded/src/dvd_input.h +index 56fe170..36fe279 100644 +--- a/libdvdread-embedded/src/dvd_input.h ++++ b/libdvdread-embedded/src/dvd_input.h +@@ -46,7 +46,15 @@ extern int (*dvdinput_read) (dvd_input_t, void *, int, int); + + /** + * Setup function accessed by dvd_reader.c. Returns 1 if there is CSS support. ++ * Otherwise it falls back to the internal dvdread implementation (without css support) ++ * which is basically the same as calling dvdinput_setup_builtin. + */ + int dvdinput_setup(void *, dvd_logger_cb *); + ++/** ++ * Setup function accessed by dvd_reader.c using the builtin libdvdread implementation ++ * (without css support) ++ */ ++void dvdinput_setup_builtin(void *, dvd_logger_cb *); ++ + #endif /* LIBDVDREAD_DVD_INPUT_H */ +-- +2.35.1 + + +From 665a98ee15896e97aa8f0c0d6499b281d0602e60 Mon Sep 17 00:00:00 2001 +From: Miguel Borges de Freitas <enen92@kodi.tv> +Date: Fri, 29 Jul 2022 12:55:19 +0100 +Subject: [PATCH 3/3] Add DVDOpenFiles supporting caller provided filesystem + implementation + +--- + libdvdread-embedded/src/dvd_reader.c | 32 +++++++++++++++++++++++++++----- + libdvdread-embedded/src/dvdread/dvd_reader.h | 13 +++++++++++++ + 2 files changed, 40 insertions(+), 5 deletions(-) + +diff --git a/libdvdread-embedded/src/dvd_reader.c b/libdvdread-embedded/src/dvd_reader.c +index 5a21056..84bef88 100644 +--- a/libdvdread-embedded/src/dvd_reader.c ++++ b/libdvdread-embedded/src/dvd_reader.c +@@ -330,7 +330,8 @@ static char *bsd_block2char( const char *path ) + static dvd_reader_t *DVDOpenCommon( void *priv, + const dvd_logger_cb *logcb, + const char *ppath, +- dvd_reader_stream_cb *stream_cb ) ++ dvd_reader_stream_cb *stream_cb, ++ dvd_reader_filesystem_h * fs ) + { + dvdstat_t fileinfo; + int ret, have_css, cdir = -1; +@@ -344,6 +345,21 @@ static dvd_reader_t *DVDOpenCommon( void *priv, + if(logcb) + ctx->logcb = *logcb; + ++ // open files using the provided filesystem implementation ++ if (fs != NULL && ppath != NULL) ++ { ++ ctx->fs = fs; ++ dvdinput_setup_builtin(ctx->priv, &ctx->logcb); ++ ctx->rd = DVDOpenPath(ppath); ++ if (!ctx->rd) ++ { ++ free(ctx); ++ return NULL; ++ } ++ return ctx; ++ } ++ ++ // create the internal filesystem + ctx->fs = InitInternalFilesystem(); + if (!ctx->fs) + { +@@ -629,25 +645,31 @@ DVDOpen_error: + + dvd_reader_t *DVDOpen( const char *ppath ) + { +- return DVDOpenCommon( NULL, NULL, ppath, NULL ); ++ return DVDOpenCommon( NULL, NULL, ppath, NULL, NULL ); + } + + dvd_reader_t *DVDOpenStream( void *stream, + dvd_reader_stream_cb *stream_cb ) + { +- return DVDOpenCommon( stream, NULL, NULL, stream_cb ); ++ return DVDOpenCommon( stream, NULL, NULL, stream_cb, NULL ); + } + + dvd_reader_t *DVDOpen2( void *priv, const dvd_logger_cb *logcb, + const char *ppath ) + { +- return DVDOpenCommon( priv, logcb, ppath, NULL ); ++ return DVDOpenCommon( priv, logcb, ppath, NULL, NULL ); + } + + dvd_reader_t *DVDOpenStream2( void *priv, const dvd_logger_cb *logcb, + dvd_reader_stream_cb *stream_cb ) + { +- return DVDOpenCommon( priv, logcb, NULL, stream_cb ); ++ return DVDOpenCommon( priv, logcb, NULL, stream_cb, NULL ); ++} ++ ++dvd_reader_t *DVDOpenFiles( void *priv, const dvd_logger_cb *logcb, ++ const char *ppath, dvd_reader_filesystem_h *fs) ++{ ++ return DVDOpenCommon( priv, logcb, ppath, NULL, fs); + } + + void DVDClose( dvd_reader_t *dvd ) +diff --git a/libdvdread-embedded/src/dvdread/dvd_reader.h b/libdvdread-embedded/src/dvdread/dvd_reader.h +index 5b15704..40ddaf2 100644 +--- a/libdvdread-embedded/src/dvdread/dvd_reader.h ++++ b/libdvdread-embedded/src/dvdread/dvd_reader.h +@@ -153,6 +153,19 @@ dvd_reader_t *DVDOpenStream( void *, dvd_reader_stream_cb * ); + dvd_reader_t *DVDOpen2( void *, const dvd_logger_cb *, const char * ); + dvd_reader_t *DVDOpenStream2( void *, const dvd_logger_cb *, dvd_reader_stream_cb * ); + ++/** ++ * Open unencrypted DVD files providing the respective filesystem implementation ++ * Useful to open files located on virtual file systems ++ * ++ * @param path Specifies the file or directory to use ++ * @param priv is a private handle ++ * @param logcb is a custom logger callback struct, or NULL if none needed ++ * @param fs is a struct containing the filesystem implementation ++ * @return If successful a read handle is returned. Otherwise 0 is returned. ++ * ++ */ ++dvd_reader_t *DVDOpenFiles( void *priv, const dvd_logger_cb *logcb, const char * path, dvd_reader_filesystem_h *fs); ++ + /** + * Closes and cleans up the DVD reader object. + * +-- +2.35.1 + |