Skip to content

Commit 85f9302

Browse files
garumajonpryor
authored andcommitted
[monodroid] Add more Windows/Unicode friendly wrapper for I/O operations. (#137)
This allows libmono-android to parse and load assemblies in a directory containing special characters on Windows. Previously the primitives (like `opendir` and `stat`) would fail to locate the various folder paths passed from Java due to not being UTF-8 aware.
1 parent 49870c4 commit 85f9302

File tree

3 files changed

+82
-13
lines changed

3 files changed

+82
-13
lines changed

src/monodroid/jni/monodroid-glue.c

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -404,8 +404,8 @@ create_update_dir (char *override_dir)
404404
static int
405405
file_exists (const char *file)
406406
{
407-
struct stat s;
408-
if (stat (file, &s) == 0 && (s.st_mode & S_IFMT) == S_IFREG)
407+
monodroid_stat_t s;
408+
if (monodroid_stat (file, &s) == 0 && (s.st_mode & S_IFMT) == S_IFREG)
409409
return 1;
410410
return 0;
411411
}
@@ -419,17 +419,17 @@ file_executable (const char *file)
419419
const int s_ixugo = S_IXUSR;
420420
#endif
421421

422-
struct stat s;
423-
if (stat (file, &s) == 0 && (s.st_mode & S_IFMT) == S_IFREG && (s.st_mode & s_ixugo) != 0)
422+
monodroid_stat_t s;
423+
if (monodroid_stat (file, &s) == 0 && (s.st_mode & S_IFMT) == S_IFREG && (s.st_mode & s_ixugo) != 0)
424424
return 1;
425425
return 0;
426426
}
427427

428428
static int
429429
directory_exists (const char *directory)
430430
{
431-
struct stat s;
432-
if (stat (directory, &s) == 0 && (s.st_mode & S_IFMT) == S_IFDIR)
431+
monodroid_stat_t s;
432+
if (monodroid_stat (directory, &s) == 0 && (s.st_mode & S_IFMT) == S_IFDIR)
433433
return 1;
434434
return 0;
435435
}
@@ -521,13 +521,13 @@ setenv(const char *name, const char *value, int overwrite)
521521
static pthread_mutex_t readdir_mutex = PTHREAD_MUTEX_INITIALIZER;
522522

523523
static int
524-
readdir_r (DIR *dirp, struct dirent *entry, struct dirent **result)
524+
readdir_r (_WDIR *dirp, struct _wdirent *entry, struct _wdirent **result)
525525
{
526526
int error_code = 0;
527527

528528
pthread_mutex_lock (&readdir_mutex);
529529
errno = 0;
530-
entry = readdir (dirp);
530+
entry = _wreaddir (dirp);
531531
*result = entry;
532532

533533
if (entry == NULL && errno != 0)
@@ -1743,21 +1743,22 @@ count_override_assemblies (void)
17431743
int i;
17441744

17451745
for (i = 0; i < MAX_OVERRIDES; ++i) {
1746-
DIR *dir;
1747-
struct dirent b, *e;
1746+
monodroid_dir_t *dir;
1747+
monodroid_dirent_t b, *e;
17481748

17491749
const char *dir_path = override_dirs [i];
1750+
17501751
if (dir_path == NULL || !directory_exists (dir_path))
17511752
continue;
17521753

1753-
if ((dir = opendir (dir_path)) == NULL)
1754+
if ((dir = monodroid_opendir (dir_path)) == NULL)
17541755
continue;
17551756

17561757
while (readdir_r (dir, &b, &e) == 0 && e) {
1757-
if (ends_with (e->d_name, ".dll"))
1758+
if (monodroid_dirent_hasextension (e, ".dll"))
17581759
++c;
17591760
}
1760-
closedir (dir);
1761+
monodroid_closedir (dir);
17611762
}
17621763

17631764
return c;

src/monodroid/jni/util.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,59 @@ monodroid_fopen (const char *filename, const char *mode)
392392
#endif // ndef WINDOWS
393393
}
394394

395+
int
396+
monodroid_stat (const char *path, monodroid_stat_t *s)
397+
{
398+
int result;
399+
400+
#ifndef WINDOWS
401+
result = stat (path, s);
402+
#else
403+
wchar_t *wpath = utf8_to_utf16 (path);
404+
result = _wstat (wpath, s);
405+
free (wpath);
406+
#endif
407+
408+
return result;
409+
}
410+
411+
monodroid_dir_t*
412+
monodroid_opendir (const char *filename)
413+
{
414+
#ifndef WINDOWS
415+
return opendir (filename);
416+
#else
417+
wchar_t *wfilename = utf8_to_utf16 (filename);
418+
monodroid_dir_t *result = _wopendir (wfilename);
419+
free (wfilename);
420+
return result;
421+
#endif
422+
}
423+
424+
int
425+
monodroid_closedir (monodroid_dir_t *dirp)
426+
{
427+
#ifndef WINDOWS
428+
return closedir (dirp);
429+
#else
430+
return _wclosedir (dirp);
431+
#endif
432+
433+
}
434+
435+
int
436+
monodroid_dirent_hasextension (monodroid_dirent_t *e, const char *extension)
437+
{
438+
#ifndef WINDOWS
439+
return ends_with (e->d_name, extension);
440+
#else
441+
char *mb_dname = utf16_to_utf8 (e->d_name);
442+
int result = ends_with (mb_dname, extension);
443+
free (mb_dname);
444+
return result;
445+
#endif
446+
}
447+
395448
#ifdef WINDOWS
396449
char*
397450
utf16_to_utf8 (const wchar_t *widestr)

src/monodroid/jni/util.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,20 @@
1515
#define MONODROID_PATH_SEPARATOR "/"
1616
#endif
1717

18+
#if WINDOWS
19+
typedef struct _stat monodroid_stat_t;
20+
#define monodroid_dir_t _WDIR
21+
typedef struct _wdirent monodroid_dirent_t;
22+
#else
23+
typedef struct stat monodroid_stat_t;
24+
#define monodroid_dir_t DIR
25+
typedef struct dirent monodroid_dirent_t;
26+
#endif
27+
1828
#include <stdlib.h>
1929
#include <unistd.h>
2030
#include <sys/stat.h>
31+
#include <dirent.h>
2132

2233
#include "dylib-mono.h"
2334
#include "monodroid.h"
@@ -37,6 +48,10 @@ MONO_API int recv_uninterrupted (int fd, void *buf, int len);
3748
int ends_with (const char *str, const char *end);
3849
char* path_combine(const char *path1, const char *path2);
3950
FILE *monodroid_fopen (const char* filename, const char* mode);
51+
int monodroid_stat (const char *path, monodroid_stat_t *s);
52+
monodroid_dir_t* monodroid_opendir (const char *filename);
53+
int monodroid_closedir (monodroid_dir_t *dirp);
54+
int monodroid_dirent_hasextension (monodroid_dirent_t *e, const char *extension);
4055

4156
static inline void*
4257
_assert_valid_pointer (void *p, size_t size)

0 commit comments

Comments
 (0)