Skip to content

Commit

Permalink
[mono][aot] Fix support for files with non-ascii characters on windows (
Browse files Browse the repository at this point in the history
#92279)

* [mono][aot] Fix support for files with non-ascii characters

Add g_fopen, g_unlink and g_rename which on windows do a utf8 to utf16 conversion and then call the corresponding wide char api.

* [mono][eglib] Avoid utf16 conversion if all characters are ASCII
  • Loading branch information
BrzVlad authored Jan 31, 2024
1 parent ba8993f commit 3bf9bee
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 32 deletions.
86 changes: 74 additions & 12 deletions src/mono/mono/eglib/gfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,27 +105,89 @@ g_file_error_from_errno (gint err_no)
}
}

FILE *
g_fopen (const char *path, const char *mode)
#ifdef HOST_WIN32
static gboolean
is_ascii_string (const gchar *str)
{
while (*str) {
if (!g_isascii (*str))
return FALSE;
}
return TRUE;
}
#endif

FILE*
g_fopen (const gchar *path, const gchar *mode)
{
FILE *fp;

if (!path)
return NULL;

#ifndef HOST_WIN32
fp = fopen (path, mode);
#else
gunichar2 *wPath = g_utf8_to_utf16 (path, -1, 0, 0, 0);
gunichar2 *wMode = g_utf8_to_utf16 (mode, -1, 0, 0, 0);
#ifdef HOST_WIN32
if (is_ascii_string (path) && is_ascii_string (mode)) {
fp = fopen (path, mode);
} else {
gunichar2 *wPath = g_utf8_to_utf16 (path, -1, 0, 0, 0);
gunichar2 *wMode = g_utf8_to_utf16 (mode, -1, 0, 0, 0);

if (!wPath || !wMode)
return NULL;
if (!wPath || !wMode)
return NULL;

fp = _wfopen ((wchar_t *) wPath, (wchar_t *) wMode);
g_free (wPath);
g_free (wMode);
fp = _wfopen ((wchar_t *) wPath, (wchar_t *) wMode);
g_free (wPath);
g_free (wMode);
}
#else
fp = fopen (path, mode);
#endif

return fp;
}

int
g_rename (const gchar *src_path, const gchar *dst_path)
{
#ifdef HOST_WIN32
if (is_ascii_string (src_path) && is_ascii_string (dst_path)) {
return rename (src_path, dst_path);
} else {
gunichar2 *wSrcPath = g_utf8_to_utf16 (src_path, -1, 0, 0, 0);
gunichar2 *wDstPath = g_utf8_to_utf16 (dst_path, -1, 0, 0, 0);

if (!wSrcPath || !wDstPath)
return -1;

int ret = _wrename ((wchar_t *) wSrcPath, (wchar_t *) wDstPath);
g_free (wSrcPath);
g_free (wDstPath);

return ret;
}
#else
return rename (src_path, dst_path);
#endif
}

int
g_unlink (const gchar *path)
{
#ifdef HOST_WIN32
if (is_ascii_string (path)) {
return unlink (path);
} else {
gunichar2 *wPath = g_utf8_to_utf16 (path, -1, 0, 0, 0);

if (!wPath)
return -1;

int ret = _wunlink ((wchar_t *) wPath);
g_free (wPath);

return ret;
}
#else
return unlink (path);
#endif
}
10 changes: 4 additions & 6 deletions src/mono/mono/eglib/glib.h
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ gint g_ascii_xdigit_value (gchar c);
#define g_ascii_isalpha(c) (isalpha (c) != 0)
#define g_ascii_isprint(c) (isprint (c) != 0)
#define g_ascii_isxdigit(c) (isxdigit (c) != 0)
#define g_isascii(c) (isascii (c) != 0)

/* FIXME: g_strcasecmp supports utf8 unicode stuff */
#ifdef _MSC_VER
Expand Down Expand Up @@ -962,7 +963,9 @@ typedef enum {

G_ENUM_FUNCTIONS (GFileTest)

FILE * g_fopen (const char *path, const char *mode);
FILE* g_fopen (const gchar *path, const gchar *mode);
int g_rename (const gchar *src_path, const gchar *dst_path);
int g_unlink (const gchar *path);
gboolean g_file_get_contents (const gchar *filename, gchar **contents, gsize *length, GError **gerror);
GFileError g_file_error_from_errno (gint err_no);
gint g_file_open_tmp (const gchar *tmpl, gchar **name_used, GError **gerror);
Expand All @@ -974,11 +977,6 @@ gboolean g_file_test (const gchar *filename, GFileTest test);
#define g_open open
#endif
#ifdef G_OS_WIN32
#define g_unlink _unlink
#else
#define g_unlink unlink
#endif
#ifdef G_OS_WIN32
#define g_write _write
#else
#define g_write write
Expand Down
28 changes: 14 additions & 14 deletions src/mono/mono/mini/aot-compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -5529,7 +5529,7 @@ MONO_RESTORE_WARNING

if (acfg->aot_opts.export_symbols_outfile) {
char *export_symbols_out = g_string_free (export_symbols, FALSE);
FILE* export_symbols_outfile = fopen (acfg->aot_opts.export_symbols_outfile, "w");
FILE* export_symbols_outfile = g_fopen (acfg->aot_opts.export_symbols_outfile, "w");
if (!export_symbols_outfile) {
fprintf (stderr, "Unable to open specified export_symbols_outfile '%s' to append symbols '%s': %s\n", acfg->aot_opts.export_symbols_outfile, export_symbols_out, strerror (errno));
g_free (export_symbols_out);
Expand Down Expand Up @@ -13446,11 +13446,11 @@ compile_asm (MonoAotCompile *acfg)
}
#endif

if (0 != rename (tmp_outfile_name, outfile_name)) {
if (0 != g_rename (tmp_outfile_name, outfile_name)) {
if (G_FILE_ERROR_EXIST == g_file_error_from_errno (errno)) {
/* Since we are rebuilding the module we need to be able to replace any old copies. Remove old file and retry rename operation. */
unlink (outfile_name);
rename (tmp_outfile_name, outfile_name);
g_unlink (outfile_name);
g_rename (tmp_outfile_name, outfile_name);
}
}

Expand All @@ -13463,7 +13463,7 @@ compile_asm (MonoAotCompile *acfg)
#endif

if (!acfg->aot_opts.save_temps)
unlink (objfile);
g_unlink (objfile);

g_free (tmp_outfile_name);
g_free (outfile_name);
Expand All @@ -13472,7 +13472,7 @@ compile_asm (MonoAotCompile *acfg)
if (acfg->aot_opts.save_temps)
aot_printf (acfg, "Retained input file.\n");
else
unlink (acfg->tmpfname);
g_unlink (acfg->tmpfname);

return 0;
}
Expand Down Expand Up @@ -13520,7 +13520,7 @@ load_profile_file (MonoAotCompile *acfg, char *filename)
int version;
char magic [32];

infile = fopen (filename, "rb");
infile = g_fopen (filename, "rb");
if (!infile) {
fprintf (stderr, "Unable to open file '%s': %s.\n", filename, strerror (errno));
exit (1);
Expand Down Expand Up @@ -14538,7 +14538,7 @@ static void aot_dump (MonoAotCompile *acfg)
mono_json_writer_object_end (&writer);

dumpname = g_strdup_printf ("%s.json", g_path_get_basename (acfg->image->name));
dumpfile = fopen (dumpname, "w+");
dumpfile = g_fopen (dumpname, "w+");
g_free (dumpname);

fprintf (dumpfile, "%s", writer.text->str);
Expand Down Expand Up @@ -14947,7 +14947,7 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options)
}

if (acfg->aot_opts.logfile) {
acfg->logfile = fopen (acfg->aot_opts.logfile, "a+");
acfg->logfile = g_fopen (acfg->aot_opts.logfile, "a+");
}

if (acfg->aot_opts.trimming_eligible_methods_outfile && acfg->dedup_phase != DEDUP_COLLECT) {
Expand All @@ -14961,7 +14961,7 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options)
}

if (acfg->aot_opts.data_outfile) {
acfg->data_outfile = fopen (acfg->aot_opts.data_outfile, "w+");
acfg->data_outfile = g_fopen (acfg->aot_opts.data_outfile, "w+");
if (!acfg->data_outfile) {
aot_printerrf (acfg, "Unable to create file '%s': %s\n", acfg->aot_opts.data_outfile, strerror (errno));
return 1;
Expand Down Expand Up @@ -15124,7 +15124,7 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options)
acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_EAGER_LOAD);

if (acfg->aot_opts.instances_logfile_path) {
acfg->instances_logfile = fopen (acfg->aot_opts.instances_logfile_path, "w");
acfg->instances_logfile = g_fopen (acfg->aot_opts.instances_logfile_path, "w");
if (!acfg->instances_logfile) {
aot_printerrf (acfg, "Unable to create logfile: '%s'.\n", acfg->aot_opts.instances_logfile_path);
return 1;
Expand Down Expand Up @@ -15387,7 +15387,7 @@ create_depfile (MonoAotCompile *acfg)
// FIXME: Support other configurations
g_assert (acfg->aot_opts.llvm_only && acfg->aot_opts.asm_only && acfg->aot_opts.llvm_outfile);

depfile = fopen (acfg->aot_opts.depfile, "w");
depfile = g_fopen (acfg->aot_opts.depfile, "w");
g_assert (depfile);

int ntargets = 1;
Expand Down Expand Up @@ -15459,14 +15459,14 @@ emit_aot_image (MonoAotCompile *acfg)
acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
else
acfg->tmpfname = g_strdup_printf ("%s.s", acfg->image->name);
acfg->fp = fopen (acfg->tmpfname, "w+");
acfg->fp = g_fopen (acfg->tmpfname, "w+");
} else {
if (strcmp (acfg->aot_opts.temp_path, "") == 0) {
acfg->fp = fdopen (g_file_open_tmp ("mono_aot_XXXXXX", &acfg->tmpfname, NULL), "w+");
} else {
acfg->tmpbasename = g_build_filename (acfg->aot_opts.temp_path, "temp", (const char*)NULL);
acfg->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename);
acfg->fp = fopen (acfg->tmpfname, "w+");
acfg->fp = g_fopen (acfg->tmpfname, "w+");
}
}
if (acfg->fp == 0 && !acfg->aot_opts.llvm_only) {
Expand Down

0 comments on commit 3bf9bee

Please sign in to comment.