Build mono runtime under none desktop Windows API family, adjustments and cleanup.
[mono.git] / mono / utils / mono-io-portability.c
index a1cad1fed8f092f63929bd183409e031b9c5c838..7e22eafa8cc9cf25b2c9870a6ad44c42e5e3df0b 100644 (file)
@@ -4,37 +4,28 @@
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
+#include <errno.h>
 #include <mono/utils/mono-io-portability.h>
+#include <mono/metadata/profiler-private.h>
+#include <mono/utils/mono-compiler.h>
 
-int __mono_io_portability_helpers = PORTABILITY_UNKNOWN;
+#ifndef DISABLE_PORTABILITY
 
-#ifdef PLATFORM_WIN32
-void 
-mono_portability_helpers_init (void)
-{
-       __mono_io_portability_helpers = PORTABILITY_NONE;
-}
-
-gchar *
-mono_portability_find_file (const gchar *pathname, gboolean last_exists)
-{
-       g_assert_not_reached();
-       return NULL;
-}
+#include <dirent.h>
 
-#else
+int mono_io_portability_helpers = PORTABILITY_UNKNOWN;
 
-#include <dirent.h>
+static inline gchar *mono_portability_find_file_internal (GString **report, const gchar *pathname, gboolean last_exists);
 
 void mono_portability_helpers_init (void)
 {
         const gchar *env;
 
-       if (__mono_io_portability_helpers != PORTABILITY_UNKNOWN)
+       if (mono_io_portability_helpers != PORTABILITY_UNKNOWN)
                return;
        
-        __mono_io_portability_helpers = PORTABILITY_NONE;
-        
+        mono_io_portability_helpers = PORTABILITY_NONE;
+       
         env = g_getenv ("MONO_IOMAP");
         if (env != NULL) {
                 /* parse the environment setting and set up some vars
@@ -54,15 +45,14 @@ void mono_portability_helpers_init (void)
                                    options[i]);
 #endif
                         if (!strncasecmp (options[i], "drive", 5)) {
-                                __mono_io_portability_helpers |= PORTABILITY_DRIVE;
+                                mono_io_portability_helpers |= PORTABILITY_DRIVE;
                         } else if (!strncasecmp (options[i], "case", 4)) {
-                                __mono_io_portability_helpers |= PORTABILITY_CASE;
+                                mono_io_portability_helpers |= PORTABILITY_CASE;
                         } else if (!strncasecmp (options[i], "all", 3)) {
-                                __mono_io_portability_helpers |= (PORTABILITY_DRIVE |
-                                                                 PORTABILITY_CASE);
-                        }
+                                mono_io_portability_helpers |= (PORTABILITY_DRIVE | PORTABILITY_CASE);
+                       }
                 }
-        }
+       }
 }
 
 /* Returns newly allocated string, or NULL on failure */
@@ -102,17 +92,66 @@ static gchar *find_in_dir (DIR *current, const gchar *name)
        return(NULL);
 }
 
-/* Returns newly-allocated string or NULL on failure */
+static inline void append_report (GString **report, const gchar *format, ...)
+{
+       va_list ap;
+       if (!*report)
+               *report = g_string_new ("");
+
+       va_start (ap, format);
+       g_string_append_vprintf (*report, format, ap);
+       va_end (ap);
+}
+
+static inline void do_mono_profiler_iomap (GString **report, const char *pathname, const char *new_pathname)
+{
+       char *rep = NULL;
+       GString *tmp = report ? *report : NULL;
+
+       if (tmp) {
+               if (tmp->len > 0)
+                       rep = g_string_free (tmp, FALSE);
+               else
+                       g_string_free (tmp, TRUE);
+               *report = NULL;
+       }
+
+       mono_profiler_iomap (rep, pathname, new_pathname);
+       g_free (rep);
+}
+
 gchar *mono_portability_find_file (const gchar *pathname, gboolean last_exists)
+{
+       GString *report = NULL;
+       gchar *ret;
+       
+       if (!pathname || !pathname [0])
+               return NULL;
+       ret = mono_portability_find_file_internal (&report, pathname, last_exists);
+
+       if (report)
+               g_string_free (report, TRUE);
+
+       return ret;
+}
+
+/* Returns newly-allocated string or NULL on failure */
+static inline gchar *mono_portability_find_file_internal (GString **report, const gchar *pathname, gboolean last_exists)
 {
        gchar *new_pathname, **components, **new_components;
        int num_components = 0, component = 0;
        DIR *scanning = NULL;
+       size_t len;
+       gboolean drive_stripped = FALSE;
+       gboolean do_report = (mono_profiler_get_events () & MONO_PROFILE_IOMAP_EVENTS) != 0;
 
        if (IS_PORTABILITY_NONE) {
                return(NULL);
        }
 
+       if (do_report)
+               append_report (report, " - Requested file path: '%s'\n", pathname);
+
        new_pathname = g_strdup (pathname);
        
 #ifdef DEBUG
@@ -143,19 +182,34 @@ gchar *mono_portability_find_file (const gchar *pathname, gboolean last_exists)
                
                g_memmove (new_pathname, new_pathname+2, len - 2);
                new_pathname[len - 2] = '\0';
-               
+
+               if (do_report) {
+                       append_report (report, " - Stripped drive letter.\n");
+                       drive_stripped = TRUE;
+               }
 #ifdef DEBUG
                g_message ("%s: Stripped drive letter, now looking for [%s]\n",
                           __func__, new_pathname);
 #endif
        }
-       
+
+       len = strlen (new_pathname);
+       if (len > 1 && new_pathname [len - 1] == '/') {
+               new_pathname [len - 1] = 0;
+#ifdef DEBUG
+               g_message ("%s: requested name had a trailing /, rewritten to '%s'\n",
+                          __func__, new_pathname);
+#endif
+       }
+
        if (last_exists &&
            access (new_pathname, F_OK) == 0) {
 #ifdef DEBUG
                g_message ("%s: Found it\n", __func__);
 #endif
-               
+               if (do_report && drive_stripped)
+                       do_mono_profiler_iomap (report, pathname, new_pathname);
+
                return(new_pathname);
        }
 
@@ -325,12 +379,18 @@ gchar *mono_portability_find_file (const gchar *pathname, gboolean last_exists)
        if ((last_exists &&
             access (new_pathname, F_OK) == 0) ||
            (!last_exists)) {
+               if (do_report && strcmp (pathname, new_pathname) != 0)
+                       do_mono_profiler_iomap (report, pathname, new_pathname);
+
                return(new_pathname);
        }
-       
+
        g_free (new_pathname);
        return(NULL);
 }
 
+#else /* DISABLE_PORTABILITY */
 
-#endif
+MONO_EMPTY_SOURCE_FILE (mono_io_portability);
+
+#endif /* DISABLE_PORTABILITY */