[libdvdnav-devel] [Git][videolan/libdvdread][master] 5 commits: win32: add utf8 -> wchar_t conversion utility
Petri Hintukainen
gitlab at videolan.org
Tue Apr 13 11:22:26 UTC 2021
Petri Hintukainen pushed to branch master at VideoLAN / libdvdread
Commits:
edadb425 by Petri Hintukainen at 2021-04-12T19:33:17+03:00
win32: add utf8 -> wchar_t conversion utility
- - - - -
2ffeb36d by Petri Hintukainen at 2021-04-12T19:34:01+03:00
win32: Fix stat() with non-ASCII paths
- - - - -
72cb63b8 by Petri Hintukainen at 2021-04-12T19:34:08+03:00
win32: Fix opening of non-ASCII paths
- - - - -
714dc268 by Petri Hintukainen at 2021-04-12T19:34:08+03:00
win32: Fix opendir()/readdir() with non-ASCII paths
- - - - -
3d8b0cbc by Petri Hintukainen at 2021-04-12T19:34:08+03:00
Move win32 helpers after all includes
- - - - -
3 changed files:
- + msvc/contrib/win32_cs.h
- src/dvd_input.c
- src/dvd_reader.c
Changes:
=====================================
msvc/contrib/win32_cs.h
=====================================
@@ -0,0 +1,40 @@
+/*
+ * This file is part of libdvdread.
+ *
+ * libdvdread is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libdvdread is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with libdvdread; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <windows.h>
+
+static inline wchar_t *_utf8_to_wchar(const char *utf8)
+{
+ wchar_t *wstr;
+ int wlen;
+
+ wlen = MultiByteToWideChar (CP_UTF8, 0, utf8, -1, NULL, 0);
+ if (wlen < 1) {
+ return NULL;
+ }
+ wstr = (wchar_t*)malloc(sizeof(wchar_t) * wlen);
+ if (!wstr ) {
+ return NULL;
+ }
+ if (!MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, wlen)) {
+ free(wstr);
+ return NULL;
+ }
+ return wstr;
+}
=====================================
src/dvd_input.c
=====================================
@@ -27,6 +27,11 @@
#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"
@@ -72,6 +77,22 @@ 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. */
struct dvd_input_s {
/* libdvdcss handle */
@@ -193,10 +214,12 @@ static dvd_input_t file_open(void *priv, dvd_logger_cb *logcb,
}
/* Open the device */
-#if !defined(_WIN32) && !defined(__OS2__)
- dev->fd = open(target, O_RDONLY);
-#else
+#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) {
char buf[256];
=====================================
src/dvd_reader.c
=====================================
@@ -34,23 +34,6 @@
#include <dirent.h> /* opendir, readdir */
#include <ctype.h> /* isalpha */
-/* misc win32 helpers */
-#ifdef _WIN32
-# ifndef HAVE_GETTIMEOFDAY
- /* replacement gettimeofday implementation */
-# include <sys/timeb.h>
-static inline int _private_gettimeofday( struct timeval *tv, void *tz )
-{
- struct timeb t;
- ftime( &t );
- tv->tv_sec = t.time;
- tv->tv_usec = t.millitm * 1000;
- return 0;
-}
-# define gettimeofday(TV, TZ) _private_gettimeofday((TV), (TZ))
-# endif
-#endif
-
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__) || defined(__APPLE__)
# define SYS_BSD 1
#endif
@@ -75,6 +58,130 @@ static inline int _private_gettimeofday( struct timeval *tv, void *tz )
#include "md5.h"
#include "dvdread/ifo_read.h"
+#if defined(_WIN32)
+# include <windows.h>
+# include "msvc/contrib/win32_cs.h"
+#endif
+
+/* misc win32 helpers */
+
+#ifdef _WIN32
+# ifndef HAVE_GETTIMEOFDAY
+ /* replacement gettimeofday implementation */
+# include <sys/timeb.h>
+static inline int _private_gettimeofday( struct timeval *tv, void *tz )
+{
+ struct timeb t;
+ ftime( &t );
+ tv->tv_sec = t.time;
+ tv->tv_usec = t.millitm * 1000;
+ return 0;
+}
+# define gettimeofday(TV, TZ) _private_gettimeofday((TV), (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 {
@@ -333,7 +440,7 @@ static dvd_reader_t *DVDOpenCommon( void *priv,
const char *ppath,
dvd_reader_stream_cb *stream_cb )
{
- struct stat fileinfo;
+ dvdstat_t fileinfo;
int ret, have_css, cdir = -1;
char *dev_name = NULL;
char *path = NULL, *new_path = NULL, *path_copy = NULL;
@@ -383,7 +490,7 @@ static dvd_reader_t *DVDOpenCommon( void *priv,
}
#endif
- ret = stat( path, &fileinfo );
+ ret = dvdstat( path, &fileinfo );
if( ret < 0 ) {
@@ -781,7 +888,7 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *ctx, const char *filename )
{
char full_path[ PATH_MAX + 1 ];
dvd_file_t *dvd_file;
- struct stat fileinfo;
+ dvdstat_t fileinfo;
dvd_input_t dev;
/* Get the full path of the file. */
@@ -804,7 +911,7 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *ctx, const char *filename )
}
dvd_file->ctx = ctx;
- if( stat( full_path, &fileinfo ) < 0 ) {
+ if( dvdstat( full_path, &fileinfo ) < 0 ) {
Log0(ctx, "Can't stat() %s.", filename );
free( dvd_file );
dvdinput_close( dev );
@@ -866,7 +973,7 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *ctx, int title, int menu )
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
char full_path[ PATH_MAX + 1 ];
- struct stat fileinfo;
+ dvdstat_t fileinfo;
dvd_file_t *dvd_file;
dvd_file = calloc( 1, sizeof( dvd_file_t ) );
@@ -893,7 +1000,7 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *ctx, int title, int menu )
return NULL;
}
- if( stat( full_path, &fileinfo ) < 0 ) {
+ if( dvdstat( full_path, &fileinfo ) < 0 ) {
Log0(ctx, "Can't stat() %s.", filename );
dvdinput_close(dev);
free( dvd_file );
@@ -914,7 +1021,7 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *ctx, int title, int menu )
break;
}
- if( stat( full_path, &fileinfo ) < 0 ) {
+ if( dvdstat( full_path, &fileinfo ) < 0 ) {
Log0(ctx, "Can't stat() %s.", filename );
break;
}
@@ -1058,7 +1165,7 @@ static int DVDFileStatVOBPath( dvd_reader_t *dvd, int title,
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
char full_path[ PATH_MAX + 1 ];
- struct stat fileinfo;
+ dvdstat_t fileinfo;
off_t tot_size;
off_t parts_size[ 9 ];
int nr_parts = 0;
@@ -1072,7 +1179,7 @@ static int DVDFileStatVOBPath( dvd_reader_t *dvd, int title,
if( !findDVDFile( dvd, filename, full_path ) )
return -1;
- if( stat( full_path, &fileinfo ) < 0 ) {
+ if( dvdstat( full_path, &fileinfo ) < 0 ) {
Log1(dvd, "Can't stat() %s.", filename );
return -1;
}
@@ -1088,7 +1195,7 @@ static int DVDFileStatVOBPath( dvd_reader_t *dvd, int title,
if( !findDVDFile( dvd, filename, full_path ) )
break;
- if( stat( full_path, &fileinfo ) < 0 ) {
+ if( dvdstat( full_path, &fileinfo ) < 0 ) {
Log1(dvd, "Can't stat() %s.", filename );
break;
}
@@ -1113,7 +1220,7 @@ int DVDFileStat( dvd_reader_t *reader, int titlenum,
{
dvd_reader_device_t *dvd = reader->rd;
char filename[ MAX_UDF_FILE_NAME_LEN ];
- struct stat fileinfo;
+ dvdstat_t fileinfo;
uint32_t size;
/* Check arguments. */
@@ -1171,7 +1278,7 @@ int DVDFileStat( dvd_reader_t *reader, int titlenum,
char full_path[ PATH_MAX + 1 ];
if( findDVDFile( reader, filename, full_path ) ) {
- if( stat( full_path, &fileinfo ) < 0 )
+ if( dvdstat( full_path, &fileinfo ) < 0 )
Log1(reader, "Can't stat() %s.", filename );
else {
statbuf->size = fileinfo.st_size;
View it on GitLab: https://code.videolan.org/videolan/libdvdread/-/compare/f56bef305b86755415200a137b7acc70889c87bf...3d8b0cbce6be3e4b6906f294d631281f4c61c96d
--
View it on GitLab: https://code.videolan.org/videolan/libdvdread/-/compare/f56bef305b86755415200a137b7acc70889c87bf...3d8b0cbce6be3e4b6906f294d631281f4c61c96d
You're receiving this email because of your account on code.videolan.org.
More information about the libdvdnav-devel
mailing list