[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