2006-10-03 Dick Porter <dick@ximian.com>
authorDick Porter <dick@acm.org>
Tue, 3 Oct 2006 15:27:48 +0000 (15:27 -0000)
committerDick Porter <dick@acm.org>
Tue, 3 Oct 2006 15:27:48 +0000 (15:27 -0000)
        * io-portability.h:
        * io-portability.c: Optional portability helpers and wrapped
        system calls to try to cope with windows filenames in
        applications.

        * io.c: Use the wrapped system calls

2006-10-03  Dick Porter  <dick@ximian.com>

        * mono.1: Document the new MONO_IO_PORTABILITY_HELP environment
        variable

svn path=/trunk/mono/; revision=66199

man/ChangeLog
man/mono.1
mono/io-layer/ChangeLog
mono/io-layer/Makefile.am
mono/io-layer/io-portability.c [new file with mode: 0644]
mono/io-layer/io-portability.h [new file with mode: 0644]
mono/io-layer/io.c

index cfbc6c30aaae921925a927efbde0df8cb7a536d9..cc9029e0dba7ee73f287d7ea308fb7081c109496 100644 (file)
@@ -1,3 +1,8 @@
+2006-10-03  Dick Porter  <dick@ximian.com>
+
+       * mono.1: Document the new MONO_IO_PORTABILITY_HELP environment
+       variable
+
 2006-09-08  Robert Jordan  <robertj@gmx.net>
 
        * mkbundle.1: The `-z' option is now supported under Windows.
index 39c1a39666f31a451ad18333cbe4f1b1a340b3b6..e571a373e0137391a27fcf039afae113bf1ef792 100644 (file)
@@ -679,6 +679,21 @@ home directories that might be shared over the network.
 .I "MONO_STRICT_IO_EMULATION"
 If set, extra checks are made during IO operations.  Currently, this
 includes only advisory locks around file writes.
+.TP
+.I "MONO_IO_PORTABILITY_HELP"
+Enables some filename rewriting support to assist badly-written
+applications that hard-code Windows paths.  Set to a colon-separated
+list of "drive" to strip drive letters, or "case" to do
+case-insensitive file matching in every directory in a path.  "all"
+enables all rewriting methods.  (Backslashes are always mapped to
+slashes if this variable is set to a valid option.)
+.fi
+.Sp
+For example:
+.nf
+
+       MONO_IO_PORTABILITY_HELP=drive:case
+
 .TP
 .I "MONO_THEME"
 The name of the theme to be used by Windows.Forms.   Available themes today
index db903884ccac56802aaa2eddd7d7699dc24e16ee..c1224677d4a258e0ffe4905baef75a34c2cbdcd0 100644 (file)
@@ -1,3 +1,12 @@
+2006-10-03  Dick Porter  <dick@ximian.com>
+
+       * io-portability.h: 
+       * io-portability.c: Optional portability helpers and wrapped
+       system calls to try to cope with windows filenames in
+       applications.
+
+       * io.c: Use the wrapped system calls
+
 2006-09-01  Zoltan Varga  <vargaz@gmail.com>
 
        * critical-sections.h critical-sections.c: Make Enter/LeaveCriticalSection a macro
index 5200050e003afca651ab8aa581a38bb730fca6e6..df9bac0f97a3c4a99cdc6203241ce2a11ea74dcf 100644 (file)
@@ -20,6 +20,7 @@ OTHER_H = \
        handles.h       \
        io.h            \
        io-layer.h      \
+       io-portability.h        \
        macros.h        \
        mono-mutex.h    \
        mutexes.h       \
@@ -57,6 +58,8 @@ OTHER_SRC = \
        handles-private.h       \
        io.c                    \
        io.h                    \
+       io-portability.c        \
+       io-portability.h        \
        io-private.h            \
        io-layer.h              \
        macros.h                \
diff --git a/mono/io-layer/io-portability.c b/mono/io-layer/io-portability.c
new file mode 100644 (file)
index 0000000..4f0e03a
--- /dev/null
@@ -0,0 +1,678 @@
+/*
+ * io-portability.c:  Optional filename mangling to try to cope with
+ *                     badly-written non-portable windows apps
+ *
+ * Author:
+ *     Dick Porter (dick@ximian.com)
+ *
+ * Copyright (c) 2006 Novell, Inc.
+ */
+
+#include <config.h>
+#include <glib.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <utime.h>
+#include <sys/stat.h>
+
+#include <mono/io-layer/mono-mutex.h>
+#include <mono/io-layer/io-portability.h>
+
+#undef DEBUG
+
+enum {
+       PORTABILITY_NONE        = 0x00,
+       PORTABILITY_UNKNOWN     = 0x01,
+       PORTABILITY_DRIVE       = 0x02,
+       PORTABILITY_CASE        = 0x04,
+};
+
+static mono_once_t options_once = MONO_ONCE_INIT;
+static int portability_helpers = PORTABILITY_UNKNOWN;
+
+static void options_init (void)
+{
+       const gchar *env;
+       
+       portability_helpers = PORTABILITY_NONE;
+       
+       env = g_getenv ("MONO_IO_PORTABILITY_HELP");
+       if (env != NULL) {
+               /* parse the environment setting and set up some vars
+                * here
+                */
+               gchar **options = g_strsplit (env, ":", 0);
+               int i;
+               
+               if (options == NULL) {
+                       /* This shouldn't happen */
+                       return;
+               }
+               
+               for (i = 0; options[i] != NULL; i++) {
+#ifdef DEBUG
+                       g_message ("%s: Setting option [%s]", __func__,
+                                  options[i]);
+#endif
+                       if (!strncasecmp (options[i], "drive", 5)) {
+                               portability_helpers |= PORTABILITY_DRIVE;
+                       } else if (!strncasecmp (options[i], "case", 4)) {
+                               portability_helpers |= PORTABILITY_CASE;
+                       } else if (!strncasecmp (options[i], "all", 3)) {
+                               portability_helpers |= (PORTABILITY_DRIVE |
+                                                       PORTABILITY_CASE);
+                       }
+               }
+       }
+}
+
+/* Returns newly allocated string, or NULL on failure */
+static gchar *find_in_dir (DIR *current, const gchar *name)
+{
+       struct dirent *entry;
+
+#ifdef DEBUG
+       g_message ("%s: looking for [%s]\n", __func__, name);
+#endif
+       
+       while((entry = readdir (current)) != NULL) {
+#ifdef DEBUGX
+               g_message ("%s: found [%s]\n", __func__, entry->d_name);
+#endif
+               
+               if (!g_ascii_strcasecmp (name, entry->d_name)) {
+#ifdef DEBUG
+                       g_message ("%s: matched [%s] to [%s]\n", __func__,
+                                  entry->d_name, name);
+#endif
+                       
+                       closedir (current);
+                       return(g_strdup (entry->d_name));
+               }
+       }
+       
+#ifdef DEBUG
+       g_message ("%s: returning NULL\n", __func__);
+#endif
+       
+       closedir (current);
+       
+       return(NULL);
+}
+
+/* Returns newly-allocated string or NULL on failure */
+static gchar *find_file (const gchar *pathname, gboolean last_exists)
+{
+       gchar *new_pathname, **components, **new_components;
+       int num_components = 0, component = 0;
+       DIR *scanning;
+       
+       mono_once (&options_once, options_init);
+
+       if (portability_helpers == PORTABILITY_NONE) {
+               return(NULL);
+       }
+
+       new_pathname = g_strdup (pathname);
+       
+#ifdef DEBUG
+       g_message ("%s: Finding [%s] last_exists: %s\n", __func__, pathname,
+                  last_exists?"TRUE":"FALSE");
+#endif
+       
+       if (last_exists &&
+           access (new_pathname, F_OK) == 0) {
+#ifdef DEBUG
+               g_message ("%s: Found it without doing anything\n", __func__);
+#endif
+               return(new_pathname);
+       }
+       
+       /* First turn '\' into '/' and strip any drive letters */
+       g_strdelimit (new_pathname, "\\", '/');
+
+#ifdef DEBUG
+       g_message ("%s: Fixed slashes, now have [%s]\n", __func__,
+                  new_pathname);
+#endif
+       
+       if (portability_helpers & PORTABILITY_DRIVE &&
+           g_ascii_isalpha (new_pathname[0]) &&
+           (new_pathname[1] == ':')) {
+               int len = strlen (new_pathname);
+               
+               g_memmove (new_pathname, new_pathname+2, len - 2);
+               new_pathname[len - 2] = '\0';
+               
+#ifdef DEBUG
+               g_message ("%s: Stripped drive letter, now looking for [%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
+               
+               return(new_pathname);
+       }
+
+       /* OK, have to work harder.  Take each path component in turn
+        * and do a case-insensitive directory scan for it
+        */
+
+       if (!(portability_helpers & PORTABILITY_CASE)) {
+               g_free (new_pathname);
+               return(NULL);
+       }
+
+       components = g_strsplit (new_pathname, "/", 0);
+       if (components == NULL) {
+               /* This shouldn't happen */
+               g_free (new_pathname);
+               return(NULL);
+       }
+       
+       while(components[num_components] != NULL) {
+               num_components++;
+       }
+       g_assert (num_components > 0);
+       
+       g_free (new_pathname);
+
+       new_components = (gchar **)g_new0 (gchar **, num_components + 1);
+
+       if (num_components > 1) {
+               if (strcmp (components[0], "") == 0) {
+                       /* first component blank, so start at / */
+                       scanning = opendir ("/");
+                       if (scanning == NULL) {
+#ifdef DEBUG
+                               g_message ("%s: opendir 1 error: %s", __func__,
+                                          g_strerror (errno));
+#endif
+                               g_strfreev (new_components);
+                               g_strfreev (components);
+                               return(NULL);
+                       }
+               
+                       new_components[component++] = g_strdup ("");
+               } else {
+                       DIR *current;
+                       gchar *entry;
+               
+                       current = opendir (".");
+                       if (current == NULL) {
+#ifdef DEBUG
+                               g_message ("%s: opendir 2 error: %s", __func__,
+                                          g_strerror (errno));
+#endif
+                               g_strfreev (new_components);
+                               g_strfreev (components);
+                               return(NULL);
+                       }
+               
+                       entry = find_in_dir (current, components[0]);
+                       if (entry == NULL) {
+                               g_strfreev (new_components);
+                               g_strfreev (components);
+                               return(NULL);
+                       }
+               
+                       scanning = opendir (entry);
+                       if (scanning == NULL) {
+#ifdef DEBUG
+                               g_message ("%s: opendir 3 error: %s", __func__,
+                                          g_strerror (errno));
+#endif
+                               g_free (entry);
+                               g_strfreev (new_components);
+                               g_strfreev (components);
+                               return(NULL);
+                       }
+               
+                       new_components[component++] = entry;
+               }
+       } else {
+               if (last_exists) {
+                       if (strcmp (components[0], "") == 0) {
+                               /* First and only component blank */
+                               new_components[component++] = g_strdup ("");
+                       } else {
+                               DIR *current;
+                               gchar *entry;
+                               
+                               current = opendir (".");
+                               if (current == NULL) {
+#ifdef DEBUG
+                                       g_message ("%s: opendir 4 error: %s",
+                                                  __func__,
+                                                  g_strerror (errno));
+#endif
+                                       g_strfreev (new_components);
+                                       g_strfreev (components);
+                                       return(NULL);
+                               }
+                               
+                               entry = find_in_dir (current, components[0]);
+                               if (entry == NULL) {
+                                       g_strfreev (new_components);
+                                       g_strfreev (components);
+                                       return(NULL);
+                               }
+                               
+                               new_components[component++] = entry;
+                       }
+               } else {
+                               new_components[component++] = g_strdup (components[0]);
+               }
+       }
+
+#ifdef DEBUG
+       g_message ("%s: Got first entry: [%s]\n", __func__, new_components[0]);
+#endif
+
+       g_assert (component == 1);
+       
+       for(; component < num_components; component++) {
+               gchar *entry;
+               gchar *path_so_far;
+               
+               if (!last_exists &&
+                   component == num_components -1) {
+                       entry = g_strdup (components[component]);
+                       closedir (scanning);
+               } else {
+                       entry = find_in_dir (scanning, components[component]);
+                       if (entry == NULL) {
+                               g_strfreev (new_components);
+                               g_strfreev (components);
+                               return(NULL);
+                       }
+               }
+               
+               new_components[component] = entry;
+               
+               if (component < num_components -1) {
+                       path_so_far = g_strjoinv ("/", new_components);
+
+                       scanning = opendir (path_so_far);
+                       g_free (path_so_far);
+                       if (scanning == NULL) {
+                               g_strfreev (new_components);
+                               g_strfreev (components);
+                               return(NULL);
+                       }
+               }
+       }
+       
+       g_strfreev (components);
+
+       new_pathname = g_strjoinv ("/", new_components);
+
+#ifdef DEBUG
+       g_message ("%s: pathname [%s] became [%s]\n", __func__, pathname,
+                  new_pathname);
+#endif
+       
+       g_strfreev (new_components);
+
+       if ((last_exists &&
+            access (new_pathname, F_OK) == 0) ||
+           (!last_exists)) {
+               return(new_pathname);
+       }
+       
+       g_free (new_pathname);
+       return(NULL);
+}
+
+int _wapi_open (const char *pathname, int flags, mode_t mode)
+{
+       int fd;
+       gchar *located_filename;
+       
+       if (flags & O_CREAT) {
+               located_filename = find_file (pathname, FALSE);
+               if (located_filename == NULL) {
+                       fd = open (pathname, flags, mode);
+               } else {
+                       fd = open (located_filename, flags, mode);
+                       g_free (located_filename);
+               }
+       } else {
+               fd = open (pathname, flags, mode);
+               if (fd == -1 &&
+                   (errno == ENOENT || errno == ENOTDIR) &&
+                   portability_helpers > 0) {
+                       int saved_errno = errno;
+                       located_filename = find_file (pathname, TRUE);
+                       
+                       if (located_filename == NULL) {
+                               errno = saved_errno;
+                               return (-1);
+                       }
+                       
+                       fd = open (located_filename, flags, mode);
+                       g_free (located_filename);
+               }
+       }
+       
+       
+       return(fd);
+}
+
+int _wapi_access (const char *pathname, int mode)
+{
+       int ret;
+       
+       ret = access (pathname, mode);
+       if (ret == -1 &&
+           (errno == ENOENT || errno == ENOTDIR) &&
+           portability_helpers > 0) {
+               int saved_errno = errno;
+               gchar *located_filename = find_file (pathname, TRUE);
+               
+               if (located_filename == NULL) {
+                       errno = saved_errno;
+                       return(-1);
+               }
+               
+               ret = access (located_filename, mode);
+               g_free (located_filename);
+       }
+       
+       return(ret);
+}
+
+int _wapi_chmod (const char *pathname, mode_t mode)
+{
+       int ret;
+       
+       ret = chmod (pathname, mode);
+       if (ret == -1 &&
+           (errno == ENOENT || errno == ENOTDIR) &&
+           portability_helpers > 0) {
+               int saved_errno = errno;
+               gchar *located_filename = find_file (pathname, TRUE);
+               
+               if (located_filename == NULL) {
+                       errno = saved_errno;
+                       return(-1);
+               }
+               
+               ret = chmod (located_filename, mode);
+               g_free (located_filename);
+       }
+       
+       return(ret);
+}
+
+int _wapi_utime (const char *filename, const struct utimbuf *buf)
+{
+       int ret;
+       
+       ret = utime (filename, buf);
+       if (ret == -1 &&
+           errno == ENOENT &&
+           portability_helpers > 0) {
+               int saved_errno = errno;
+               gchar *located_filename = find_file (filename, TRUE);
+               
+               if (located_filename == NULL) {
+                       errno = saved_errno;
+                       return(-1);
+               }
+               
+               ret = utime (located_filename, buf);
+               g_free (located_filename);
+       }
+       
+       return(ret);
+}
+
+int _wapi_unlink (const char *pathname)
+{
+       int ret;
+       
+       ret = unlink (pathname);
+       if (ret == -1 &&
+           (errno == ENOENT || errno == ENOTDIR || errno == EISDIR) &&
+           portability_helpers > 0) {
+               int saved_errno = errno;
+               gchar *located_filename = find_file (pathname, TRUE);
+               
+               if (located_filename == NULL) {
+                       errno = saved_errno;
+                       return(-1);
+               }
+               
+               ret = unlink (located_filename);
+               g_free (located_filename);
+       }
+       
+       return(ret);
+}
+
+int _wapi_rename (const char *oldpath, const char *newpath)
+{
+       int ret;
+       gchar *located_newpath = find_file (newpath, FALSE);
+       
+       if (located_newpath == NULL) {
+               ret = rename (oldpath, newpath);
+       } else {
+               ret = rename (oldpath, located_newpath);
+       
+               if (ret == -1 &&
+                   (errno == EISDIR || errno == ENAMETOOLONG ||
+                    errno == ENOENT || errno == ENOTDIR || errno == EXDEV) &&
+                   portability_helpers > 0) {
+                       int saved_errno = errno;
+                       gchar *located_oldpath = find_file (oldpath, TRUE);
+                       
+                       if (located_oldpath == NULL) {
+                               g_free (located_oldpath);
+                               g_free (located_newpath);
+                       
+                               errno = saved_errno;
+                               return(-1);
+                       }
+                       
+                       ret = rename (located_oldpath, located_newpath);
+                       g_free (located_oldpath);
+               }
+               g_free (located_newpath);
+       }
+       
+       return(ret);
+}
+
+int _wapi_stat (const char *path, struct stat *buf)
+{
+       int ret;
+       
+       ret = stat (path, buf);
+       if (ret == -1 &&
+           (errno == ENOENT || errno == ENOTDIR) &&
+           portability_helpers > 0) {
+               int saved_errno = errno;
+               gchar *located_filename = find_file (path, TRUE);
+               
+               if (located_filename == NULL) {
+                       errno = saved_errno;
+                       return(-1);
+               }
+               
+               ret = stat (located_filename, buf);
+               g_free (located_filename);
+       }
+       
+       return(ret);
+}
+
+int _wapi_lstat (const char *path, struct stat *buf)
+{
+       int ret;
+       
+       ret = lstat (path, buf);
+       if (ret == -1 &&
+           (errno == ENOENT || errno == ENOTDIR) &&
+           portability_helpers > 0) {
+               int saved_errno = errno;
+               gchar *located_filename = find_file (path, TRUE);
+               
+               if (located_filename == NULL) {
+                       errno = saved_errno;
+                       return(-1);
+               }
+               
+               ret = lstat (located_filename, buf);
+               g_free (located_filename);
+       }
+       
+       return(ret);
+}
+
+int _wapi_mkdir (const char *pathname, mode_t mode)
+{
+       int ret;
+       gchar *located_filename = find_file (pathname, FALSE);
+       
+       if (located_filename == NULL) {
+               ret = mkdir (pathname, mode);
+       } else {
+               ret = mkdir (located_filename, mode);
+               g_free (located_filename);
+       }
+       
+       return(ret);
+}
+
+int _wapi_rmdir (const char *pathname)
+{
+       int ret;
+       
+       ret = rmdir (pathname);
+       if (ret == -1 &&
+           (errno == ENOENT || errno == ENOTDIR || errno == ENAMETOOLONG) &&
+           portability_helpers > 0) {
+               int saved_errno = errno;
+               gchar *located_filename = find_file (pathname, TRUE);
+               
+               if (located_filename == NULL) {
+                       errno = saved_errno;
+                       return(-1);
+               }
+               
+               ret = rmdir (located_filename);
+               g_free (located_filename);
+       }
+       
+       return(ret);
+}
+
+int _wapi_chdir (const char *path)
+{
+       int ret;
+       
+       ret = chdir (path);
+       if (ret == -1 &&
+           (errno == ENOENT || errno == ENOTDIR || errno == ENAMETOOLONG) &&
+           portability_helpers > 0) {
+               int saved_errno = errno;
+               gchar *located_filename = find_file (path, TRUE);
+               
+               if (located_filename == NULL) {
+                       errno = saved_errno;
+                       return(-1);
+               }
+               
+               ret = chdir (located_filename);
+               g_free (located_filename);
+       }
+       
+       return(ret);
+}
+
+gchar *_wapi_basename (const gchar *filename)
+{
+       gchar *new_filename = g_strdup (filename), *ret;
+
+       mono_once (&options_once, options_init);
+       
+       g_strdelimit (new_filename, "\\", '/');
+
+       if (portability_helpers & PORTABILITY_DRIVE &&
+           g_ascii_isalpha (new_filename[0]) &&
+           (new_filename[1] == ':')) {
+               int len = strlen (new_filename);
+               
+               g_memmove (new_filename, new_filename + 2, len - 2);
+               new_filename[len - 2] = '\0';
+       }
+       
+       ret = g_path_get_basename (new_filename);
+       g_free (new_filename);
+       
+       return(ret);
+}
+
+gchar *_wapi_dirname (const gchar *filename)
+{
+       gchar *new_filename = g_strdup (filename), *ret;
+
+       mono_once (&options_once, options_init);
+       
+       g_strdelimit (new_filename, "\\", '/');
+
+       if (portability_helpers & PORTABILITY_DRIVE &&
+           g_ascii_isalpha (new_filename[0]) &&
+           (new_filename[1] == ':')) {
+               int len = strlen (new_filename);
+               
+               g_memmove (new_filename, new_filename + 2, len - 2);
+               new_filename[len - 2] = '\0';
+       }
+       
+       ret = g_path_get_dirname (new_filename);
+       g_free (new_filename);
+       
+       return(ret);
+}
+
+GDir *_wapi_g_dir_open (const gchar *path, guint flags, GError **error)
+{
+       GDir *ret;
+       
+       ret = g_dir_open (path, flags, error);
+       if (ret == NULL &&
+           ((*error)->code == G_FILE_ERROR_NOENT ||
+            (*error)->code == G_FILE_ERROR_NOTDIR ||
+            (*error)->code == G_FILE_ERROR_NAMETOOLONG) &&
+           portability_helpers > 0) {
+               gchar *located_filename = find_file (path, TRUE);
+               GError *tmp_error;
+               
+               if (located_filename == NULL) {
+                       return(NULL);
+               }
+               
+               ret = g_dir_open (located_filename, flags, &tmp_error);
+               g_free (located_filename);
+               if (tmp_error != NULL) {
+                       g_propagate_error (error, tmp_error);
+               }
+       }
+       
+       return(ret);
+}
diff --git a/mono/io-layer/io-portability.h b/mono/io-layer/io-portability.h
new file mode 100644 (file)
index 0000000..dfbe777
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * io-portability.h:   Optional filename mangling to try to cope with
+ *                     badly-written non-portable windows apps
+ *
+ * Author:
+ *     Dick Porter (dick@ximian.com)
+ *
+ * Copyright (C) 2006 Novell, Inc.
+ */
+
+#ifndef _WAPI_IO_PORTABILITY_H_
+#define _WAPI_IO_PORTABILITY_H_
+
+#include <glib.h>
+#include <sys/types.h>
+#include <utime.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+G_BEGIN_DECLS
+
+extern int _wapi_open (const char *pathname, int flags, mode_t mode);
+extern int _wapi_access (const char *pathname, int mode);
+extern int _wapi_chmod (const char *pathname, mode_t mode);
+extern int _wapi_utime (const char *filename, const struct utimbuf *buf);
+extern int _wapi_unlink (const char *pathname);
+extern int _wapi_rename (const char *oldpath, const char *newpath);
+extern int _wapi_stat (const char *path, struct stat *buf);
+extern int _wapi_lstat (const char *path, struct stat *buf);
+extern int _wapi_mkdir (const char *pathname, mode_t mode);
+extern int _wapi_rmdir (const char *pathname);
+extern int _wapi_chdir (const char *path);
+extern gchar *_wapi_basename (const gchar *filename);
+extern gchar *_wapi_dirname (const gchar *filename);
+extern GDir *_wapi_g_dir_open (const gchar *path, guint flags, GError **error);
+
+G_END_DECLS
+
+#endif /* _WAPI_IO_PORTABILITY_H_ */
index c0286be2f2554f7d12eed47e3442fcd9095038fb..6173a3db111eb6dbfebfb44092a218b1ffca62f1 100644 (file)
@@ -27,6 +27,7 @@
 #include <mono/io-layer/io-private.h>
 #include <mono/io-layer/timefuncs-private.h>
 #include <mono/io-layer/thread-private.h>
+#include <mono/io-layer/io-portability.h>
 #include <mono/utils/strenc.h>
 
 #undef DEBUG
@@ -234,7 +235,7 @@ static guint32 _wapi_stat_to_file_attributes (const gchar *pathname,
        if (S_ISSOCK (buf->st_mode))
                buf->st_mode &= ~S_IFSOCK; /* don't consider socket protection */
 
-       filename = g_path_get_basename (pathname);
+       filename = _wapi_basename (pathname);
 
        if (S_ISDIR (buf->st_mode)) {
                attrs = FILE_ATTRIBUTE_DIRECTORY;
@@ -280,12 +281,12 @@ static void _wapi_set_last_path_error_from_errno (const gchar *dir,
 
 
                if (dir == NULL) {
-                       dirname = g_path_get_dirname (path);
+                       dirname = _wapi_dirname (path);
                } else {
                        dirname = g_strdup (dir);
                }
                
-               if (access (dirname, F_OK) == 0) {
+               if (_wapi_access (dirname, F_OK) == 0) {
                        SetLastError (ERROR_FILE_NOT_FOUND);
                } else {
                        SetLastError (ERROR_PATH_NOT_FOUND);
@@ -309,7 +310,7 @@ static void file_close (gpointer handle, gpointer data)
 #endif
 
        if (file_handle->attrs & FILE_FLAG_DELETE_ON_CLOSE)
-               unlink (file_handle->filename);
+               _wapi_unlink (file_handle->filename);
        
        g_free (file_handle->filename);
        
@@ -988,15 +989,15 @@ static gboolean file_setfiletime(gpointer handle,
        }
 
 #ifdef DEBUG
-       g_message("%s: setting handle %p access %ld write %ld", __func__,
-                 handle, utbuf.actime, utbuf.modtime);
+       g_message ("%s: setting handle %p access %ld write %ld", __func__,
+                  handle, utbuf.actime, utbuf.modtime);
 #endif
 
-       ret=utime(file_handle->filename, &utbuf);
-       if(ret==-1) {
+       ret = _wapi_utime (file_handle->filename, &utbuf);
+       if (ret == -1) {
 #ifdef DEBUG
-               g_message("%s: handle %p [%s] utime failed: %s", __func__,
-                         handle, file_handle->filename, strerror(errno));
+               g_message ("%s: handle %p [%s] utime failed: %s", __func__,
+                          handle, file_handle->filename, strerror(errno));
 
 #endif
                SetLastError (ERROR_INVALID_PARAMETER);
@@ -1543,7 +1544,7 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
                   filename, sharemode, fileaccess);
 #endif
        
-       fd = open(filename, flags, perms);
+       fd = _wapi_open (filename, flags, perms);
     
        /* If we were trying to open a directory with write permissions
         * (e.g. O_WRONLY or O_RDWR), this call will fail with
@@ -1697,7 +1698,7 @@ gboolean DeleteFile(const gunichar2 *name)
                return(FALSE);
        }
        
-       retval = unlink (filename);
+       retval = _wapi_unlink (filename);
        
        if (retval == -1) {
                _wapi_set_last_path_error_from_errno (NULL, filename);
@@ -1775,14 +1776,16 @@ gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_name)
         * We check it here and return the failure if dest exists and is not
         * the same file as src.
         */
-       if (!stat (utf8_dest_name, &stat_dest) && !stat (utf8_name, &stat_src)) {
-               if (stat_dest.st_dev != stat_src.st_dev || stat_dest.st_ino != stat_src.st_ino) {
+       if (!_wapi_stat (utf8_dest_name, &stat_dest) &&
+           !_wapi_stat (utf8_name, &stat_src)) {
+               if (stat_dest.st_dev != stat_src.st_dev ||
+                   stat_dest.st_ino != stat_src.st_ino) {
                        SetLastError (ERROR_ALREADY_EXISTS);
                        return FALSE;
                }       
        }
 
-       result = rename (utf8_name, utf8_dest_name);
+       result = _wapi_rename (utf8_name, utf8_dest_name);
 
        if (result == -1) {
                switch(errno) {
@@ -1881,7 +1884,7 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name,
                return(FALSE);
        }
        
-       src_fd = open (utf8_src, O_RDONLY);
+       src_fd = _wapi_open (utf8_src, O_RDONLY, 0);
        if (src_fd < 0) {
                _wapi_set_last_path_error_from_errno (NULL, utf8_src);
                
@@ -2729,15 +2732,15 @@ mono_io_scandir (const gchar *dirname, const gchar *pattern, gchar ***namelist)
        gint result;
        GPatternSpec *patspec;
 
-       dir = g_dir_open (dirname, 0, &error);
+       dir = _wapi_g_dir_open (dirname, 0, &error);
        if (dir == NULL) {
                /* g_dir_open returns ENOENT on directories on which we don't
                 * have read/x permission */
                gint errnum = get_errno_from_g_file_error (error->code);
                g_error_free (error);
                if (errnum == ENOENT &&
-                   !access (dirname, F_OK) &&
-                   access (dirname, R_OK|X_OK)) {
+                   !_wapi_access (dirname, F_OK) &&
+                   _wapi_access (dirname, R_OK|X_OK)) {
                        errnum = EACCES;
                }
 
@@ -2798,8 +2801,8 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
 #endif
        
        /* Figure out which bit of the pattern is the directory */
-       dir_part = g_path_get_dirname (utf8_pattern);
-       entry_part = g_path_get_basename (utf8_pattern);
+       dir_part = _wapi_dirname (utf8_pattern);
+       entry_part = _wapi_basename (utf8_pattern);
 
 #if 0
        /* Don't do this check for now, it breaks if directories
@@ -2932,7 +2935,7 @@ retry:
        /* stat next match */
 
        filename = g_build_filename (find_handle->dir_part, find_handle->namelist[find_handle->count ++], NULL);
-       if (lstat (filename, &buf) != 0) {
+       if (_wapi_lstat (filename, &buf) != 0) {
 #ifdef DEBUG
                g_message ("%s: stat failed: %s", __func__, filename);
 #endif
@@ -2947,7 +2950,7 @@ retry:
         * it isn't there.)
         */
        if(S_ISLNK (buf.st_mode)) {
-               if(stat (filename, &buf) != 0) {
+               if(_wapi_stat (filename, &buf) != 0) {
                        g_free (filename);
                        goto retry;
                }
@@ -2992,7 +2995,7 @@ retry:
        find_data->dwReserved0 = 0;
        find_data->dwReserved1 = 0;
 
-       utf8_basename = g_path_get_basename (utf8_filename);
+       utf8_basename = _wapi_basename (utf8_filename);
        utf16_basename = g_utf8_to_utf16 (utf8_basename, -1, NULL, &bytes,
                                          NULL);
        if(utf16_basename==NULL) {
@@ -3107,7 +3110,7 @@ gboolean CreateDirectory (const gunichar2 *name,
                return FALSE;
        }
 
-       result = mkdir (utf8_name, 0777);
+       result = _wapi_mkdir (utf8_name, 0777);
 
        if (result == 0) {
                g_free (utf8_name);
@@ -3152,7 +3155,7 @@ gboolean RemoveDirectory (const gunichar2 *name)
                return FALSE;
        }
 
-       result = rmdir (utf8_name);
+       result = _wapi_rmdir (utf8_name);
        if (result == -1) {
                _wapi_set_last_path_error_from_errno (NULL, utf8_name);
                g_free (utf8_name);
@@ -3198,10 +3201,10 @@ guint32 GetFileAttributes (const gunichar2 *name)
                return (INVALID_FILE_ATTRIBUTES);
        }
 
-       result = stat (utf8_name, &buf);
+       result = _wapi_stat (utf8_name, &buf);
        if (result == -1 && errno == ENOENT) {
                /* Might be a dangling symlink... */
-               result = lstat (utf8_name, &buf);
+               result = _wapi_lstat (utf8_name, &buf);
        }
 
        if (result != 0) {
@@ -3264,10 +3267,10 @@ gboolean GetFileAttributesEx (const gunichar2 *name, WapiGetFileExInfoLevels lev
                return FALSE;
        }
 
-       result = stat (utf8_name, &buf);
+       result = _wapi_stat (utf8_name, &buf);
        if (result == -1 && errno == ENOENT) {
                /* Might be a dangling symlink... */
-               result = lstat (utf8_name, &buf);
+               result = _wapi_lstat (utf8_name, &buf);
        }
        
        if (result != 0) {
@@ -3346,7 +3349,7 @@ extern gboolean SetFileAttributes (const gunichar2 *name, guint32 attrs)
                return FALSE;
        }
 
-       result = stat (utf8_name, &buf);
+       result = _wapi_stat (utf8_name, &buf);
        if (result != 0) {
                _wapi_set_last_path_error_from_errno (NULL, utf8_name);
                g_free (utf8_name);
@@ -3358,9 +3361,9 @@ extern gboolean SetFileAttributes (const gunichar2 *name, guint32 attrs)
         * catch that case here.
         */
        if (attrs & FILE_ATTRIBUTE_READONLY) {
-               result = chmod (utf8_name, buf.st_mode & ~(S_IWRITE | S_IWOTH | S_IWGRP));
+               result = _wapi_chmod (utf8_name, buf.st_mode & ~(S_IWRITE | S_IWOTH | S_IWGRP));
        } else {
-               result = chmod (utf8_name, buf.st_mode | S_IWRITE);
+               result = _wapi_chmod (utf8_name, buf.st_mode | S_IWRITE);
        }
 
        /* Ignore the other attributes for now */
@@ -3451,7 +3454,7 @@ extern gboolean SetCurrentDirectory (const gunichar2 *path)
        }
        
        utf8_path = mono_unicode_to_external (path);
-       if (chdir (utf8_path) != 0) {
+       if (_wapi_chdir (utf8_path) != 0) {
                _wapi_set_last_error_from_errno ();
                result = FALSE;
        }