[io-layer] Extract file (#4255)
authorLudovic Henry <ludovic@xamarin.com>
Fri, 20 Jan 2017 16:32:48 +0000 (11:32 -0500)
committerGitHub <noreply@github.com>
Fri, 20 Jan 2017 16:32:48 +0000 (11:32 -0500)
* [io-layer] Merge io related headers

* [io-layer] Remove global variable _wapi_had_shut_down

* [io-layer] Inline io-portability.c file into io.c

* [io-layer] Inline locking.c file into io.c

* [io-layer] Inline posix.c file into io.c

* [file] Move metadata/file-io* files to metadata/w32file*

* [io-layer] Extract file functions

* [file] Remove overlapped parameter which is always NULL

* [file] Remove SECURITY_ATTRIBUTES parameter which is always NULL

* [file] Remove GET_FILEEX_INFO_LEVELS parameter which is always GetFileExInfoStandard

* [file] Replace ULARGE_INTEGER parameter type with guint64

* [file] Replace WIN32_FILE_ATTRIBUTE_DATA parameter type with MonoIOStat

* [file] Remove mono_w32file_create unused parameter tmplate

* [file] Fix win32 build

55 files changed:
mcs/class/corlib/System.IO/FileOptions.cs
mono/io-layer/Makefile.am
mono/io-layer/error.c
mono/io-layer/error.h
mono/io-layer/io-layer.h
mono/io-layer/io-portability.c [deleted file]
mono/io-layer/io-portability.h [deleted file]
mono/io-layer/io-private.h [deleted file]
mono/io-layer/io-trace.h [deleted file]
mono/io-layer/io.c [deleted file]
mono/io-layer/io.h [deleted file]
mono/io-layer/locking.c [deleted file]
mono/io-layer/posix.c [deleted file]
mono/io-layer/uglify.h [deleted file]
mono/io-layer/wapi-private.h [deleted file]
mono/io-layer/wapi-remap.h
mono/io-layer/wapi.c
mono/io-layer/wapi.h
mono/io-layer/wapi_glob.c [deleted file]
mono/io-layer/wapi_glob.h [deleted file]
mono/metadata/Makefile.am
mono/metadata/appdomain.c
mono/metadata/console-null.c
mono/metadata/domain.c
mono/metadata/file-io-internals.h [deleted file]
mono/metadata/file-io-windows-internals.h [deleted file]
mono/metadata/file-io-windows-uwp.c [deleted file]
mono/metadata/file-io-windows.c [deleted file]
mono/metadata/file-io.c [deleted file]
mono/metadata/file-io.h [deleted file]
mono/metadata/file-mmap-posix.c
mono/metadata/icall.c
mono/metadata/sre-save.c
mono/metadata/threads-types.h
mono/metadata/w32event-unix.c
mono/metadata/w32file-internals.h [new file with mode: 0644]
mono/metadata/w32file-unix-glob.c [new file with mode: 0644]
mono/metadata/w32file-unix-glob.h [new file with mode: 0644]
mono/metadata/w32file-unix.c [new file with mode: 0644]
mono/metadata/w32file-win32-internals.h [new file with mode: 0644]
mono/metadata/w32file-win32-uwp.c [new file with mode: 0644]
mono/metadata/w32file-win32.c [new file with mode: 0644]
mono/metadata/w32file.c [new file with mode: 0644]
mono/metadata/w32file.h [new file with mode: 0644]
mono/metadata/w32handle.c
mono/metadata/w32mutex-unix.c
mono/metadata/w32process-unix.c
mono/metadata/w32process.c
mono/metadata/w32semaphore-unix.c
mono/metadata/w32socket-internals.h
mono/metadata/w32socket.c
msvc/libmonoruntime.vcxproj
msvc/libmonoruntime.vcxproj.filters
msvc/pedump.vcxproj
msvc/pedump.vcxproj.filters

index 499319e343a3f629470e7681bd932de3752c5d8b..502974e7b00fb79412a709be16601479fb3c96ac 100644 (file)
@@ -50,7 +50,7 @@ namespace System.IO
                //    The above is an internal value used by Path.GetTempFile to
                //    get a file with 600 permissions, regardless of the umask
                //    settings.  If a value "1" must be introduced here, update
-               //    both metadata/file-io.c and Path.GetTempFile
+               //    both metadata/w32file.c and Path.GetTempFile
                //
        }
 }
index 2247a51a71c391abbdef66445a3230cb040dcfe7..48e48baada29407beed8f94eaacf6c749ce7ebe4 100644 (file)
@@ -12,30 +12,15 @@ libwapiincludedir = $(includedir)/mono-$(API_VER)/mono/io-layer
 
 OTHER_H = \
        error.h         \
-       io.h            \
-       io-trace.h      \
        io-layer.h      \
-       io-portability.h        \
-       uglify.h        \
        wapi.h          \
        wapi-remap.h
 
 OTHER_SRC = \
        error.c                 \
        error.h                 \
-       io.c                    \
-       io.h                    \
-       io-portability.c        \
-       io-portability.h        \
-       io-private.h            \
        io-layer.h              \
-       locking.c               \
-       posix.c                 \
-       uglify.h                \
-       wapi_glob.h             \
-       wapi_glob.c             \
        wapi.h                  \
-       wapi-private.h          \
        wapi.c
 
 
index 5b1b22d6dcd08d7cd3871e3ce99c52310f6cc7cf..38a9141d2e1caad4f1bd43420d4643ca072e802d 100644 (file)
@@ -14,7 +14,6 @@
 #include <errno.h>
 
 #include "mono/io-layer/wapi.h"
-#include "mono/io-layer/wapi-private.h"
 #include "mono/utils/mono-lazy-init.h"
 
 static pthread_key_t error_key;
@@ -28,19 +27,6 @@ static void error_init(void)
        g_assert (ret == 0);
 }
 
-static void error_cleanup (void)
-{
-       int ret;
-
-       ret = pthread_key_delete (error_key);
-       g_assert (ret == 0);
-}
-
-void _wapi_error_cleanup (void)
-{
-       mono_lazy_cleanup (&error_key_once, error_cleanup);
-}
-
 /**
  * GetLastError:
  *
@@ -54,8 +40,6 @@ guint32 GetLastError(void)
        guint32 err;
        void *errptr;
 
-       if (_wapi_has_shut_down)
-               return 0;
        mono_lazy_initialize(&error_key_once, error_init);
        errptr=pthread_getspecific(error_key);
        err=GPOINTER_TO_UINT(errptr);
@@ -73,8 +57,6 @@ void SetLastError(guint32 code)
 {
        int ret;
        
-       if (_wapi_has_shut_down)
-               return;
        /* Set the thread-local error code */
        mono_lazy_initialize(&error_key_once, error_init);
        ret = pthread_setspecific(error_key, GUINT_TO_POINTER(code));
index d4ffe1e92359b9d7d01b7b4f0547ccc45c963c78..9f6c640cc5e19f7c1b17598b5b54e3077dd0963c 100644 (file)
@@ -82,7 +82,6 @@ G_BEGIN_DECLS
 guint32 GetLastError (void);
 void SetLastError (guint32 code);
 gint _wapi_get_win32_file_error (gint err);
-void _wapi_error_cleanup (void);
 
 G_END_DECLS
 
index e9096e25580ee216938e36854d2668b6325b4a45..f1d2e05344eb2be4543ae5971b631ef84694a6d6 100755 (executable)
@@ -47,7 +47,6 @@ typedef struct pollfd {
 
 #else  /* EVERYONE ELSE */
 #include "mono/io-layer/wapi.h"
-#include "mono/io-layer/uglify.h"
 #endif /* HOST_WIN32 */
 
 #ifdef __native_client__
diff --git a/mono/io-layer/io-portability.c b/mono/io-layer/io-portability.c
deleted file mode 100644 (file)
index 282cbe9..0000000
+++ /dev/null
@@ -1,581 +0,0 @@
-/*
- * 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.
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#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 <sys/time.h>
-#ifdef HAVE_DIRENT_H
-# include <dirent.h>
-#endif
-#include <utime.h>
-#include <sys/stat.h>
-
-#include <mono/io-layer/error.h>
-#include <mono/io-layer/wapi_glob.h>
-#include <mono/io-layer/io-portability.h>
-#include <mono/utils/mono-io-portability.h>
-
-#undef DEBUG
-
-int _wapi_open (const char *pathname, int flags, mode_t mode)
-{
-       int fd;
-       gchar *located_filename;
-       
-       if (flags & O_CREAT) {
-               located_filename = mono_portability_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) &&
-                   IS_PORTABILITY_SET) {
-                       int saved_errno = errno;
-                       located_filename = mono_portability_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) &&
-           IS_PORTABILITY_SET) {
-               int saved_errno = errno;
-               gchar *located_filename = mono_portability_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) &&
-           IS_PORTABILITY_SET) {
-               int saved_errno = errno;
-               gchar *located_filename = mono_portability_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 &&
-           IS_PORTABILITY_SET) {
-               int saved_errno = errno;
-               gchar *located_filename = mono_portability_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) &&
-           IS_PORTABILITY_SET) {
-               int saved_errno = errno;
-               gchar *located_filename = mono_portability_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 = mono_portability_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) &&
-                   IS_PORTABILITY_SET) {
-                       int saved_errno = errno;
-                       gchar *located_oldpath = mono_portability_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) &&
-           IS_PORTABILITY_SET) {
-               int saved_errno = errno;
-               gchar *located_filename = mono_portability_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) &&
-           IS_PORTABILITY_SET) {
-               int saved_errno = errno;
-               gchar *located_filename = mono_portability_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 = mono_portability_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) &&
-           IS_PORTABILITY_SET) {
-               int saved_errno = errno;
-               gchar *located_filename = mono_portability_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) &&
-           IS_PORTABILITY_SET) {
-               int saved_errno = errno;
-               gchar *located_filename = mono_portability_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;
-
-       if (IS_PORTABILITY_SET) {
-               g_strdelimit (new_filename, "\\", '/');
-       }
-
-       if (IS_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;
-
-       if (IS_PORTABILITY_SET) {
-               g_strdelimit (new_filename, "\\", '/');
-       }
-
-       if (IS_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) &&
-           IS_PORTABILITY_SET) {
-               gchar *located_filename = mono_portability_find_file (path, TRUE);
-               GError *tmp_error = NULL;
-               
-               if (located_filename == NULL) {
-                       return(NULL);
-               }
-               
-               ret = g_dir_open (located_filename, flags, &tmp_error);
-               g_free (located_filename);
-               if (tmp_error == NULL) {
-                       g_clear_error (error);
-               }
-       }
-       
-       return(ret);
-}
-
-
-static gint
-file_compare (gconstpointer a, gconstpointer b)
-{
-       gchar *astr = *(gchar **) a;
-       gchar *bstr = *(gchar **) b;
-
-       return strcmp (astr, bstr);
-}
-
-static gint
-get_errno_from_g_file_error (gint error)
-{
-       switch (error) {
-#ifdef EACCESS
-       case G_FILE_ERROR_ACCES:
-               error = EACCES;
-               break;
-#endif
-#ifdef ENAMETOOLONG
-       case G_FILE_ERROR_NAMETOOLONG:
-               error = ENAMETOOLONG;
-               break;
-#endif
-#ifdef ENOENT
-       case G_FILE_ERROR_NOENT:
-               error = ENOENT;
-               break;
-#endif
-#ifdef ENOTDIR
-       case G_FILE_ERROR_NOTDIR:
-               error = ENOTDIR;
-               break;
-#endif
-#ifdef ENXIO
-       case G_FILE_ERROR_NXIO:
-               error = ENXIO;
-               break;
-#endif
-#ifdef ENODEV
-       case G_FILE_ERROR_NODEV:
-               error = ENODEV;
-               break;
-#endif
-#ifdef EROFS
-       case G_FILE_ERROR_ROFS:
-               error = EROFS;
-               break;
-#endif
-#ifdef ETXTBSY
-       case G_FILE_ERROR_TXTBSY:
-               error = ETXTBSY;
-               break;
-#endif
-#ifdef EFAULT
-       case G_FILE_ERROR_FAULT:
-               error = EFAULT;
-               break;
-#endif
-#ifdef ELOOP
-       case G_FILE_ERROR_LOOP:
-               error = ELOOP;
-               break;
-#endif
-#ifdef ENOSPC
-       case G_FILE_ERROR_NOSPC:
-               error = ENOSPC;
-               break;
-#endif
-#ifdef ENOMEM
-       case G_FILE_ERROR_NOMEM:
-               error = ENOMEM;
-               break;
-#endif
-#ifdef EMFILE
-       case G_FILE_ERROR_MFILE:
-               error = EMFILE;
-               break;
-#endif
-#ifdef ENFILE
-       case G_FILE_ERROR_NFILE:
-               error = ENFILE;
-               break;
-#endif
-#ifdef EBADF
-       case G_FILE_ERROR_BADF:
-               error = EBADF;
-               break;
-#endif
-#ifdef EINVAL
-       case G_FILE_ERROR_INVAL:
-               error = EINVAL;
-               break;
-#endif
-#ifdef EPIPE
-       case G_FILE_ERROR_PIPE:
-               error = EPIPE;
-               break;
-#endif
-#ifdef EAGAIN
-       case G_FILE_ERROR_AGAIN:
-               error = EAGAIN;
-               break;
-#endif
-#ifdef EINTR
-       case G_FILE_ERROR_INTR:
-               error = EINTR;
-               break;
-#endif
-#ifdef EWIO
-       case G_FILE_ERROR_IO:
-               error = EIO;
-               break;
-#endif
-#ifdef EPERM
-       case G_FILE_ERROR_PERM:
-               error = EPERM;
-               break;
-#endif
-       case G_FILE_ERROR_FAILED:
-               error = ERROR_INVALID_PARAMETER;
-               break;
-       }
-
-       return error;
-}
-
-/* scandir using glib */
-gint _wapi_io_scandir (const gchar *dirname, const gchar *pattern,
-                      gchar ***namelist)
-{
-       GError *error = NULL;
-       GDir *dir;
-       GPtrArray *names;
-       gint result;
-       wapi_glob_t glob_buf;
-       int flags = 0, i;
-       
-       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 &&
-                   !_wapi_access (dirname, F_OK) &&
-                   _wapi_access (dirname, R_OK|X_OK)) {
-                       errnum = EACCES;
-               }
-
-               errno = errnum;
-               return -1;
-       }
-
-       if (IS_PORTABILITY_CASE) {
-               flags = WAPI_GLOB_IGNORECASE;
-       }
-       
-       result = _wapi_glob (dir, pattern, flags, &glob_buf);
-       if (g_str_has_suffix (pattern, ".*")) {
-               /* Special-case the patterns ending in '.*', as
-                * windows also matches entries with no extension with
-                * this pattern.
-                * 
-                * TODO: should this be a MONO_IOMAP option?
-                */
-               gchar *pattern2 = g_strndup (pattern, strlen (pattern) - 2);
-               gint result2;
-               
-               g_dir_rewind (dir);
-               result2 = _wapi_glob (dir, pattern2, flags | WAPI_GLOB_APPEND | WAPI_GLOB_UNIQUE, &glob_buf);
-
-               g_free (pattern2);
-
-               if (result != 0) {
-                       result = result2;
-               }
-       }
-       
-       g_dir_close (dir);
-       if (glob_buf.gl_pathc == 0) {
-               return(0);
-       } else if (result != 0) {
-               return(-1);
-       }
-       
-       names = g_ptr_array_new ();
-       for (i = 0; i < glob_buf.gl_pathc; i++) {
-               g_ptr_array_add (names, g_strdup (glob_buf.gl_pathv[i]));
-       }
-
-       _wapi_globfree (&glob_buf);
-
-       result = names->len;
-       if (result > 0) {
-               g_ptr_array_sort (names, file_compare);
-               g_ptr_array_set_size (names, result + 1);
-
-               *namelist = (gchar **) g_ptr_array_free (names, FALSE);
-       } else {
-               g_ptr_array_free (names, TRUE);
-       }
-
-       return result;
-}
diff --git a/mono/io-layer/io-portability.h b/mono/io-layer/io-portability.h
deleted file mode 100644 (file)
index d7e9dba..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#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);
-extern gint _wapi_io_scandir (const gchar *dirname, const gchar *pattern,
-                             gchar ***namelist);
-
-G_END_DECLS
-
-#endif /* _WAPI_IO_PORTABILITY_H_ */
diff --git a/mono/io-layer/io-private.h b/mono/io-layer/io-private.h
deleted file mode 100644 (file)
index 392b081..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * io-private.h:  Private definitions for file, console and find handles
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- * Copyright 2011 Xamarin Inc
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#ifndef _WAPI_IO_PRIVATE_H_
-#define _WAPI_IO_PRIVATE_H_
-
-#include <config.h>
-#include <glib.h>
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-
-#include <mono/io-layer/io.h>
-#include <mono/io-layer/wapi-private.h>
-
-extern gboolean _wapi_lock_file_region (int fd, off_t offset, off_t length);
-extern gboolean _wapi_unlock_file_region (int fd, off_t offset, off_t length);
-extern gpointer _wapi_stdhandle_create (int fd, const gchar *name);
-
-/* Currently used for both FILE, CONSOLE and PIPE handle types.  This may
- * have to change in future.
- */
-struct _WapiHandle_file
-{
-       gchar *filename;
-       struct _WapiFileShare *share_info;      /* Pointer into shared mem */
-       int fd;
-       guint32 security_attributes;
-       guint32 fileaccess;
-       guint32 sharemode;
-       guint32 attrs;
-};
-
-struct _WapiHandle_find
-{
-       gchar **namelist;
-       gchar *dir_part;
-       int num;
-       size_t count;
-};
-
-#endif /* _WAPI_IO_PRIVATE_H_ */
diff --git a/mono/io-layer/io-trace.h b/mono/io-layer/io-trace.h
deleted file mode 100644 (file)
index e65fdc3..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * io-trace.h: tracing macros
- *
- * Authors:
- *  Marek Habersack <grendel@twistedcode.net>
- *
- * Copyright 2016 Xamarin, Inc (http://xamarin.com/)
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#ifndef __IO_TRACE_H
-
-#ifdef DISABLE_IO_LAYER_TRACE
-#define MONO_TRACE(...)
-#else
-#include "mono/utils/mono-logger-internals.h"
-#define MONO_TRACE(...) mono_trace (__VA_ARGS__)
-#endif
-
-#endif
diff --git a/mono/io-layer/io.c b/mono/io-layer/io.c
deleted file mode 100644 (file)
index 05d554a..0000000
+++ /dev/null
@@ -1,4453 +0,0 @@
-/*
- * io.c:  File, console and find handles
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- * Copyright (c) 2002-2006 Novell, Inc.
- * Copyright 2011 Xamarin Inc (http://www.xamarin.com).
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/stat.h>
-#ifdef HAVE_SYS_STATVFS_H
-#include <sys/statvfs.h>
-#endif
-#if defined(HAVE_SYS_STATFS_H)
-#include <sys/statfs.h>
-#endif
-#if defined(HAVE_SYS_PARAM_H) && defined(HAVE_SYS_MOUNT_H)
-#include <sys/param.h>
-#include <sys/mount.h>
-#endif
-#include <sys/types.h>
-#include <stdio.h>
-#include <utime.h>
-#ifdef __linux__
-#include <sys/ioctl.h>
-#include <linux/fs.h>
-#include <mono/utils/linux_magic.h>
-#endif
-
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/io-private.h>
-#include <mono/io-layer/io-portability.h>
-#include <mono/io-layer/io-trace.h>
-#include <mono/utils/strenc.h>
-#include <mono/utils/mono-once.h>
-#include <mono/utils/mono-logger-internals.h>
-#include <mono/metadata/w32handle.h>
-
-/*
- * If SHM is disabled, this will point to a hash of _WapiFileShare structures, otherwise
- * it will be NULL. We use this instead of _wapi_fileshare_layout to avoid allocating a
- * 4MB array.
- */
-static GHashTable *file_share_hash;
-static mono_mutex_t file_share_mutex;
-
-static void
-time_t_to_filetime (time_t timeval, WapiFileTime *filetime)
-{
-       guint64 ticks;
-       
-       ticks = ((guint64)timeval * 10000000) + 116444736000000000ULL;
-       filetime->dwLowDateTime = ticks & 0xFFFFFFFF;
-       filetime->dwHighDateTime = ticks >> 32;
-}
-
-static void
-_wapi_handle_share_release (_WapiFileShare *share_info)
-{
-       /* Prevent new entries racing with us */
-       mono_os_mutex_lock (&file_share_mutex);
-
-       g_assert (share_info->handle_refs > 0);
-       share_info->handle_refs -= 1;
-
-       if (share_info->handle_refs == 0)
-               g_hash_table_remove (file_share_hash, share_info);
-
-       mono_os_mutex_unlock (&file_share_mutex);
-}
-
-static gint
-wapi_share_info_equal (gconstpointer ka, gconstpointer kb)
-{
-       const _WapiFileShare *s1 = (const _WapiFileShare *)ka;
-       const _WapiFileShare *s2 = (const _WapiFileShare *)kb;
-
-       return (s1->device == s2->device && s1->inode == s2->inode) ? 1 : 0;
-}
-
-static guint
-wapi_share_info_hash (gconstpointer data)
-{
-       const _WapiFileShare *s = (const _WapiFileShare *)data;
-
-       return s->inode;
-}
-
-static gboolean
-_wapi_handle_get_or_set_share (guint64 device, guint64 inode, guint32 new_sharemode, guint32 new_access,
-       guint32 *old_sharemode, guint32 *old_access, struct _WapiFileShare **share_info)
-{
-       struct _WapiFileShare *file_share;
-       gboolean exists = FALSE;
-
-       /* Prevent new entries racing with us */
-       mono_os_mutex_lock (&file_share_mutex);
-
-       _WapiFileShare tmp;
-
-       /*
-        * Instead of allocating a 4MB array, we use a hash table to keep track of this
-        * info. This is needed even if SHM is disabled, to track sharing inside
-        * the current process.
-        */
-       if (!file_share_hash)
-               file_share_hash = g_hash_table_new_full (wapi_share_info_hash, wapi_share_info_equal, NULL, g_free);
-
-       tmp.device = device;
-       tmp.inode = inode;
-
-       file_share = (_WapiFileShare *)g_hash_table_lookup (file_share_hash, &tmp);
-       if (file_share) {
-               *old_sharemode = file_share->sharemode;
-               *old_access = file_share->access;
-               *share_info = file_share;
-
-               g_assert (file_share->handle_refs > 0);
-               file_share->handle_refs += 1;
-
-               exists = TRUE;
-       } else {
-               file_share = g_new0 (_WapiFileShare, 1);
-
-               file_share->device = device;
-               file_share->inode = inode;
-               file_share->opened_by_pid = wapi_getpid ();
-               file_share->sharemode = new_sharemode;
-               file_share->access = new_access;
-               file_share->handle_refs = 1;
-               *share_info = file_share;
-
-               g_hash_table_insert (file_share_hash, file_share, file_share);
-       }
-
-       mono_os_mutex_unlock (&file_share_mutex);
-
-       return(exists);
-}
-
-static void file_close (gpointer handle, gpointer data);
-static void file_details (gpointer data);
-static const gchar* file_typename (void);
-static gsize file_typesize (void);
-static WapiFileType file_getfiletype(void);
-static gboolean file_read(gpointer handle, gpointer buffer,
-                         guint32 numbytes, guint32 *bytesread,
-                         WapiOverlapped *overlapped);
-static gboolean file_write(gpointer handle, gconstpointer buffer,
-                          guint32 numbytes, guint32 *byteswritten,
-                          WapiOverlapped *overlapped);
-static gboolean file_flush(gpointer handle);
-static guint32 file_seek(gpointer handle, gint32 movedistance,
-                        gint32 *highmovedistance, WapiSeekMethod method);
-static gboolean file_setendoffile(gpointer handle);
-static guint32 file_getfilesize(gpointer handle, guint32 *highsize);
-static gboolean file_getfiletime(gpointer handle, WapiFileTime *create_time,
-                                WapiFileTime *last_access,
-                                WapiFileTime *last_write);
-static gboolean file_setfiletime(gpointer handle,
-                                const WapiFileTime *create_time,
-                                const WapiFileTime *last_access,
-                                const WapiFileTime *last_write);
-static guint32 GetDriveTypeFromPath (const gchar *utf8_root_path_name);
-
-/* File handle is only signalled for overlapped IO */
-static MonoW32HandleOps _wapi_file_ops = {
-       file_close,             /* close */
-       NULL,                   /* signal */
-       NULL,                   /* own */
-       NULL,                   /* is_owned */
-       NULL,                   /* special_wait */
-       NULL,                   /* prewait */
-       file_details,   /* details */
-       file_typename,  /* typename */
-       file_typesize,  /* typesize */
-};
-
-static void console_close (gpointer handle, gpointer data);
-static void console_details (gpointer data);
-static const gchar* console_typename (void);
-static gsize console_typesize (void);
-static WapiFileType console_getfiletype(void);
-static gboolean console_read(gpointer handle, gpointer buffer,
-                            guint32 numbytes, guint32 *bytesread,
-                            WapiOverlapped *overlapped);
-static gboolean console_write(gpointer handle, gconstpointer buffer,
-                             guint32 numbytes, guint32 *byteswritten,
-                             WapiOverlapped *overlapped);
-
-/* Console is mostly the same as file, except it can block waiting for
- * input or output
- */
-static MonoW32HandleOps _wapi_console_ops = {
-       console_close,          /* close */
-       NULL,                   /* signal */
-       NULL,                   /* own */
-       NULL,                   /* is_owned */
-       NULL,                   /* special_wait */
-       NULL,                   /* prewait */
-       console_details,        /* details */
-       console_typename,       /* typename */
-       console_typesize,       /* typesize */
-};
-
-static const gchar* find_typename (void);
-static gsize find_typesize (void);
-
-static MonoW32HandleOps _wapi_find_ops = {
-       NULL,                   /* close */
-       NULL,                   /* signal */
-       NULL,                   /* own */
-       NULL,                   /* is_owned */
-       NULL,                   /* special_wait */
-       NULL,                   /* prewait */
-       NULL,                   /* details */
-       find_typename,  /* typename */
-       find_typesize,  /* typesize */
-};
-
-static void pipe_close (gpointer handle, gpointer data);
-static void pipe_details (gpointer data);
-static const gchar* pipe_typename (void);
-static gsize pipe_typesize (void);
-static WapiFileType pipe_getfiletype (void);
-static gboolean pipe_read (gpointer handle, gpointer buffer, guint32 numbytes,
-                          guint32 *bytesread, WapiOverlapped *overlapped);
-static gboolean pipe_write (gpointer handle, gconstpointer buffer,
-                           guint32 numbytes, guint32 *byteswritten,
-                           WapiOverlapped *overlapped);
-
-/* Pipe handles
- */
-static MonoW32HandleOps _wapi_pipe_ops = {
-       pipe_close,             /* close */
-       NULL,                   /* signal */
-       NULL,                   /* own */
-       NULL,                   /* is_owned */
-       NULL,                   /* special_wait */
-       NULL,                   /* prewait */
-       pipe_details,   /* details */
-       pipe_typename,  /* typename */
-       pipe_typesize,  /* typesize */
-};
-
-static const struct {
-       /* File, console and pipe handles */
-       WapiFileType (*getfiletype)(void);
-       
-       /* File, console and pipe handles */
-       gboolean (*readfile)(gpointer handle, gpointer buffer,
-                            guint32 numbytes, guint32 *bytesread,
-                            WapiOverlapped *overlapped);
-       gboolean (*writefile)(gpointer handle, gconstpointer buffer,
-                             guint32 numbytes, guint32 *byteswritten,
-                             WapiOverlapped *overlapped);
-       gboolean (*flushfile)(gpointer handle);
-       
-       /* File handles */
-       guint32 (*seek)(gpointer handle, gint32 movedistance,
-                       gint32 *highmovedistance, WapiSeekMethod method);
-       gboolean (*setendoffile)(gpointer handle);
-       guint32 (*getfilesize)(gpointer handle, guint32 *highsize);
-       gboolean (*getfiletime)(gpointer handle, WapiFileTime *create_time,
-                               WapiFileTime *last_access,
-                               WapiFileTime *last_write);
-       gboolean (*setfiletime)(gpointer handle,
-                               const WapiFileTime *create_time,
-                               const WapiFileTime *last_access,
-                               const WapiFileTime *last_write);
-} io_ops[MONO_W32HANDLE_COUNT]={
-       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
-       /* file */
-       {file_getfiletype,
-        file_read, file_write,
-        file_flush, file_seek,
-        file_setendoffile,
-        file_getfilesize,
-        file_getfiletime,
-        file_setfiletime},
-       /* console */
-       {console_getfiletype,
-        console_read,
-        console_write,
-        NULL, NULL, NULL, NULL, NULL, NULL},
-       /* thread */
-       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
-       /* sem */
-       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
-       /* mutex */
-       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
-       /* event */
-       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
-       /* socket (will need at least read and write) */
-       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
-       /* find */
-       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
-       /* process */
-       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
-       /* pipe */
-       {pipe_getfiletype,
-        pipe_read,
-        pipe_write,
-        NULL, NULL, NULL, NULL, NULL, NULL},
-};
-
-static gboolean lock_while_writing = FALSE;
-
-/* Some utility functions.
- */
-
-/*
- * Check if a file is writable by the current user.
- *
- * This is is a best effort kind of thing. It assumes a reasonable sane set
- * of permissions by the underlying OS.
- *
- * We generally assume that basic unix permission bits are authoritative. Which might not
- * be the case under systems with extended permissions systems (posix ACLs, SELinux, OSX/iOS sandboxing, etc)
- *
- * The choice of access as the fallback is due to the expected lower overhead compared to trying to open the file.
- *
- * The only expected problem with using access are for root, setuid or setgid programs as access is not consistent
- * under those situations. It's to be expected that this should not happen in practice as those bits are very dangerous
- * and should not be used with a dynamic runtime.
- */
-static gboolean
-is_file_writable (struct stat *st, const char *path)
-{
-#if __APPLE__
-       // OS X Finder "locked" or `ls -lO` "uchg".
-       // This only covers one of several cases where an OS X file could be unwritable through special flags.
-       if (st->st_flags & (UF_IMMUTABLE|SF_IMMUTABLE))
-               return 0;
-#endif
-
-       /* Is it globally writable? */
-       if (st->st_mode & S_IWOTH)
-               return 1;
-
-       /* Am I the owner? */
-       if ((st->st_uid == geteuid ()) && (st->st_mode & S_IWUSR))
-               return 1;
-
-       /* Am I in the same group? */
-       if ((st->st_gid == getegid ()) && (st->st_mode & S_IWGRP))
-               return 1;
-
-       /* Fallback to using access(2). It's not ideal as it might not take into consideration euid/egid
-        * but it's the only sane option we have on unix.
-        */
-       return access (path, W_OK) == 0;
-}
-
-
-static guint32 _wapi_stat_to_file_attributes (const gchar *pathname,
-                                             struct stat *buf,
-                                             struct stat *lbuf)
-{
-       guint32 attrs = 0;
-       gchar *filename;
-       
-       /* FIXME: this could definitely be better, but there seems to
-        * be no pattern to the attributes that are set
-        */
-
-       /* Sockets (0140000) != Directory (040000) + Regular file (0100000) */
-       if (S_ISSOCK (buf->st_mode))
-               buf->st_mode &= ~S_IFSOCK; /* don't consider socket protection */
-
-       filename = _wapi_basename (pathname);
-
-       if (S_ISDIR (buf->st_mode)) {
-               attrs = FILE_ATTRIBUTE_DIRECTORY;
-               if (!is_file_writable (buf, pathname)) {
-                       attrs |= FILE_ATTRIBUTE_READONLY;
-               }
-               if (filename[0] == '.') {
-                       attrs |= FILE_ATTRIBUTE_HIDDEN;
-               }
-       } else {
-               if (!is_file_writable (buf, pathname)) {
-                       attrs = FILE_ATTRIBUTE_READONLY;
-
-                       if (filename[0] == '.') {
-                               attrs |= FILE_ATTRIBUTE_HIDDEN;
-                       }
-               } else if (filename[0] == '.') {
-                       attrs = FILE_ATTRIBUTE_HIDDEN;
-               } else {
-                       attrs = FILE_ATTRIBUTE_NORMAL;
-               }
-       }
-
-       if (lbuf != NULL) {
-               if (S_ISLNK (lbuf->st_mode)) {
-                       attrs |= FILE_ATTRIBUTE_REPARSE_POINT;
-               }
-       }
-       
-       g_free (filename);
-       
-       return attrs;
-}
-
-static void
-_wapi_set_last_error_from_errno (void)
-{
-       SetLastError (_wapi_get_win32_file_error (errno));
-}
-
-static void _wapi_set_last_path_error_from_errno (const gchar *dir,
-                                                 const gchar *path)
-{
-       if (errno == ENOENT) {
-               /* Check the path - if it's a missing directory then
-                * we need to set PATH_NOT_FOUND not FILE_NOT_FOUND
-                */
-               gchar *dirname;
-
-
-               if (dir == NULL) {
-                       dirname = _wapi_dirname (path);
-               } else {
-                       dirname = g_strdup (dir);
-               }
-               
-               if (_wapi_access (dirname, F_OK) == 0) {
-                       SetLastError (ERROR_FILE_NOT_FOUND);
-               } else {
-                       SetLastError (ERROR_PATH_NOT_FOUND);
-               }
-
-               g_free (dirname);
-       } else {
-               _wapi_set_last_error_from_errno ();
-       }
-}
-
-/* Handle ops.
- */
-static void file_close (gpointer handle, gpointer data)
-{
-       struct _WapiHandle_file *file_handle = (struct _WapiHandle_file *)data;
-       int fd = file_handle->fd;
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing file handle %p [%s]", __func__, handle,
-                 file_handle->filename);
-
-       if (file_handle->attrs & FILE_FLAG_DELETE_ON_CLOSE)
-               _wapi_unlink (file_handle->filename);
-       
-       g_free (file_handle->filename);
-       
-       if (file_handle->share_info)
-               _wapi_handle_share_release (file_handle->share_info);
-       
-       close (fd);
-}
-
-static void file_details (gpointer data)
-{
-       struct _WapiHandle_file *file = (struct _WapiHandle_file *)data;
-       
-       g_print ("[%20s] acc: %c%c%c, shr: %c%c%c, attrs: %5u",
-                file->filename,
-                file->fileaccess&GENERIC_READ?'R':'.',
-                file->fileaccess&GENERIC_WRITE?'W':'.',
-                file->fileaccess&GENERIC_EXECUTE?'X':'.',
-                file->sharemode&FILE_SHARE_READ?'R':'.',
-                file->sharemode&FILE_SHARE_WRITE?'W':'.',
-                file->sharemode&FILE_SHARE_DELETE?'D':'.',
-                file->attrs);
-}
-
-static const gchar* file_typename (void)
-{
-       return "File";
-}
-
-static gsize file_typesize (void)
-{
-       return sizeof (struct _WapiHandle_file);
-}
-
-static WapiFileType file_getfiletype(void)
-{
-       return(FILE_TYPE_DISK);
-}
-
-static gboolean file_read(gpointer handle, gpointer buffer,
-                         guint32 numbytes, guint32 *bytesread,
-                         WapiOverlapped *overlapped)
-{
-       struct _WapiHandle_file *file_handle;
-       gboolean ok;
-       int fd, ret;
-       MonoThreadInfo *info = mono_thread_info_current ();
-       
-       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
-                               (gpointer *)&file_handle);
-       if(ok==FALSE) {
-               g_warning ("%s: error looking up file handle %p", __func__,
-                          handle);
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-
-       fd = file_handle->fd;
-       if(bytesread!=NULL) {
-               *bytesread=0;
-       }
-       
-       if(!(file_handle->fileaccess & GENERIC_READ) &&
-          !(file_handle->fileaccess & GENERIC_ALL)) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
-                         __func__, handle, file_handle->fileaccess);
-
-               SetLastError (ERROR_ACCESS_DENIED);
-               return(FALSE);
-       }
-
-       do {
-               ret = read (fd, buffer, numbytes);
-       } while (ret == -1 && errno == EINTR &&
-                !mono_thread_info_is_interrupt_state (info));
-                       
-       if(ret==-1) {
-               gint err = errno;
-
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__,
-                         handle, strerror(err));
-               SetLastError (_wapi_get_win32_file_error (err));
-               return(FALSE);
-       }
-               
-       if (bytesread != NULL) {
-               *bytesread = ret;
-       }
-               
-       return(TRUE);
-}
-
-static gboolean file_write(gpointer handle, gconstpointer buffer,
-                          guint32 numbytes, guint32 *byteswritten,
-                          WapiOverlapped *overlapped G_GNUC_UNUSED)
-{
-       struct _WapiHandle_file *file_handle;
-       gboolean ok;
-       int ret, fd;
-       off_t current_pos = 0;
-       MonoThreadInfo *info = mono_thread_info_current ();
-       
-       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
-                               (gpointer *)&file_handle);
-       if(ok==FALSE) {
-               g_warning ("%s: error looking up file handle %p", __func__,
-                          handle);
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-
-       fd = file_handle->fd;
-       
-       if(byteswritten!=NULL) {
-               *byteswritten=0;
-       }
-       
-       if(!(file_handle->fileaccess & GENERIC_WRITE) &&
-          !(file_handle->fileaccess & GENERIC_ALL)) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
-
-               SetLastError (ERROR_ACCESS_DENIED);
-               return(FALSE);
-       }
-       
-       if (lock_while_writing) {
-               /* Need to lock the region we're about to write to,
-                * because we only do advisory locking on POSIX
-                * systems
-                */
-               current_pos = lseek (fd, (off_t)0, SEEK_CUR);
-               if (current_pos == -1) {
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p lseek failed: %s", __func__,
-                                  handle, strerror (errno));
-                       _wapi_set_last_error_from_errno ();
-                       return(FALSE);
-               }
-               
-               if (_wapi_lock_file_region (fd, current_pos,
-                                           numbytes) == FALSE) {
-                       /* The error has already been set */
-                       return(FALSE);
-               }
-       }
-               
-       do {
-               ret = write (fd, buffer, numbytes);
-       } while (ret == -1 && errno == EINTR &&
-                !mono_thread_info_is_interrupt_state (info));
-       
-       if (lock_while_writing) {
-               _wapi_unlock_file_region (fd, current_pos, numbytes);
-       }
-
-       if (ret == -1) {
-               if (errno == EINTR) {
-                       ret = 0;
-               } else {
-                       _wapi_set_last_error_from_errno ();
-                               
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s",
-                                 __func__, handle, strerror(errno));
-
-                       return(FALSE);
-               }
-       }
-       if (byteswritten != NULL) {
-               *byteswritten = ret;
-       }
-       return(TRUE);
-}
-
-static gboolean file_flush(gpointer handle)
-{
-       struct _WapiHandle_file *file_handle;
-       gboolean ok;
-       int ret, fd;
-       
-       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
-                               (gpointer *)&file_handle);
-       if(ok==FALSE) {
-               g_warning ("%s: error looking up file handle %p", __func__,
-                          handle);
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-
-       fd = file_handle->fd;
-
-       if(!(file_handle->fileaccess & GENERIC_WRITE) &&
-          !(file_handle->fileaccess & GENERIC_ALL)) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
-
-               SetLastError (ERROR_ACCESS_DENIED);
-               return(FALSE);
-       }
-
-       ret=fsync(fd);
-       if (ret==-1) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fsync of handle %p error: %s", __func__, handle,
-                         strerror(errno));
-
-               _wapi_set_last_error_from_errno ();
-               return(FALSE);
-       }
-       
-       return(TRUE);
-}
-
-static guint32 file_seek(gpointer handle, gint32 movedistance,
-                        gint32 *highmovedistance, WapiSeekMethod method)
-{
-       struct _WapiHandle_file *file_handle;
-       gboolean ok;
-       gint64 offset, newpos;
-       int whence, fd;
-       guint32 ret;
-       
-       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
-                               (gpointer *)&file_handle);
-       if(ok==FALSE) {
-               g_warning ("%s: error looking up file handle %p", __func__,
-                          handle);
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(INVALID_SET_FILE_POINTER);
-       }
-       
-       fd = file_handle->fd;
-
-       if(!(file_handle->fileaccess & GENERIC_READ) &&
-          !(file_handle->fileaccess & GENERIC_WRITE) &&
-          !(file_handle->fileaccess & GENERIC_ALL)) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
-
-               SetLastError (ERROR_ACCESS_DENIED);
-               return(INVALID_SET_FILE_POINTER);
-       }
-
-       switch(method) {
-       case FILE_BEGIN:
-               whence=SEEK_SET;
-               break;
-       case FILE_CURRENT:
-               whence=SEEK_CUR;
-               break;
-       case FILE_END:
-               whence=SEEK_END;
-               break;
-       default:
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: invalid seek type %d", __func__, method);
-
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return(INVALID_SET_FILE_POINTER);
-       }
-
-#ifdef HAVE_LARGE_FILE_SUPPORT
-       if(highmovedistance==NULL) {
-               offset=movedistance;
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting offset to %lld (low %d)", __func__,
-                         offset, movedistance);
-       } else {
-               offset=((gint64) *highmovedistance << 32) | (guint32)movedistance;
-               
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting offset to %lld 0x%llx (high %d 0x%x, low %d 0x%x)", __func__, offset, offset, *highmovedistance, *highmovedistance, movedistance, movedistance);
-       }
-#else
-       offset=movedistance;
-#endif
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: moving handle %p by %lld bytes from %d", __func__,
-                  handle, (long long)offset, whence);
-
-#ifdef PLATFORM_ANDROID
-       /* bionic doesn't support -D_FILE_OFFSET_BITS=64 */
-       newpos=lseek64(fd, offset, whence);
-#else
-       newpos=lseek(fd, offset, whence);
-#endif
-       if(newpos==-1) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek on handle %p returned error %s",
-                         __func__, handle, strerror(errno));
-
-               _wapi_set_last_error_from_errno ();
-               return(INVALID_SET_FILE_POINTER);
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek returns %lld", __func__, newpos);
-
-#ifdef HAVE_LARGE_FILE_SUPPORT
-       ret=newpos & 0xFFFFFFFF;
-       if(highmovedistance!=NULL) {
-               *highmovedistance=newpos>>32;
-       }
-#else
-       ret=newpos;
-       if(highmovedistance!=NULL) {
-               /* Accurate, but potentially dodgy :-) */
-               *highmovedistance=0;
-       }
-#endif
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: move of handle %p returning %d/%d", __func__,
-                  handle, ret, highmovedistance==NULL?0:*highmovedistance);
-
-       return(ret);
-}
-
-static gboolean file_setendoffile(gpointer handle)
-{
-       struct _WapiHandle_file *file_handle;
-       gboolean ok;
-       struct stat statbuf;
-       off_t pos;
-       int ret, fd;
-       MonoThreadInfo *info = mono_thread_info_current ();
-       
-       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
-                               (gpointer *)&file_handle);
-       if(ok==FALSE) {
-               g_warning ("%s: error looking up file handle %p", __func__,
-                          handle);
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       fd = file_handle->fd;
-       
-       if(!(file_handle->fileaccess & GENERIC_WRITE) &&
-          !(file_handle->fileaccess & GENERIC_ALL)) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
-
-               SetLastError (ERROR_ACCESS_DENIED);
-               return(FALSE);
-       }
-
-       /* Find the current file position, and the file length.  If
-        * the file position is greater than the length, write to
-        * extend the file with a hole.  If the file position is less
-        * than the length, truncate the file.
-        */
-       
-       ret=fstat(fd, &statbuf);
-       if(ret==-1) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__,
-                          handle, strerror(errno));
-
-               _wapi_set_last_error_from_errno ();
-               return(FALSE);
-       }
-
-       pos=lseek(fd, (off_t)0, SEEK_CUR);
-       if(pos==-1) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p lseek failed: %s", __func__,
-                         handle, strerror(errno));
-
-               _wapi_set_last_error_from_errno ();
-               return(FALSE);
-       }
-       
-#ifdef FTRUNCATE_DOESNT_EXTEND
-       off_t size = statbuf.st_size;
-       /* I haven't bothered to write the configure.ac stuff for this
-        * because I don't know if any platform needs it.  I'm leaving
-        * this code just in case though
-        */
-       if(pos>size) {
-               /* Extend the file.  Use write() here, because some
-                * manuals say that ftruncate() behaviour is undefined
-                * when the file needs extending.  The POSIX spec says
-                * that on XSI-conformant systems it extends, so if
-                * every system we care about conforms, then we can
-                * drop this write.
-                */
-               do {
-                       ret = write (fd, "", 1);
-               } while (ret == -1 && errno == EINTR &&
-                        !mono_thread_info_is_interrupt_state (info));
-
-               if(ret==-1) {
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p extend write failed: %s", __func__, handle, strerror(errno));
-
-                       _wapi_set_last_error_from_errno ();
-                       return(FALSE);
-               }
-
-               /* And put the file position back after the write */
-               ret = lseek (fd, pos, SEEK_SET);
-               if (ret == -1) {
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p second lseek failed: %s",
-                                  __func__, handle, strerror(errno));
-
-                       _wapi_set_last_error_from_errno ();
-                       return(FALSE);
-               }
-       }
-#endif
-
-/* Native Client has no ftruncate function, even in standalone sel_ldr. */
-#ifndef __native_client__
-       /* always truncate, because the extend write() adds an extra
-        * byte to the end of the file
-        */
-       do {
-               ret=ftruncate(fd, pos);
-       }
-       while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info)); 
-       if(ret==-1) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p ftruncate failed: %s", __func__,
-                         handle, strerror(errno));
-               
-               _wapi_set_last_error_from_errno ();
-               return(FALSE);
-       }
-#endif
-               
-       return(TRUE);
-}
-
-static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
-{
-       struct _WapiHandle_file *file_handle;
-       gboolean ok;
-       struct stat statbuf;
-       guint32 size;
-       int ret;
-       int fd;
-       
-       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
-                               (gpointer *)&file_handle);
-       if(ok==FALSE) {
-               g_warning ("%s: error looking up file handle %p", __func__,
-                          handle);
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(INVALID_FILE_SIZE);
-       }
-       fd = file_handle->fd;
-       
-       if(!(file_handle->fileaccess & GENERIC_READ) &&
-          !(file_handle->fileaccess & GENERIC_WRITE) &&
-          !(file_handle->fileaccess & GENERIC_ALL)) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
-
-               SetLastError (ERROR_ACCESS_DENIED);
-               return(INVALID_FILE_SIZE);
-       }
-
-       /* If the file has a size with the low bits 0xFFFFFFFF the
-        * caller can't tell if this is an error, so clear the error
-        * value
-        */
-       SetLastError (ERROR_SUCCESS);
-       
-       ret = fstat(fd, &statbuf);
-       if (ret == -1) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__,
-                          handle, strerror(errno));
-
-               _wapi_set_last_error_from_errno ();
-               return(INVALID_FILE_SIZE);
-       }
-       
-       /* fstat indicates block devices as zero-length, so go a different path */
-#ifdef BLKGETSIZE64
-       if (S_ISBLK(statbuf.st_mode)) {
-               guint64 bigsize;
-               if (ioctl(fd, BLKGETSIZE64, &bigsize) < 0) {
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p ioctl BLKGETSIZE64 failed: %s",
-                                  __func__, handle, strerror(errno));
-
-                       _wapi_set_last_error_from_errno ();
-                       return(INVALID_FILE_SIZE);
-               }
-               
-               size = bigsize & 0xFFFFFFFF;
-               if (highsize != NULL) {
-                       *highsize = bigsize>>32;
-               }
-
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning block device size %d/%d",
-                          __func__, size, *highsize);
-       
-               return(size);
-       }
-#endif
-       
-#ifdef HAVE_LARGE_FILE_SUPPORT
-       size = statbuf.st_size & 0xFFFFFFFF;
-       if (highsize != NULL) {
-               *highsize = statbuf.st_size>>32;
-       }
-#else
-       if (highsize != NULL) {
-               /* Accurate, but potentially dodgy :-) */
-               *highsize = 0;
-       }
-       size = statbuf.st_size;
-#endif
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning size %d/%d", __func__, size, *highsize);
-       
-       return(size);
-}
-
-static gboolean file_getfiletime(gpointer handle, WapiFileTime *create_time,
-                                WapiFileTime *last_access,
-                                WapiFileTime *last_write)
-{
-       struct _WapiHandle_file *file_handle;
-       gboolean ok;
-       struct stat statbuf;
-       guint64 create_ticks, access_ticks, write_ticks;
-       int ret, fd;
-       
-       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
-                               (gpointer *)&file_handle);
-       if(ok==FALSE) {
-               g_warning ("%s: error looking up file handle %p", __func__,
-                          handle);
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       fd = file_handle->fd;
-
-       if(!(file_handle->fileaccess & GENERIC_READ) &&
-          !(file_handle->fileaccess & GENERIC_ALL)) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
-                         __func__, handle, file_handle->fileaccess);
-
-               SetLastError (ERROR_ACCESS_DENIED);
-               return(FALSE);
-       }
-       
-       ret=fstat(fd, &statbuf);
-       if(ret==-1) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle,
-                         strerror(errno));
-
-               _wapi_set_last_error_from_errno ();
-               return(FALSE);
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: atime: %ld ctime: %ld mtime: %ld", __func__,
-                 statbuf.st_atime, statbuf.st_ctime,
-                 statbuf.st_mtime);
-
-       /* Try and guess a meaningful create time by using the older
-        * of atime or ctime
-        */
-       /* The magic constant comes from msdn documentation
-        * "Converting a time_t Value to a File Time"
-        */
-       if(statbuf.st_atime < statbuf.st_ctime) {
-               create_ticks=((guint64)statbuf.st_atime*10000000)
-                       + 116444736000000000ULL;
-       } else {
-               create_ticks=((guint64)statbuf.st_ctime*10000000)
-                       + 116444736000000000ULL;
-       }
-       
-       access_ticks=((guint64)statbuf.st_atime*10000000)+116444736000000000ULL;
-       write_ticks=((guint64)statbuf.st_mtime*10000000)+116444736000000000ULL;
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: aticks: %llu cticks: %llu wticks: %llu", __func__,
-                 access_ticks, create_ticks, write_ticks);
-
-       if(create_time!=NULL) {
-               create_time->dwLowDateTime = create_ticks & 0xFFFFFFFF;
-               create_time->dwHighDateTime = create_ticks >> 32;
-       }
-       
-       if(last_access!=NULL) {
-               last_access->dwLowDateTime = access_ticks & 0xFFFFFFFF;
-               last_access->dwHighDateTime = access_ticks >> 32;
-       }
-       
-       if(last_write!=NULL) {
-               last_write->dwLowDateTime = write_ticks & 0xFFFFFFFF;
-               last_write->dwHighDateTime = write_ticks >> 32;
-       }
-
-       return(TRUE);
-}
-
-static gboolean file_setfiletime(gpointer handle,
-                                const WapiFileTime *create_time G_GNUC_UNUSED,
-                                const WapiFileTime *last_access,
-                                const WapiFileTime *last_write)
-{
-       struct _WapiHandle_file *file_handle;
-       gboolean ok;
-       struct utimbuf utbuf;
-       struct stat statbuf;
-       guint64 access_ticks, write_ticks;
-       int ret, fd;
-       
-       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
-                               (gpointer *)&file_handle);
-       if(ok==FALSE) {
-               g_warning ("%s: error looking up file handle %p", __func__,
-                          handle);
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       fd = file_handle->fd;
-       
-       if(!(file_handle->fileaccess & GENERIC_WRITE) &&
-          !(file_handle->fileaccess & GENERIC_ALL)) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
-
-               SetLastError (ERROR_ACCESS_DENIED);
-               return(FALSE);
-       }
-
-       if(file_handle->filename == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p unknown filename", __func__, handle);
-
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       
-       /* Get the current times, so we can put the same times back in
-        * the event that one of the FileTime structs is NULL
-        */
-       ret=fstat (fd, &statbuf);
-       if(ret==-1) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle,
-                         strerror(errno));
-
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return(FALSE);
-       }
-
-       if(last_access!=NULL) {
-               access_ticks=((guint64)last_access->dwHighDateTime << 32) +
-                       last_access->dwLowDateTime;
-               /* This is (time_t)0.  We can actually go to INT_MIN,
-                * but this will do for now.
-                */
-               if (access_ticks < 116444736000000000ULL) {
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt to set access time too early",
-                                  __func__);
-                       SetLastError (ERROR_INVALID_PARAMETER);
-                       return(FALSE);
-               }
-
-               if (sizeof (utbuf.actime) == 4 && ((access_ticks - 116444736000000000ULL) / 10000000) > INT_MAX) {
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt to set write time that is too big for a 32bits time_t",
-                                  __func__);
-                       SetLastError (ERROR_INVALID_PARAMETER);
-                       return(FALSE);
-               }
-
-               utbuf.actime=(access_ticks - 116444736000000000ULL) / 10000000;
-       } else {
-               utbuf.actime=statbuf.st_atime;
-       }
-
-       if(last_write!=NULL) {
-               write_ticks=((guint64)last_write->dwHighDateTime << 32) +
-                       last_write->dwLowDateTime;
-               /* This is (time_t)0.  We can actually go to INT_MIN,
-                * but this will do for now.
-                */
-               if (write_ticks < 116444736000000000ULL) {
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt to set write time too early",
-                                  __func__);
-                       SetLastError (ERROR_INVALID_PARAMETER);
-                       return(FALSE);
-               }
-               if (sizeof (utbuf.modtime) == 4 && ((write_ticks - 116444736000000000ULL) / 10000000) > INT_MAX) {
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt to set write time that is too big for a 32bits time_t",
-                                  __func__);
-                       SetLastError (ERROR_INVALID_PARAMETER);
-                       return(FALSE);
-               }
-               
-               utbuf.modtime=(write_ticks - 116444736000000000ULL) / 10000000;
-       } else {
-               utbuf.modtime=statbuf.st_mtime;
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting handle %p access %ld write %ld", __func__,
-                  handle, utbuf.actime, utbuf.modtime);
-
-       ret = _wapi_utime (file_handle->filename, &utbuf);
-       if (ret == -1) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p [%s] utime failed: %s", __func__,
-                          handle, file_handle->filename, strerror(errno));
-
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return(FALSE);
-       }
-       
-       return(TRUE);
-}
-
-static void console_close (gpointer handle, gpointer data)
-{
-       struct _WapiHandle_file *console_handle = (struct _WapiHandle_file *)data;
-       int fd = console_handle->fd;
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing console handle %p", __func__, handle);
-
-       g_free (console_handle->filename);
-
-       if (fd > 2) {
-               if (console_handle->share_info)
-                       _wapi_handle_share_release (console_handle->share_info);
-               close (fd);
-       }
-}
-
-static void console_details (gpointer data)
-{
-       file_details (data);
-}
-
-static const gchar* console_typename (void)
-{
-       return "Console";
-}
-
-static gsize console_typesize (void)
-{
-       return sizeof (struct _WapiHandle_file);
-}
-
-static WapiFileType console_getfiletype(void)
-{
-       return(FILE_TYPE_CHAR);
-}
-
-static gboolean console_read(gpointer handle, gpointer buffer,
-                            guint32 numbytes, guint32 *bytesread,
-                            WapiOverlapped *overlapped G_GNUC_UNUSED)
-{
-       struct _WapiHandle_file *console_handle;
-       gboolean ok;
-       int ret, fd;
-       MonoThreadInfo *info = mono_thread_info_current ();
-
-       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
-                               (gpointer *)&console_handle);
-       if(ok==FALSE) {
-               g_warning ("%s: error looking up console handle %p", __func__,
-                          handle);
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       fd = console_handle->fd;
-       
-       if(bytesread!=NULL) {
-               *bytesread=0;
-       }
-       
-       if(!(console_handle->fileaccess & GENERIC_READ) &&
-          !(console_handle->fileaccess & GENERIC_ALL)) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
-                          __func__, handle, console_handle->fileaccess);
-
-               SetLastError (ERROR_ACCESS_DENIED);
-               return(FALSE);
-       }
-       
-       do {
-               ret=read(fd, buffer, numbytes);
-       } while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info));
-
-       if(ret==-1) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__, handle,
-                         strerror(errno));
-
-               _wapi_set_last_error_from_errno ();
-               return(FALSE);
-       }
-       
-       if(bytesread!=NULL) {
-               *bytesread=ret;
-       }
-       
-       return(TRUE);
-}
-
-static gboolean console_write(gpointer handle, gconstpointer buffer,
-                             guint32 numbytes, guint32 *byteswritten,
-                             WapiOverlapped *overlapped G_GNUC_UNUSED)
-{
-       struct _WapiHandle_file *console_handle;
-       gboolean ok;
-       int ret, fd;
-       MonoThreadInfo *info = mono_thread_info_current ();
-       
-       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
-                               (gpointer *)&console_handle);
-       if(ok==FALSE) {
-               g_warning ("%s: error looking up console handle %p", __func__,
-                          handle);
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       fd = console_handle->fd;
-       
-       if(byteswritten!=NULL) {
-               *byteswritten=0;
-       }
-       
-       if(!(console_handle->fileaccess & GENERIC_WRITE) &&
-          !(console_handle->fileaccess & GENERIC_ALL)) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, console_handle->fileaccess);
-
-               SetLastError (ERROR_ACCESS_DENIED);
-               return(FALSE);
-       }
-       
-       do {
-               ret = write(fd, buffer, numbytes);
-       } while (ret == -1 && errno == EINTR &&
-                !mono_thread_info_is_interrupt_state (info));
-
-       if (ret == -1) {
-               if (errno == EINTR) {
-                       ret = 0;
-               } else {
-                       _wapi_set_last_error_from_errno ();
-                       
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s",
-                                  __func__, handle, strerror(errno));
-
-                       return(FALSE);
-               }
-       }
-       if(byteswritten!=NULL) {
-               *byteswritten=ret;
-       }
-       
-       return(TRUE);
-}
-
-static const gchar* find_typename (void)
-{
-       return "Find";
-}
-
-static gsize find_typesize (void)
-{
-       return sizeof (struct _WapiHandle_find);
-}
-
-static void pipe_close (gpointer handle, gpointer data)
-{
-       struct _WapiHandle_file *pipe_handle = (struct _WapiHandle_file*)data;
-       int fd = pipe_handle->fd;
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing pipe handle %p fd %d", __func__, handle, fd);
-
-       /* No filename with pipe handles */
-
-       if (pipe_handle->share_info)
-               _wapi_handle_share_release (pipe_handle->share_info);
-
-       close (fd);
-}
-
-static void pipe_details (gpointer data)
-{
-       file_details (data);
-}
-
-static const gchar* pipe_typename (void)
-{
-       return "Pipe";
-}
-
-static gsize pipe_typesize (void)
-{
-       return sizeof (struct _WapiHandle_file);
-}
-
-static WapiFileType pipe_getfiletype(void)
-{
-       return(FILE_TYPE_PIPE);
-}
-
-static gboolean pipe_read (gpointer handle, gpointer buffer,
-                          guint32 numbytes, guint32 *bytesread,
-                          WapiOverlapped *overlapped G_GNUC_UNUSED)
-{
-       struct _WapiHandle_file *pipe_handle;
-       gboolean ok;
-       int ret, fd;
-       MonoThreadInfo *info = mono_thread_info_current ();
-
-       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_PIPE,
-                               (gpointer *)&pipe_handle);
-       if(ok==FALSE) {
-               g_warning ("%s: error looking up pipe handle %p", __func__,
-                          handle);
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       fd = pipe_handle->fd;
-
-       if(bytesread!=NULL) {
-               *bytesread=0;
-       }
-       
-       if(!(pipe_handle->fileaccess & GENERIC_READ) &&
-          !(pipe_handle->fileaccess & GENERIC_ALL)) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
-                         __func__, handle, pipe_handle->fileaccess);
-
-               SetLastError (ERROR_ACCESS_DENIED);
-               return(FALSE);
-       }
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: reading up to %d bytes from pipe %p", __func__,
-                  numbytes, handle);
-
-       do {
-               ret=read(fd, buffer, numbytes);
-       } while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info));
-               
-       if (ret == -1) {
-               if (errno == EINTR) {
-                       ret = 0;
-               } else {
-                       _wapi_set_last_error_from_errno ();
-                       
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__,
-                                 handle, strerror(errno));
-
-                       return(FALSE);
-               }
-       }
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read %d bytes from pipe %p", __func__, ret, handle);
-
-       if(bytesread!=NULL) {
-               *bytesread=ret;
-       }
-       
-       return(TRUE);
-}
-
-static gboolean pipe_write(gpointer handle, gconstpointer buffer,
-                          guint32 numbytes, guint32 *byteswritten,
-                          WapiOverlapped *overlapped G_GNUC_UNUSED)
-{
-       struct _WapiHandle_file *pipe_handle;
-       gboolean ok;
-       int ret, fd;
-       MonoThreadInfo *info = mono_thread_info_current ();
-       
-       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_PIPE,
-                               (gpointer *)&pipe_handle);
-       if(ok==FALSE) {
-               g_warning ("%s: error looking up pipe handle %p", __func__,
-                          handle);
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       fd = pipe_handle->fd;
-       
-       if(byteswritten!=NULL) {
-               *byteswritten=0;
-       }
-       
-       if(!(pipe_handle->fileaccess & GENERIC_WRITE) &&
-          !(pipe_handle->fileaccess & GENERIC_ALL)) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, pipe_handle->fileaccess);
-
-               SetLastError (ERROR_ACCESS_DENIED);
-               return(FALSE);
-       }
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: writing up to %d bytes to pipe %p", __func__, numbytes,
-                  handle);
-
-       do {
-               ret = write (fd, buffer, numbytes);
-       } while (ret == -1 && errno == EINTR &&
-                !mono_thread_info_is_interrupt_state (info));
-
-       if (ret == -1) {
-               if (errno == EINTR) {
-                       ret = 0;
-               } else {
-                       _wapi_set_last_error_from_errno ();
-                       
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s", __func__,
-                                 handle, strerror(errno));
-
-                       return(FALSE);
-               }
-       }
-       if(byteswritten!=NULL) {
-               *byteswritten=ret;
-       }
-       
-       return(TRUE);
-}
-
-static int convert_flags(guint32 fileaccess, guint32 createmode)
-{
-       int flags=0;
-       
-       switch(fileaccess) {
-       case GENERIC_READ:
-               flags=O_RDONLY;
-               break;
-       case GENERIC_WRITE:
-               flags=O_WRONLY;
-               break;
-       case GENERIC_READ|GENERIC_WRITE:
-               flags=O_RDWR;
-               break;
-       default:
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown access type 0x%x", __func__,
-                         fileaccess);
-               break;
-       }
-
-       switch(createmode) {
-       case CREATE_NEW:
-               flags|=O_CREAT|O_EXCL;
-               break;
-       case CREATE_ALWAYS:
-               flags|=O_CREAT|O_TRUNC;
-               break;
-       case OPEN_EXISTING:
-               break;
-       case OPEN_ALWAYS:
-               flags|=O_CREAT;
-               break;
-       case TRUNCATE_EXISTING:
-               flags|=O_TRUNC;
-               break;
-       default:
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown create mode 0x%x", __func__,
-                         createmode);
-               break;
-       }
-       
-       return(flags);
-}
-
-#if 0 /* unused */
-static mode_t convert_perms(guint32 sharemode)
-{
-       mode_t perms=0600;
-       
-       if(sharemode&FILE_SHARE_READ) {
-               perms|=044;
-       }
-       if(sharemode&FILE_SHARE_WRITE) {
-               perms|=022;
-       }
-
-       return(perms);
-}
-#endif
-
-static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode,
-                                  guint32 fileaccess,
-                                  struct _WapiFileShare **share_info)
-{
-       gboolean file_already_shared;
-       guint32 file_existing_share, file_existing_access;
-
-       file_already_shared = _wapi_handle_get_or_set_share (statbuf->st_dev, statbuf->st_ino, sharemode, fileaccess, &file_existing_share, &file_existing_access, share_info);
-       
-       if (file_already_shared) {
-               /* The reference to this share info was incremented
-                * when we looked it up, so be careful to put it back
-                * if we conclude we can't use this file.
-                */
-               if (file_existing_share == 0) {
-                       /* Quick and easy, no possibility to share */
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing = NONE", __func__, fileaccess);
-
-                       _wapi_handle_share_release (*share_info);
-                       
-                       return(FALSE);
-               }
-
-               if (((file_existing_share == FILE_SHARE_READ) &&
-                    (fileaccess != GENERIC_READ)) ||
-                   ((file_existing_share == FILE_SHARE_WRITE) &&
-                    (fileaccess != GENERIC_WRITE))) {
-                       /* New access mode doesn't match up */
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing: 0x%x", __func__, fileaccess, file_existing_share);
-
-                       _wapi_handle_share_release (*share_info);
-               
-                       return(FALSE);
-               }
-
-               if (((file_existing_access & GENERIC_READ) &&
-                    !(sharemode & FILE_SHARE_READ)) ||
-                   ((file_existing_access & GENERIC_WRITE) &&
-                    !(sharemode & FILE_SHARE_WRITE))) {
-                       /* New share mode doesn't match up */
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Access mode prevents open: requested share: 0x%x, file has access: 0x%x", __func__, sharemode, file_existing_access);
-
-                       _wapi_handle_share_release (*share_info);
-               
-                       return(FALSE);
-               }
-       } else {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: New file!", __func__);
-       }
-
-       return(TRUE);
-}
-
-
-static gboolean
-share_allows_delete (struct stat *statbuf, struct _WapiFileShare **share_info)
-{
-       gboolean file_already_shared;
-       guint32 file_existing_share, file_existing_access;
-
-       file_already_shared = _wapi_handle_get_or_set_share (statbuf->st_dev, statbuf->st_ino, FILE_SHARE_DELETE, GENERIC_READ, &file_existing_share, &file_existing_access, share_info);
-
-       if (file_already_shared) {
-               /* The reference to this share info was incremented
-                * when we looked it up, so be careful to put it back
-                * if we conclude we can't use this file.
-                */
-               if (file_existing_share == 0) {
-                       /* Quick and easy, no possibility to share */
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing = NONE", __func__, (*share_info)->access);
-
-                       _wapi_handle_share_release (*share_info);
-
-                       return(FALSE);
-               }
-
-               if (!(file_existing_share & FILE_SHARE_DELETE)) {
-                       /* New access mode doesn't match up */
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing: 0x%x", __func__, (*share_info)->access, file_existing_share);
-
-                       _wapi_handle_share_release (*share_info);
-
-                       return(FALSE);
-               }
-       } else {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: New file!", __func__);
-       }
-
-       return(TRUE);
-}
-
-/**
- * CreateFile:
- * @name: a pointer to a NULL-terminated unicode string, that names
- * the file or other object to create.
- * @fileaccess: specifies the file access mode
- * @sharemode: whether the file should be shared.  This parameter is
- * currently ignored.
- * @security: Ignored for now.
- * @createmode: specifies whether to create a new file, whether to
- * overwrite an existing file, whether to truncate the file, etc.
- * @attrs: specifies file attributes and flags.  On win32 attributes
- * are characteristics of the file, not the handle, and are ignored
- * when an existing file is opened.  Flags give the library hints on
- * how to process a file to optimise performance.
- * @template: the handle of an open %GENERIC_READ file that specifies
- * attributes to apply to a newly created file, ignoring @attrs.
- * Normally this parameter is NULL.  This parameter is ignored when an
- * existing file is opened.
- *
- * Creates a new file handle.  This only applies to normal files:
- * pipes are handled by CreatePipe(), and console handles are created
- * with GetStdHandle().
- *
- * Return value: the new handle, or %INVALID_HANDLE_VALUE on error.
- */
-gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
-                   guint32 sharemode, WapiSecurityAttributes *security,
-                   guint32 createmode, guint32 attrs,
-                   gpointer template_ G_GNUC_UNUSED)
-{
-       struct _WapiHandle_file file_handle = {0};
-       gpointer handle;
-       int flags=convert_flags(fileaccess, createmode);
-       /*mode_t perms=convert_perms(sharemode);*/
-       /* we don't use sharemode, because that relates to sharing of
-        * the file when the file is open and is already handled by
-        * other code, perms instead are the on-disk permissions and
-        * this is a sane default.
-        */
-       mode_t perms=0666;
-       gchar *filename;
-       int fd, ret;
-       MonoW32HandleType handle_type;
-       struct stat statbuf;
-
-       if (attrs & FILE_ATTRIBUTE_TEMPORARY)
-               perms = 0600;
-       
-       if (attrs & FILE_ATTRIBUTE_ENCRYPTED){
-               SetLastError (ERROR_ENCRYPTION_FAILED);
-               return INVALID_HANDLE_VALUE;
-       }
-       
-       if (name == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
-               SetLastError (ERROR_INVALID_NAME);
-               return(INVALID_HANDLE_VALUE);
-       }
-
-       filename = mono_unicode_to_external (name);
-       if (filename == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
-               SetLastError (ERROR_INVALID_NAME);
-               return(INVALID_HANDLE_VALUE);
-       }
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening %s with share 0x%x and access 0x%x", __func__,
-                  filename, sharemode, fileaccess);
-       
-       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
-        * EISDIR. However, this is a bit bogus because calls to
-        * manipulate the directory (e.g. SetFileTime) will still work on
-        * the directory because they use other API calls
-        * (e.g. utime()). Hence, if we failed with the EISDIR error, try
-        * to open the directory again without write permission.
-        */
-       if (fd == -1 && errno == EISDIR)
-       {
-               /* Try again but don't try to make it writable */
-               fd = _wapi_open (filename, flags & ~(O_RDWR|O_WRONLY), perms);
-       }
-       
-       if (fd == -1) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s: %s", __func__, filename,
-                         strerror(errno));
-               _wapi_set_last_path_error_from_errno (NULL, filename);
-               g_free (filename);
-
-               return(INVALID_HANDLE_VALUE);
-       }
-
-       if (fd >= mono_w32handle_fd_reserve) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
-
-               SetLastError (ERROR_TOO_MANY_OPEN_FILES);
-               
-               close (fd);
-               g_free (filename);
-               
-               return(INVALID_HANDLE_VALUE);
-       }
-
-       ret = fstat (fd, &statbuf);
-       if (ret == -1) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fstat error of file %s: %s", __func__,
-                          filename, strerror (errno));
-               _wapi_set_last_error_from_errno ();
-               g_free (filename);
-               close (fd);
-               
-               return(INVALID_HANDLE_VALUE);
-       }
-#ifdef __native_client__
-       /* Workaround: Native Client currently returns the same fake inode
-        * for all files, so do a simple hash on the filename so we don't
-        * use the same share info for each file.
-        */
-       statbuf.st_ino = g_str_hash(filename);
-#endif
-
-       if (share_allows_open (&statbuf, sharemode, fileaccess,
-                        &file_handle.share_info) == FALSE) {
-               SetLastError (ERROR_SHARING_VIOLATION);
-               g_free (filename);
-               close (fd);
-               
-               return (INVALID_HANDLE_VALUE);
-       }
-       if (file_handle.share_info == NULL) {
-               /* No space, so no more files can be opened */
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: No space in the share table", __func__);
-
-               SetLastError (ERROR_TOO_MANY_OPEN_FILES);
-               close (fd);
-               g_free (filename);
-               
-               return(INVALID_HANDLE_VALUE);
-       }
-       
-       file_handle.filename = filename;
-
-       if(security!=NULL) {
-               //file_handle->security_attributes=_wapi_handle_scratch_store (
-               //security, sizeof(WapiSecurityAttributes));
-       }
-       
-       file_handle.fd = fd;
-       file_handle.fileaccess=fileaccess;
-       file_handle.sharemode=sharemode;
-       file_handle.attrs=attrs;
-
-#ifdef HAVE_POSIX_FADVISE
-       if (attrs & FILE_FLAG_SEQUENTIAL_SCAN)
-               posix_fadvise (fd, 0, 0, POSIX_FADV_SEQUENTIAL);
-       if (attrs & FILE_FLAG_RANDOM_ACCESS)
-               posix_fadvise (fd, 0, 0, POSIX_FADV_RANDOM);
-#endif
-
-#ifdef F_RDAHEAD
-       if (attrs & FILE_FLAG_SEQUENTIAL_SCAN)
-               fcntl(fd, F_RDAHEAD, 1);
-#endif
-
-#ifndef S_ISFIFO
-#define S_ISFIFO(m) ((m & S_IFIFO) != 0)
-#endif
-       if (S_ISFIFO (statbuf.st_mode)) {
-               handle_type = MONO_W32HANDLE_PIPE;
-               /* maintain invariant that pipes have no filename */
-               file_handle.filename = NULL;
-               g_free (filename);
-               filename = NULL;
-       } else if (S_ISCHR (statbuf.st_mode)) {
-               handle_type = MONO_W32HANDLE_CONSOLE;
-       } else {
-               handle_type = MONO_W32HANDLE_FILE;
-       }
-
-       handle = mono_w32handle_new_fd (handle_type, fd, &file_handle);
-       if (handle == INVALID_HANDLE_VALUE) {
-               g_warning ("%s: error creating file handle", __func__);
-               g_free (filename);
-               close (fd);
-               
-               SetLastError (ERROR_GEN_FAILURE);
-               return(INVALID_HANDLE_VALUE);
-       }
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, handle);
-       
-       return(handle);
-}
-
-/**
- * DeleteFile:
- * @name: a pointer to a NULL-terminated unicode string, that names
- * the file to be deleted.
- *
- * Deletes file @name.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean DeleteFile(const gunichar2 *name)
-{
-       gchar *filename;
-       int retval;
-       gboolean ret = FALSE;
-       guint32 attrs;
-#if 0
-       struct stat statbuf;
-       struct _WapiFileShare *shareinfo;
-#endif
-       
-       if(name==NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
-               SetLastError (ERROR_INVALID_NAME);
-               return(FALSE);
-       }
-
-       filename=mono_unicode_to_external(name);
-       if(filename==NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
-               SetLastError (ERROR_INVALID_NAME);
-               return(FALSE);
-       }
-
-       attrs = GetFileAttributes (name);
-       if (attrs == INVALID_FILE_ATTRIBUTES) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file attributes error", __func__);
-               /* Error set by GetFileAttributes() */
-               g_free (filename);
-               return(FALSE);
-       }
-
-#if 0
-       /* Check to make sure sharing allows us to open the file for
-        * writing.  See bug 323389.
-        *
-        * Do the checks that don't need an open file descriptor, for
-        * simplicity's sake.  If we really have to do the full checks
-        * then we can implement that later.
-        */
-       if (_wapi_stat (filename, &statbuf) < 0) {
-               _wapi_set_last_path_error_from_errno (NULL, filename);
-               g_free (filename);
-               return(FALSE);
-       }
-       
-       if (share_allows_open (&statbuf, 0, GENERIC_WRITE,
-                              &shareinfo) == FALSE) {
-               SetLastError (ERROR_SHARING_VIOLATION);
-               g_free (filename);
-               return FALSE;
-       }
-       if (shareinfo)
-               _wapi_handle_share_release (shareinfo);
-#endif
-
-       retval = _wapi_unlink (filename);
-       
-       if (retval == -1) {
-               _wapi_set_last_path_error_from_errno (NULL, filename);
-       } else {
-               ret = TRUE;
-       }
-
-       g_free(filename);
-
-       return(ret);
-}
-
-/**
- * MoveFile:
- * @name: a pointer to a NULL-terminated unicode string, that names
- * the file to be moved.
- * @dest_name: a pointer to a NULL-terminated unicode string, that is the
- * new name for the file.
- *
- * Renames file @name to @dest_name.
- * MoveFile sets ERROR_ALREADY_EXISTS if the destination exists, except
- * when it is the same file as the source.  In that case it silently succeeds.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_name)
-{
-       gchar *utf8_name, *utf8_dest_name;
-       int result, errno_copy;
-       struct stat stat_src, stat_dest;
-       gboolean ret = FALSE;
-       struct _WapiFileShare *shareinfo;
-       
-       if(name==NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
-               SetLastError (ERROR_INVALID_NAME);
-               return(FALSE);
-       }
-
-       utf8_name = mono_unicode_to_external (name);
-       if (utf8_name == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-               
-               SetLastError (ERROR_INVALID_NAME);
-               return FALSE;
-       }
-       
-       if(dest_name==NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
-               g_free (utf8_name);
-               SetLastError (ERROR_INVALID_NAME);
-               return(FALSE);
-       }
-
-       utf8_dest_name = mono_unicode_to_external (dest_name);
-       if (utf8_dest_name == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
-               g_free (utf8_name);
-               SetLastError (ERROR_INVALID_NAME);
-               return FALSE;
-       }
-
-       /*
-        * In C# land we check for the existence of src, but not for dest.
-        * We check it here and return the failure if dest exists and is not
-        * the same file as src.
-        */
-       if (_wapi_stat (utf8_name, &stat_src) < 0) {
-               if (errno != ENOENT || _wapi_lstat (utf8_name, &stat_src) < 0) {
-                       _wapi_set_last_path_error_from_errno (NULL, utf8_name);
-                       g_free (utf8_name);
-                       g_free (utf8_dest_name);
-                       return FALSE;
-               }
-       }
-       
-       if (!_wapi_stat (utf8_dest_name, &stat_dest)) {
-               if (stat_dest.st_dev != stat_src.st_dev ||
-                   stat_dest.st_ino != stat_src.st_ino) {
-                       g_free (utf8_name);
-                       g_free (utf8_dest_name);
-                       SetLastError (ERROR_ALREADY_EXISTS);
-                       return FALSE;
-               }
-       }
-
-       /* Check to make that we have delete sharing permission.
-        * See https://bugzilla.xamarin.com/show_bug.cgi?id=17009
-        *
-        * Do the checks that don't need an open file descriptor, for
-        * simplicity's sake.  If we really have to do the full checks
-        * then we can implement that later.
-        */
-       if (share_allows_delete (&stat_src, &shareinfo) == FALSE) {
-               SetLastError (ERROR_SHARING_VIOLATION);
-               return FALSE;
-       }
-       if (shareinfo)
-               _wapi_handle_share_release (shareinfo);
-
-       result = _wapi_rename (utf8_name, utf8_dest_name);
-       errno_copy = errno;
-       
-       if (result == -1) {
-               switch(errno_copy) {
-               case EEXIST:
-                       SetLastError (ERROR_ALREADY_EXISTS);
-                       break;
-
-               case EXDEV:
-                       /* Ignore here, it is dealt with below */
-                       break;
-
-               case ENOENT:
-                       /* We already know src exists. Must be dest that doesn't exist. */
-                       _wapi_set_last_path_error_from_errno (NULL, utf8_dest_name);
-                       break;
-
-               default:
-                       _wapi_set_last_error_from_errno ();
-               }
-       }
-       
-       g_free (utf8_name);
-       g_free (utf8_dest_name);
-
-       if (result != 0 && errno_copy == EXDEV) {
-               if (S_ISDIR (stat_src.st_mode)) {
-                       SetLastError (ERROR_NOT_SAME_DEVICE);
-                       return FALSE;
-               }
-               /* Try a copy to the new location, and delete the source */
-               if (CopyFile (name, dest_name, TRUE)==FALSE) {
-                       /* CopyFile will set the error */
-                       return(FALSE);
-               }
-               
-               return(DeleteFile (name));
-       }
-
-       if (result == 0) {
-               ret = TRUE;
-       }
-
-       return(ret);
-}
-
-static gboolean
-write_file (int src_fd, int dest_fd, struct stat *st_src, gboolean report_errors)
-{
-       int remain, n;
-       char *buf, *wbuf;
-       int buf_size = st_src->st_blksize;
-       MonoThreadInfo *info = mono_thread_info_current ();
-
-       buf_size = buf_size < 8192 ? 8192 : (buf_size > 65536 ? 65536 : buf_size);
-       buf = (char *) g_malloc (buf_size);
-
-       for (;;) {
-               remain = read (src_fd, buf, buf_size);
-               if (remain < 0) {
-                       if (errno == EINTR && !mono_thread_info_is_interrupt_state (info))
-                               continue;
-
-                       if (report_errors)
-                               _wapi_set_last_error_from_errno ();
-
-                       g_free (buf);
-                       return FALSE;
-               }
-               if (remain == 0) {
-                       break;
-               }
-
-               wbuf = buf;
-               while (remain > 0) {
-                       if ((n = write (dest_fd, wbuf, remain)) < 0) {
-                               if (errno == EINTR && !mono_thread_info_is_interrupt_state (info))
-                                       continue;
-
-                               if (report_errors)
-                                       _wapi_set_last_error_from_errno ();
-                               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write failed.", __func__);
-                               g_free (buf);
-                               return FALSE;
-                       }
-
-                       remain -= n;
-                       wbuf += n;
-               }
-       }
-
-       g_free (buf);
-       return TRUE ;
-}
-
-/**
- * CopyFile:
- * @name: a pointer to a NULL-terminated unicode string, that names
- * the file to be copied.
- * @dest_name: a pointer to a NULL-terminated unicode string, that is the
- * new name for the file.
- * @fail_if_exists: if TRUE and dest_name exists, the copy will fail.
- *
- * Copies file @name to @dest_name
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name,
-                  gboolean fail_if_exists)
-{
-       gchar *utf8_src, *utf8_dest;
-       int src_fd, dest_fd;
-       struct stat st, dest_st;
-       struct utimbuf dest_time;
-       gboolean ret = TRUE;
-       int ret_utime;
-       
-       if(name==NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
-               SetLastError (ERROR_INVALID_NAME);
-               return(FALSE);
-       }
-       
-       utf8_src = mono_unicode_to_external (name);
-       if (utf8_src == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion of source returned NULL",
-                          __func__);
-
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return(FALSE);
-       }
-       
-       if(dest_name==NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: dest is NULL", __func__);
-
-               g_free (utf8_src);
-               SetLastError (ERROR_INVALID_NAME);
-               return(FALSE);
-       }
-       
-       utf8_dest = mono_unicode_to_external (dest_name);
-       if (utf8_dest == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion of dest returned NULL",
-                          __func__);
-
-               SetLastError (ERROR_INVALID_PARAMETER);
-
-               g_free (utf8_src);
-               
-               return(FALSE);
-       }
-       
-       src_fd = _wapi_open (utf8_src, O_RDONLY, 0);
-       if (src_fd < 0) {
-               _wapi_set_last_path_error_from_errno (NULL, utf8_src);
-               
-               g_free (utf8_src);
-               g_free (utf8_dest);
-               
-               return(FALSE);
-       }
-
-       if (fstat (src_fd, &st) < 0) {
-               _wapi_set_last_error_from_errno ();
-
-               g_free (utf8_src);
-               g_free (utf8_dest);
-               close (src_fd);
-               
-               return(FALSE);
-       }
-
-       /* Before trying to open/create the dest, we need to report a 'file busy'
-        * error if src and dest are actually the same file. We do the check here to take
-        * advantage of the IOMAP capability */
-       if (!_wapi_stat (utf8_dest, &dest_st) && st.st_dev == dest_st.st_dev && 
-                       st.st_ino == dest_st.st_ino) {
-
-               g_free (utf8_src);
-               g_free (utf8_dest);
-               close (src_fd);
-
-               SetLastError (ERROR_SHARING_VIOLATION);
-               return (FALSE);
-       }
-       
-       if (fail_if_exists) {
-               dest_fd = _wapi_open (utf8_dest, O_WRONLY | O_CREAT | O_EXCL, st.st_mode);
-       } else {
-               /* FIXME: it kinda sucks that this code path potentially scans
-                * the directory twice due to the weird SetLastError()
-                * behavior. */
-               dest_fd = _wapi_open (utf8_dest, O_WRONLY | O_TRUNC, st.st_mode);
-               if (dest_fd < 0) {
-                       /* The file does not exist, try creating it */
-                       dest_fd = _wapi_open (utf8_dest, O_WRONLY | O_CREAT | O_TRUNC, st.st_mode);
-               } else {
-                       /* Apparently this error is set if we
-                        * overwrite the dest file
-                        */
-                       SetLastError (ERROR_ALREADY_EXISTS);
-               }
-       }
-       if (dest_fd < 0) {
-               _wapi_set_last_error_from_errno ();
-
-               g_free (utf8_src);
-               g_free (utf8_dest);
-               close (src_fd);
-
-               return(FALSE);
-       }
-
-       if (!write_file (src_fd, dest_fd, &st, TRUE))
-               ret = FALSE;
-
-       close (src_fd);
-       close (dest_fd);
-       
-       dest_time.modtime = st.st_mtime;
-       dest_time.actime = st.st_atime;
-       ret_utime = utime (utf8_dest, &dest_time);
-       if (ret_utime == -1)
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file [%s] utime failed: %s", __func__, utf8_dest, strerror(errno));
-       
-       g_free (utf8_src);
-       g_free (utf8_dest);
-
-       return ret;
-}
-
-static gchar*
-convert_arg_to_utf8 (const gunichar2 *arg, const gchar *arg_name)
-{
-       gchar *utf8_ret;
-
-       if (arg == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s is NULL", __func__, arg_name);
-               SetLastError (ERROR_INVALID_NAME);
-               return NULL;
-       }
-
-       utf8_ret = mono_unicode_to_external (arg);
-       if (utf8_ret == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion of %s returned NULL",
-                          __func__, arg_name);
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return NULL;
-       }
-
-       return utf8_ret;
-}
-
-gboolean
-ReplaceFile (const gunichar2 *replacedFileName, const gunichar2 *replacementFileName,
-                     const gunichar2 *backupFileName, guint32 replaceFlags, 
-                     gpointer exclude, gpointer reserved)
-{
-       int result, backup_fd = -1,replaced_fd = -1;
-       gchar *utf8_replacedFileName, *utf8_replacementFileName = NULL, *utf8_backupFileName = NULL;
-       struct stat stBackup;
-       gboolean ret = FALSE;
-
-       if (!(utf8_replacedFileName = convert_arg_to_utf8 (replacedFileName, "replacedFileName")))
-               return FALSE;
-       if (!(utf8_replacementFileName = convert_arg_to_utf8 (replacementFileName, "replacementFileName")))
-               goto replace_cleanup;
-       if (backupFileName != NULL) {
-               if (!(utf8_backupFileName = convert_arg_to_utf8 (backupFileName, "backupFileName")))
-                       goto replace_cleanup;
-       }
-
-       if (utf8_backupFileName) {
-               // Open the backup file for read so we can restore the file if an error occurs.
-               backup_fd = _wapi_open (utf8_backupFileName, O_RDONLY, 0);
-               result = _wapi_rename (utf8_replacedFileName, utf8_backupFileName);
-               if (result == -1)
-                       goto replace_cleanup;
-       }
-
-       result = _wapi_rename (utf8_replacementFileName, utf8_replacedFileName);
-       if (result == -1) {
-               _wapi_set_last_path_error_from_errno (NULL, utf8_replacementFileName);
-               _wapi_rename (utf8_backupFileName, utf8_replacedFileName);
-               if (backup_fd != -1 && !fstat (backup_fd, &stBackup)) {
-                       replaced_fd = _wapi_open (utf8_backupFileName, O_WRONLY | O_CREAT | O_TRUNC,
-                                                 stBackup.st_mode);
-                       
-                       if (replaced_fd == -1)
-                               goto replace_cleanup;
-
-                       write_file (backup_fd, replaced_fd, &stBackup, FALSE);
-               }
-
-               goto replace_cleanup;
-       }
-
-       ret = TRUE;
-
-replace_cleanup:
-       g_free (utf8_replacedFileName);
-       g_free (utf8_replacementFileName);
-       g_free (utf8_backupFileName);
-       if (backup_fd != -1)
-               close (backup_fd);
-       if (replaced_fd != -1)
-               close (replaced_fd);
-       return ret;
-}
-
-/**
- * GetStdHandle:
- * @stdhandle: specifies the file descriptor
- *
- * Returns a handle for stdin, stdout, or stderr.  Always returns the
- * same handle for the same @stdhandle.
- *
- * Return value: the handle, or %INVALID_HANDLE_VALUE on error
- */
-
-static mono_mutex_t stdhandle_mutex;
-
-gpointer GetStdHandle(WapiStdHandle stdhandle)
-{
-       struct _WapiHandle_file *file_handle;
-       gpointer handle;
-       int fd;
-       const gchar *name;
-       gboolean ok;
-       
-       switch(stdhandle) {
-       case STD_INPUT_HANDLE:
-               fd = 0;
-               name = "<stdin>";
-               break;
-
-       case STD_OUTPUT_HANDLE:
-               fd = 1;
-               name = "<stdout>";
-               break;
-
-       case STD_ERROR_HANDLE:
-               fd = 2;
-               name = "<stderr>";
-               break;
-
-       default:
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unknown standard handle type", __func__);
-
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return(INVALID_HANDLE_VALUE);
-       }
-
-       handle = GINT_TO_POINTER (fd);
-
-       mono_os_mutex_lock (&stdhandle_mutex);
-
-       ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
-                                 (gpointer *)&file_handle);
-       if (ok == FALSE) {
-               /* Need to create this console handle */
-               handle = _wapi_stdhandle_create (fd, name);
-               
-               if (handle == INVALID_HANDLE_VALUE) {
-                       SetLastError (ERROR_NO_MORE_FILES);
-                       goto done;
-               }
-       } else {
-               /* Add a reference to this handle */
-               mono_w32handle_ref (handle);
-       }
-       
-  done:
-       mono_os_mutex_unlock (&stdhandle_mutex);
-       
-       return(handle);
-}
-
-/**
- * ReadFile:
- * @handle: The file handle to read from.  The handle must have
- * %GENERIC_READ access.
- * @buffer: The buffer to store read data in
- * @numbytes: The maximum number of bytes to read
- * @bytesread: The actual number of bytes read is stored here.  This
- * value can be zero if the handle is positioned at the end of the
- * file.
- * @overlapped: points to a required %WapiOverlapped structure if
- * @handle has the %FILE_FLAG_OVERLAPPED option set, should be NULL
- * otherwise.
- *
- * If @handle does not have the %FILE_FLAG_OVERLAPPED option set, this
- * function reads up to @numbytes bytes from the file from the current
- * file position, and stores them in @buffer.  If there are not enough
- * bytes left in the file, just the amount available will be read.
- * The actual number of bytes read is stored in @bytesread.
-
- * If @handle has the %FILE_FLAG_OVERLAPPED option set, the current
- * file position is ignored and the read position is taken from data
- * in the @overlapped structure.
- *
- * Return value: %TRUE if the read succeeds (even if no bytes were
- * read due to an attempt to read past the end of the file), %FALSE on
- * error.
- */
-gboolean ReadFile(gpointer handle, gpointer buffer, guint32 numbytes,
-                 guint32 *bytesread, WapiOverlapped *overlapped)
-{
-       MonoW32HandleType type;
-
-       type = mono_w32handle_get_type (handle);
-       
-       if(io_ops[type].readfile==NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       
-       return(io_ops[type].readfile (handle, buffer, numbytes, bytesread,
-                                     overlapped));
-}
-
-/**
- * WriteFile:
- * @handle: The file handle to write to.  The handle must have
- * %GENERIC_WRITE access.
- * @buffer: The buffer to read data from.
- * @numbytes: The maximum number of bytes to write.
- * @byteswritten: The actual number of bytes written is stored here.
- * If the handle is positioned at the file end, the length of the file
- * is extended.  This parameter may be %NULL.
- * @overlapped: points to a required %WapiOverlapped structure if
- * @handle has the %FILE_FLAG_OVERLAPPED option set, should be NULL
- * otherwise.
- *
- * If @handle does not have the %FILE_FLAG_OVERLAPPED option set, this
- * function writes up to @numbytes bytes from @buffer to the file at
- * the current file position.  If @handle is positioned at the end of
- * the file, the file is extended.  The actual number of bytes written
- * is stored in @byteswritten.
- *
- * If @handle has the %FILE_FLAG_OVERLAPPED option set, the current
- * file position is ignored and the write position is taken from data
- * in the @overlapped structure.
- *
- * Return value: %TRUE if the write succeeds, %FALSE on error.
- */
-gboolean WriteFile(gpointer handle, gconstpointer buffer, guint32 numbytes,
-                  guint32 *byteswritten, WapiOverlapped *overlapped)
-{
-       MonoW32HandleType type;
-
-       type = mono_w32handle_get_type (handle);
-       
-       if(io_ops[type].writefile==NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       
-       return(io_ops[type].writefile (handle, buffer, numbytes, byteswritten,
-                                      overlapped));
-}
-
-/**
- * FlushFileBuffers:
- * @handle: Handle to open file.  The handle must have
- * %GENERIC_WRITE access.
- *
- * Flushes buffers of the file and causes all unwritten data to
- * be written.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean FlushFileBuffers(gpointer handle)
-{
-       MonoW32HandleType type;
-
-       type = mono_w32handle_get_type (handle);
-       
-       if(io_ops[type].flushfile==NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       
-       return(io_ops[type].flushfile (handle));
-}
-
-/**
- * SetEndOfFile:
- * @handle: The file handle to set.  The handle must have
- * %GENERIC_WRITE access.
- *
- * Moves the end-of-file position to the current position of the file
- * pointer.  This function is used to truncate or extend a file.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean SetEndOfFile(gpointer handle)
-{
-       MonoW32HandleType type;
-
-       type = mono_w32handle_get_type (handle);
-       
-       if (io_ops[type].setendoffile == NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       
-       return(io_ops[type].setendoffile (handle));
-}
-
-/**
- * SetFilePointer:
- * @handle: The file handle to set.  The handle must have
- * %GENERIC_READ or %GENERIC_WRITE access.
- * @movedistance: Low 32 bits of a signed value that specifies the
- * number of bytes to move the file pointer.
- * @highmovedistance: Pointer to the high 32 bits of a signed value
- * that specifies the number of bytes to move the file pointer, or
- * %NULL.
- * @method: The starting point for the file pointer move.
- *
- * Sets the file pointer of an open file.
- *
- * The distance to move the file pointer is calculated from
- * @movedistance and @highmovedistance: If @highmovedistance is %NULL,
- * @movedistance is the 32-bit signed value; otherwise, @movedistance
- * is the low 32 bits and @highmovedistance a pointer to the high 32
- * bits of a 64 bit signed value.  A positive distance moves the file
- * pointer forward from the position specified by @method; a negative
- * distance moves the file pointer backward.
- *
- * If the library is compiled without large file support,
- * @highmovedistance is ignored and its value is set to zero on a
- * successful return.
- *
- * Return value: On success, the low 32 bits of the new file pointer.
- * If @highmovedistance is not %NULL, the high 32 bits of the new file
- * pointer are stored there.  On failure, %INVALID_SET_FILE_POINTER.
- */
-guint32 SetFilePointer(gpointer handle, gint32 movedistance,
-                      gint32 *highmovedistance, WapiSeekMethod method)
-{
-       MonoW32HandleType type;
-
-       type = mono_w32handle_get_type (handle);
-       
-       if (io_ops[type].seek == NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(INVALID_SET_FILE_POINTER);
-       }
-       
-       return(io_ops[type].seek (handle, movedistance, highmovedistance,
-                                 method));
-}
-
-/**
- * GetFileType:
- * @handle: The file handle to test.
- *
- * Finds the type of file @handle.
- *
- * Return value: %FILE_TYPE_UNKNOWN - the type of the file @handle is
- * unknown.  %FILE_TYPE_DISK - @handle is a disk file.
- * %FILE_TYPE_CHAR - @handle is a character device, such as a console.
- * %FILE_TYPE_PIPE - @handle is a named or anonymous pipe.
- */
-WapiFileType GetFileType(gpointer handle)
-{
-       MonoW32HandleType type;
-
-       type = mono_w32handle_get_type (handle);
-       
-       if (io_ops[type].getfiletype == NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FILE_TYPE_UNKNOWN);
-       }
-       
-       return(io_ops[type].getfiletype ());
-}
-
-/**
- * GetFileSize:
- * @handle: The file handle to query.  The handle must have
- * %GENERIC_READ or %GENERIC_WRITE access.
- * @highsize: If non-%NULL, the high 32 bits of the file size are
- * stored here.
- *
- * Retrieves the size of the file @handle.
- *
- * If the library is compiled without large file support, @highsize
- * has its value set to zero on a successful return.
- *
- * Return value: On success, the low 32 bits of the file size.  If
- * @highsize is non-%NULL then the high 32 bits of the file size are
- * stored here.  On failure %INVALID_FILE_SIZE is returned.
- */
-guint32 GetFileSize(gpointer handle, guint32 *highsize)
-{
-       MonoW32HandleType type;
-
-       type = mono_w32handle_get_type (handle);
-       
-       if (io_ops[type].getfilesize == NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(INVALID_FILE_SIZE);
-       }
-       
-       return(io_ops[type].getfilesize (handle, highsize));
-}
-
-/**
- * GetFileTime:
- * @handle: The file handle to query.  The handle must have
- * %GENERIC_READ access.
- * @create_time: Points to a %WapiFileTime structure to receive the
- * number of ticks since the epoch that file was created.  May be
- * %NULL.
- * @last_access: Points to a %WapiFileTime structure to receive the
- * number of ticks since the epoch when file was last accessed.  May be
- * %NULL.
- * @last_write: Points to a %WapiFileTime structure to receive the
- * number of ticks since the epoch when file was last written to.  May
- * be %NULL.
- *
- * Finds the number of ticks since the epoch that the file referenced
- * by @handle was created, last accessed and last modified.  A tick is
- * a 100 nanosecond interval.  The epoch is Midnight, January 1 1601
- * GMT.
- *
- * Create time isn't recorded on POSIX file systems or reported by
- * stat(2), so that time is guessed by returning the oldest of the
- * other times.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean GetFileTime(gpointer handle, WapiFileTime *create_time,
-                    WapiFileTime *last_access, WapiFileTime *last_write)
-{
-       MonoW32HandleType type;
-
-       type = mono_w32handle_get_type (handle);
-       
-       if (io_ops[type].getfiletime == NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       
-       return(io_ops[type].getfiletime (handle, create_time, last_access,
-                                        last_write));
-}
-
-/**
- * SetFileTime:
- * @handle: The file handle to set.  The handle must have
- * %GENERIC_WRITE access.
- * @create_time: Points to a %WapiFileTime structure that contains the
- * number of ticks since the epoch that the file was created.  May be
- * %NULL.
- * @last_access: Points to a %WapiFileTime structure that contains the
- * number of ticks since the epoch when the file was last accessed.
- * May be %NULL.
- * @last_write: Points to a %WapiFileTime structure that contains the
- * number of ticks since the epoch when the file was last written to.
- * May be %NULL.
- *
- * Sets the number of ticks since the epoch that the file referenced
- * by @handle was created, last accessed or last modified.  A tick is
- * a 100 nanosecond interval.  The epoch is Midnight, January 1 1601
- * GMT.
- *
- * Create time isn't recorded on POSIX file systems, and is ignored.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean SetFileTime(gpointer handle, const WapiFileTime *create_time,
-                    const WapiFileTime *last_access,
-                    const WapiFileTime *last_write)
-{
-       MonoW32HandleType type;
-
-       type = mono_w32handle_get_type (handle);
-       
-       if (io_ops[type].setfiletime == NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       
-       return(io_ops[type].setfiletime (handle, create_time, last_access,
-                                        last_write));
-}
-
-/* A tick is a 100-nanosecond interval.  File time epoch is Midnight,
- * January 1 1601 GMT
- */
-
-#define TICKS_PER_MILLISECOND 10000L
-#define TICKS_PER_SECOND 10000000L
-#define TICKS_PER_MINUTE 600000000L
-#define TICKS_PER_HOUR 36000000000LL
-#define TICKS_PER_DAY 864000000000LL
-
-#define isleap(y) ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
-
-static const guint16 mon_yday[2][13]={
-       {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
-       {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366},
-};
-
-/**
- * FileTimeToSystemTime:
- * @file_time: Points to a %WapiFileTime structure that contains the
- * number of ticks to convert.
- * @system_time: Points to a %WapiSystemTime structure to receive the
- * broken-out time.
- *
- * Converts a tick count into broken-out time values.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
-                             WapiSystemTime *system_time)
-{
-       gint64 file_ticks, totaldays, rem, y;
-       const guint16 *ip;
-       
-       if(system_time==NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: system_time NULL", __func__);
-
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return(FALSE);
-       }
-       
-       file_ticks=((gint64)file_time->dwHighDateTime << 32) +
-               file_time->dwLowDateTime;
-       
-       /* Really compares if file_ticks>=0x8000000000000000
-        * (LLONG_MAX+1) but we're working with a signed value for the
-        * year and day calculation to work later
-        */
-       if(file_ticks<0) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file_time too big", __func__);
-
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return(FALSE);
-       }
-
-       totaldays=(file_ticks / TICKS_PER_DAY);
-       rem = file_ticks % TICKS_PER_DAY;
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld rem: %lld", __func__, totaldays, rem);
-
-       system_time->wHour=rem/TICKS_PER_HOUR;
-       rem %= TICKS_PER_HOUR;
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Hour: %d rem: %lld", __func__, system_time->wHour, rem);
-       
-       system_time->wMinute = rem / TICKS_PER_MINUTE;
-       rem %= TICKS_PER_MINUTE;
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Minute: %d rem: %lld", __func__, system_time->wMinute,
-                 rem);
-       
-       system_time->wSecond = rem / TICKS_PER_SECOND;
-       rem %= TICKS_PER_SECOND;
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Second: %d rem: %lld", __func__, system_time->wSecond,
-                 rem);
-       
-       system_time->wMilliseconds = rem / TICKS_PER_MILLISECOND;
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Milliseconds: %d", __func__,
-                 system_time->wMilliseconds);
-
-       /* January 1, 1601 was a Monday, according to Emacs calendar */
-       system_time->wDayOfWeek = ((1 + totaldays) % 7) + 1;
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Day of week: %d", __func__, system_time->wDayOfWeek);
-       
-       /* This algorithm to find year and month given days from epoch
-        * from glibc
-        */
-       y=1601;
-       
-#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
-#define LEAPS_THRU_END_OF(y) (DIV(y, 4) - DIV (y, 100) + DIV (y, 400))
-
-       while(totaldays < 0 || totaldays >= (isleap(y)?366:365)) {
-               /* Guess a corrected year, assuming 365 days per year */
-               gint64 yg = y + totaldays / 365 - (totaldays % 365 < 0);
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld yg: %lld y: %lld", __func__,
-                         totaldays, yg,
-                         y);
-               g_message("%s: LEAPS(yg): %lld LEAPS(y): %lld", __func__,
-                         LEAPS_THRU_END_OF(yg-1), LEAPS_THRU_END_OF(y-1));
-               
-               /* Adjust days and y to match the guessed year. */
-               totaldays -= ((yg - y) * 365
-                             + LEAPS_THRU_END_OF (yg - 1)
-                             - LEAPS_THRU_END_OF (y - 1));
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld", __func__, totaldays);
-               y = yg;
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: y: %lld", __func__, y);
-       }
-       
-       system_time->wYear = y;
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Year: %d", __func__, system_time->wYear);
-
-       ip = mon_yday[isleap(y)];
-       
-       for(y=11; totaldays < ip[y]; --y) {
-               continue;
-       }
-       totaldays-=ip[y];
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld", __func__, totaldays);
-       
-       system_time->wMonth = y + 1;
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Month: %d", __func__, system_time->wMonth);
-
-       system_time->wDay = totaldays + 1;
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Day: %d", __func__, system_time->wDay);
-       
-       return(TRUE);
-}
-
-gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
-{
-       struct _WapiHandle_find find_handle = {0};
-       gpointer handle;
-       gchar *utf8_pattern = NULL, *dir_part, *entry_part;
-       int result;
-       
-       if (pattern == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: pattern is NULL", __func__);
-
-               SetLastError (ERROR_PATH_NOT_FOUND);
-               return(INVALID_HANDLE_VALUE);
-       }
-
-       utf8_pattern = mono_unicode_to_external (pattern);
-       if (utf8_pattern == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-               
-               SetLastError (ERROR_INVALID_NAME);
-               return(INVALID_HANDLE_VALUE);
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: looking for [%s]", __func__, utf8_pattern);
-       
-       /* Figure out which bit of the pattern is the directory */
-       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
-        * really do have metachars in their names (see bug 58116).
-        * FIXME: Figure out a better solution to keep some checks...
-        */
-       if (strchr (dir_part, '*') || strchr (dir_part, '?')) {
-               SetLastError (ERROR_INVALID_NAME);
-               g_free (dir_part);
-               g_free (entry_part);
-               g_free (utf8_pattern);
-               return(INVALID_HANDLE_VALUE);
-       }
-#endif
-
-       /* The pattern can specify a directory or a set of files.
-        *
-        * The pattern can have wildcard characters ? and *, but only
-        * in the section after the last directory delimiter.  (Return
-        * ERROR_INVALID_NAME if there are wildcards in earlier path
-        * sections.)  "*" has the usual 0-or-more chars meaning.  "?" 
-        * means "match one character", "??" seems to mean "match one
-        * or two characters", "???" seems to mean "match one, two or
-        * three characters", etc.  Windows will also try and match
-        * the mangled "short name" of files, so 8 character patterns
-        * with wildcards will show some surprising results.
-        *
-        * All the written documentation I can find says that '?' 
-        * should only match one character, and doesn't mention '??',
-        * '???' etc.  I'm going to assume that the strict behaviour
-        * (ie '???' means three and only three characters) is the
-        * correct one, because that lets me use fnmatch(3) rather
-        * than mess around with regexes.
-        */
-
-       find_handle.namelist = NULL;
-       result = _wapi_io_scandir (dir_part, entry_part,
-                                  &find_handle.namelist);
-       
-       if (result == 0) {
-               /* No files, which windows seems to call
-                * FILE_NOT_FOUND
-                */
-               SetLastError (ERROR_FILE_NOT_FOUND);
-               g_free (utf8_pattern);
-               g_free (entry_part);
-               g_free (dir_part);
-               return (INVALID_HANDLE_VALUE);
-       }
-       
-       if (result < 0) {
-               _wapi_set_last_path_error_from_errno (dir_part, NULL);
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: scandir error: %s", __func__, g_strerror (errno));
-               g_free (utf8_pattern);
-               g_free (entry_part);
-               g_free (dir_part);
-               return (INVALID_HANDLE_VALUE);
-       }
-
-       g_free (utf8_pattern);
-       g_free (entry_part);
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Got %d matches", __func__, result);
-
-       find_handle.dir_part = dir_part;
-       find_handle.num = result;
-       find_handle.count = 0;
-       
-       handle = mono_w32handle_new (MONO_W32HANDLE_FIND, &find_handle);
-       if (handle == INVALID_HANDLE_VALUE) {
-               g_warning ("%s: error creating find handle", __func__);
-               g_free (dir_part);
-               g_free (entry_part);
-               g_free (utf8_pattern);
-               SetLastError (ERROR_GEN_FAILURE);
-               
-               return(INVALID_HANDLE_VALUE);
-       }
-
-       if (handle != INVALID_HANDLE_VALUE &&
-           !FindNextFile (handle, find_data)) {
-               FindClose (handle);
-               SetLastError (ERROR_NO_MORE_FILES);
-               handle = INVALID_HANDLE_VALUE;
-       }
-
-       return (handle);
-}
-
-gboolean FindNextFile (gpointer handle, WapiFindData *find_data)
-{
-       struct _WapiHandle_find *find_handle;
-       gboolean ok;
-       struct stat buf, linkbuf;
-       int result;
-       gchar *filename;
-       gchar *utf8_filename, *utf8_basename;
-       gunichar2 *utf16_basename;
-       time_t create_time;
-       glong bytes;
-       gboolean ret = FALSE;
-       
-       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FIND,
-                               (gpointer *)&find_handle);
-       if(ok==FALSE) {
-               g_warning ("%s: error looking up find handle %p", __func__,
-                          handle);
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-
-       mono_w32handle_lock_handle (handle);
-       
-retry:
-       if (find_handle->count >= find_handle->num) {
-               SetLastError (ERROR_NO_MORE_FILES);
-               goto cleanup;
-       }
-
-       /* stat next match */
-
-       filename = g_build_filename (find_handle->dir_part, find_handle->namelist[find_handle->count ++], NULL);
-
-       result = _wapi_stat (filename, &buf);
-       if (result == -1 && errno == ENOENT) {
-               /* Might be a dangling symlink */
-               result = _wapi_lstat (filename, &buf);
-       }
-       
-       if (result != 0) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: stat failed: %s", __func__, filename);
-
-               g_free (filename);
-               goto retry;
-       }
-
-#ifndef __native_client__
-       result = _wapi_lstat (filename, &linkbuf);
-       if (result != 0) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lstat failed: %s", __func__, filename);
-
-               g_free (filename);
-               goto retry;
-       }
-#endif
-
-       utf8_filename = mono_utf8_from_external (filename);
-       if (utf8_filename == NULL) {
-               /* We couldn't turn this filename into utf8 (eg the
-                * encoding of the name wasn't convertible), so just
-                * ignore it.
-                */
-               g_warning ("%s: Bad encoding for '%s'\nConsider using MONO_EXTERNAL_ENCODINGS\n", __func__, filename);
-               
-               g_free (filename);
-               goto retry;
-       }
-       g_free (filename);
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Found [%s]", __func__, utf8_filename);
-       
-       /* fill data block */
-
-       if (buf.st_mtime < buf.st_ctime)
-               create_time = buf.st_mtime;
-       else
-               create_time = buf.st_ctime;
-       
-#ifdef __native_client__
-       find_data->dwFileAttributes = _wapi_stat_to_file_attributes (utf8_filename, &buf, NULL);
-#else
-       find_data->dwFileAttributes = _wapi_stat_to_file_attributes (utf8_filename, &buf, &linkbuf);
-#endif
-
-       time_t_to_filetime (create_time, &find_data->ftCreationTime);
-       time_t_to_filetime (buf.st_atime, &find_data->ftLastAccessTime);
-       time_t_to_filetime (buf.st_mtime, &find_data->ftLastWriteTime);
-
-       if (find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-               find_data->nFileSizeHigh = 0;
-               find_data->nFileSizeLow = 0;
-       } else {
-               find_data->nFileSizeHigh = buf.st_size >> 32;
-               find_data->nFileSizeLow = buf.st_size & 0xFFFFFFFF;
-       }
-
-       find_data->dwReserved0 = 0;
-       find_data->dwReserved1 = 0;
-
-       utf8_basename = _wapi_basename (utf8_filename);
-       utf16_basename = g_utf8_to_utf16 (utf8_basename, -1, NULL, &bytes,
-                                         NULL);
-       if(utf16_basename==NULL) {
-               g_free (utf8_basename);
-               g_free (utf8_filename);
-               goto retry;
-       }
-       ret = TRUE;
-       
-       /* utf16 is 2 * utf8 */
-       bytes *= 2;
-
-       memset (find_data->cFileName, '\0', (MAX_PATH*2));
-
-       /* Truncating a utf16 string like this might leave the last
-        * char incomplete
-        */
-       memcpy (find_data->cFileName, utf16_basename,
-               bytes<(MAX_PATH*2)-2?bytes:(MAX_PATH*2)-2);
-
-       find_data->cAlternateFileName [0] = 0;  /* not used */
-
-       g_free (utf8_basename);
-       g_free (utf8_filename);
-       g_free (utf16_basename);
-
-cleanup:
-       mono_w32handle_unlock_handle (handle);
-       
-       return(ret);
-}
-
-/**
- * FindClose:
- * @wapi_handle: the find handle to close.
- *
- * Closes find handle @wapi_handle
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean FindClose (gpointer handle)
-{
-       struct _WapiHandle_find *find_handle;
-       gboolean ok;
-
-       if (handle == NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       
-       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FIND,
-                               (gpointer *)&find_handle);
-       if(ok==FALSE) {
-               g_warning ("%s: error looking up find handle %p", __func__,
-                          handle);
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-
-       mono_w32handle_lock_handle (handle);
-       
-       g_strfreev (find_handle->namelist);
-       g_free (find_handle->dir_part);
-
-       mono_w32handle_unlock_handle (handle);
-       
-       mono_w32handle_unref (handle);
-       
-       return(TRUE);
-}
-
-/**
- * CreateDirectory:
- * @name: a pointer to a NULL-terminated unicode string, that names
- * the directory to be created.
- * @security: ignored for now
- *
- * Creates directory @name
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean CreateDirectory (const gunichar2 *name,
-                         WapiSecurityAttributes *security)
-{
-       gchar *utf8_name;
-       int result;
-       
-       if (name == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
-               SetLastError (ERROR_INVALID_NAME);
-               return(FALSE);
-       }
-       
-       utf8_name = mono_unicode_to_external (name);
-       if (utf8_name == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-       
-               SetLastError (ERROR_INVALID_NAME);
-               return FALSE;
-       }
-
-       result = _wapi_mkdir (utf8_name, 0777);
-
-       if (result == 0) {
-               g_free (utf8_name);
-               return TRUE;
-       }
-
-       _wapi_set_last_path_error_from_errno (NULL, utf8_name);
-       g_free (utf8_name);
-       return FALSE;
-}
-
-/**
- * RemoveDirectory:
- * @name: a pointer to a NULL-terminated unicode string, that names
- * the directory to be removed.
- *
- * Removes directory @name
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean RemoveDirectory (const gunichar2 *name)
-{
-       gchar *utf8_name;
-       int result;
-       
-       if (name == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
-               SetLastError (ERROR_INVALID_NAME);
-               return(FALSE);
-       }
-
-       utf8_name = mono_unicode_to_external (name);
-       if (utf8_name == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-               
-               SetLastError (ERROR_INVALID_NAME);
-               return FALSE;
-       }
-
-       result = _wapi_rmdir (utf8_name);
-       if (result == -1) {
-               _wapi_set_last_path_error_from_errno (NULL, utf8_name);
-               g_free (utf8_name);
-               
-               return(FALSE);
-       }
-       g_free (utf8_name);
-
-       return(TRUE);
-}
-
-/**
- * GetFileAttributes:
- * @name: a pointer to a NULL-terminated unicode filename.
- *
- * Gets the attributes for @name;
- *
- * Return value: %INVALID_FILE_ATTRIBUTES on failure
- */
-guint32 GetFileAttributes (const gunichar2 *name)
-{
-       gchar *utf8_name;
-       struct stat buf, linkbuf;
-       int result;
-       guint32 ret;
-       
-       if (name == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
-               SetLastError (ERROR_INVALID_NAME);
-               return(FALSE);
-       }
-       
-       utf8_name = mono_unicode_to_external (name);
-       if (utf8_name == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return (INVALID_FILE_ATTRIBUTES);
-       }
-
-       result = _wapi_stat (utf8_name, &buf);
-       if (result == -1 && errno == ENOENT) {
-               /* Might be a dangling symlink... */
-               result = _wapi_lstat (utf8_name, &buf);
-       }
-
-       if (result != 0) {
-               _wapi_set_last_path_error_from_errno (NULL, utf8_name);
-               g_free (utf8_name);
-               return (INVALID_FILE_ATTRIBUTES);
-       }
-
-#ifndef __native_client__
-       result = _wapi_lstat (utf8_name, &linkbuf);
-       if (result != 0) {
-               _wapi_set_last_path_error_from_errno (NULL, utf8_name);
-               g_free (utf8_name);
-               return (INVALID_FILE_ATTRIBUTES);
-       }
-#endif
-       
-#ifdef __native_client__
-       ret = _wapi_stat_to_file_attributes (utf8_name, &buf, NULL);
-#else
-       ret = _wapi_stat_to_file_attributes (utf8_name, &buf, &linkbuf);
-#endif
-       
-       g_free (utf8_name);
-
-       return(ret);
-}
-
-/**
- * GetFileAttributesEx:
- * @name: a pointer to a NULL-terminated unicode filename.
- * @level: must be GetFileExInfoStandard
- * @info: pointer to a WapiFileAttributesData structure
- *
- * Gets attributes, size and filetimes for @name;
- *
- * Return value: %TRUE on success, %FALSE on failure
- */
-gboolean GetFileAttributesEx (const gunichar2 *name, WapiGetFileExInfoLevels level, gpointer info)
-{
-       gchar *utf8_name;
-       WapiFileAttributesData *data;
-
-       struct stat buf, linkbuf;
-       time_t create_time;
-       int result;
-       
-       if (level != GetFileExInfoStandard) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: info level %d not supported.", __func__,
-                          level);
-
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return FALSE;
-       }
-       
-       if (name == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
-               SetLastError (ERROR_INVALID_NAME);
-               return(FALSE);
-       }
-
-       utf8_name = mono_unicode_to_external (name);
-       if (utf8_name == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return FALSE;
-       }
-
-       result = _wapi_stat (utf8_name, &buf);
-       if (result == -1 && errno == ENOENT) {
-               /* Might be a dangling symlink... */
-               result = _wapi_lstat (utf8_name, &buf);
-       }
-       
-       if (result != 0) {
-               _wapi_set_last_path_error_from_errno (NULL, utf8_name);
-               g_free (utf8_name);
-               return FALSE;
-       }
-
-       result = _wapi_lstat (utf8_name, &linkbuf);
-       if (result != 0) {
-               _wapi_set_last_path_error_from_errno (NULL, utf8_name);
-               g_free (utf8_name);
-               return(FALSE);
-       }
-
-       /* fill data block */
-
-       data = (WapiFileAttributesData *)info;
-
-       if (buf.st_mtime < buf.st_ctime)
-               create_time = buf.st_mtime;
-       else
-               create_time = buf.st_ctime;
-       
-       data->dwFileAttributes = _wapi_stat_to_file_attributes (utf8_name,
-                                                               &buf,
-                                                               &linkbuf);
-
-       g_free (utf8_name);
-
-       time_t_to_filetime (create_time, &data->ftCreationTime);
-       time_t_to_filetime (buf.st_atime, &data->ftLastAccessTime);
-       time_t_to_filetime (buf.st_mtime, &data->ftLastWriteTime);
-
-       if (data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-               data->nFileSizeHigh = 0;
-               data->nFileSizeLow = 0;
-       }
-       else {
-               data->nFileSizeHigh = buf.st_size >> 32;
-               data->nFileSizeLow = buf.st_size & 0xFFFFFFFF;
-       }
-
-       return TRUE;
-}
-
-/**
- * SetFileAttributes
- * @name: name of file
- * @attrs: attributes to set
- *
- * Changes the attributes on a named file.
- *
- * Return value: %TRUE on success, %FALSE on failure.
- */
-extern gboolean SetFileAttributes (const gunichar2 *name, guint32 attrs)
-{
-       /* FIXME: think of something clever to do on unix */
-       gchar *utf8_name;
-       struct stat buf;
-       int result;
-
-       /*
-        * Currently we only handle one *internal* case, with a value that is
-        * not standard: 0x80000000, which means `set executable bit'
-        */
-       
-       if (name == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
-               SetLastError (ERROR_INVALID_NAME);
-               return(FALSE);
-       }
-
-       utf8_name = mono_unicode_to_external (name);
-       if (utf8_name == NULL) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
-               SetLastError (ERROR_INVALID_NAME);
-               return FALSE;
-       }
-
-       result = _wapi_stat (utf8_name, &buf);
-       if (result == -1 && errno == ENOENT) {
-               /* Might be a dangling symlink... */
-               result = _wapi_lstat (utf8_name, &buf);
-       }
-
-       if (result != 0) {
-               _wapi_set_last_path_error_from_errno (NULL, utf8_name);
-               g_free (utf8_name);
-               return FALSE;
-       }
-
-       /* Contrary to the documentation, ms allows NORMAL to be
-        * specified along with other attributes, so dont bother to
-        * catch that case here.
-        */
-       if (attrs & FILE_ATTRIBUTE_READONLY) {
-               result = _wapi_chmod (utf8_name, buf.st_mode & ~(S_IWUSR | S_IWOTH | S_IWGRP));
-       } else {
-               result = _wapi_chmod (utf8_name, buf.st_mode | S_IWUSR);
-       }
-
-       /* Ignore the other attributes for now */
-
-       if (attrs & 0x80000000){
-               mode_t exec_mask = 0;
-
-               if ((buf.st_mode & S_IRUSR) != 0)
-                       exec_mask |= S_IXUSR;
-
-               if ((buf.st_mode & S_IRGRP) != 0)
-                       exec_mask |= S_IXGRP;
-
-               if ((buf.st_mode & S_IROTH) != 0)
-                       exec_mask |= S_IXOTH;
-
-               result = chmod (utf8_name, buf.st_mode | exec_mask);
-       }
-       /* Don't bother to reset executable (might need to change this
-        * policy)
-        */
-       
-       g_free (utf8_name);
-
-       return(TRUE);
-}
-
-/**
- * GetCurrentDirectory
- * @length: size of the buffer
- * @buffer: pointer to buffer that recieves path
- *
- * Retrieves the current directory for the current process.
- *
- * Return value: number of characters in buffer on success, zero on failure
- */
-extern guint32 GetCurrentDirectory (guint32 length, gunichar2 *buffer)
-{
-       gunichar2 *utf16_path;
-       glong count;
-       gsize bytes;
-
-#ifdef __native_client__
-       gchar *path = g_get_current_dir ();
-       if (length < strlen(path) + 1 || path == NULL)
-               return 0;
-       memcpy (buffer, path, strlen(path) + 1);
-#else
-       if (getcwd ((char*)buffer, length) == NULL) {
-               if (errno == ERANGE) { /*buffer length is not big enough */ 
-                       gchar *path = g_get_current_dir (); /*FIXME g_get_current_dir doesn't work with broken paths and calling it just to know the path length is silly*/
-                       if (path == NULL)
-                               return 0;
-                       utf16_path = mono_unicode_from_external (path, &bytes);
-                       g_free (utf16_path);
-                       g_free (path);
-                       return (bytes/2)+1;
-               }
-               _wapi_set_last_error_from_errno ();
-               return 0;
-       }
-#endif
-
-       utf16_path = mono_unicode_from_external ((gchar*)buffer, &bytes);
-       count = (bytes/2)+1;
-       g_assert (count <= length); /*getcwd must have failed before with ERANGE*/
-
-       /* Add the terminator */
-       memset (buffer, '\0', bytes+2);
-       memcpy (buffer, utf16_path, bytes);
-       
-       g_free (utf16_path);
-
-       return count;
-}
-
-/**
- * SetCurrentDirectory
- * @path: path to new directory
- *
- * Changes the directory path for the current process.
- *
- * Return value: %TRUE on success, %FALSE on failure.
- */
-extern gboolean SetCurrentDirectory (const gunichar2 *path)
-{
-       gchar *utf8_path;
-       gboolean result;
-
-       if (path == NULL) {
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return(FALSE);
-       }
-       
-       utf8_path = mono_unicode_to_external (path);
-       if (_wapi_chdir (utf8_path) != 0) {
-               _wapi_set_last_error_from_errno ();
-               result = FALSE;
-       }
-       else
-               result = TRUE;
-
-       g_free (utf8_path);
-       return result;
-}
-
-gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe,
-                    WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 size)
-{
-       struct _WapiHandle_file pipe_read_handle = {0};
-       struct _WapiHandle_file pipe_write_handle = {0};
-       gpointer read_handle;
-       gpointer write_handle;
-       int filedes[2];
-       int ret;
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating pipe", __func__);
-
-       ret=pipe (filedes);
-       if(ret==-1) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error creating pipe: %s", __func__,
-                          strerror (errno));
-               
-               _wapi_set_last_error_from_errno ();
-               return(FALSE);
-       }
-
-       if (filedes[0] >= mono_w32handle_fd_reserve ||
-           filedes[1] >= mono_w32handle_fd_reserve) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
-
-               SetLastError (ERROR_TOO_MANY_OPEN_FILES);
-               
-               close (filedes[0]);
-               close (filedes[1]);
-               
-               return(FALSE);
-       }
-       
-       /* filedes[0] is open for reading, filedes[1] for writing */
-
-       pipe_read_handle.fd = filedes [0];
-       pipe_read_handle.fileaccess = GENERIC_READ;
-       read_handle = mono_w32handle_new_fd (MONO_W32HANDLE_PIPE, filedes[0],
-                                          &pipe_read_handle);
-       if (read_handle == INVALID_HANDLE_VALUE) {
-               g_warning ("%s: error creating pipe read handle", __func__);
-               close (filedes[0]);
-               close (filedes[1]);
-               SetLastError (ERROR_GEN_FAILURE);
-               
-               return(FALSE);
-       }
-       
-       pipe_write_handle.fd = filedes [1];
-       pipe_write_handle.fileaccess = GENERIC_WRITE;
-       write_handle = mono_w32handle_new_fd (MONO_W32HANDLE_PIPE, filedes[1],
-                                           &pipe_write_handle);
-       if (write_handle == INVALID_HANDLE_VALUE) {
-               g_warning ("%s: error creating pipe write handle", __func__);
-               mono_w32handle_unref (read_handle);
-               
-               close (filedes[0]);
-               close (filedes[1]);
-               SetLastError (ERROR_GEN_FAILURE);
-               
-               return(FALSE);
-       }
-       
-       *readpipe = read_handle;
-       *writepipe = write_handle;
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning pipe: read handle %p, write handle %p",
-                  __func__, read_handle, write_handle);
-
-       return(TRUE);
-}
-
-#ifdef HAVE_GETFSSTAT
-/* Darwin has getfsstat */
-gint32 GetLogicalDriveStrings (guint32 len, gunichar2 *buf)
-{
-       struct statfs *stats;
-       int size, n, i;
-       gunichar2 *dir;
-       glong length, total = 0;
-       
-       n = getfsstat (NULL, 0, MNT_NOWAIT);
-       if (n == -1)
-               return 0;
-       size = n * sizeof (struct statfs);
-       stats = (struct statfs *) g_malloc (size);
-       if (stats == NULL)
-               return 0;
-       if (getfsstat (stats, size, MNT_NOWAIT) == -1){
-               g_free (stats);
-               return 0;
-       }
-       for (i = 0; i < n; i++){
-               dir = g_utf8_to_utf16 (stats [i].f_mntonname, -1, NULL, &length, NULL);
-               if (total + length < len){
-                       memcpy (buf + total, dir, sizeof (gunichar2) * length);
-                       buf [total+length] = 0;
-               } 
-               g_free (dir);
-               total += length + 1;
-       }
-       if (total < len)
-               buf [total] = 0;
-       total++;
-       g_free (stats);
-       return total;
-}
-#else
-/* In-place octal sequence replacement */
-static void
-unescape_octal (gchar *str)
-{
-       gchar *rptr;
-       gchar *wptr;
-
-       if (str == NULL)
-               return;
-
-       rptr = wptr = str;
-       while (*rptr != '\0') {
-               if (*rptr == '\\') {
-                       char c;
-                       rptr++;
-                       c = (*(rptr++) - '0') << 6;
-                       c += (*(rptr++) - '0') << 3;
-                       c += *(rptr++) - '0';
-                       *wptr++ = c;
-               } else if (wptr != rptr) {
-                       *wptr++ = *rptr++;
-               } else {
-                       rptr++; wptr++;
-               }
-       }
-       *wptr = '\0';
-}
-static gint32 GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf);
-
-#if __linux__
-#define GET_LOGICAL_DRIVE_STRINGS_BUFFER 512
-#define GET_LOGICAL_DRIVE_STRINGS_MOUNTPOINT_BUFFER 512
-#define GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER 64
-
-typedef struct 
-{
-       glong total;
-       guint32 buffer_index;
-       guint32 mountpoint_index;
-       guint32 field_number;
-       guint32 allocated_size;
-       guint32 fsname_index;
-       guint32 fstype_index;
-       gchar mountpoint [GET_LOGICAL_DRIVE_STRINGS_MOUNTPOINT_BUFFER + 1];
-       gchar *mountpoint_allocated;
-       gchar buffer [GET_LOGICAL_DRIVE_STRINGS_BUFFER];
-       gchar fsname [GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER + 1];
-       gchar fstype [GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER + 1];
-       ssize_t nbytes;
-       gchar delimiter;
-       gboolean check_mount_source;
-} LinuxMountInfoParseState;
-
-static gboolean GetLogicalDriveStrings_Mounts (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state);
-static gboolean GetLogicalDriveStrings_MountInfo (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state);
-static void append_to_mountpoint (LinuxMountInfoParseState *state);
-static gboolean add_drive_string (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state);
-
-gint32 GetLogicalDriveStrings (guint32 len, gunichar2 *buf)
-{
-       int fd;
-       gint32 ret = 0;
-       LinuxMountInfoParseState state;
-       gboolean (*parser)(guint32, gunichar2*, LinuxMountInfoParseState*) = NULL;
-
-       memset (buf, 0, len * sizeof (gunichar2));
-       fd = open ("/proc/self/mountinfo", O_RDONLY);
-       if (fd != -1)
-               parser = GetLogicalDriveStrings_MountInfo;
-       else {
-               fd = open ("/proc/mounts", O_RDONLY);
-               if (fd != -1)
-                       parser = GetLogicalDriveStrings_Mounts;
-       }
-
-       if (!parser) {
-               ret = GetLogicalDriveStrings_Mtab (len, buf);
-               goto done_and_out;
-       }
-
-       memset (&state, 0, sizeof (LinuxMountInfoParseState));
-       state.field_number = 1;
-       state.delimiter = ' ';
-
-       while ((state.nbytes = read (fd, state.buffer, GET_LOGICAL_DRIVE_STRINGS_BUFFER)) > 0) {
-               state.buffer_index = 0;
-
-               while ((*parser)(len, buf, &state)) {
-                       if (state.buffer [state.buffer_index] == '\n') {
-                               gboolean quit = add_drive_string (len, buf, &state);
-                               state.field_number = 1;
-                               state.buffer_index++;
-                               if (state.mountpoint_allocated) {
-                                       g_free (state.mountpoint_allocated);
-                                       state.mountpoint_allocated = NULL;
-                               }
-                               if (quit) {
-                                       ret = state.total;
-                                       goto done_and_out;
-                               }
-                       }
-               }
-       };
-       ret = state.total;
-
-  done_and_out:
-       if (fd != -1)
-               close (fd);
-       return ret;
-}
-
-static gboolean GetLogicalDriveStrings_Mounts (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state)
-{
-       gchar *ptr;
-
-       if (state->field_number == 1)
-               state->check_mount_source = TRUE;
-
-       while (state->buffer_index < (guint32)state->nbytes) {
-               if (state->buffer [state->buffer_index] == state->delimiter) {
-                       state->field_number++;
-                       switch (state->field_number) {
-                               case 2:
-                                       state->mountpoint_index = 0;
-                                       break;
-
-                               case 3:
-                                       if (state->mountpoint_allocated)
-                                               state->mountpoint_allocated [state->mountpoint_index] = 0;
-                                       else
-                                               state->mountpoint [state->mountpoint_index] = 0;
-                                       break;
-
-                               default:
-                                       ptr = (gchar*)memchr (state->buffer + state->buffer_index, '\n', GET_LOGICAL_DRIVE_STRINGS_BUFFER - state->buffer_index);
-                                       if (ptr)
-                                               state->buffer_index = (ptr - (gchar*)state->buffer) - 1;
-                                       else
-                                               state->buffer_index = state->nbytes;
-                                       return TRUE;
-                       }
-                       state->buffer_index++;
-                       continue;
-               } else if (state->buffer [state->buffer_index] == '\n')
-                       return TRUE;
-
-               switch (state->field_number) {
-                       case 1:
-                               if (state->check_mount_source) {
-                                       if (state->fsname_index == 0 && state->buffer [state->buffer_index] == '/') {
-                                               /* We can ignore the rest, it's a device
-                                                * path */
-                                               state->check_mount_source = FALSE;
-                                               state->fsname [state->fsname_index++] = '/';
-                                               break;
-                                       }
-                                       if (state->fsname_index < GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER)
-                                               state->fsname [state->fsname_index++] = state->buffer [state->buffer_index];
-                               }
-                               break;
-
-                       case 2:
-                               append_to_mountpoint (state);
-                               break;
-
-                       case 3:
-                               if (state->fstype_index < GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER)
-                                       state->fstype [state->fstype_index++] = state->buffer [state->buffer_index];
-                               break;
-               }
-
-               state->buffer_index++;
-       }
-
-       return FALSE;
-}
-
-static gboolean GetLogicalDriveStrings_MountInfo (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state)
-{
-       while (state->buffer_index < (guint32)state->nbytes) {
-               if (state->buffer [state->buffer_index] == state->delimiter) {
-                       state->field_number++;
-                       switch (state->field_number) {
-                               case 5:
-                                       state->mountpoint_index = 0;
-                                       break;
-
-                               case 6:
-                                       if (state->mountpoint_allocated)
-                                               state->mountpoint_allocated [state->mountpoint_index] = 0;
-                                       else
-                                               state->mountpoint [state->mountpoint_index] = 0;
-                                       break;
-
-                               case 7:
-                                       state->delimiter = '-';
-                                       break;
-
-                               case 8:
-                                       state->delimiter = ' ';
-                                       break;
-
-                               case 10:
-                                       state->check_mount_source = TRUE;
-                                       break;
-                       }
-                       state->buffer_index++;
-                       continue;
-               } else if (state->buffer [state->buffer_index] == '\n')
-                       return TRUE;
-
-               switch (state->field_number) {
-                       case 5:
-                               append_to_mountpoint (state);
-                               break;
-
-                       case 9:
-                               if (state->fstype_index < GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER)
-                                       state->fstype [state->fstype_index++] = state->buffer [state->buffer_index];
-                               break;
-
-                       case 10:
-                               if (state->check_mount_source) {
-                                       if (state->fsname_index == 0 && state->buffer [state->buffer_index] == '/') {
-                                               /* We can ignore the rest, it's a device
-                                                * path */
-                                               state->check_mount_source = FALSE;
-                                               state->fsname [state->fsname_index++] = '/';
-                                               break;
-                                       }
-                                       if (state->fsname_index < GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER)
-                                               state->fsname [state->fsname_index++] = state->buffer [state->buffer_index];
-                               }
-                               break;
-               }
-
-               state->buffer_index++;
-       }
-
-       return FALSE;
-}
-
-static void
-append_to_mountpoint (LinuxMountInfoParseState *state)
-{
-       gchar ch = state->buffer [state->buffer_index];
-       if (state->mountpoint_allocated) {
-               if (state->mountpoint_index >= state->allocated_size) {
-                       guint32 newsize = (state->allocated_size << 1) + 1;
-                       gchar *newbuf = (gchar *)g_malloc0 (newsize * sizeof (gchar));
-
-                       memcpy (newbuf, state->mountpoint_allocated, state->mountpoint_index);
-                       g_free (state->mountpoint_allocated);
-                       state->mountpoint_allocated = newbuf;
-                       state->allocated_size = newsize;
-               }
-               state->mountpoint_allocated [state->mountpoint_index++] = ch;
-       } else {
-               if (state->mountpoint_index >= GET_LOGICAL_DRIVE_STRINGS_MOUNTPOINT_BUFFER) {
-                       state->allocated_size = (state->mountpoint_index << 1) + 1;
-                       state->mountpoint_allocated = (gchar *)g_malloc0 (state->allocated_size * sizeof (gchar));
-                       memcpy (state->mountpoint_allocated, state->mountpoint, state->mountpoint_index);
-                       state->mountpoint_allocated [state->mountpoint_index++] = ch;
-               } else
-                       state->mountpoint [state->mountpoint_index++] = ch;
-       }
-}
-
-static gboolean
-add_drive_string (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state)
-{
-       gboolean quit = FALSE;
-       gboolean ignore_entry;
-
-       if (state->fsname_index == 1 && state->fsname [0] == '/')
-               ignore_entry = FALSE;
-       else if (memcmp ("overlay", state->fsname, state->fsname_index) == 0 ||
-               memcmp ("aufs", state->fstype, state->fstype_index) == 0) {
-               /* Don't ignore overlayfs and aufs - these might be used on Docker
-                * (https://bugzilla.xamarin.com/show_bug.cgi?id=31021) */
-               ignore_entry = FALSE;
-       } else if (state->fsname_index == 0 || memcmp ("none", state->fsname, state->fsname_index) == 0) {
-               ignore_entry = TRUE;
-       } else if (state->fstype_index >= 5 && memcmp ("fuse.", state->fstype, 5) == 0) {
-               /* Ignore GNOME's gvfs */
-               if (state->fstype_index == 21 && memcmp ("fuse.gvfs-fuse-daemon", state->fstype, state->fstype_index) == 0)
-                       ignore_entry = TRUE;
-               else
-                       ignore_entry = FALSE;
-       } else if (state->fstype_index == 3 && memcmp ("nfs", state->fstype, state->fstype_index) == 0)
-               ignore_entry = FALSE;
-       else
-               ignore_entry = TRUE;
-
-       if (!ignore_entry) {
-               gunichar2 *dir;
-               glong length;
-               gchar *mountpoint = state->mountpoint_allocated ? state->mountpoint_allocated : state->mountpoint;
-
-               unescape_octal (mountpoint);
-               dir = g_utf8_to_utf16 (mountpoint, -1, NULL, &length, NULL);
-               if (state->total + length + 1 > len) {
-                       quit = TRUE;
-                       state->total = len * 2;
-               } else {
-                       length++;
-                       memcpy (buf + state->total, dir, sizeof (gunichar2) * length);
-                       state->total += length;
-               }
-               g_free (dir);
-       }
-       state->fsname_index = 0;
-       state->fstype_index = 0;
-
-       return quit;
-}
-#else
-gint32
-GetLogicalDriveStrings (guint32 len, gunichar2 *buf)
-{
-       return GetLogicalDriveStrings_Mtab (len, buf);
-}
-#endif
-static gint32
-GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf)
-{
-       FILE *fp;
-       gunichar2 *ptr, *dir;
-       glong length, total = 0;
-       gchar buffer [512];
-       gchar **splitted;
-
-       memset (buf, 0, sizeof (gunichar2) * (len + 1)); 
-       buf [0] = '/';
-       buf [1] = 0;
-       buf [2] = 0;
-
-       /* Sigh, mntent and friends don't work well.
-        * It stops on the first line that doesn't begin with a '/'.
-        * (linux 2.6.5, libc 2.3.2.ds1-12) - Gonz */
-       fp = fopen ("/etc/mtab", "rt");
-       if (fp == NULL) {
-               fp = fopen ("/etc/mnttab", "rt");
-               if (fp == NULL)
-                       return 1;
-       }
-
-       ptr = buf;
-       while (fgets (buffer, 512, fp) != NULL) {
-               if (*buffer != '/')
-                       continue;
-
-               splitted = g_strsplit (buffer, " ", 0);
-               if (!*splitted || !*(splitted + 1)) {
-                       g_strfreev (splitted);
-                       continue;
-               }
-
-               unescape_octal (*(splitted + 1));
-               dir = g_utf8_to_utf16 (*(splitted + 1), -1, NULL, &length, NULL);
-               g_strfreev (splitted);
-               if (total + length + 1 > len) {
-                       fclose (fp);
-                       g_free (dir);
-                       return len * 2; /* guess */
-               }
-
-               memcpy (ptr + total, dir, sizeof (gunichar2) * length);
-               g_free (dir);
-               total += length + 1;
-       }
-
-       fclose (fp);
-       return total;
-/* Commented out, does not work with my mtab!!! - Gonz */
-#ifdef NOTENABLED /* HAVE_MNTENT_H */
-{
-       FILE *fp;
-       struct mntent *mnt;
-       gunichar2 *ptr, *dir;
-       glong len, total = 0;
-       
-
-       fp = setmntent ("/etc/mtab", "rt");
-       if (fp == NULL) {
-               fp = setmntent ("/etc/mnttab", "rt");
-               if (fp == NULL)
-                       return;
-       }
-
-       ptr = buf;
-       while ((mnt = getmntent (fp)) != NULL) {
-               g_print ("GOT %s\n", mnt->mnt_dir);
-               dir = g_utf8_to_utf16 (mnt->mnt_dir, &len, NULL, NULL, NULL);
-               if (total + len + 1 > len) {
-                       return len * 2; /* guess */
-               }
-
-               memcpy (ptr + total, dir, sizeof (gunichar2) * len);
-               g_free (dir);
-               total += len + 1;
-       }
-
-       endmntent (fp);
-       return total;
-}
-#endif
-}
-#endif
-
-#if defined(HAVE_STATVFS) || defined(HAVE_STATFS)
-gboolean GetDiskFreeSpaceEx(const gunichar2 *path_name, ULARGE_INTEGER *free_bytes_avail,
-                           ULARGE_INTEGER *total_number_of_bytes,
-                           ULARGE_INTEGER *total_number_of_free_bytes)
-{
-#ifdef HAVE_STATVFS
-       struct statvfs fsstat;
-#elif defined(HAVE_STATFS)
-       struct statfs fsstat;
-#endif
-       gboolean isreadonly;
-       gchar *utf8_path_name;
-       int ret;
-       unsigned long block_size;
-
-       if (path_name == NULL) {
-               utf8_path_name = g_strdup (g_get_current_dir());
-               if (utf8_path_name == NULL) {
-                       SetLastError (ERROR_DIRECTORY);
-                       return(FALSE);
-               }
-       }
-       else {
-               utf8_path_name = mono_unicode_to_external (path_name);
-               if (utf8_path_name == NULL) {
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
-                       SetLastError (ERROR_INVALID_NAME);
-                       return(FALSE);
-               }
-       }
-
-       do {
-#ifdef HAVE_STATVFS
-               ret = statvfs (utf8_path_name, &fsstat);
-               isreadonly = ((fsstat.f_flag & ST_RDONLY) == ST_RDONLY);
-               block_size = fsstat.f_frsize;
-#elif defined(HAVE_STATFS)
-               ret = statfs (utf8_path_name, &fsstat);
-#if defined (MNT_RDONLY)
-               isreadonly = ((fsstat.f_flags & MNT_RDONLY) == MNT_RDONLY);
-#elif defined (MS_RDONLY)
-               isreadonly = ((fsstat.f_flags & MS_RDONLY) == MS_RDONLY);
-#endif
-               block_size = fsstat.f_bsize;
-#endif
-       } while(ret == -1 && errno == EINTR);
-
-       g_free(utf8_path_name);
-
-       if (ret == -1) {
-               _wapi_set_last_error_from_errno ();
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: statvfs failed: %s", __func__, strerror (errno));
-               return(FALSE);
-       }
-
-       /* total number of free bytes for non-root */
-       if (free_bytes_avail != NULL) {
-               if (isreadonly) {
-                       free_bytes_avail->QuadPart = 0;
-               }
-               else {
-                       free_bytes_avail->QuadPart = block_size * (guint64)fsstat.f_bavail;
-               }
-       }
-
-       /* total number of bytes available for non-root */
-       if (total_number_of_bytes != NULL) {
-               total_number_of_bytes->QuadPart = block_size * (guint64)fsstat.f_blocks;
-       }
-
-       /* total number of bytes available for root */
-       if (total_number_of_free_bytes != NULL) {
-               if (isreadonly) {
-                       total_number_of_free_bytes->QuadPart = 0;
-               }
-               else {
-                       total_number_of_free_bytes->QuadPart = block_size * (guint64)fsstat.f_bfree;
-               }
-       }
-       
-       return(TRUE);
-}
-#else
-gboolean GetDiskFreeSpaceEx(const gunichar2 *path_name, ULARGE_INTEGER *free_bytes_avail,
-                           ULARGE_INTEGER *total_number_of_bytes,
-                           ULARGE_INTEGER *total_number_of_free_bytes)
-{
-       if (free_bytes_avail != NULL) {
-               free_bytes_avail->QuadPart = (guint64) -1;
-       }
-
-       if (total_number_of_bytes != NULL) {
-               total_number_of_bytes->QuadPart = (guint64) -1;
-       }
-
-       if (total_number_of_free_bytes != NULL) {
-               total_number_of_free_bytes->QuadPart = (guint64) -1;
-       }
-
-       return(TRUE);
-}
-#endif
-
-/*
- * General Unix support
- */
-typedef struct {
-       guint32 drive_type;
-#if __linux__
-       const long fstypeid;
-#endif
-       const gchar* fstype;
-} _wapi_drive_type;
-
-static _wapi_drive_type _wapi_drive_types[] = {
-#if PLATFORM_MACOSX
-       { DRIVE_REMOTE, "afp" },
-       { DRIVE_REMOTE, "autofs" },
-       { DRIVE_CDROM, "cddafs" },
-       { DRIVE_CDROM, "cd9660" },
-       { DRIVE_RAMDISK, "devfs" },
-       { DRIVE_FIXED, "exfat" },
-       { DRIVE_RAMDISK, "fdesc" },
-       { DRIVE_REMOTE, "ftp" },
-       { DRIVE_FIXED, "hfs" },
-       { DRIVE_FIXED, "msdos" },
-       { DRIVE_REMOTE, "nfs" },
-       { DRIVE_FIXED, "ntfs" },
-       { DRIVE_REMOTE, "smbfs" },
-       { DRIVE_FIXED, "udf" },
-       { DRIVE_REMOTE, "webdav" },
-       { DRIVE_UNKNOWN, NULL }
-#elif __linux__
-       { DRIVE_FIXED, ADFS_SUPER_MAGIC, "adfs"},
-       { DRIVE_FIXED, AFFS_SUPER_MAGIC, "affs"},
-       { DRIVE_REMOTE, AFS_SUPER_MAGIC, "afs"},
-       { DRIVE_RAMDISK, AUTOFS_SUPER_MAGIC, "autofs"},
-       { DRIVE_RAMDISK, AUTOFS_SBI_MAGIC, "autofs4"},
-       { DRIVE_REMOTE, CODA_SUPER_MAGIC, "coda" },
-       { DRIVE_RAMDISK, CRAMFS_MAGIC, "cramfs"},
-       { DRIVE_RAMDISK, CRAMFS_MAGIC_WEND, "cramfs"},
-       { DRIVE_REMOTE, CIFS_MAGIC_NUMBER, "cifs"},
-       { DRIVE_RAMDISK, DEBUGFS_MAGIC, "debugfs"},
-       { DRIVE_RAMDISK, SYSFS_MAGIC, "sysfs"},
-       { DRIVE_RAMDISK, SECURITYFS_MAGIC, "securityfs"},
-       { DRIVE_RAMDISK, SELINUX_MAGIC, "selinuxfs"},
-       { DRIVE_RAMDISK, RAMFS_MAGIC, "ramfs"},
-       { DRIVE_FIXED, SQUASHFS_MAGIC, "squashfs"},
-       { DRIVE_FIXED, EFS_SUPER_MAGIC, "efs"},
-       { DRIVE_FIXED, EXT2_SUPER_MAGIC, "ext"},
-       { DRIVE_FIXED, EXT3_SUPER_MAGIC, "ext"},
-       { DRIVE_FIXED, EXT4_SUPER_MAGIC, "ext"},
-       { DRIVE_REMOTE, XENFS_SUPER_MAGIC, "xenfs"},
-       { DRIVE_FIXED, BTRFS_SUPER_MAGIC, "btrfs"},
-       { DRIVE_FIXED, HFS_SUPER_MAGIC, "hfs"},
-       { DRIVE_FIXED, HFSPLUS_SUPER_MAGIC, "hfsplus"},
-       { DRIVE_FIXED, HPFS_SUPER_MAGIC, "hpfs"},
-       { DRIVE_RAMDISK, HUGETLBFS_MAGIC, "hugetlbfs"},
-       { DRIVE_CDROM, ISOFS_SUPER_MAGIC, "iso"},
-       { DRIVE_FIXED, JFFS2_SUPER_MAGIC, "jffs2"},
-       { DRIVE_RAMDISK, ANON_INODE_FS_MAGIC, "anon_inode"},
-       { DRIVE_FIXED, JFS_SUPER_MAGIC, "jfs"},
-       { DRIVE_FIXED, MINIX_SUPER_MAGIC, "minix"},
-       { DRIVE_FIXED, MINIX_SUPER_MAGIC2, "minix v2"},
-       { DRIVE_FIXED, MINIX2_SUPER_MAGIC, "minix2"},
-       { DRIVE_FIXED, MINIX2_SUPER_MAGIC2, "minix2 v2"},
-       { DRIVE_FIXED, MINIX3_SUPER_MAGIC, "minix3"},
-       { DRIVE_FIXED, MSDOS_SUPER_MAGIC, "msdos"},
-       { DRIVE_REMOTE, NCP_SUPER_MAGIC, "ncp"},
-       { DRIVE_REMOTE, NFS_SUPER_MAGIC, "nfs"},
-       { DRIVE_FIXED, NTFS_SB_MAGIC, "ntfs"},
-       { DRIVE_RAMDISK, OPENPROM_SUPER_MAGIC, "openpromfs"},
-       { DRIVE_RAMDISK, PROC_SUPER_MAGIC, "proc"},
-       { DRIVE_FIXED, QNX4_SUPER_MAGIC, "qnx4"},
-       { DRIVE_FIXED, REISERFS_SUPER_MAGIC, "reiserfs"},
-       { DRIVE_RAMDISK, ROMFS_MAGIC, "romfs"},
-       { DRIVE_REMOTE, SMB_SUPER_MAGIC, "samba"},
-       { DRIVE_RAMDISK, CGROUP_SUPER_MAGIC, "cgroupfs"},
-       { DRIVE_RAMDISK, FUTEXFS_SUPER_MAGIC, "futexfs"},
-       { DRIVE_FIXED, SYSV2_SUPER_MAGIC, "sysv2"},
-       { DRIVE_FIXED, SYSV4_SUPER_MAGIC, "sysv4"},
-       { DRIVE_RAMDISK, TMPFS_MAGIC, "tmpfs"},
-       { DRIVE_RAMDISK, DEVPTS_SUPER_MAGIC, "devpts"},
-       { DRIVE_CDROM, UDF_SUPER_MAGIC, "udf"},
-       { DRIVE_FIXED, UFS_MAGIC, "ufs"},
-       { DRIVE_FIXED, UFS_MAGIC_BW, "ufs"},
-       { DRIVE_FIXED, UFS2_MAGIC, "ufs2"},
-       { DRIVE_FIXED, UFS_CIGAM, "ufs"},
-       { DRIVE_RAMDISK, USBDEVICE_SUPER_MAGIC, "usbdev"},
-       { DRIVE_FIXED, XENIX_SUPER_MAGIC, "xenix"},
-       { DRIVE_FIXED, XFS_SB_MAGIC, "xfs"},
-       { DRIVE_RAMDISK, FUSE_SUPER_MAGIC, "fuse"},
-       { DRIVE_FIXED, V9FS_MAGIC, "9p"},
-       { DRIVE_REMOTE, CEPH_SUPER_MAGIC, "ceph"},
-       { DRIVE_RAMDISK, CONFIGFS_MAGIC, "configfs"},
-       { DRIVE_RAMDISK, ECRYPTFS_SUPER_MAGIC, "eCryptfs"},
-       { DRIVE_FIXED, EXOFS_SUPER_MAGIC, "exofs"},
-       { DRIVE_FIXED, VXFS_SUPER_MAGIC, "vxfs"},
-       { DRIVE_FIXED, VXFS_OLT_MAGIC, "vxfs_olt"},
-       { DRIVE_REMOTE, GFS2_MAGIC, "gfs2"},
-       { DRIVE_FIXED, LOGFS_MAGIC_U32, "logfs"},
-       { DRIVE_FIXED, OCFS2_SUPER_MAGIC, "ocfs2"},
-       { DRIVE_FIXED, OMFS_MAGIC, "omfs"},
-       { DRIVE_FIXED, UBIFS_SUPER_MAGIC, "ubifs"},
-       { DRIVE_UNKNOWN, 0, NULL}
-#else
-       { DRIVE_RAMDISK, "ramfs"      },
-       { DRIVE_RAMDISK, "tmpfs"      },
-       { DRIVE_RAMDISK, "proc"       },
-       { DRIVE_RAMDISK, "sysfs"      },
-       { DRIVE_RAMDISK, "debugfs"    },
-       { DRIVE_RAMDISK, "devpts"     },
-       { DRIVE_RAMDISK, "securityfs" },
-       { DRIVE_CDROM,   "iso9660"    },
-       { DRIVE_FIXED,   "ext2"       },
-       { DRIVE_FIXED,   "ext3"       },
-       { DRIVE_FIXED,   "ext4"       },
-       { DRIVE_FIXED,   "sysv"       },
-       { DRIVE_FIXED,   "reiserfs"   },
-       { DRIVE_FIXED,   "ufs"        },
-       { DRIVE_FIXED,   "vfat"       },
-       { DRIVE_FIXED,   "msdos"      },
-       { DRIVE_FIXED,   "udf"        },
-       { DRIVE_FIXED,   "hfs"        },
-       { DRIVE_FIXED,   "hpfs"       },
-       { DRIVE_FIXED,   "qnx4"       },
-       { DRIVE_FIXED,   "ntfs"       },
-       { DRIVE_FIXED,   "ntfs-3g"    },
-       { DRIVE_REMOTE,  "smbfs"      },
-       { DRIVE_REMOTE,  "fuse"       },
-       { DRIVE_REMOTE,  "nfs"        },
-       { DRIVE_REMOTE,  "nfs4"       },
-       { DRIVE_REMOTE,  "cifs"       },
-       { DRIVE_REMOTE,  "ncpfs"      },
-       { DRIVE_REMOTE,  "coda"       },
-       { DRIVE_REMOTE,  "afs"        },
-       { DRIVE_UNKNOWN, NULL         }
-#endif
-};
-
-#if __linux__
-static guint32 _wapi_get_drive_type(long f_type)
-{
-       _wapi_drive_type *current;
-
-       current = &_wapi_drive_types[0];
-       while (current->drive_type != DRIVE_UNKNOWN) {
-               if (current->fstypeid == f_type)
-                       return current->drive_type;
-               current++;
-       }
-
-       return DRIVE_UNKNOWN;
-}
-#else
-static guint32 _wapi_get_drive_type(const gchar* fstype)
-{
-       _wapi_drive_type *current;
-
-       current = &_wapi_drive_types[0];
-       while (current->drive_type != DRIVE_UNKNOWN) {
-               if (strcmp (current->fstype, fstype) == 0)
-                       break;
-
-               current++;
-       }
-       
-       return current->drive_type;
-}
-#endif
-
-#if defined (PLATFORM_MACOSX) || defined (__linux__)
-static guint32
-GetDriveTypeFromPath (const char *utf8_root_path_name)
-{
-       struct statfs buf;
-       
-       if (statfs (utf8_root_path_name, &buf) == -1)
-               return DRIVE_UNKNOWN;
-#if PLATFORM_MACOSX
-       return _wapi_get_drive_type (buf.f_fstypename);
-#else
-       return _wapi_get_drive_type (buf.f_type);
-#endif
-}
-#else
-static guint32
-GetDriveTypeFromPath (const gchar *utf8_root_path_name)
-{
-       guint32 drive_type;
-       FILE *fp;
-       gchar buffer [512];
-       gchar **splitted;
-
-       fp = fopen ("/etc/mtab", "rt");
-       if (fp == NULL) {
-               fp = fopen ("/etc/mnttab", "rt");
-               if (fp == NULL) 
-                       return(DRIVE_UNKNOWN);
-       }
-
-       drive_type = DRIVE_NO_ROOT_DIR;
-       while (fgets (buffer, 512, fp) != NULL) {
-               splitted = g_strsplit (buffer, " ", 0);
-               if (!*splitted || !*(splitted + 1) || !*(splitted + 2)) {
-                       g_strfreev (splitted);
-                       continue;
-               }
-
-               /* compare given root_path_name with the one from mtab, 
-                 if length of utf8_root_path_name is zero it must be the root dir */
-               if (strcmp (*(splitted + 1), utf8_root_path_name) == 0 ||
-                   (strcmp (*(splitted + 1), "/") == 0 && strlen (utf8_root_path_name) == 0)) {
-                       drive_type = _wapi_get_drive_type (*(splitted + 2));
-                       /* it is possible this path might be mounted again with
-                          a known type...keep looking */
-                       if (drive_type != DRIVE_UNKNOWN) {
-                               g_strfreev (splitted);
-                               break;
-                       }
-               }
-
-               g_strfreev (splitted);
-       }
-
-       fclose (fp);
-       return drive_type;
-}
-#endif
-
-guint32 GetDriveType(const gunichar2 *root_path_name)
-{
-       gchar *utf8_root_path_name;
-       guint32 drive_type;
-
-       if (root_path_name == NULL) {
-               utf8_root_path_name = g_strdup (g_get_current_dir());
-               if (utf8_root_path_name == NULL) {
-                       return(DRIVE_NO_ROOT_DIR);
-               }
-       }
-       else {
-               utf8_root_path_name = mono_unicode_to_external (root_path_name);
-               if (utf8_root_path_name == NULL) {
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-                       return(DRIVE_NO_ROOT_DIR);
-               }
-               
-               /* strip trailing slash for compare below */
-               if (g_str_has_suffix(utf8_root_path_name, "/") && utf8_root_path_name [1] != 0) {
-                       utf8_root_path_name[strlen(utf8_root_path_name) - 1] = 0;
-               }
-       }
-       drive_type = GetDriveTypeFromPath (utf8_root_path_name);
-       g_free (utf8_root_path_name);
-
-       return (drive_type);
-}
-
-#if defined (PLATFORM_MACOSX) || defined (__linux__) || defined(PLATFORM_BSD) || defined(__native_client__) || defined(__FreeBSD_kernel__)
-static gchar*
-get_fstypename (gchar *utfpath)
-{
-#if defined (PLATFORM_MACOSX) || defined (__linux__)
-       struct statfs stat;
-#if __linux__
-       _wapi_drive_type *current;
-#endif
-       if (statfs (utfpath, &stat) == -1)
-               return NULL;
-#if PLATFORM_MACOSX
-       return g_strdup (stat.f_fstypename);
-#else
-       current = &_wapi_drive_types[0];
-       while (current->drive_type != DRIVE_UNKNOWN) {
-               if (stat.f_type == current->fstypeid)
-                       return g_strdup (current->fstype);
-               current++;
-       }
-       return NULL;
-#endif
-#else
-       return NULL;
-#endif
-}
-
-/* Linux has struct statfs which has a different layout */
-gboolean
-GetVolumeInformation (const gunichar2 *path, gunichar2 *volumename, int volumesize, int *outserial, int *maxcomp, int *fsflags, gunichar2 *fsbuffer, int fsbuffersize)
-{
-       gchar *utfpath;
-       gchar *fstypename;
-       gboolean status = FALSE;
-       glong len;
-       
-       // We only support getting the file system type
-       if (fsbuffer == NULL)
-               return 0;
-       
-       utfpath = mono_unicode_to_external (path);
-       if ((fstypename = get_fstypename (utfpath)) != NULL){
-               gunichar2 *ret = g_utf8_to_utf16 (fstypename, -1, NULL, &len, NULL);
-               if (ret != NULL && len < fsbuffersize){
-                       memcpy (fsbuffer, ret, len * sizeof (gunichar2));
-                       fsbuffer [len] = 0;
-                       status = TRUE;
-               }
-               if (ret != NULL)
-                       g_free (ret);
-               g_free (fstypename);
-       }
-       g_free (utfpath);
-       return status;
-}
-#endif
-
-void
-_wapi_io_init (void)
-{
-       mono_os_mutex_init (&stdhandle_mutex);
-       mono_os_mutex_init (&file_share_mutex);
-
-       mono_w32handle_register_ops (MONO_W32HANDLE_FILE,    &_wapi_file_ops);
-       mono_w32handle_register_ops (MONO_W32HANDLE_CONSOLE, &_wapi_console_ops);
-       mono_w32handle_register_ops (MONO_W32HANDLE_FIND,    &_wapi_find_ops);
-       mono_w32handle_register_ops (MONO_W32HANDLE_PIPE,    &_wapi_pipe_ops);
-
-/*     mono_w32handle_register_capabilities (MONO_W32HANDLE_FILE, */
-/*                                         MONO_W32HANDLE_CAP_WAIT); */
-/*     mono_w32handle_register_capabilities (MONO_W32HANDLE_CONSOLE, */
-/*                                         MONO_W32HANDLE_CAP_WAIT); */
-
-       if (g_getenv ("MONO_STRICT_IO_EMULATION"))
-               lock_while_writing = TRUE;
-}
-
-void
-_wapi_io_cleanup (void)
-{
-       mono_os_mutex_destroy (&file_share_mutex);
-
-       if (file_share_hash)
-               g_hash_table_destroy (file_share_hash);
-}
diff --git a/mono/io-layer/io.h b/mono/io-layer/io.h
deleted file mode 100644 (file)
index 6e518b6..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * io.h: File, console and find handles
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_IO_H_
-#define _WAPI_IO_H_
-
-#include <stdlib.h>
-
-#include "mono/io-layer/wapi.h"
-
-G_BEGIN_DECLS
-
-typedef struct _WapiSecurityAttributes WapiSecurityAttributes;
-
-struct _WapiSecurityAttributes 
-{
-       guint32 nLength;
-       gpointer lpSecurityDescriptor;
-       gboolean bInheritHandle;
-};
-
-typedef struct _WapiOverlapped WapiOverlapped;
-
-struct _WapiOverlapped
-{
-       guint32 Internal;
-       guint32 InternalHigh;
-       guint32 Offset;
-       guint32 OffsetHigh;
-       gpointer hEvent;
-       gpointer handle1;
-       gpointer handle2;
-};
-
-typedef void (*WapiOverlappedCB) (guint32 error, guint32 numbytes,
-                                 WapiOverlapped *overlapped);
-
-#define GENERIC_READ   0x80000000
-#define GENERIC_WRITE  0x40000000
-#define GENERIC_EXECUTE        0x20000000
-#define GENERIC_ALL    0x10000000
-
-#define FILE_SHARE_READ                0x00000001
-#define FILE_SHARE_WRITE       0x00000002
-#define FILE_SHARE_DELETE      0x00000004
-
-#define CREATE_NEW             1
-#define CREATE_ALWAYS          2
-#define OPEN_EXISTING          3
-#define OPEN_ALWAYS            4
-#define TRUNCATE_EXISTING      5
-
-
-#define FILE_ATTRIBUTE_READONLY                        0x00000001
-#define FILE_ATTRIBUTE_HIDDEN                  0x00000002
-#define FILE_ATTRIBUTE_SYSTEM                  0x00000004
-#define FILE_ATTRIBUTE_DIRECTORY               0x00000010
-#define FILE_ATTRIBUTE_ARCHIVE                 0x00000020
-#define FILE_ATTRIBUTE_ENCRYPTED               0x00000040
-#define FILE_ATTRIBUTE_NORMAL                  0x00000080
-#define FILE_ATTRIBUTE_TEMPORARY               0x00000100
-#define FILE_ATTRIBUTE_SPARSE_FILE             0x00000200
-#define FILE_ATTRIBUTE_REPARSE_POINT           0x00000400
-#define FILE_ATTRIBUTE_COMPRESSED              0x00000800
-#define FILE_ATTRIBUTE_OFFLINE                 0x00001000
-#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED     0x00002000
-#define FILE_FLAG_OPEN_NO_RECALL               0x00100000
-#define FILE_FLAG_OPEN_REPARSE_POINT           0x00200000
-#define FILE_FLAG_POSIX_SEMANTICS              0x01000000
-#define FILE_FLAG_BACKUP_SEMANTICS             0x02000000
-#define FILE_FLAG_DELETE_ON_CLOSE              0x04000000
-#define FILE_FLAG_SEQUENTIAL_SCAN              0x08000000
-#define FILE_FLAG_RANDOM_ACCESS                        0x10000000
-#define FILE_FLAG_NO_BUFFERING                 0x20000000
-#define FILE_FLAG_OVERLAPPED                   0x40000000
-#define FILE_FLAG_WRITE_THROUGH                        0x80000000
-
-#define REPLACEFILE_WRITE_THROUGH       0x00000001
-#define REPLACEFILE_IGNORE_MERGE_ERRORS 0x00000002
-
-#define MAX_PATH       260
-
-typedef enum {
-       STD_INPUT_HANDLE=-10,
-       STD_OUTPUT_HANDLE=-11,
-       STD_ERROR_HANDLE=-12
-} WapiStdHandle;
-
-typedef enum {
-       FILE_BEGIN=0,
-       FILE_CURRENT=1,
-       FILE_END=2
-} WapiSeekMethod;
-
-typedef enum {
-       FILE_TYPE_UNKNOWN=0x0000,
-       FILE_TYPE_DISK=0x0001,
-       FILE_TYPE_CHAR=0x0002,
-       FILE_TYPE_PIPE=0x0003,
-       FILE_TYPE_REMOTE=0x8000
-} WapiFileType;
-
-typedef enum {
-       DRIVE_UNKNOWN=0,
-       DRIVE_NO_ROOT_DIR=1,
-       DRIVE_REMOVABLE=2,
-       DRIVE_FIXED=3,
-       DRIVE_REMOTE=4,
-       DRIVE_CDROM=5,
-       DRIVE_RAMDISK=6
-} WapiDriveType;
-
-typedef enum {
-       GetFileExInfoStandard=0x0000,
-       GetFileExMaxInfoLevel=0x0001
-} WapiGetFileExInfoLevels;
-
-typedef struct 
-{
-       guint16 wYear;
-       guint16 wMonth;
-       guint16 wDayOfWeek;
-       guint16 wDay;
-       guint16 wHour;
-       guint16 wMinute;
-       guint16 wSecond;
-       guint16 wMilliseconds;
-} WapiSystemTime;
-
-typedef struct {
-#if G_BYTE_ORDER == G_BIG_ENDIAN
-       guint32 dwHighDateTime;
-       guint32 dwLowDateTime;
-#else
-       guint32 dwLowDateTime;
-       guint32 dwHighDateTime;
-#endif
-} WapiFileTime;
-
-typedef struct
-{
-       guint32 dwFileAttributes;
-       WapiFileTime ftCreationTime;
-       WapiFileTime ftLastAccessTime;
-       WapiFileTime ftLastWriteTime;
-       guint32 nFileSizeHigh;
-       guint32 nFileSizeLow;
-       guint32 dwReserved0;
-       guint32 dwReserved1;
-       gunichar2 cFileName [MAX_PATH];
-       gunichar2 cAlternateFileName [14];
-} WapiFindData;
-
-typedef struct
-{
-       guint32 dwFileAttributes;
-       WapiFileTime ftCreationTime;
-       WapiFileTime ftLastAccessTime;
-       WapiFileTime ftLastWriteTime;
-       guint32 nFileSizeHigh;
-       guint32 nFileSizeLow;
-} WapiFileAttributesData;
-
-typedef union {
-       struct {
-               guint32 LowPart;
-               guint32 HighPart;
-       } u;
-       guint64 QuadPart;
-} ULARGE_INTEGER;
-
-#define INVALID_SET_FILE_POINTER ((guint32)-1)
-#define INVALID_FILE_SIZE ((guint32)0xFFFFFFFF)
-#define INVALID_FILE_ATTRIBUTES ((guint32)-1)
-
-extern gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
-                          guint32 sharemode,
-                          WapiSecurityAttributes *security,
-                          guint32 createmode,
-                          guint32 attrs, gpointer tmplate);
-extern gboolean DeleteFile(const gunichar2 *name);
-extern gpointer GetStdHandle(WapiStdHandle stdhandle);
-extern gboolean ReadFile(gpointer handle, gpointer buffer, guint32 numbytes,
-                        guint32 *bytesread, WapiOverlapped *overlapped);
-extern gboolean WriteFile(gpointer handle, gconstpointer buffer,
-                         guint32 numbytes, guint32 *byteswritten,
-                         WapiOverlapped *overlapped);
-extern gboolean FlushFileBuffers(gpointer handle);
-extern gboolean SetEndOfFile(gpointer handle);
-extern guint32 SetFilePointer(gpointer handle, gint32 movedistance,
-                             gint32 *highmovedistance, guint32 method);
-extern WapiFileType GetFileType(gpointer handle);
-extern guint32 GetFileSize(gpointer handle, guint32 *highsize);
-extern gboolean GetFileTime(gpointer handle, WapiFileTime *create_time,
-                           WapiFileTime *last_access,
-                           WapiFileTime *last_write);
-extern gboolean SetFileTime(gpointer handle, const WapiFileTime *create_time,
-                           const WapiFileTime *last_access,
-                           const WapiFileTime *last_write);
-extern gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
-                                    WapiSystemTime *system_time);
-extern gpointer FindFirstFile (const gunichar2 *pattern,
-                              WapiFindData *find_data);
-extern gboolean FindNextFile (gpointer handle, WapiFindData *find_data);
-extern gboolean FindClose (gpointer handle);
-extern gboolean CreateDirectory (const gunichar2 *name,
-                                WapiSecurityAttributes *security);
-extern gboolean RemoveDirectory (const gunichar2 *name);
-extern gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_name);
-extern gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name,
-                         gboolean fail_if_exists);
-extern gboolean ReplaceFile (const gunichar2 *replacedFileName, const gunichar2 *replacementFileName,
-                            const gunichar2 *backupFileName, guint32 replaceFlags, 
-                            gpointer exclude, gpointer reserved);
-extern guint32 GetFileAttributes (const gunichar2 *name);
-extern gboolean GetFileAttributesEx (const gunichar2 *name,
-                                    WapiGetFileExInfoLevels level,
-                                    gpointer info);
-extern gboolean SetFileAttributes (const gunichar2 *name, guint32 attrs);
-extern guint32 GetCurrentDirectory (guint32 length, gunichar2 *buffer);
-extern gboolean SetCurrentDirectory (const gunichar2 *path);
-extern gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe,
-                           WapiSecurityAttributes *security, guint32 size);
-extern gint32 GetLogicalDriveStrings (guint32 len, gunichar2 *buf);
-extern gboolean GetDiskFreeSpaceEx(const gunichar2 *path_name, ULARGE_INTEGER *free_bytes_avail,
-                                  ULARGE_INTEGER *total_number_of_bytes,
-                                  ULARGE_INTEGER *total_number_of_free_bytes);
-extern guint32 GetDriveType(const gunichar2 *root_path_name);
-extern gboolean LockFile (gpointer handle, guint32 offset_low,
-                         guint32 offset_high, guint32 length_low,
-                         guint32 length_high);
-extern gboolean UnlockFile (gpointer handle, guint32 offset_low,
-                           guint32 offset_high, guint32 length_low,
-                           guint32 length_high);
-extern gboolean GetVolumeInformation (const gunichar2 *path, gunichar2 *volumename, int volumesize, int *outserial, int *maxcomp, int *fsflags, gunichar2 *fsbuffer, int fsbuffersize);
-
-
-extern void _wapi_io_init (void);
-extern void _wapi_io_cleanup (void);
-
-G_END_DECLS
-
-#endif /* _WAPI_IO_H_ */
diff --git a/mono/io-layer/locking.c b/mono/io-layer/locking.c
deleted file mode 100644 (file)
index 86eb864..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * io.c:  File, console and find handles
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- * Copyright (c) 2002-2009 Novell, Inc.
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-#include <config.h>
-#include <stdio.h>
-#include <glib.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/io-private.h>
-#include <mono/io-layer/io-trace.h>
-#include <mono/utils/mono-logger-internals.h>
-#include <mono/metadata/w32handle.h>
-
-gboolean
-_wapi_lock_file_region (int fd, off_t offset, off_t length)
-{
-#if defined(__native_client__)
-       printf("WARNING: locking.c: _wapi_lock_file_region(): fcntl() not available on Native Client!\n");
-       // behave as below -- locks are not available
-       return(TRUE);
-#else
-       struct flock lock_data;
-       int ret;
-
-       if (offset < 0 || length < 0) {
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return(FALSE);
-       }
-
-       lock_data.l_type = F_WRLCK;
-       lock_data.l_whence = SEEK_SET;
-       lock_data.l_start = offset;
-       lock_data.l_len = length;
-       
-       do {
-               ret = fcntl (fd, F_SETLK, &lock_data);
-       } while(ret == -1 && errno == EINTR);
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl returns %d", __func__, ret);
-
-       if (ret == -1) {
-               /*
-                * if locks are not available (NFS for example),
-                * ignore the error
-                */
-               if (errno == ENOLCK
-#ifdef EOPNOTSUPP
-                   || errno == EOPNOTSUPP
-#endif
-#ifdef ENOTSUP
-                   || errno == ENOTSUP
-#endif
-                  ) {
-                       return (TRUE);
-               }
-               
-               SetLastError (ERROR_LOCK_VIOLATION);
-               return(FALSE);
-       }
-
-       return(TRUE);
-#endif /* __native_client__ */
-}
-
-gboolean
-_wapi_unlock_file_region (int fd, off_t offset, off_t length)
-{
-#if defined(__native_client__)
-       printf("WARNING: locking.c: _wapi_unlock_file_region(): fcntl() not available on Native Client!\n");
-       return (TRUE);
-#else
-       struct flock lock_data;
-       int ret;
-
-       lock_data.l_type = F_UNLCK;
-       lock_data.l_whence = SEEK_SET;
-       lock_data.l_start = offset;
-       lock_data.l_len = length;
-       
-       do {
-               ret = fcntl (fd, F_SETLK, &lock_data);
-       } while(ret == -1 && errno == EINTR);
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl returns %d", __func__, ret);
-       
-       if (ret == -1) {
-               /*
-                * if locks are not available (NFS for example),
-                * ignore the error
-                */
-               if (errno == ENOLCK
-#ifdef EOPNOTSUPP
-                   || errno == EOPNOTSUPP
-#endif
-#ifdef ENOTSUP
-                   || errno == ENOTSUP
-#endif
-                  ) {
-                       return (TRUE);
-               }
-               
-               SetLastError (ERROR_LOCK_VIOLATION);
-               return(FALSE);
-       }
-
-       return(TRUE);
-#endif /* __native_client__ */
-}
-
-gboolean
-LockFile (gpointer handle, guint32 offset_low, guint32 offset_high,
-         guint32 length_low, guint32 length_high)
-{
-       struct _WapiHandle_file *file_handle;
-       gboolean ok;
-       off_t offset, length;
-       int fd = GPOINTER_TO_UINT(handle);
-       
-       ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
-                                 (gpointer *)&file_handle);
-       if (ok == FALSE) {
-               g_warning ("%s: error looking up file handle %p", __func__,
-                          handle);
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-
-       if (!(file_handle->fileaccess & GENERIC_READ) &&
-           !(file_handle->fileaccess & GENERIC_WRITE) &&
-           !(file_handle->fileaccess & GENERIC_ALL)) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
-               SetLastError (ERROR_ACCESS_DENIED);
-               return(FALSE);
-       }
-
-#ifdef HAVE_LARGE_FILE_SUPPORT
-       offset = ((gint64)offset_high << 32) | offset_low;
-       length = ((gint64)length_high << 32) | length_low;
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking handle %p, offset %lld, length %lld", __func__, handle, offset, length);
-#else
-       if (offset_high > 0 || length_high > 0) {
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return (FALSE);
-       }
-       offset = offset_low;
-       length = length_low;
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking handle %p, offset %ld, length %ld", __func__,
-                  handle, offset, length);
-#endif
-
-       return(_wapi_lock_file_region (fd, offset, length));
-}
-
-gboolean
-UnlockFile (gpointer handle, guint32 offset_low,
-           guint32 offset_high, guint32 length_low,
-           guint32 length_high)
-{
-       struct _WapiHandle_file *file_handle;
-       gboolean ok;
-       off_t offset, length;
-       int fd = GPOINTER_TO_UINT(handle);
-       
-       ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
-                                 (gpointer *)&file_handle);
-       if (ok == FALSE) {
-               g_warning ("%s: error looking up file handle %p", __func__,
-                          handle);
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       
-       if (!(file_handle->fileaccess & GENERIC_READ) &&
-           !(file_handle->fileaccess & GENERIC_WRITE) &&
-           !(file_handle->fileaccess & GENERIC_ALL)) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
-               SetLastError (ERROR_ACCESS_DENIED);
-               return(FALSE);
-       }
-
-#ifdef HAVE_LARGE_FILE_SUPPORT
-       offset = ((gint64)offset_high << 32) | offset_low;
-       length = ((gint64)length_high << 32) | length_low;
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking handle %p, offset %lld, length %lld", __func__, handle, offset, length);
-#else
-       offset = offset_low;
-       length = length_low;
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking handle %p, offset %ld, length %ld", __func__, handle, offset, length);
-#endif
-
-       return(_wapi_unlock_file_region (fd, offset, length));
-}
diff --git a/mono/io-layer/posix.c b/mono/io-layer/posix.c
deleted file mode 100644 (file)
index 995795b..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * posix.c:  Posix-specific support.
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- * Copyright (c) 2002-2009 Novell, Inc.
- * Copyright 2011 Xamarin Inc
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <stdio.h>
-
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/io-private.h>
-#include <mono/io-layer/io-trace.h>
-#include <mono/utils/mono-logger-internals.h>
-#include <mono/metadata/w32handle.h>
-
-static guint32
-convert_from_flags(int flags)
-{
-       guint32 fileaccess=0;
-       
-#ifndef O_ACCMODE
-#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
-#endif
-
-       if((flags & O_ACCMODE) == O_RDONLY) {
-               fileaccess=GENERIC_READ;
-       } else if ((flags & O_ACCMODE) == O_WRONLY) {
-               fileaccess=GENERIC_WRITE;
-       } else if ((flags & O_ACCMODE) == O_RDWR) {
-               fileaccess=GENERIC_READ|GENERIC_WRITE;
-       } else {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't figure out flags 0x%x", __func__, flags);
-       }
-
-       /* Maybe sort out create mode too */
-
-       return(fileaccess);
-}
-
-
-gpointer _wapi_stdhandle_create (int fd, const gchar *name)
-{
-       struct _WapiHandle_file file_handle = {0};
-       gpointer handle;
-       int flags;
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating standard handle type %s, fd %d", __func__,
-                 name, fd);
-
-#if !defined(__native_client__)        
-       /* Check if fd is valid */
-       do {
-               flags=fcntl(fd, F_GETFL);
-       } while (flags == -1 && errno == EINTR);
-
-       if(flags==-1) {
-               /* Invalid fd.  Not really much point checking for EBADF
-                * specifically
-                */
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl error on fd %d: %s", __func__, fd,
-                         strerror(errno));
-
-               SetLastError (_wapi_get_win32_file_error (errno));
-               return(INVALID_HANDLE_VALUE);
-       }
-       file_handle.fileaccess=convert_from_flags(flags);
-#else
-       /* 
-        * fcntl will return -1 in nacl, as there is no real file system API. 
-        * Yet, standard streams are available.
-        */
-       file_handle.fileaccess = (fd == STDIN_FILENO) ? GENERIC_READ : GENERIC_WRITE;
-#endif
-
-       file_handle.fd = fd;
-       file_handle.filename = g_strdup(name);
-       /* some default security attributes might be needed */
-       file_handle.security_attributes=0;
-
-       /* Apparently input handles can't be written to.  (I don't
-        * know if output or error handles can't be read from.)
-        */
-       if (fd == 0) {
-               file_handle.fileaccess &= ~GENERIC_WRITE;
-       }
-       
-       file_handle.sharemode=0;
-       file_handle.attrs=0;
-
-       handle = mono_w32handle_new_fd (MONO_W32HANDLE_CONSOLE, fd, &file_handle);
-       if (handle == INVALID_HANDLE_VALUE) {
-               g_warning ("%s: error creating file handle", __func__);
-               SetLastError (ERROR_GEN_FAILURE);
-               return(INVALID_HANDLE_VALUE);
-       }
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, handle);
-
-       return(handle);
-}
-
diff --git a/mono/io-layer/uglify.h b/mono/io-layer/uglify.h
deleted file mode 100644 (file)
index 0335d0a..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * uglify.h:  Optional header to provide the nasty w32 typedefs
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_UGLIFY_H_
-#define _WAPI_UGLIFY_H_
-
-/* Include this file if you insist on using the nasty Win32 typedefs */
-
-#include <stdlib.h>
-
-#include "mono/io-layer/wapi.h"
-
-typedef const gunichar2 *LPCTSTR;
-typedef gunichar2 *LPTSTR;
-typedef const char *LPCSTR;
-typedef char *LPSTR;
-typedef guint8 BYTE;
-typedef guint8 *LPBYTE;
-typedef guint16 WORD;
-typedef guint32 DWORD;
-typedef gpointer PVOID;
-typedef gpointer LPVOID;
-typedef gboolean BOOL;
-typedef guint32 *LPDWORD;
-typedef gint32 LONG;
-typedef guint32 ULONG;
-typedef gint32 *PLONG;
-typedef guint64 LONGLONG;
-typedef gunichar2 TCHAR;
-typedef size_t SIZE_T;
-typedef guint64 ULONG64;
-typedef guint UINT;
-typedef gconstpointer LPCVOID;
-
-typedef gpointer HANDLE;
-typedef gpointer *LPHANDLE;
-typedef gpointer HMODULE;
-typedef gpointer HINSTANCE;
-typedef gpointer HWND;
-typedef gpointer HKEY;
-
-typedef WapiSecurityAttributes SECURITY_ATTRIBUTES;
-typedef WapiSecurityAttributes *LPSECURITY_ATTRIBUTES;
-typedef WapiOverlapped *LPOVERLAPPED;
-typedef WapiOverlappedCB LPOVERLAPPED_COMPLETION_ROUTINE;
-typedef WapiFileTime FILETIME;
-typedef WapiFileTime *LPFILETIME;
-typedef WapiSystemTime SYSTEMTIME;
-typedef WapiSystemTime *LPSYSTEMTIME;
-typedef WapiFindData WIN32_FIND_DATA;
-typedef WapiFindData *LPWIN32_FIND_DATA;
-typedef WapiFileAttributesData WIN32_FILE_ATTRIBUTE_DATA;
-typedef WapiGetFileExInfoLevels GET_FILEEX_INFO_LEVELS;
-
-#define CONST const
-#define VOID void
-
-#define IN
-#define OUT
-#define WINAPI
-
-#endif /* _WAPI_UGLIFY_H_ */
diff --git a/mono/io-layer/wapi-private.h b/mono/io-layer/wapi-private.h
deleted file mode 100644 (file)
index f39d4e4..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * wapi-private.h:  internal definitions of handles and shared memory layout
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002-2006 Novell, Inc.
- */
-
-#ifndef _WAPI_PRIVATE_H_
-#define _WAPI_PRIVATE_H_
-
-#include <config.h>
-#include <glib.h>
-#include <sys/stat.h>
-
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/io.h>
-
-#include <mono/utils/mono-os-mutex.h>
-
-/* There doesn't seem to be a defined symbol for this */
-#define _WAPI_THREAD_CURRENT (gpointer)0xFFFFFFFE
-
-extern gboolean _wapi_has_shut_down;
-
-#include <mono/io-layer/io-private.h>
-#include <mono/metadata/w32handle.h>
-
-struct _WapiHandle_shared_ref
-{
-       /* This will be split 16:16 with the shared file segment in
-        * the top half, when I implement space increases
-        */
-       guint32 offset;
-};
-
-struct _WapiFileShare
-{
-#ifdef WAPI_FILE_SHARE_PLATFORM_EXTRA_DATA
-       WAPI_FILE_SHARE_PLATFORM_EXTRA_DATA
-#endif
-       guint64 device;
-       guint64 inode;
-       pid_t opened_by_pid;
-       guint32 sharemode;
-       guint32 access;
-       guint32 handle_refs;
-       guint32 timestamp;
-};
-
-typedef struct _WapiFileShare _WapiFileShare;
-
-#endif /* _WAPI_PRIVATE_H_ */
index 7cc3b89ff380dc094993a8b58c983d5881740c49..80034f50be7df80d6bc06cb881a6f68b89ecf0ed 100644 (file)
 #define GetLastError wapi_GetLastError
 #define SetLastError wapi_SetLastError
 #define CloseHandle wapi_CloseHandle 
-#define CreateFile wapi_CreateFile
-#define DeleteFile wapi_DeleteFile
-#define GetStdHandle wapi_GetStdHandle
-#define ReadFile wapi_ReadFile
-#define WriteFile wapi_WriteFile
-#define FlushFileBuffers wapi_FlushFileBuffers
-#define SetEndOfFile wapi_SetEndOfFile
-#define SetFilePointer wapi_SetFilePointer
-#define GetFileType wapi_GetFileType
-#define GetFileSize wapi_GetFileSize
-#define GetFileTime wapi_GetFileTime
-#define SetFileTime wapi_SetFileTime
-#define FileTimeToSystemTime wapi_FileTimeToSystemTime
-#define FindFirstFile wapi_FindFirstFile 
-#define FindNextFile wapi_FindNextFile 
-#define FindClose wapi_FindClose 
-#define CreateDirectory wapi_CreateDirectory 
-#define RemoveDirectory wapi_RemoveDirectory 
-#define MoveFile wapi_MoveFile 
-#define CopyFile wapi_CopyFile 
-#define ReplaceFile wapi_ReplaceFile 
-#define GetFileAttributes wapi_GetFileAttributes 
-#define GetFileAttributesEx wapi_GetFileAttributesEx 
-#define SetFileAttributes wapi_SetFileAttributes 
-#define GetCurrentDirectory wapi_GetCurrentDirectory 
-#define SetCurrentDirectory wapi_SetCurrentDirectory 
-#define CreatePipe wapi_CreatePipe 
-#define GetLogicalDriveStrings wapi_GetLogicalDriveStrings 
-#define GetDiskFreeSpaceEx wapi_GetDiskFreeSpaceEx
-#define GetDriveType wapi_GetDriveType
-#define LockFile wapi_LockFile 
-#define UnlockFile wapi_UnlockFile 
-#define GetVolumeInformation wapi_GetVolumeInformation 
-#define ImpersonateLoggedOnUser wapi_ImpersonateLoggedOnUser 
-#define RevertToSelf wapi_RevertToSelf 
-#define GetSystemInfo wapi_GetSystemInfo
 
 #endif /* __WAPI_REMAP_H__ */
index d4da229603e49264010aa78f072d525d308dd690..14dc672e8ee9ac879a21bb175e3de57a9101d31f 100644 (file)
@@ -1,30 +1,9 @@
 
 #include "wapi.h"
 
-#include "io-trace.h"
-#include "io.h"
-
 #include "mono/utils/mono-lazy-init.h"
 #include "mono/metadata/w32handle.h"
 
-gboolean _wapi_has_shut_down = FALSE;
-
-void
-wapi_init (void)
-{
-       _wapi_io_init ();
-}
-
-void
-wapi_cleanup (void)
-{
-       g_assert (_wapi_has_shut_down == FALSE);
-       _wapi_has_shut_down = TRUE;
-
-       _wapi_error_cleanup ();
-       _wapi_io_cleanup ();
-}
-
 /* Use this instead of getpid(), to cope with linuxthreads.  It's a
  * function rather than a variable lookup because we need to get at
  * this before share_init() might have been called. */
index fb0bf4fbce951609667fcddafd9692ca8e024ad7..4409210db2d89b515e29e9dc9cf505645a8f1a62 100644 (file)
 #ifndef _WAPI_WAPI_H_
 #define _WAPI_WAPI_H_
 
+#include <config.h>
 #include <glib.h>
 
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#include <unistd.h>
+#include <utime.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 
 #include <mono/io-layer/wapi-remap.h>
-#include <mono/io-layer/io.h>
-#include <mono/io-layer/io-portability.h>
 #include <mono/io-layer/error.h>
+#include <mono/utils/mono-logger-internals.h>
 
 G_BEGIN_DECLS
 
-#define WAIT_FAILED        ((int) 0xFFFFFFFF)
-#define WAIT_OBJECT_0      ((int) 0x00000000)
-#define WAIT_ABANDONED_0   ((int) 0x00000080)
-#define WAIT_TIMEOUT       ((int) 0x00000102)
-#define WAIT_IO_COMPLETION ((int) 0x000000C0)
+#define WAIT_FAILED        ((gint) 0xFFFFFFFF)
+#define WAIT_OBJECT_0      ((gint) 0x00000000)
+#define WAIT_ABANDONED_0   ((gint) 0x00000080)
+#define WAIT_TIMEOUT       ((gint) 0x00000102)
+#define WAIT_IO_COMPLETION ((gint) 0x000000C0)
 
-void
-wapi_init (void);
+#ifdef DISABLE_IO_LAYER_TRACE
+#define MONO_TRACE(...)
+#else
+#define MONO_TRACE(...) mono_trace (__VA_ARGS__)
+#endif
 
-void
-wapi_cleanup (void);
+#define WINAPI
+
+typedef guint32 DWORD;
+typedef gboolean BOOL;
+typedef gint32 LONG;
+typedef guint32 ULONG;
+typedef guint UINT;
+
+typedef gpointer HANDLE;
+typedef gpointer HMODULE;
 
 gboolean
 CloseHandle (gpointer handle);
diff --git a/mono/io-layer/wapi_glob.c b/mono/io-layer/wapi_glob.c
deleted file mode 100644 (file)
index 013b778..0000000
+++ /dev/null
@@ -1,398 +0,0 @@
-/*     $OpenBSD: glob.c,v 1.26 2005/11/28 17:50:12 deraadt Exp $ */
-/*
- * Copyright (c) 1989, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Guido van Rossum.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * _wapi_glob(3) -- a subset of the one defined in POSIX 1003.2.
- *
- * Optional extra services, controlled by flags not defined by POSIX:
- *
- * GLOB_MAGCHAR:
- *     Set in gl_flags if pattern contained a globbing character.
- */
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <glib.h>
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "wapi_glob.h"
-
-#define        EOS             '\0'
-#define        NOT             '!'
-#define        QUESTION        '?'
-#define        QUOTE           '\\'
-#define        STAR            '*'
-
-#ifndef DEBUG
-
-#define        M_QUOTE         0x8000
-#define        M_PROTECT       0x4000
-#define        M_MASK          0xffff
-#define        M_ASCII         0x00ff
-
-typedef unsigned short Char;
-
-#else
-
-#define        M_QUOTE         0x80
-#define        M_PROTECT       0x40
-#define        M_MASK          0xff
-#define        M_ASCII         0x7f
-
-typedef char Char;
-
-#endif
-
-
-#define        CHAR(c)         ((gchar)((c)&M_ASCII))
-#define        META(c)         ((gchar)((c)|M_QUOTE))
-#define        M_ALL           META('*')
-#define        M_ONE           META('?')
-#define        ismeta(c)       (((c)&M_QUOTE) != 0)
-
-
-static int      g_Ctoc(const gchar *, char *, unsigned int);
-static int      glob0(GDir *dir, const gchar *, wapi_glob_t *, gboolean,
-                      gboolean);
-static int      glob1(GDir *dir, gchar *, gchar *, wapi_glob_t *, size_t *,
-                      gboolean, gboolean);
-static int      glob3(GDir *dir, gchar *, gchar *, wapi_glob_t *, size_t *,
-                      gboolean, gboolean);
-static int      globextend(const gchar *, wapi_glob_t *, size_t *);
-static int      match(const gchar *, gchar *, gchar *, gboolean);
-#ifdef DEBUG_ENABLED
-static void     qprintf(const char *, Char *);
-#endif
-
-int
-_wapi_glob(GDir *dir, const char *pattern, int flags, wapi_glob_t *pglob)
-{
-       const unsigned char *patnext;
-       int c;
-       gchar *bufnext, *bufend, patbuf[PATH_MAX];
-
-       patnext = (unsigned char *) pattern;
-       if (!(flags & WAPI_GLOB_APPEND)) {
-               pglob->gl_pathc = 0;
-               pglob->gl_pathv = NULL;
-               pglob->gl_offs = 0;
-       }
-       pglob->gl_flags = flags & ~WAPI_GLOB_MAGCHAR;
-
-       bufnext = patbuf;
-       bufend = bufnext + PATH_MAX - 1;
-
-       /* Protect the quoted characters. */
-       while (bufnext < bufend && (c = *patnext++) != EOS)
-               if (c == QUOTE) {
-                       if ((c = *patnext++) == EOS) {
-                               c = QUOTE;
-                               --patnext;
-                       }
-                       *bufnext++ = c | M_PROTECT;
-               } else
-                       *bufnext++ = c;
-
-       *bufnext = EOS;
-
-       return glob0(dir, patbuf, pglob, flags & WAPI_GLOB_IGNORECASE,
-                    flags & WAPI_GLOB_UNIQUE);
-}
-
-/*
- * The main glob() routine: compiles the pattern (optionally processing
- * quotes), calls glob1() to do the real pattern matching, and finally
- * sorts the list (unless unsorted operation is requested).  Returns 0
- * if things went well, nonzero if errors occurred.  It is not an error
- * to find no matches.
- */
-static int
-glob0(GDir *dir, const gchar *pattern, wapi_glob_t *pglob, gboolean ignorecase,
-       gboolean unique)
-{
-       const gchar *qpatnext;
-       int c, err, oldpathc;
-       gchar *bufnext, patbuf[PATH_MAX];
-       size_t limit = 0;
-
-       qpatnext = pattern;
-       oldpathc = pglob->gl_pathc;
-       bufnext = patbuf;
-
-       /* We don't need to check for buffer overflow any more. */
-       while ((c = *qpatnext++) != EOS) {
-               switch (c) {
-               case QUESTION:
-                       pglob->gl_flags |= WAPI_GLOB_MAGCHAR;
-                       *bufnext++ = M_ONE;
-                       break;
-               case STAR:
-                       pglob->gl_flags |= WAPI_GLOB_MAGCHAR;
-                       /* collapse adjacent stars to one,
-                        * to avoid exponential behavior
-                        */
-                       if (bufnext == patbuf || bufnext[-1] != M_ALL)
-                               *bufnext++ = M_ALL;
-                       break;
-               default:
-                       *bufnext++ = CHAR(c);
-                       break;
-               }
-       }
-       *bufnext = EOS;
-#ifdef DEBUG_ENABLED
-       qprintf("glob0:", patbuf);
-#endif
-
-       if ((err = glob1(dir, patbuf, patbuf+PATH_MAX-1, pglob, &limit,
-                        ignorecase, unique)) != 0)
-               return(err);
-
-       if (pglob->gl_pathc == oldpathc) {
-               return(WAPI_GLOB_NOMATCH);
-       }
-
-       return(0);
-}
-
-static int
-glob1(GDir *dir, gchar *pattern, gchar *pattern_last, wapi_glob_t *pglob,
-      size_t *limitp, gboolean ignorecase, gboolean unique)
-{
-       /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
-       if (*pattern == EOS)
-               return(0);
-       return(glob3(dir, pattern, pattern_last, pglob, limitp, ignorecase,
-                    unique));
-}
-
-static gboolean contains (wapi_glob_t *pglob, const gchar *name)
-{
-       int i;
-       char **pp;
-       
-       if (pglob->gl_pathv != NULL) {
-               pp = pglob->gl_pathv + pglob->gl_offs;
-               for (i = pglob->gl_pathc; i--; ++pp) {
-                       if (*pp) {
-                               if (!strcmp (*pp, name)) {
-                                       return(TRUE);
-                               }
-                       }
-               }
-       }
-       
-       return(FALSE);
-}
-
-static int
-glob3(GDir *dir, gchar *pattern, gchar *pattern_last, wapi_glob_t *pglob,
-      size_t *limitp, gboolean ignorecase, gboolean unique)
-{
-       const gchar *name;
-
-       /* Search directory for matching names. */
-       while ((name = g_dir_read_name(dir))) {
-               if (!match(name, pattern, pattern + strlen (pattern),
-                          ignorecase)) {
-                       continue;
-               }
-               if (!unique ||
-                   !contains (pglob, name)) {
-                       globextend (name, pglob, limitp);
-               }
-       }
-
-       return(0);
-}
-
-
-/*
- * Extend the gl_pathv member of a wapi_glob_t structure to accommodate a new item,
- * add the new item, and update gl_pathc.
- *
- * This assumes the BSD realloc, which only copies the block when its size
- * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
- * behavior.
- *
- * Return 0 if new item added, error code if memory couldn't be allocated.
- *
- * Invariant of the wapi_glob_t structure:
- *     Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
- *     gl_pathv points to (gl_offs + gl_pathc + 1) items.
- */
-static int
-globextend(const gchar *path, wapi_glob_t *pglob, size_t *limitp)
-{
-       char **pathv;
-       int i;
-       unsigned int newsize, len;
-       char *copy;
-       const gchar *p;
-
-       newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
-       /* FIXME: Can just use realloc(). */
-       pathv = (char **)(pglob->gl_pathv ? g_realloc ((char *)pglob->gl_pathv, newsize) :
-           g_malloc (newsize));
-       if (pathv == NULL) {
-               if (pglob->gl_pathv) {
-                       g_free (pglob->gl_pathv);
-                       pglob->gl_pathv = NULL;
-               }
-               return(WAPI_GLOB_NOSPACE);
-       }
-
-       if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
-               /* first time around -- clear initial gl_offs items */
-               pathv += pglob->gl_offs;
-               for (i = pglob->gl_offs; --i >= 0; )
-                       *--pathv = NULL;
-       }
-       pglob->gl_pathv = pathv;
-
-       for (p = path; *p++;)
-               ;
-       len = (size_t)(p - path);
-       *limitp += len;
-       if ((copy = (char *)malloc(len)) != NULL) {
-               if (g_Ctoc(path, copy, len)) {
-                       g_free (copy);
-                       return(WAPI_GLOB_NOSPACE);
-               }
-               pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
-       }
-       pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
-
-#if 0
-       /* Broken on opensuse 11 */
-       if ((pglob->gl_flags & WAPI_GLOB_LIMIT) &&
-           newsize + *limitp >= ARG_MAX) {
-               errno = 0;
-               return(WAPI_GLOB_NOSPACE);
-       }
-#endif
-
-       return(copy == NULL ? WAPI_GLOB_NOSPACE : 0);
-}
-
-
-/*
- * pattern matching function for filenames.  Each occurrence of the *
- * pattern causes a recursion level.
- */
-static int
-match(const gchar *name, gchar *pat, gchar *patend, gboolean ignorecase)
-{
-       gchar c;
-
-       while (pat < patend) {
-               c = *pat++;
-               switch (c & M_MASK) {
-               case M_ALL:
-                       if (pat == patend)
-                               return(1);
-                       do {
-                               if (match(name, pat, patend, ignorecase))
-                                       return(1);
-                       } while (*name++ != EOS);
-                       return(0);
-               case M_ONE:
-                       if (*name++ == EOS)
-                               return(0);
-                       break;
-               default:
-                       if (ignorecase) {
-                               if (g_ascii_tolower (*name++) != g_ascii_tolower (c))
-                                       return(0);
-                       } else {
-                               if (*name++ != c)
-                                       return(0);
-                       }
-                       
-                       break;
-               }
-       }
-       return(*name == EOS);
-}
-
-/* Free allocated data belonging to a wapi_glob_t structure. */
-void
-_wapi_globfree(wapi_glob_t *pglob)
-{
-       int i;
-       char **pp;
-
-       if (pglob->gl_pathv != NULL) {
-               pp = pglob->gl_pathv + pglob->gl_offs;
-               for (i = pglob->gl_pathc; i--; ++pp)
-                       if (*pp)
-                               g_free (*pp);
-               g_free (pglob->gl_pathv);
-               pglob->gl_pathv = NULL;
-       }
-}
-
-static int
-g_Ctoc(const gchar *str, char *buf, unsigned int len)
-{
-
-       while (len--) {
-               if ((*buf++ = *str++) == EOS)
-                       return (0);
-       }
-       return (1);
-}
-
-#ifdef DEBUG_ENABLED
-static void
-qprintf(const char *str, Char *s)
-{
-       Char *p;
-
-       (void)printf("%s:\n", str);
-       for (p = s; *p; p++)
-               (void)printf("%c", CHAR(*p));
-       (void)printf("\n");
-       for (p = s; *p; p++)
-               (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
-       (void)printf("\n");
-       for (p = s; *p; p++)
-               (void)printf("%c", ismeta(*p) ? '_' : ' ');
-       (void)printf("\n");
-}
-#endif
diff --git a/mono/io-layer/wapi_glob.h b/mono/io-layer/wapi_glob.h
deleted file mode 100644 (file)
index fc9d7ba..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*     $OpenBSD: glob.h,v 1.10 2005/12/13 00:35:22 millert Exp $       */
-/*     $NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp $     */
-
-/*
- * Copyright (c) 1989, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Guido van Rossum.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *     @(#)glob.h      8.1 (Berkeley) 6/2/93
- */
-
-#ifndef _WAPI_GLOB_H_
-#define        _WAPI_GLOB_H_
-
-#include <glib.h>
-
-struct stat;
-typedef struct {
-       int gl_pathc;           /* Count of total paths so far. */
-       int gl_offs;            /* Reserved at beginning of gl_pathv. */
-       int gl_flags;           /* Copy of flags parameter to glob. */
-       char **gl_pathv;        /* List of paths matching pattern. */
-} wapi_glob_t;
-
-#define WAPI_GLOB_APPEND       0x0001  /* Append to output from previous call. */
-#define WAPI_GLOB_UNIQUE       0x0040  /* When appending only add items that aren't already in the list */
-#define        WAPI_GLOB_NOSPACE       (-1)    /* Malloc call failed. */
-#define        WAPI_GLOB_ABORTED       (-2)    /* Unignored error. */
-#define        WAPI_GLOB_NOMATCH       (-3)    /* No match and WAPI_GLOB_NOCHECK not set. */
-#define        WAPI_GLOB_NOSYS (-4)    /* Function not supported. */
-
-#define        WAPI_GLOB_MAGCHAR       0x0100  /* Pattern had globbing characters. */
-#define WAPI_GLOB_LIMIT        0x2000  /* Limit pattern match output to ARG_MAX */
-#define WAPI_GLOB_IGNORECASE 0x4000    /* Ignore case when matching */
-#define WAPI_GLOB_ABEND        WAPI_GLOB_ABORTED /* backward compatibility */
-
-G_BEGIN_DECLS
-int    _wapi_glob(GDir *dir, const char *, int, wapi_glob_t *);
-void   _wapi_globfree(wapi_glob_t *);
-G_END_DECLS
-
-#endif /* !_WAPI_GLOB_H_ */
index 5deda477e2d9a083748b77e8fb56e6f37100c9fb..4a997d3fc4c072affba54f944099c505451deb6c 100644 (file)
@@ -3,8 +3,8 @@ win32_sources = \
        console-win32.c \
        console-win32-internals.h \
        cominterop-win32-internals.h \
-       file-io-windows.c \
-       file-io-windows-internals.h \
+       w32file-win32.c \
+       w32file-win32-internals.h \
        icall-windows.c \
        icall-windows-internals.h \
        marshal-windows.c \
@@ -49,7 +49,10 @@ unix_sources = \
        w32process-unix-bsd.c \
        w32process-unix-haiku.c \
        w32process-unix-default.c \
-       w32socket-unix.c
+       w32socket-unix.c \
+       w32file-unix.c \
+       w32file-unix-glob.c \
+       w32file-unix-glob.h
 
 platform_sources = $(unix_sources)
 endif
@@ -151,9 +154,9 @@ common_sources = \
        exception.c             \
        exception.h             \
        exception-internals.h   \
-       file-io.c               \
-       file-io.h               \
-       file-io-internals.h \
+       w32file.c               \
+       w32file.h               \
+       w32file-internals.h \
        filewatcher.c           \
        filewatcher.h           \
        gc-internals.h          \
index 74323ab37b36e9a6fc94a85a049c4c2910d3ce3e..a2c8c353fd3a1d11c502f2901f5d015198047b97 100644 (file)
@@ -51,7 +51,7 @@
 #include <mono/metadata/mono-debug.h>
 #include <mono/metadata/mono-debug-debugger.h>
 #include <mono/metadata/attach.h>
-#include <mono/metadata/file-io.h>
+#include <mono/metadata/w32file.h>
 #include <mono/metadata/lock-tracer.h>
 #include <mono/metadata/console-io.h>
 #include <mono/metadata/threads-types.h>
@@ -1398,6 +1398,7 @@ shadow_copy_sibling (gchar *src, gint srclen, const char *extension, gchar *targ
 {
        guint16 *orig, *dest;
        gboolean copy_result;
+       gint32 copy_error;
        
        strcpy (src + srclen - tail_len, extension);
 
@@ -1417,18 +1418,14 @@ shadow_copy_sibling (gchar *src, gint srclen, const char *extension, gchar *targ
        strcpy (target + targetlen - tail_len, extension);
        dest = g_utf8_to_utf16 (target, strlen (target), NULL, NULL, NULL);
        
-       DeleteFile (dest);
+       mono_w32file_delete (dest);
 
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-       copy_result = CopyFile (orig, dest, FALSE);
-#else
-       copy_result = SUCCEEDED (CopyFile2 (orig, dest, NULL));
-#endif
+       copy_result = mono_w32file_copy (orig, dest, TRUE, &copy_error);
 
        /* Fix for bug #556884 - make sure the files have the correct mode so that they can be
         * overwritten when updated in their original locations. */
        if (copy_result)
-               copy_result = SetFileAttributes (dest, FILE_ATTRIBUTE_NORMAL);
+               copy_result = mono_w32file_set_attributes (dest, FILE_ATTRIBUTE_NORMAL);
 
        g_free (orig);
        g_free (dest);
@@ -1592,15 +1589,14 @@ shadow_copy_create_ini (const char *shadow, const char *filename)
        if (!u16_ini) {
                return FALSE;
        }
-       handle = (void **)CreateFile (u16_ini, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
-                               NULL, CREATE_NEW, FileAttributes_Normal, NULL);
+       handle = (void **)mono_w32file_create (u16_ini, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, CREATE_NEW, FileAttributes_Normal);
        g_free (u16_ini);
        if (handle == INVALID_HANDLE_VALUE) {
                return FALSE;
        }
 
        full_path = mono_path_resolve_symlinks (filename);
-       result = WriteFile (handle, full_path, strlen (full_path), &n, NULL);
+       result = mono_w32file_write (handle, full_path, strlen (full_path), &n);
        g_free (full_path);
        CloseHandle (handle);
        return result;
@@ -1695,6 +1691,7 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror)
        char *dir_name = g_path_get_dirname (filename);
        MonoDomain *domain = mono_domain_get ();
        char *shadow_dir;
+       gint32 copy_error;
 
        mono_error_init (oerror);
 
@@ -1740,27 +1737,23 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror)
 
        orig = g_utf8_to_utf16 (filename, strlen (filename), NULL, NULL, NULL);
        dest = g_utf8_to_utf16 (shadow, strlen (shadow), NULL, NULL, NULL);
-       DeleteFile (dest);
+       mono_w32file_delete (dest);
 
        /* Fix for bug #17066 - make sure we can read the file. if not then don't error but rather 
         * let the assembly fail to load. This ensures you can do Type.GetType("NS.T, NonExistantAssembly)
         * and not have it runtime error" */
-       attrs = GetFileAttributes (orig);
+       attrs = mono_w32file_get_attributes (orig);
        if (attrs == INVALID_FILE_ATTRIBUTES) {
                g_free (shadow);
                return (char *)filename;
        }
 
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-       copy_result = CopyFile (orig, dest, FALSE);
-#else
-       copy_result = SUCCEEDED (CopyFile2 (orig, dest, NULL));
-#endif
+       copy_result = mono_w32file_copy (orig, dest, TRUE, &copy_error);
 
        /* Fix for bug #556884 - make sure the files have the correct mode so that they can be
         * overwritten when updated in their original locations. */
        if (copy_result)
-               copy_result = SetFileAttributes (dest, FILE_ATTRIBUTE_NORMAL);
+               copy_result = mono_w32file_set_attributes (dest, FILE_ATTRIBUTE_NORMAL);
 
        g_free (dest);
        g_free (orig);
@@ -1772,7 +1765,7 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror)
                if (GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND)
                        return NULL; /* file not found, shadow copy failed */
 
-               mono_error_set_execution_engine (oerror, "Failed to create shadow copy (CopyFile).");
+               mono_error_set_execution_engine (oerror, "Failed to create shadow copy (mono_w32file_copy).");
                return NULL;
        }
 
@@ -1791,7 +1784,7 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror)
        
        if (!copy_result)  {
                g_free (shadow);
-               mono_error_set_execution_engine (oerror, "Failed to create shadow copy of sibling data (CopyFile).");
+               mono_error_set_execution_engine (oerror, "Failed to create shadow copy of sibling data (mono_w32file_copy).");
                return NULL;
        }
 
index b8367e888f7b851970cb4f7a2668558db116b90c..233e2aef04e734058d89cc489fefd13fd135d998 100644 (file)
@@ -30,7 +30,7 @@ mono_console_handle_async_ops (void)
 MonoBoolean
 ves_icall_System_ConsoleDriver_Isatty (HANDLE handle)
 {
-       return (GetFileType (handle) == FILE_TYPE_CHAR);
+       return mono_w32file_get_type (handle) == FILE_TYPE_CHAR;
 }
 
 MonoBoolean
index 76cfe9979db3b8498e9f195c71787832da9ed2d0..908f572a5ff33369610201492ca721aa7ca93297 100644 (file)
@@ -44,6 +44,7 @@
 #include <mono/metadata/w32semaphore.h>
 #include <mono/metadata/w32event.h>
 #include <mono/metadata/w32process.h>
+#include <mono/metadata/w32file.h>
 #include <metadata/threads.h>
 #include <metadata/profiler-private.h>
 #include <mono/metadata/coree.h>
@@ -484,13 +485,13 @@ mono_init_internal (const char *filename, const char *exe_filename, const char *
 #ifndef HOST_WIN32
        mono_w32handle_init ();
        mono_w32handle_namespace_init ();
-       wapi_init ();
 #endif
 
        mono_w32mutex_init ();
        mono_w32semaphore_init ();
        mono_w32event_init ();
        mono_w32process_init ();
+       mono_w32file_init ();
 
 #ifndef DISABLE_PERFCOUNTERS
        mono_perfcounters_init ();
@@ -852,10 +853,7 @@ mono_cleanup (void)
        mono_coop_mutex_destroy (&appdomains_mutex);
 
        mono_w32process_cleanup ();
-
-#ifndef HOST_WIN32
-       wapi_cleanup ();
-#endif
+       mono_w32file_cleanup ();
 }
 
 void
diff --git a/mono/metadata/file-io-internals.h b/mono/metadata/file-io-internals.h
deleted file mode 100644 (file)
index ad45529..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2016 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-#ifndef __MONO_FILE_IO_INTERNALS_H__
-#define __MONO_FILE_IO_INTERNALS_H__
-
-#include <config.h>
-#include <glib.h>
-#include "mono/metadata/object.h"
-#include "mono/metadata/object-internals.h"
-
-gboolean
-mono_file_io_move_file (gunichar2 *path, gunichar2 *dest, gint32 *error);
-
-gboolean
-mono_file_io_copy_file (gunichar2 *path, gunichar2 *dest, gboolean overwrite, gint32 *error);
-
-gint64
-mono_file_io_get_file_size (HANDLE handle, gint32 *error);
-
-gboolean
-mono_file_io_lock_file (HANDLE handle, gint64 position, gint64 length, gint32 *error);
-
-gboolean
-mono_file_io_replace_file (gunichar2 *destinationFileName, gunichar2 *sourceFileName,
-                          gunichar2 *destinationBackupFileName, guint32 flags, gint32 *error);
-
-gboolean
-mono_file_io_unlock_file (HANDLE handle, gint64 position, gint64 length, gint32 *error);
-
-HANDLE
-mono_file_io_get_console_output (void);
-
-HANDLE
-mono_file_io_get_console_error (void);
-
-HANDLE
-mono_file_io_get_console_input (void);
-
-#endif /* __MONO_FILE_IO_INTERNALS_H__ */
diff --git a/mono/metadata/file-io-windows-internals.h b/mono/metadata/file-io-windows-internals.h
deleted file mode 100644 (file)
index df372e8..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright 2016 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-#ifndef _MONO_METADATA_FILEIO_WINDOWS_H_
-#define _MONO_METADATA_FILEIO_WINDOWS_H_
-
-#include <config.h>
-#include <glib.h>
-
-#ifdef HOST_WIN32
-#include "mono/metadata/file-io.h"
-#include "mono/metadata/file-io-internals.h"
-#endif /* HOST_WIN32 */
-#endif /* _MONO_METADATA_FILEIO_WINDOWS_H_ */
diff --git a/mono/metadata/file-io-windows-uwp.c b/mono/metadata/file-io-windows-uwp.c
deleted file mode 100644 (file)
index 3af6c05..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * file-io-windows-uwp.c: UWP file-io support for Mono.
- *
- * Copyright 2016 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
-*/
-#include <config.h>
-#include <glib.h>
-#include "mono/utils/mono-compiler.h"
-
-#if G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT)
-#include <windows.h>
-#include "mono/metadata/file-io-windows-internals.h"
-
-gboolean
-mono_file_io_move_file (gunichar2 *path, gunichar2 *dest, gint32 *error)
-{
-       gboolean result = FALSE;
-       MONO_ENTER_GC_SAFE;
-
-       result = MoveFileEx (path, dest, MOVEFILE_COPY_ALLOWED);
-       if (result == FALSE) {
-               *error=GetLastError ();
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return result;
-}
-
-gboolean
-mono_file_io_replace_file (gunichar2 *destinationFileName, gunichar2 *sourceFileName,
-                          gunichar2 *destinationBackupFileName, guint32 flags, gint32 *error)
-{
-       gboolean result = FALSE;
-       MONO_ENTER_GC_SAFE;
-
-       result = ReplaceFile (destinationFileName, sourceFileName, destinationBackupFileName, flags, NULL, NULL);
-       if (result == FALSE) {
-               *error=GetLastError ();
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return result;
-}
-
-gboolean
-mono_file_io_copy_file (gunichar2 *path, gunichar2 *dest, gboolean overwrite, gint32 *error)
-{
-       gboolean                                                result = FALSE;
-       COPYFILE2_EXTENDED_PARAMETERS   copy_param = {0};
-
-       copy_param.dwSize = sizeof (COPYFILE2_EXTENDED_PARAMETERS);
-       copy_param.dwCopyFlags = (!overwrite) ? COPY_FILE_FAIL_IF_EXISTS : 0;
-
-       MONO_ENTER_GC_SAFE;
-
-       result = SUCCEEDED (CopyFile2 (path, dest, &copy_param));
-       if (result == FALSE) {
-               *error=GetLastError ();
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return result;
-}
-
-gint64
-mono_file_io_get_file_size (HANDLE handle, gint32 *error)
-{
-       LARGE_INTEGER length;
-
-       MONO_ENTER_GC_SAFE;
-
-       if (!GetFileSizeEx (handle, &length)) {
-               *error=GetLastError ();
-               length.QuadPart = INVALID_FILE_SIZE;
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return length.QuadPart;
-}
-
-gboolean
-mono_file_io_lock_file (HANDLE handle, gint64 position, gint64 length, gint32 *error)
-{
-       gboolean result = FALSE;
-       MONO_ENTER_GC_SAFE;
-
-       result = LockFile (handle, position & 0xFFFFFFFF, position >> 32,
-                          length & 0xFFFFFFFF, length >> 32);
-
-       if (result == FALSE) {
-               *error = GetLastError ();
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return result;
-}
-
-gboolean
-mono_file_io_unlock_file (HANDLE handle, gint64 position, gint64 length, gint32 *error)
-{
-       gboolean result = FALSE;
-       MONO_ENTER_GC_SAFE;
-
-       result = UnlockFile (handle, position & 0xFFFFFFFF, position >> 32,
-                            length & 0xFFFFFFFF, length >> 32);
-
-       if (result == FALSE) {
-               *error = GetLastError ();
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return result;
-}
-
-HANDLE
-mono_file_io_get_console_output (void)
-{
-       MonoError mono_error;
-       mono_error_init (&mono_error);
-
-       g_unsupported_api ("GetStdHandle (STD_OUTPUT_HANDLE)");
-
-       mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "GetStdHandle (STD_OUTPUT_HANDLE)");
-       mono_error_set_pending_exception (&mono_error);
-
-       SetLastError (ERROR_NOT_SUPPORTED);
-
-       return INVALID_HANDLE_VALUE;
-}
-
-HANDLE
-mono_file_io_get_console_input (void)
-{
-       MonoError mono_error;
-       mono_error_init (&mono_error);
-
-       g_unsupported_api ("GetStdHandle (STD_INPUT_HANDLE)");
-
-       mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "GetStdHandle (STD_INPUT_HANDLE)");
-       mono_error_set_pending_exception (&mono_error);
-
-       SetLastError (ERROR_NOT_SUPPORTED);
-
-       return INVALID_HANDLE_VALUE;
-}
-
-HANDLE
-mono_file_io_get_console_error (void)
-{
-       MonoError mono_error;
-       mono_error_init (&mono_error);
-
-       g_unsupported_api ("GetStdHandle (STD_ERROR_HANDLE)");
-
-       mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "GetStdHandle (STD_ERROR_HANDLE)");
-       mono_error_set_pending_exception (&mono_error);
-
-       SetLastError (ERROR_NOT_SUPPORTED);
-
-       return INVALID_HANDLE_VALUE;
-}
-
-#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
-
-MONO_EMPTY_SOURCE_FILE (file_io_windows_uwp);
-#endif /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
diff --git a/mono/metadata/file-io-windows.c b/mono/metadata/file-io-windows.c
deleted file mode 100644 (file)
index e7dd111..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * file-io-windows.c: Windows File IO internal calls.
- *
- * Copyright 2016 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-#include <config.h>
-#include <glib.h>
-
-#if defined(HOST_WIN32)
-#include <winsock2.h>
-#include <windows.h>
-#include "mono/metadata/file-io-windows-internals.h"
-
-gunichar2
-ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
-{
-       return (gunichar2) ':'; /* colon */
-}
-
-gunichar2
-ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
-{
-       return (gunichar2) '\\';        /* backslash */
-}
-
-gunichar2
-ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
-{
-       return (gunichar2) '/'; /* forward slash */
-}
-
-gunichar2
-ves_icall_System_IO_MonoIO_get_PathSeparator ()
-{
-       return (gunichar2) ';'; /* semicolon */
-}
-
-void ves_icall_System_IO_MonoIO_DumpHandles (void)
-{
-       return;
-}
-#endif /* HOST_WIN32 */
diff --git a/mono/metadata/file-io.c b/mono/metadata/file-io.c
deleted file mode 100644 (file)
index 44fde40..0000000
+++ /dev/null
@@ -1,1408 +0,0 @@
-/*
- * file-io.c: File IO internal calls
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *     Gonzalo Paniagua Javier (gonzalo@ximian.com)
- *
- * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
- * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
- * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-
-#include <glib.h>
-#include <string.h>
-#include <errno.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include <mono/metadata/object.h>
-#include <mono/io-layer/io-layer.h>
-#include <mono/metadata/file-io.h>
-#include <mono/metadata/file-io-internals.h>
-#include <mono/metadata/exception.h>
-#include <mono/metadata/appdomain.h>
-#include <mono/metadata/marshal.h>
-#include <mono/utils/strenc.h>
-#include <utils/mono-io-portability.h>
-#include <mono/metadata/w32handle.h>
-
-#undef DEBUG
-
-/* conversion functions */
-
-static guint32 convert_mode(MonoFileMode mono_mode)
-{
-       guint32 mode;
-
-       switch(mono_mode) {
-       case FileMode_CreateNew:
-               mode=CREATE_NEW;
-               break;
-       case FileMode_Create:
-               mode=CREATE_ALWAYS;
-               break;
-       case FileMode_Open:
-               mode=OPEN_EXISTING;
-               break;
-       case FileMode_OpenOrCreate:
-               mode=OPEN_ALWAYS;
-               break;
-       case FileMode_Truncate:
-               mode=TRUNCATE_EXISTING;
-               break;
-       case FileMode_Append:
-               mode=OPEN_ALWAYS;
-               break;
-       default:
-               g_warning("System.IO.FileMode has unknown value 0x%x",
-                         mono_mode);
-               /* Safe fallback */
-               mode=OPEN_EXISTING;
-       }
-       
-       return(mode);
-}
-
-static guint32 convert_access(MonoFileAccess mono_access)
-{
-       guint32 access;
-       
-       switch(mono_access) {
-       case FileAccess_Read:
-               access=GENERIC_READ;
-               break;
-       case FileAccess_Write:
-               access=GENERIC_WRITE;
-               break;
-       case FileAccess_ReadWrite:
-               access=GENERIC_READ|GENERIC_WRITE;
-               break;
-       default:
-               g_warning("System.IO.FileAccess has unknown value 0x%x",
-                         mono_access);
-               /* Safe fallback */
-               access=GENERIC_READ;
-       }
-       
-       return(access);
-}
-
-static guint32 convert_share(MonoFileShare mono_share)
-{
-       guint32 share = 0;
-       
-       if (mono_share & FileShare_Read) {
-               share |= FILE_SHARE_READ;
-       }
-       if (mono_share & FileShare_Write) {
-               share |= FILE_SHARE_WRITE;
-       }
-       if (mono_share & FileShare_Delete) {
-               share |= FILE_SHARE_DELETE;
-       }
-       
-       if (mono_share & ~(FileShare_Read|FileShare_Write|FileShare_Delete)) {
-               g_warning("System.IO.FileShare has unknown value 0x%x",
-                         mono_share);
-               /* Safe fallback */
-               share=0;
-       }
-
-       return(share);
-}
-
-#if 0
-static guint32 convert_stdhandle(guint32 fd)
-{
-       guint32 stdhandle;
-       
-       switch(fd) {
-       case 0:
-               stdhandle=STD_INPUT_HANDLE;
-               break;
-       case 1:
-               stdhandle=STD_OUTPUT_HANDLE;
-               break;
-       case 2:
-               stdhandle=STD_ERROR_HANDLE;
-               break;
-       default:
-               g_warning("unknown standard file descriptor %d", fd);
-               stdhandle=STD_INPUT_HANDLE;
-       }
-       
-       return(stdhandle);
-}
-#endif
-
-static guint32 convert_seekorigin(MonoSeekOrigin origin)
-{
-       guint32 w32origin;
-       
-       switch(origin) {
-       case SeekOrigin_Begin:
-               w32origin=FILE_BEGIN;
-               break;
-       case SeekOrigin_Current:
-               w32origin=FILE_CURRENT;
-               break;
-       case SeekOrigin_End:
-               w32origin=FILE_END;
-               break;
-       default:
-               g_warning("System.IO.SeekOrigin has unknown value 0x%x",
-                         origin);
-               /* Safe fallback */
-               w32origin=FILE_CURRENT;
-       }
-       
-       return(w32origin);
-}
-
-static gint64 convert_filetime (const FILETIME *filetime)
-{
-       guint64 ticks = filetime->dwHighDateTime;
-       ticks <<= 32;
-       ticks += filetime->dwLowDateTime;
-       return (gint64)ticks;
-}
-
-static void convert_win32_file_attribute_data (const WIN32_FILE_ATTRIBUTE_DATA *data, MonoIOStat *stat)
-{
-       stat->attributes = data->dwFileAttributes;
-       stat->creation_time = convert_filetime (&data->ftCreationTime);
-       stat->last_access_time = convert_filetime (&data->ftLastAccessTime);
-       stat->last_write_time = convert_filetime (&data->ftLastWriteTime);
-       stat->length = ((gint64)data->nFileSizeHigh << 32) | data->nFileSizeLow;
-}
-
-/* Managed file attributes have nearly but not quite the same values
- * as the w32 equivalents.
- */
-static guint32 convert_attrs(MonoFileAttributes attrs)
-{
-       if(attrs & FileAttributes_Encrypted) {
-               attrs = (MonoFileAttributes)(attrs | FILE_ATTRIBUTE_ENCRYPTED);
-       }
-       
-       return(attrs);
-}
-
-/*
- * On Win32, GetFileAttributes|Ex () seems to try opening the file,
- * which might lead to sharing violation errors, whereas FindFirstFile
- * always succeeds. These 2 wrappers resort to FindFirstFile if
- * GetFileAttributes|Ex () has failed.
- */
-static guint32
-get_file_attributes (const gunichar2 *path)
-{
-       guint32 res;
-       WIN32_FIND_DATA find_data;
-       HANDLE find_handle;
-       gint32 error;
-
-       res = GetFileAttributes (path);
-       if (res != -1)
-               return res;
-
-       error = GetLastError ();
-
-       if (error != ERROR_SHARING_VIOLATION)
-               return res;
-
-       find_handle = FindFirstFile (path, &find_data);
-
-       if (find_handle == INVALID_HANDLE_VALUE)
-               return res;
-
-       FindClose (find_handle);
-
-       return find_data.dwFileAttributes;
-}
-
-static gboolean
-get_file_attributes_ex (const gunichar2 *path, WIN32_FILE_ATTRIBUTE_DATA *data)
-{
-       gboolean res;
-       WIN32_FIND_DATA find_data;
-       HANDLE find_handle;
-       gint32 error;
-
-       res = GetFileAttributesEx (path, GetFileExInfoStandard, data);
-       if (res)
-               return TRUE;
-
-       error = GetLastError ();
-
-       if (error != ERROR_SHARING_VIOLATION)
-               return FALSE;
-
-       find_handle = FindFirstFile (path, &find_data);
-
-       if (find_handle == INVALID_HANDLE_VALUE)
-               return FALSE;
-
-       FindClose (find_handle);
-
-       data->dwFileAttributes = find_data.dwFileAttributes;
-       data->ftCreationTime = find_data.ftCreationTime;
-       data->ftLastAccessTime = find_data.ftLastAccessTime;
-       data->ftLastWriteTime = find_data.ftLastWriteTime;
-       data->nFileSizeHigh = find_data.nFileSizeHigh;
-       data->nFileSizeLow = find_data.nFileSizeLow;
-       
-       return TRUE;
-}
-
-/* System.IO.MonoIO internal calls */
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error)
-{
-       gboolean ret;
-       MONO_ENTER_GC_SAFE;
-       
-       *error=ERROR_SUCCESS;
-       
-       ret=CreateDirectory (mono_string_chars (path), NULL);
-       if(ret==FALSE) {
-               *error=GetLastError ();
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return(ret);
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error)
-{
-       gboolean ret;
-       MONO_ENTER_GC_SAFE;
-       
-       *error=ERROR_SUCCESS;
-       
-       ret=RemoveDirectory (mono_string_chars (path));
-       if(ret==FALSE) {
-               *error=GetLastError ();
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return(ret);
-}
-
-static gchar *
-get_search_dir (const gunichar2 *pattern)
-{
-       gchar *p;
-       gchar *result;
-
-       p = g_utf16_to_utf8 (pattern, -1, NULL, NULL, NULL);
-       result = g_path_get_dirname (p);
-       g_free (p);
-       return result;
-}
-
-static GPtrArray *
-get_filesystem_entries (const gunichar2 *path,
-                                                const gunichar2 *path_with_pattern,
-                                                gint attrs, gint mask,
-                                                gint32 *error)
-{
-       int i;
-       WIN32_FIND_DATA data;
-       HANDLE find_handle;
-       GPtrArray *names = NULL;
-       gchar *utf8_path = NULL, *utf8_result, *full_name;
-       gint32 attributes;
-
-       mask = convert_attrs ((MonoFileAttributes)mask);
-       attributes = get_file_attributes (path);
-       if (attributes != -1) {
-               if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
-                       *error = ERROR_INVALID_NAME;
-                       goto fail;
-               }
-       } else {
-               *error = GetLastError ();
-               goto fail;
-       }
-       
-       find_handle = FindFirstFile (path_with_pattern, &data);
-       if (find_handle == INVALID_HANDLE_VALUE) {
-               gint32 find_error = GetLastError ();
-               
-               if (find_error == ERROR_FILE_NOT_FOUND || find_error == ERROR_NO_MORE_FILES) {
-                       /* No files, so just return an empty array */
-                       goto fail;
-               }
-               
-               *error = find_error;
-               goto fail;
-       }
-
-       utf8_path = get_search_dir (path_with_pattern);
-       names = g_ptr_array_new ();
-
-       do {
-               if ((data.cFileName[0] == '.' && data.cFileName[1] == 0) ||
-                   (data.cFileName[0] == '.' && data.cFileName[1] == '.' && data.cFileName[2] == 0)) {
-                       continue;
-               }
-               
-               if ((data.dwFileAttributes & mask) == attrs) {
-                       utf8_result = g_utf16_to_utf8 (data.cFileName, -1, NULL, NULL, NULL);
-                       if (utf8_result == NULL) {
-                               continue;
-                       }
-                       
-                       full_name = g_build_filename (utf8_path, utf8_result, NULL);
-                       g_ptr_array_add (names, full_name);
-
-                       g_free (utf8_result);
-               }
-       } while(FindNextFile (find_handle, &data));
-
-       if (FindClose (find_handle) == FALSE) {
-               *error = GetLastError ();
-               goto fail;
-       }
-
-       g_free (utf8_path);
-       return names;
-fail:
-       if (names) {
-               for (i = 0; i < names->len; i++)
-                       g_free (g_ptr_array_index (names, i));
-               g_ptr_array_free (names, TRUE);
-       }
-       g_free (utf8_path);
-       return FALSE;
-}
-
-
-MonoArray *
-ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
-                                                MonoString *path_with_pattern,
-                                                gint attrs, gint mask,
-                                                gint32 *ioerror)
-{
-       MonoError error;
-       MonoDomain *domain = mono_domain_get ();
-       MonoArray *result;
-       int i;
-       GPtrArray *names;
-       
-       *ioerror = ERROR_SUCCESS;
-
-       MONO_ENTER_GC_SAFE;
-       names = get_filesystem_entries (mono_string_chars (path), mono_string_chars (path_with_pattern), attrs, mask, ioerror);
-       MONO_EXIT_GC_SAFE;
-
-       if (!names) {
-               // If there's no array and no error, then return an empty array.
-               if (*ioerror == ERROR_SUCCESS) {
-                       MonoArray *arr = mono_array_new_checked (domain, mono_defaults.string_class, 0, &error);
-                       mono_error_set_pending_exception (&error);
-                       return arr;
-               }
-               return NULL;
-       }
-
-       result = mono_array_new_checked (domain, mono_defaults.string_class, names->len, &error);
-       if (mono_error_set_pending_exception (&error))
-               goto leave;
-       for (i = 0; i < names->len; i++) {
-               mono_array_setref (result, i, mono_string_new (domain, (const char *)g_ptr_array_index (names, i)));
-               g_free (g_ptr_array_index (names, i));
-       }
-leave:
-       g_ptr_array_free (names, TRUE);
-       return result;
-}
-
-typedef struct {
-       MonoDomain *domain;
-       gchar *utf8_path;
-       HANDLE find_handle;
-} IncrementalFind;
-       
-static gboolean
-incremental_find_check_match (IncrementalFind *handle, WIN32_FIND_DATA *data, MonoString **result)
-{
-       gchar *utf8_result;
-       gchar *full_name;
-       
-       if ((data->cFileName[0] == '.' && data->cFileName[1] == 0) || (data->cFileName[0] == '.' && data->cFileName[1] == '.' && data->cFileName[2] == 0))
-               return FALSE;
-
-       utf8_result = g_utf16_to_utf8 (data->cFileName, -1, NULL, NULL, NULL);
-       if (utf8_result == NULL) 
-               return FALSE;
-       
-       full_name = g_build_filename (handle->utf8_path, utf8_result, NULL);
-       g_free (utf8_result);
-       *result = mono_string_new (mono_domain_get (), full_name);
-       g_free (full_name);
-       
-       return TRUE;
-}
-
-HANDLE
-ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path_with_pattern, MonoString **file_name, gint32 *file_attr, gint32 *ioerror)
-{
-       HANDLE hnd;
-       WIN32_FIND_DATA data;
-       MonoError error;
-
-       hnd = FindFirstFile (mono_string_chars (path_with_pattern), &data);
-
-       if (hnd == INVALID_HANDLE_VALUE) {
-               *file_name = NULL;
-               *file_attr = 0;
-               *ioerror = GetLastError ();
-               return hnd;
-       }
-
-       mono_gc_wbarrier_generic_store (file_name, (MonoObject*) mono_string_from_utf16_checked (data.cFileName, &error));
-       mono_error_set_pending_exception (&error);
-
-       *file_attr = data.dwFileAttributes;
-       *ioerror = ERROR_SUCCESS;
-
-       return hnd;
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_FindNextFile (HANDLE hnd, MonoString **file_name, gint32 *file_attr, gint32 *ioerror)
-{
-       MonoBoolean res;
-       WIN32_FIND_DATA data;
-       MonoError error;
-
-       res = FindNextFile (hnd, &data);
-
-       if (res == FALSE) {
-               *file_name = NULL;
-               *file_attr = 0;
-               *ioerror = GetLastError ();
-               return res;
-       }
-
-       mono_gc_wbarrier_generic_store (file_name, (MonoObject*) mono_string_from_utf16_checked (data.cFileName, &error));
-       mono_error_set_pending_exception (&error);
-
-       *file_attr = data.dwFileAttributes;
-       *ioerror = ERROR_SUCCESS;
-
-       return res;
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_FindCloseFile (HANDLE hnd)
-{
-       return FindClose (hnd);
-}
-
-/* FIXME make gc suspendable */
-MonoString *
-ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
-                                     MonoString *path_with_pattern,
-                                     gint32 *result_attr, gint32 *ioerror,
-                                     gpointer *handle)
-{
-       MonoError error;
-       WIN32_FIND_DATA data;
-       HANDLE find_handle;
-       IncrementalFind *ifh;
-       MonoString *result;
-       
-       *ioerror = ERROR_SUCCESS;
-       
-       find_handle = FindFirstFile (mono_string_chars (path_with_pattern), &data);
-       
-       if (find_handle == INVALID_HANDLE_VALUE) {
-               gint32 find_error = GetLastError ();
-               *handle = NULL;
-               
-               if (find_error == ERROR_FILE_NOT_FOUND) 
-                       return NULL;
-               
-               *ioerror = find_error;
-               return NULL;
-       }
-
-       ifh = g_new (IncrementalFind, 1);
-       ifh->find_handle = find_handle;
-       ifh->utf8_path = mono_string_to_utf8_checked (path, &error);
-       if (mono_error_set_pending_exception (&error)) {
-               MONO_ENTER_GC_SAFE;
-               FindClose (find_handle);
-               MONO_EXIT_GC_SAFE;
-               g_free (ifh);
-               return NULL;
-       }
-       ifh->domain = mono_domain_get ();
-       *handle = ifh;
-
-       while (incremental_find_check_match (ifh, &data, &result) == 0){
-               if (FindNextFile (find_handle, &data) == FALSE){
-                       int e = GetLastError ();
-                       if (e != ERROR_NO_MORE_FILES)
-                               *ioerror = e;
-                       return NULL;
-               }
-       }
-       *result_attr = data.dwFileAttributes;
-       
-       return result;
-}
-
-/* FIXME make gc suspendable */
-MonoString *
-ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_attr, gint32 *error)
-{
-       IncrementalFind *ifh = (IncrementalFind *)handle;
-       WIN32_FIND_DATA data;
-       MonoString *result;
-
-       *error = ERROR_SUCCESS;
-       do {
-               if (FindNextFile (ifh->find_handle, &data) == FALSE){
-                       int e = GetLastError ();
-                       if (e != ERROR_NO_MORE_FILES)
-                               *error = e;
-                       return NULL;
-               }
-       } while (incremental_find_check_match (ifh, &data, &result) == 0);
-
-       *result_attr = data.dwFileAttributes;
-       return result;
-}
-
-int
-ves_icall_System_IO_MonoIO_FindClose (gpointer handle)
-{
-       IncrementalFind *ifh = (IncrementalFind *)handle;
-       gint32 error;
-
-       MONO_ENTER_GC_SAFE;
-       if (FindClose (ifh->find_handle) == FALSE){
-               error = GetLastError ();
-       } else
-               error = ERROR_SUCCESS;
-       g_free (ifh->utf8_path);
-       g_free (ifh);
-       MONO_EXIT_GC_SAFE;
-
-       return error;
-}
-
-MonoString *
-ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *io_error)
-{
-       MonoError error;
-       MonoString *result;
-       gunichar2 *buf;
-       int len, res_len;
-
-       len = MAX_PATH + 1; /*FIXME this is too smal under most unix systems.*/
-       buf = g_new (gunichar2, len);
-       
-       mono_error_init (&error);
-       *io_error=ERROR_SUCCESS;
-       result = NULL;
-
-       res_len = GetCurrentDirectory (len, buf);
-       if (res_len > len) { /*buf is too small.*/
-               int old_res_len = res_len;
-               g_free (buf);
-               buf = g_new (gunichar2, res_len);
-               res_len = GetCurrentDirectory (res_len, buf) == old_res_len;
-       }
-       
-       if (res_len) {
-               len = 0;
-               while (buf [len])
-                       ++ len;
-
-               result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
-       } else {
-               *io_error=GetLastError ();
-       }
-
-       g_free (buf);
-       mono_error_set_pending_exception (&error);
-       return result;
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString *path,
-                                               gint32 *error)
-{
-       gboolean ret;
-       
-       *error=ERROR_SUCCESS;
-       
-       ret=SetCurrentDirectory (mono_string_chars (path));
-       if(ret==FALSE) {
-               *error=GetLastError ();
-       }
-       
-       return(ret);
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-gboolean
-mono_file_io_move_file (gunichar2 *path, gunichar2 *dest, gint32 *error)
-{
-       gboolean result = FALSE;
-       MONO_ENTER_GC_SAFE;
-
-       result = MoveFile (path, dest);
-       if (result == FALSE) {
-               *error=GetLastError ();
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return result;
-}
-#endif /* HAVE_CLASSIC_WINAPI_SUPPORT */
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest, gint32 *error)
-{
-       *error=ERROR_SUCCESS;
-       return mono_file_io_move_file (mono_string_chars (path), mono_string_chars (dest), error);
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-gboolean
-mono_file_io_replace_file (gunichar2 *destinationFileName, gunichar2 *sourceFileName,
-                          gunichar2 *destinationBackupFileName, guint32 flags, gint32 *error)
-{
-       gboolean result = FALSE;
-       MONO_ENTER_GC_SAFE;
-
-       result = ReplaceFile (destinationFileName, sourceFileName, destinationBackupFileName, flags, NULL, NULL);
-       if (result == FALSE) {
-               *error=GetLastError ();
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return result;
-}
-#endif /* HAVE_CLASSIC_WINAPI_SUPPORT */
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *destinationFileName,
-                                       MonoString *destinationBackupFileName, MonoBoolean ignoreMetadataErrors,
-                                       gint32 *error)
-{
-       gunichar2 *utf16_sourceFileName = NULL, *utf16_destinationFileName = NULL, *utf16_destinationBackupFileName = NULL;
-       guint32 replaceFlags = REPLACEFILE_WRITE_THROUGH;
-
-       if (sourceFileName)
-               utf16_sourceFileName = mono_string_chars (sourceFileName);
-       if (destinationFileName)
-               utf16_destinationFileName = mono_string_chars (destinationFileName);
-       if (destinationBackupFileName)
-               utf16_destinationBackupFileName = mono_string_chars (destinationBackupFileName);
-
-       *error = ERROR_SUCCESS;
-       if (ignoreMetadataErrors)
-               replaceFlags |= REPLACEFILE_IGNORE_MERGE_ERRORS;
-
-       /* FIXME: source and destination file names must not be NULL, but apparently they might be! */
-       return mono_file_io_replace_file (utf16_destinationFileName, utf16_sourceFileName,
-                                         utf16_destinationBackupFileName, replaceFlags, error);
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-gboolean
-mono_file_io_copy_file (gunichar2 *path, gunichar2 *dest, gboolean overwrite, gint32 *error)
-{
-       gboolean result = FALSE;
-       MONO_ENTER_GC_SAFE;
-
-       result = CopyFile (path, dest, !overwrite);
-       if (result == FALSE) {
-               *error=GetLastError ();
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return result;
-}
-#endif /* HAVE_CLASSIC_WINAPI_SUPPORT */
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest,
-                                    MonoBoolean overwrite, gint32 *error)
-{
-       *error=ERROR_SUCCESS;
-       return mono_file_io_copy_file (mono_string_chars (path), mono_string_chars (dest), overwrite, error);
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error)
-{
-       gboolean ret;
-       MONO_ENTER_GC_SAFE;
-       
-       *error=ERROR_SUCCESS;
-       
-       ret=DeleteFile (mono_string_chars (path));
-       if(ret==FALSE) {
-               *error=GetLastError ();
-       }
-       
-       MONO_EXIT_GC_SAFE;
-       return(ret);
-}
-
-gint32 
-ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
-{
-       gint32 ret;
-       MONO_ENTER_GC_SAFE;
-
-       *error=ERROR_SUCCESS;
-       
-       ret=get_file_attributes (mono_string_chars (path));
-
-       /* 
-        * The definition of INVALID_FILE_ATTRIBUTES in the cygwin win32
-        * headers is wrong, hence this temporary workaround.
-        * See
-        * http://cygwin.com/ml/cygwin/2003-09/msg01771.html
-        */
-       if (ret==-1) {
-         /* if(ret==INVALID_FILE_ATTRIBUTES) { */
-               *error=GetLastError ();
-       }
-       
-       MONO_EXIT_GC_SAFE;
-       return(ret);
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
-                                             gint32 *error)
-{
-       gboolean ret;
-       MONO_ENTER_GC_SAFE;
-       
-       *error=ERROR_SUCCESS;
-       
-       ret=SetFileAttributes (mono_string_chars (path),
-               convert_attrs ((MonoFileAttributes)attrs));
-       if(ret==FALSE) {
-               *error=GetLastError ();
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return(ret);
-}
-
-gint32
-ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
-{
-       gboolean ret;
-       MONO_ENTER_GC_SAFE;
-
-       *error=ERROR_SUCCESS;
-       
-       ret=GetFileType (handle);
-       if(ret==FILE_TYPE_UNKNOWN) {
-               /* Not necessarily an error, but the caller will have
-                * to decide based on the error value.
-                */
-               *error=GetLastError ();
-       }
-       
-       MONO_EXIT_GC_SAFE;
-       return(ret);
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat,
-                                       gint32 *error)
-{
-       gboolean result;
-       WIN32_FILE_ATTRIBUTE_DATA data;
-       MONO_ENTER_GC_SAFE;
-
-       *error=ERROR_SUCCESS;
-       
-       result = get_file_attributes_ex (mono_string_chars (path), &data);
-
-       if (result) {
-               convert_win32_file_attribute_data (&data, stat);
-       } else {
-               *error=GetLastError ();
-               memset (stat, 0, sizeof (MonoIOStat));
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return result;
-}
-
-HANDLE 
-ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
-                                gint32 access_mode, gint32 share, gint32 options,
-                                gint32 *error)
-{
-       HANDLE ret;
-       int attributes, attrs;
-       gunichar2 *chars;
-       MONO_ENTER_GC_SAFE;
-
-       chars = mono_string_chars (filename);   
-       *error=ERROR_SUCCESS;
-
-       if (options != 0){
-               if (options & FileOptions_Encrypted)
-                       attributes = FILE_ATTRIBUTE_ENCRYPTED;
-               else
-                       attributes = FILE_ATTRIBUTE_NORMAL;
-               if (options & FileOptions_DeleteOnClose)
-                       attributes |= FILE_FLAG_DELETE_ON_CLOSE;
-               if (options & FileOptions_SequentialScan)
-                       attributes |= FILE_FLAG_SEQUENTIAL_SCAN;
-               if (options & FileOptions_RandomAccess)
-                       attributes |= FILE_FLAG_RANDOM_ACCESS;
-
-               if (options & FileOptions_Temporary)
-                       attributes |= FILE_ATTRIBUTE_TEMPORARY;
-               
-               if (options & FileOptions_WriteThrough)
-                       attributes |= FILE_FLAG_WRITE_THROUGH;
-       } else
-               attributes = FILE_ATTRIBUTE_NORMAL;
-
-       /* If we're opening a directory we need to set the extra flag
-        */
-       attrs = get_file_attributes (chars);
-       if (attrs != INVALID_FILE_ATTRIBUTES) {
-               if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
-                       attributes |= FILE_FLAG_BACKUP_SEMANTICS;
-               }
-       }
-       
-       ret=CreateFile (chars, convert_access ((MonoFileAccess)access_mode),
-                       convert_share ((MonoFileShare)share), NULL, convert_mode ((MonoFileMode)mode),
-                       attributes, NULL);
-       if(ret==INVALID_HANDLE_VALUE) {
-               *error=GetLastError ();
-       } 
-       
-       MONO_EXIT_GC_SAFE;
-       return(ret);
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error)
-{
-       gboolean ret;
-       MONO_ENTER_GC_SAFE;
-
-       *error=ERROR_SUCCESS;
-       
-       ret=CloseHandle (handle);
-       if(ret==FALSE) {
-               *error=GetLastError ();
-       }
-       
-       MONO_EXIT_GC_SAFE;
-       return(ret);
-}
-
-gint32 
-ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArray *dest,
-                                gint32 dest_offset, gint32 count,
-                                gint32 *error)
-{
-       guchar *buffer;
-       gboolean result;
-       guint32 n;
-
-       *error=ERROR_SUCCESS;
-
-       MONO_CHECK_ARG_NULL (dest, 0);
-
-       if (dest_offset > mono_array_length (dest) - count) {
-               mono_set_pending_exception (mono_get_exception_argument ("array", "array too small. numBytes/offset wrong."));
-               return 0;
-       }
-
-       buffer = mono_array_addr (dest, guchar, dest_offset);
-
-       MONO_ENTER_GC_SAFE;
-       result = ReadFile (handle, buffer, count, &n, NULL);
-       MONO_EXIT_GC_SAFE;
-
-       if (!result) {
-               *error=GetLastError ();
-               return -1;
-       }
-
-       return (gint32)n;
-}
-
-gint32 
-ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArray *src,
-                                 gint32 src_offset, gint32 count,
-                                 gint32 *error)
-{
-       guchar *buffer;
-       gboolean result;
-       guint32 n;
-
-       *error=ERROR_SUCCESS;
-
-       MONO_CHECK_ARG_NULL (src, 0);
-       
-       if (src_offset > mono_array_length (src) - count) {
-               mono_set_pending_exception (mono_get_exception_argument ("array", "array too small. numBytes/offset wrong."));
-               return 0;
-       }
-       
-       buffer = mono_array_addr (src, guchar, src_offset);
-       MONO_ENTER_GC_SAFE;
-       result = WriteFile (handle, buffer, count, &n, NULL);
-       MONO_EXIT_GC_SAFE;
-
-       if (!result) {
-               *error=GetLastError ();
-               return -1;
-       }
-
-       return (gint32)n;
-}
-
-gint64 
-ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
-                                gint32 *error)
-{
-       gint32 offset_hi;
-       MONO_ENTER_GC_SAFE;
-
-       *error=ERROR_SUCCESS;
-       
-       offset_hi = offset >> 32;
-       offset = SetFilePointer (handle, (gint32) (offset & 0xFFFFFFFF), &offset_hi,
-                                convert_seekorigin ((MonoSeekOrigin)origin));
-
-       if(offset==INVALID_SET_FILE_POINTER) {
-               *error=GetLastError ();
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return offset | ((gint64)offset_hi << 32);
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
-{
-       gboolean ret;
-       MONO_ENTER_GC_SAFE;
-
-       *error=ERROR_SUCCESS;
-       
-       ret=FlushFileBuffers (handle);
-       if(ret==FALSE) {
-               *error=GetLastError ();
-       }
-       
-       MONO_EXIT_GC_SAFE;
-       return(ret);
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-gint64
-mono_file_io_get_file_size (HANDLE handle, gint32 *error)
-{
-       gint64 length;
-       guint32 length_hi;
-
-       MONO_ENTER_GC_SAFE;
-
-       length = GetFileSize (handle, &length_hi);
-       if(length==INVALID_FILE_SIZE) {
-               *error=GetLastError ();
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return length | ((gint64)length_hi << 32);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-gint64
-ves_icall_System_IO_MonoIO_GetLength (HANDLE handle, gint32 *error)
-{
-       *error=ERROR_SUCCESS;
-       return mono_file_io_get_file_size (handle, error);
-}
-
-/* FIXME make gc suspendable */
-MonoBoolean
-ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length,
-                                     gint32 *error)
-{
-       gint64 offset, offset_set;
-       gint32 offset_hi;
-       gint32 length_hi;
-       gboolean result;
-
-       *error=ERROR_SUCCESS;
-       
-       /* save file pointer */
-
-       offset_hi = 0;
-       offset = SetFilePointer (handle, 0, &offset_hi, FILE_CURRENT);
-       if(offset==INVALID_SET_FILE_POINTER) {
-               *error=GetLastError ();
-               return(FALSE);
-       }
-
-       /* extend or truncate */
-
-       length_hi = length >> 32;
-       offset_set=SetFilePointer (handle, length & 0xFFFFFFFF, &length_hi,
-                                  FILE_BEGIN);
-       if(offset_set==INVALID_SET_FILE_POINTER) {
-               *error=GetLastError ();
-               return(FALSE);
-       }
-
-       result = SetEndOfFile (handle);
-       if(result==FALSE) {
-               *error=GetLastError ();
-               return(FALSE);
-       }
-
-       /* restore file pointer */
-
-       offset_set=SetFilePointer (handle, offset & 0xFFFFFFFF, &offset_hi,
-                                  FILE_BEGIN);
-       if(offset_set==INVALID_SET_FILE_POINTER) {
-               *error=GetLastError ();
-               return(FALSE);
-       }
-
-       return result;
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
-                                       gint64 last_access_time,
-                                       gint64 last_write_time, gint32 *error)
-{
-       gboolean ret;
-       const FILETIME *creation_filetime;
-       const FILETIME *last_access_filetime;
-       const FILETIME *last_write_filetime;
-       MONO_ENTER_GC_SAFE;
-
-       *error=ERROR_SUCCESS;
-       
-       if (creation_time < 0)
-               creation_filetime = NULL;
-       else
-               creation_filetime = (FILETIME *)&creation_time;
-
-       if (last_access_time < 0)
-               last_access_filetime = NULL;
-       else
-               last_access_filetime = (FILETIME *)&last_access_time;
-
-       if (last_write_time < 0)
-               last_write_filetime = NULL;
-       else
-               last_write_filetime = (FILETIME *)&last_write_time;
-
-       ret=SetFileTime (handle, creation_filetime, last_access_filetime, last_write_filetime);
-       if(ret==FALSE) {
-               *error=GetLastError ();
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return(ret);
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-HANDLE
-mono_file_io_get_console_output (void)
-{
-       return GetStdHandle (STD_OUTPUT_HANDLE);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-HANDLE 
-ves_icall_System_IO_MonoIO_get_ConsoleOutput ()
-{
-       return mono_file_io_get_console_output ();
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-HANDLE
-mono_file_io_get_console_input (void)
-{
-       return GetStdHandle (STD_INPUT_HANDLE);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-HANDLE 
-ves_icall_System_IO_MonoIO_get_ConsoleInput ()
-{
-       return mono_file_io_get_console_input ();
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-HANDLE
-mono_file_io_get_console_error (void)
-{
-       return GetStdHandle (STD_ERROR_HANDLE);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-HANDLE 
-ves_icall_System_IO_MonoIO_get_ConsoleError ()
-{
-       return mono_file_io_get_console_error ();
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle, HANDLE *write_handle, gint32 *error)
-{
-       SECURITY_ATTRIBUTES attr;
-       gboolean ret;
-       
-       attr.nLength=sizeof(SECURITY_ATTRIBUTES);
-       attr.bInheritHandle=TRUE;
-       attr.lpSecurityDescriptor=NULL;
-
-       MONO_ENTER_GC_SAFE;
-       ret=CreatePipe (read_handle, write_handle, &attr, 0);
-       MONO_EXIT_GC_SAFE;
-
-       if(ret==FALSE) {
-               *error = GetLastError ();
-               /* FIXME: throw an exception? */
-               return(FALSE);
-       }
-       
-       return(TRUE);
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_handle, HANDLE source_handle,
-               HANDLE target_process_handle, HANDLE *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error)
-{
-       /* This is only used on Windows */
-       gboolean ret;
-       
-       MONO_ENTER_GC_SAFE;
-#ifdef HOST_WIN32
-       ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options);
-#else
-       mono_w32handle_ref (source_handle);
-       *target_handle = source_handle;
-       ret = TRUE;
-#endif
-       MONO_EXIT_GC_SAFE;
-
-       if(ret==FALSE) {
-               *error = GetLastError ();
-               /* FIXME: throw an exception? */
-               return(FALSE);
-       }
-       
-       return(TRUE);
-}
-
-#ifndef HOST_WIN32
-gunichar2 
-ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
-{
-       return (gunichar2) '/'; /* forward slash */
-}
-
-gunichar2 
-ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
-{
-       return (gunichar2) '/'; /* forward slash */
-}
-
-gunichar2 
-ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
-{
-       if (IS_PORTABILITY_SET)
-               return (gunichar2) '\\';        /* backslash */
-       else
-               return (gunichar2) '/'; /* forward slash */
-}
-
-gunichar2 
-ves_icall_System_IO_MonoIO_get_PathSeparator ()
-{
-       return (gunichar2) ':'; /* colon */
-}
-#endif /* !HOST_WIN32 */
-
-static const gunichar2
-invalid_path_chars [] = {
-#if defined (TARGET_WIN32)
-       0x0022,                         /* double quote, which seems allowed in MS.NET but should be rejected */
-       0x003c,                         /* less than */
-       0x003e,                         /* greater than */
-       0x007c,                         /* pipe */
-       0x0008,
-       0x0010,
-       0x0011,
-       0x0012,
-       0x0014,
-       0x0015,
-       0x0016,
-       0x0017,
-       0x0018,
-       0x0019,
-#endif
-       0x0000                          /* null */
-};
-
-MonoArray *
-ves_icall_System_IO_MonoIO_get_InvalidPathChars ()
-{
-       MonoError error;
-       MonoArray *chars;
-       MonoDomain *domain;
-       int i, n;
-
-       domain = mono_domain_get ();
-       n = sizeof (invalid_path_chars) / sizeof (gunichar2);
-       chars = mono_array_new_checked (domain, mono_defaults.char_class, n, &error);
-       if (mono_error_set_pending_exception (&error))
-               return NULL;
-
-       for (i = 0; i < n; ++ i)
-               mono_array_set (chars, gunichar2, i, invalid_path_chars [i]);
-       
-       return chars;
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-gboolean
-mono_file_io_lock_file (HANDLE handle, gint64 position, gint64 length, gint32 *error)
-{
-       gboolean result = FALSE;
-       MONO_ENTER_GC_SAFE;
-
-       result = LockFile (handle, position & 0xFFFFFFFF, position >> 32,
-                          length & 0xFFFFFFFF, length >> 32);
-
-       if (result == FALSE) {
-               *error = GetLastError ();
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return result;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position,
-                                     gint64 length, gint32 *error)
-{
-       *error=ERROR_SUCCESS;
-       mono_file_io_lock_file (handle, position, length, error);
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-gboolean
-mono_file_io_unlock_file (HANDLE handle, gint64 position, gint64 length, gint32 *error)
-{
-       gboolean result = FALSE;
-       MONO_ENTER_GC_SAFE;
-       
-       result = UnlockFile (handle, position & 0xFFFFFFFF, position >> 32,
-                            length & 0xFFFFFFFF, length >> 32);
-
-       if (result == FALSE) {
-               *error = GetLastError ();
-       }
-
-       MONO_EXIT_GC_SAFE;
-       return result;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position,
-                                       gint64 length, gint32 *error)
-{
-       *error=ERROR_SUCCESS;
-       mono_file_io_unlock_file (handle, position, length, error);
-}
-
-//Support for io-layer free mmap'd files.
-
-#if defined (TARGET_IOS) || defined (TARGET_ANDROID)
-
-gint64
-mono_filesize_from_path (MonoString *string)
-{
-       MonoError error;
-       struct stat buf;
-       gint64 res;
-       char *path = mono_string_to_utf8_checked (string, &error);
-       mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */
-
-       MONO_ENTER_GC_SAFE;
-       if (stat (path, &buf) == -1)
-               res = -1;
-       else
-               res = (gint64)buf.st_size;
-
-       g_free (path);
-
-       MONO_EXIT_GC_SAFE;
-       return res;
-}
-
-gint64
-mono_filesize_from_fd (int fd)
-{
-       struct stat buf;
-       int res;
-
-       MONO_ENTER_GC_SAFE;
-       res = fstat (fd, &buf);
-       MONO_EXIT_GC_SAFE;
-       
-       if (res == -1)
-               return (gint64)-1;
-
-       return (gint64)buf.st_size;
-}
-
-#endif
-
-#ifndef HOST_WIN32
-void mono_w32handle_dump (void);
-
-void ves_icall_System_IO_MonoIO_DumpHandles (void)
-{
-
-       mono_w32handle_dump ();
-}
-#endif /* !HOST_WIN32 */
diff --git a/mono/metadata/file-io.h b/mono/metadata/file-io.h
deleted file mode 100644 (file)
index b7b7320..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * file-io.h: File IO internal calls
- *
- * Authors:
- *     Dick Porter (dick@ximian.com)
- *     Dan Lewis (dihlewis@yahoo.co.uk)
- *
- * (C) 2001 Ximian, Inc.
- * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#ifndef _MONO_METADATA_FILEIO_H_
-#define _MONO_METADATA_FILEIO_H_
-
-#include <config.h>
-#include <glib.h>
-
-#include <mono/metadata/object-internals.h>
-#include <mono/utils/mono-compiler.h>
-
-G_BEGIN_DECLS
-
-/* This is a copy of System.IO.FileAccess */
-typedef enum {
-       FileAccess_Read=0x01,
-       FileAccess_Write=0x02,
-       FileAccess_ReadWrite=FileAccess_Read|FileAccess_Write
-} MonoFileAccess;
-
-/* This is a copy of System.IO.FileMode */
-typedef enum {
-       FileMode_CreateNew=1,
-       FileMode_Create=2,
-       FileMode_Open=3,
-       FileMode_OpenOrCreate=4,
-       FileMode_Truncate=5,
-       FileMode_Append=6
-} MonoFileMode;
-
-/* This is a copy of System.IO.FileShare */
-typedef enum {
-       FileShare_None=0x0,
-       FileShare_Read=0x01,
-       FileShare_Write=0x02,
-       FileShare_ReadWrite=FileShare_Read|FileShare_Write,
-       FileShare_Delete=0x04
-} MonoFileShare;
-
-/* This is a copy of System.IO.FileOptions */
-typedef enum {
-       FileOptions_None = 0,
-       FileOptions_Temporary = 1,              // Internal.   See note in System.IO.FileOptions
-       FileOptions_Encrypted = 0x4000,
-       FileOptions_DeleteOnClose = 0x4000000,
-       FileOptions_SequentialScan = 0x8000000,
-       FileOptions_RandomAccess = 0x10000000,
-       FileOptions_Asynchronous = 0x40000000,
-       FileOptions_WriteThrough = 0x80000000
-} MonoFileOptions;
-
-/* This is a copy of System.IO.SeekOrigin */
-typedef enum {
-       SeekOrigin_Begin=0,
-       SeekOrigin_Current=1,
-       SeekOrigin_End=2
-} MonoSeekOrigin;
-
-/* This is a copy of System.IO.MonoIOStat */
-typedef struct _MonoIOStat {
-       gint32 attributes;
-       gint64 length;
-       gint64 creation_time;
-       gint64 last_access_time;
-       gint64 last_write_time;
-} MonoIOStat;
-
-/* This is a copy of System.IO.FileAttributes */
-typedef enum {
-       FileAttributes_ReadOnly=0x00001,
-       FileAttributes_Hidden=0x00002,
-       FileAttributes_System=0x00004,
-       FileAttributes_Directory=0x00010,
-       FileAttributes_Archive=0x00020,
-       FileAttributes_Device=0x00040,
-       FileAttributes_Normal=0x00080,
-       FileAttributes_Temporary=0x00100,
-       FileAttributes_SparseFile=0x00200,
-       FileAttributes_ReparsePoint=0x00400,
-       FileAttributes_Compressed=0x00800,
-       FileAttributes_Offline=0x01000,
-       FileAttributes_NotContentIndexed=0x02000,
-       FileAttributes_Encrypted=0x04000,
-       FileAttributes_MonoExecutable= (int) 0x80000000
-} MonoFileAttributes;
-/* This is not used anymore
-typedef struct _MonoFSAsyncResult {
-       MonoObject obj;
-       MonoObject *state;
-       MonoBoolean completed;
-       MonoBoolean done;
-       MonoException *exc;
-       MonoWaitHandle *wait_handle;
-       MonoDelegate *async_callback;
-       MonoBoolean completed_synch;
-       MonoArray *buffer;
-       gint offset;
-       gint count;
-       gint original_count;
-       gint bytes_read;
-       MonoDelegate *real_cb;
-} MonoFSAsyncResult;
-*/
-/* System.IO.MonoIO */
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error);
-
-MonoArray *
-ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
-                                                MonoString *path_with_pattern,
-                                                gint mask, gint attrs,
-                                                gint32 *error);
-
-extern gpointer
-ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path_with_pattern,
-                                               MonoString **file_name,
-                                               gint32 *file_attr,
-                                               gint32 *ioerror);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_FindNextFile (gpointer hnd,
-                                               MonoString **file_name,
-                                               gint32 *file_attr,
-                                               gint32 *ioerror);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_FindCloseFile (gpointer hnd);
-
-extern MonoString *
-ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
-                                     MonoString *path_with_pattern,
-                                     gint32 *result_mask,
-                                     gint32 *error,
-                                     gpointer *handle);
-extern MonoString *
-ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_mask, gint32 *error);
-
-extern int
-ves_icall_System_IO_MonoIO_FindClose (gpointer handle);
-
-extern MonoString *
-ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString *path,
-                                               gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest,
-                                    gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest,
-                                    MonoBoolean overwrite, gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error);
-
-extern gint32 
-ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
-                                             gint32 *error);
-
-extern gint32
-ves_icall_System_IO_MonoIO_GetFileType (gpointer handle, gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat,
-                                       gint32 *error);
-
-extern gpointer 
-ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
-                                gint32 access_mode, gint32 share, gint32 options,
-                                gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_Close (gpointer handle, gint32 *error);
-
-extern gint32 
-ves_icall_System_IO_MonoIO_Read (gpointer handle, MonoArray *dest,
-                                gint32 dest_offset, gint32 count,
-                                gint32 *error);
-
-extern gint32 
-ves_icall_System_IO_MonoIO_Write (gpointer handle, MonoArray *src,
-                                 gint32 src_offset, gint32 count,
-                                 gint32 *error);
-
-extern gint64 
-ves_icall_System_IO_MonoIO_Seek (gpointer handle, gint64 offset, gint32 origin,
-                                gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_Flush (gpointer handle, gint32 *error);
-
-extern gint64 
-ves_icall_System_IO_MonoIO_GetLength (gpointer handle, gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_SetLength (gpointer handle, gint64 length,
-                                     gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_SetFileTime (gpointer handle, gint64 creation_time,
-                                       gint64 last_access_time,
-                                       gint64 last_write_time, gint32 *error);
-
-extern gpointer 
-ves_icall_System_IO_MonoIO_get_ConsoleOutput (void);
-
-extern gpointer 
-ves_icall_System_IO_MonoIO_get_ConsoleInput (void);
-
-extern gpointer 
-ves_icall_System_IO_MonoIO_get_ConsoleError (void);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_CreatePipe (gpointer *read_handle, gpointer *write_handle, gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_DuplicateHandle (gpointer source_process_handle, gpointer source_handle,
-               gpointer target_process_handle, gpointer *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error);
-
-extern gunichar2 
-ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar (void);
-
-extern gunichar2 
-ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar (void);
-
-extern gunichar2 
-ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar (void);
-
-extern gunichar2 
-ves_icall_System_IO_MonoIO_get_PathSeparator (void);
-
-extern MonoArray *
-ves_icall_System_IO_MonoIO_get_InvalidPathChars (void);
-
-extern void ves_icall_System_IO_MonoIO_Lock (gpointer handle, gint64 position,
-                                            gint64 length, gint32 *error);
-extern void ves_icall_System_IO_MonoIO_Unlock (gpointer handle, gint64 position,
-                                              gint64 length, gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *destinationFileName,
-                                       MonoString *destinationBackupFileName, MonoBoolean ignoreMetadataErrors,
-                                       gint32 *error);
-
-MONO_RT_EXTERNAL_ONLY
-extern gint64
-mono_filesize_from_path (MonoString *path);
-
-extern gint64
-mono_filesize_from_fd (int fd);
-
-void
-ves_icall_System_IO_MonoIO_DumpHandles (void);
-
-G_END_DECLS
-
-#endif /* _MONO_METADATA_FILEIO_H_ */
index 4b9ce74499e04ec81a5b1ad1e422615d7c44636b..64332ed18d12f7273e6e7d868165a01e49167d41 100644 (file)
@@ -32,7 +32,7 @@
 
 
 #include <mono/metadata/object.h>
-#include <mono/metadata/file-io.h>
+#include <mono/metadata/w32file.h>
 #include <mono/metadata/file-mmap.h>
 #include <mono/utils/atomic.h>
 #include <mono/utils/mono-memory-model.h>
index b798a6e7c29f7b328ee0a02ac9c906587f9b07a1..f0dc4ef12388e9e8d7c8225536fbe2167062c753 100644 (file)
@@ -46,7 +46,7 @@
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/exception.h>
 #include <mono/metadata/exception-internals.h>
-#include <mono/metadata/file-io.h>
+#include <mono/metadata/w32file.h>
 #include <mono/metadata/console-io.h>
 #include <mono/metadata/mono-route.h>
 #include <mono/metadata/w32socket.h>
@@ -6691,7 +6691,7 @@ mono_icall_get_logical_drives (void)
        ptr = buf;
 
        while (size > initial_size) {
-               size = (guint) GetLogicalDriveStrings (initial_size, ptr);
+               size = (guint) mono_w32file_get_logical_drive (initial_size, ptr);
                if (size > initial_size) {
                        if (ptr != buf)
                                g_free (ptr);
@@ -6747,7 +6747,7 @@ ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
        MonoError error;
        gunichar2 volume_name [MAX_PATH + 1];
        
-       if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
+       if (mono_w32file_get_volume_information (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
                return NULL;
        MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
        mono_error_set_pending_exception (&error);
@@ -7026,24 +7026,12 @@ ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *
                                                gint32 *error)
 {
        gboolean result;
-       ULARGE_INTEGER wapi_free_bytes_avail;
-       ULARGE_INTEGER wapi_total_number_of_bytes;
-       ULARGE_INTEGER wapi_total_number_of_free_bytes;
 
        *error = ERROR_SUCCESS;
-       result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
-                                    &wapi_total_number_of_free_bytes);
 
-       if (result) {
-               *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
-               *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
-               *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
-       } else {
-               *free_bytes_avail = 0;
-               *total_number_of_bytes = 0;
-               *total_number_of_free_bytes = 0;
+       result = mono_w32file_get_disk_free_space (mono_string_chars (path_name), free_bytes_avail, total_number_of_bytes, total_number_of_free_bytes);
+       if (!result)
                *error = GetLastError ();
-       }
 
        return result;
 }
@@ -7052,7 +7040,7 @@ ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *
 static inline guint32
 mono_icall_drive_info_get_drive_type (MonoString *root_path_name)
 {
-       return GetDriveType (mono_string_chars (root_path_name));
+       return mono_w32file_get_drive_type (mono_string_chars (root_path_name));
 }
 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
 
index 421216d8113f6057023d6f04f4623df351de818c..4d94b5524b9cc102c17ec41b9bd4ab487e0698f2 100644 (file)
@@ -24,6 +24,7 @@
 #include "mono/metadata/security-manager.h"
 #include "mono/metadata/tabledefs.h"
 #include "mono/metadata/tokentype.h"
+#include "mono/metadata/w32file.h"
 
 #include "mono/utils/checked-build.h"
 #include "mono/utils/mono-digest.h"
@@ -2737,8 +2738,8 @@ static void
 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
 {
        guint32 dummy;
-       if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
-               g_error ("WriteFile returned %d\n", GetLastError ());
+       if (!mono_w32file_write (f, buffer, numbytes, &dummy))
+               g_error ("mono_w32file_write returned %d\n", GetLastError ());
 }
 
 /*
@@ -3032,8 +3033,8 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoErro
                if (!assembly->sections [i].size)
                        continue;
                
-               if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
-                       g_error ("SetFilePointer returned %d\n", GetLastError ());
+               if (mono_w32file_seek (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+                       g_error ("mono_w32file_seek returned %d\n", GetLastError ());
                
                switch (i) {
                case MONO_SECTION_TEXT:
@@ -3092,10 +3093,10 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoErro
        }
        
        /* check that the file is properly padded */
-       if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
-               g_error ("SetFilePointer returned %d\n", GetLastError ());
-       if (! SetEndOfFile (file))
-               g_error ("SetEndOfFile returned %d\n", GetLastError ());
+       if (mono_w32file_seek (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+               g_error ("mono_w32file_seek returned %d\n", GetLastError ());
+       if (! mono_w32file_truncate (file))
+               g_error ("mono_w32file_truncate returned %d\n", GetLastError ());
        
        mono_dynamic_stream_reset (&assembly->code);
        mono_dynamic_stream_reset (&assembly->us);
index 4387f013cdb19bf4f750b59887458e5b90f1575e..626a26bb31b61b214a561a40402e1cb8ffeb7fa4 100644 (file)
@@ -53,10 +53,6 @@ typedef enum {
 #define SPECIAL_STATIC_THREAD 1
 #define SPECIAL_STATIC_CONTEXT 2
 
-#ifdef HOST_WIN32
-typedef SECURITY_ATTRIBUTES WapiSecurityAttributes;
-#endif
-
 typedef struct _MonoInternalThread MonoInternalThread;
 
 typedef void (*MonoThreadCleanupFunc) (MonoNativeThreadId tid);
index af5b890d16279cc8bbc2d4ea525d55db84b6a4fe..8c9b1b1f765c5342dc35c9272c6f9339ff5ae555 100644 (file)
@@ -14,6 +14,8 @@
 #include "mono/utils/mono-logger-internals.h"
 #include "mono/metadata/w32handle.h"
 
+#define MAX_PATH 260
+
 typedef struct {
        gboolean manual;
        guint32 set_count;
diff --git a/mono/metadata/w32file-internals.h b/mono/metadata/w32file-internals.h
new file mode 100644 (file)
index 0000000..0458a64
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#ifndef _MONO_METADATA_W32FILE_INTERNALS_H_
+#define _MONO_METADATA_W32FILE_INTERNALS_H_
+
+#include <config.h>
+#include <glib.h>
+
+#endif /* _MONO_METADATA_W32FILE_INTERNALS_H_ */
diff --git a/mono/metadata/w32file-unix-glob.c b/mono/metadata/w32file-unix-glob.c
new file mode 100644 (file)
index 0000000..99e02a4
--- /dev/null
@@ -0,0 +1,406 @@
+/*     $OpenBSD: glob.c,v 1.26 2005/11/28 17:50:12 deraadt Exp $ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * mono_w32file_unix_glob(3) -- a subset of the one defined in POSIX 1003.2.
+ *
+ * Optional extra services, controlled by flags not defined by POSIX:
+ *
+ * GLOB_MAGCHAR:
+ *     Set in gl_flags if pattern contained a globbing character.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <glib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "w32file-unix-glob.h"
+
+#define        EOS             '\0'
+#define        NOT             '!'
+#define        QUESTION        '?'
+#define        QUOTE           '\\'
+#define        STAR            '*'
+
+#ifndef DEBUG
+
+#define        M_QUOTE         0x8000
+#define        M_PROTECT       0x4000
+#define        M_MASK          0xffff
+#define        M_ASCII         0x00ff
+
+typedef unsigned short Char;
+
+#else
+
+#define        M_QUOTE         0x80
+#define        M_PROTECT       0x40
+#define        M_MASK          0xff
+#define        M_ASCII         0x7f
+
+typedef char Char;
+
+#endif
+
+
+#define        CHAR(c)         ((gchar)((c)&M_ASCII))
+#define        META(c)         ((gchar)((c)|M_QUOTE))
+#define        M_ALL           META('*')
+#define        M_ONE           META('?')
+#define        ismeta(c)       (((c)&M_QUOTE) != 0)
+
+
+static int
+g_Ctoc(const gchar *, char *, unsigned int);
+
+static int
+glob0(GDir *dir, const gchar *, mono_w32file_unix_glob_t *, gboolean, gboolean);
+static int
+glob1(GDir *dir, gchar *, gchar *, mono_w32file_unix_glob_t *, size_t *, gboolean, gboolean);
+
+static int
+glob3(GDir *dir, gchar *, gchar *, mono_w32file_unix_glob_t *, size_t *, gboolean, gboolean);
+
+static int
+globextend(const gchar *, mono_w32file_unix_glob_t *, size_t *);
+
+static int
+match(const gchar *, gchar *, gchar *, gboolean);
+
+#ifdef DEBUG_ENABLED
+static void     qprintf(const char *, Char *);
+#endif
+
+int
+mono_w32file_unix_glob(GDir *dir, const char *pattern, int flags, mono_w32file_unix_glob_t *pglob)
+{
+       const unsigned char *patnext;
+       int c;
+       gchar *bufnext, *bufend, patbuf[PATH_MAX];
+
+       patnext = (unsigned char *) pattern;
+       if (!(flags & W32FILE_UNIX_GLOB_APPEND)) {
+               pglob->gl_pathc = 0;
+               pglob->gl_pathv = NULL;
+               pglob->gl_offs = 0;
+       }
+       pglob->gl_flags = flags & ~W32FILE_UNIX_GLOB_MAGCHAR;
+
+       bufnext = patbuf;
+       bufend = bufnext + PATH_MAX - 1;
+
+       /* Protect the quoted characters. */
+       while (bufnext < bufend && (c = *patnext++) != EOS)
+               if (c == QUOTE) {
+                       if ((c = *patnext++) == EOS) {
+                               c = QUOTE;
+                               --patnext;
+                       }
+                       *bufnext++ = c | M_PROTECT;
+               } else
+                       *bufnext++ = c;
+
+       *bufnext = EOS;
+
+       return glob0(dir, patbuf, pglob, flags & W32FILE_UNIX_GLOB_IGNORECASE,
+                    flags & W32FILE_UNIX_GLOB_UNIQUE);
+}
+
+/*
+ * The main glob() routine: compiles the pattern (optionally processing
+ * quotes), calls glob1() to do the real pattern matching, and finally
+ * sorts the list (unless unsorted operation is requested).  Returns 0
+ * if things went well, nonzero if errors occurred.  It is not an error
+ * to find no matches.
+ */
+static int
+glob0(GDir *dir, const gchar *pattern, mono_w32file_unix_glob_t *pglob, gboolean ignorecase,
+       gboolean unique)
+{
+       const gchar *qpatnext;
+       int c, err, oldpathc;
+       gchar *bufnext, patbuf[PATH_MAX];
+       size_t limit = 0;
+
+       qpatnext = pattern;
+       oldpathc = pglob->gl_pathc;
+       bufnext = patbuf;
+
+       /* We don't need to check for buffer overflow any more. */
+       while ((c = *qpatnext++) != EOS) {
+               switch (c) {
+               case QUESTION:
+                       pglob->gl_flags |= W32FILE_UNIX_GLOB_MAGCHAR;
+                       *bufnext++ = M_ONE;
+                       break;
+               case STAR:
+                       pglob->gl_flags |= W32FILE_UNIX_GLOB_MAGCHAR;
+                       /* collapse adjacent stars to one,
+                        * to avoid exponential behavior
+                        */
+                       if (bufnext == patbuf || bufnext[-1] != M_ALL)
+                               *bufnext++ = M_ALL;
+                       break;
+               default:
+                       *bufnext++ = CHAR(c);
+                       break;
+               }
+       }
+       *bufnext = EOS;
+#ifdef DEBUG_ENABLED
+       qprintf("glob0:", patbuf);
+#endif
+
+       if ((err = glob1(dir, patbuf, patbuf+PATH_MAX-1, pglob, &limit,
+                        ignorecase, unique)) != 0)
+               return(err);
+
+       if (pglob->gl_pathc == oldpathc) {
+               return(W32FILE_UNIX_GLOB_NOMATCH);
+       }
+
+       return(0);
+}
+
+static int
+glob1(GDir *dir, gchar *pattern, gchar *pattern_last, mono_w32file_unix_glob_t *pglob,
+      size_t *limitp, gboolean ignorecase, gboolean unique)
+{
+       /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
+       if (*pattern == EOS)
+               return(0);
+       return(glob3(dir, pattern, pattern_last, pglob, limitp, ignorecase,
+                    unique));
+}
+
+static gboolean contains (mono_w32file_unix_glob_t *pglob, const gchar *name)
+{
+       int i;
+       char **pp;
+       
+       if (pglob->gl_pathv != NULL) {
+               pp = pglob->gl_pathv + pglob->gl_offs;
+               for (i = pglob->gl_pathc; i--; ++pp) {
+                       if (*pp) {
+                               if (!strcmp (*pp, name)) {
+                                       return(TRUE);
+                               }
+                       }
+               }
+       }
+       
+       return(FALSE);
+}
+
+static int
+glob3(GDir *dir, gchar *pattern, gchar *pattern_last, mono_w32file_unix_glob_t *pglob,
+      size_t *limitp, gboolean ignorecase, gboolean unique)
+{
+       const gchar *name;
+
+       /* Search directory for matching names. */
+       while ((name = g_dir_read_name(dir))) {
+               if (!match(name, pattern, pattern + strlen (pattern),
+                          ignorecase)) {
+                       continue;
+               }
+               if (!unique ||
+                   !contains (pglob, name)) {
+                       globextend (name, pglob, limitp);
+               }
+       }
+
+       return(0);
+}
+
+
+/*
+ * Extend the gl_pathv member of a mono_w32file_unix_glob_t structure to accommodate a new item,
+ * add the new item, and update gl_pathc.
+ *
+ * This assumes the BSD realloc, which only copies the block when its size
+ * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
+ * behavior.
+ *
+ * Return 0 if new item added, error code if memory couldn't be allocated.
+ *
+ * Invariant of the mono_w32file_unix_glob_t structure:
+ *     Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
+ *     gl_pathv points to (gl_offs + gl_pathc + 1) items.
+ */
+static int
+globextend(const gchar *path, mono_w32file_unix_glob_t *pglob, size_t *limitp)
+{
+       char **pathv;
+       int i;
+       unsigned int newsize, len;
+       char *copy;
+       const gchar *p;
+
+       newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
+       /* FIXME: Can just use realloc(). */
+       pathv = (char **)(pglob->gl_pathv ? g_realloc ((char *)pglob->gl_pathv, newsize) :
+           g_malloc (newsize));
+       if (pathv == NULL) {
+               if (pglob->gl_pathv) {
+                       g_free (pglob->gl_pathv);
+                       pglob->gl_pathv = NULL;
+               }
+               return(W32FILE_UNIX_GLOB_NOSPACE);
+       }
+
+       if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
+               /* first time around -- clear initial gl_offs items */
+               pathv += pglob->gl_offs;
+               for (i = pglob->gl_offs; --i >= 0; )
+                       *--pathv = NULL;
+       }
+       pglob->gl_pathv = pathv;
+
+       for (p = path; *p++;)
+               ;
+       len = (size_t)(p - path);
+       *limitp += len;
+       if ((copy = (char *)malloc(len)) != NULL) {
+               if (g_Ctoc(path, copy, len)) {
+                       g_free (copy);
+                       return(W32FILE_UNIX_GLOB_NOSPACE);
+               }
+               pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
+       }
+       pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+
+#if 0
+       /* Broken on opensuse 11 */
+       if ((pglob->gl_flags & W32FILE_UNIX_GLOB_LIMIT) &&
+           newsize + *limitp >= ARG_MAX) {
+               errno = 0;
+               return(W32FILE_UNIX_GLOB_NOSPACE);
+       }
+#endif
+
+       return(copy == NULL ? W32FILE_UNIX_GLOB_NOSPACE : 0);
+}
+
+
+/*
+ * pattern matching function for filenames.  Each occurrence of the *
+ * pattern causes a recursion level.
+ */
+static int
+match(const gchar *name, gchar *pat, gchar *patend, gboolean ignorecase)
+{
+       gchar c;
+
+       while (pat < patend) {
+               c = *pat++;
+               switch (c & M_MASK) {
+               case M_ALL:
+                       if (pat == patend)
+                               return(1);
+                       do {
+                               if (match(name, pat, patend, ignorecase))
+                                       return(1);
+                       } while (*name++ != EOS);
+                       return(0);
+               case M_ONE:
+                       if (*name++ == EOS)
+                               return(0);
+                       break;
+               default:
+                       if (ignorecase) {
+                               if (g_ascii_tolower (*name++) != g_ascii_tolower (c))
+                                       return(0);
+                       } else {
+                               if (*name++ != c)
+                                       return(0);
+                       }
+                       
+                       break;
+               }
+       }
+       return(*name == EOS);
+}
+
+/* Free allocated data belonging to a mono_w32file_unix_glob_t structure. */
+void
+mono_w32file_unix_globfree(mono_w32file_unix_glob_t *pglob)
+{
+       int i;
+       char **pp;
+
+       if (pglob->gl_pathv != NULL) {
+               pp = pglob->gl_pathv + pglob->gl_offs;
+               for (i = pglob->gl_pathc; i--; ++pp)
+                       if (*pp)
+                               g_free (*pp);
+               g_free (pglob->gl_pathv);
+               pglob->gl_pathv = NULL;
+       }
+}
+
+static int
+g_Ctoc(const gchar *str, char *buf, unsigned int len)
+{
+
+       while (len--) {
+               if ((*buf++ = *str++) == EOS)
+                       return (0);
+       }
+       return (1);
+}
+
+#ifdef DEBUG_ENABLED
+static void
+qprintf(const char *str, Char *s)
+{
+       Char *p;
+
+       (void)printf("%s:\n", str);
+       for (p = s; *p; p++)
+               (void)printf("%c", CHAR(*p));
+       (void)printf("\n");
+       for (p = s; *p; p++)
+               (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
+       (void)printf("\n");
+       for (p = s; *p; p++)
+               (void)printf("%c", ismeta(*p) ? '_' : ' ');
+       (void)printf("\n");
+}
+#endif
diff --git a/mono/metadata/w32file-unix-glob.h b/mono/metadata/w32file-unix-glob.h
new file mode 100644 (file)
index 0000000..b192308
--- /dev/null
@@ -0,0 +1,73 @@
+/*     $OpenBSD: glob.h,v 1.10 2005/12/13 00:35:22 millert Exp $       */
+/*     $NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp $     */
+
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)glob.h      8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef __MONO_METADATA_W32FILE_UNIX_GLOB_H__
+#define        __MONO_METADATA_W32FILE_UNIX_GLOB_H__
+
+#include <glib.h>
+
+struct stat;
+typedef struct {
+       int gl_pathc;           /* Count of total paths so far. */
+       int gl_offs;            /* Reserved at beginning of gl_pathv. */
+       int gl_flags;           /* Copy of flags parameter to glob. */
+       char **gl_pathv;        /* List of paths matching pattern. */
+} mono_w32file_unix_glob_t;
+
+#define W32FILE_UNIX_GLOB_APPEND       0x0001  /* Append to output from previous call. */
+#define W32FILE_UNIX_GLOB_UNIQUE       0x0040  /* When appending only add items that aren't already in the list */
+#define        W32FILE_UNIX_GLOB_NOSPACE       (-1)    /* Malloc call failed. */
+#define        W32FILE_UNIX_GLOB_ABORTED       (-2)    /* Unignored error. */
+#define        W32FILE_UNIX_GLOB_NOMATCH       (-3)    /* No match and W32FILE_UNIX_GLOB_NOCHECK not set. */
+#define        W32FILE_UNIX_GLOB_NOSYS (-4)    /* Function not supported. */
+
+#define        W32FILE_UNIX_GLOB_MAGCHAR       0x0100  /* Pattern had globbing characters. */
+#define W32FILE_UNIX_GLOB_LIMIT        0x2000  /* Limit pattern match output to ARG_MAX */
+#define W32FILE_UNIX_GLOB_IGNORECASE 0x4000    /* Ignore case when matching */
+#define W32FILE_UNIX_GLOB_ABEND        W32FILE_UNIX_GLOB_ABORTED /* backward compatibility */
+
+G_BEGIN_DECLS
+
+int
+mono_w32file_unix_glob (GDir *dir, const char *, int, mono_w32file_unix_glob_t *);
+
+void
+mono_w32file_unix_globfree (mono_w32file_unix_glob_t *);
+
+G_END_DECLS
+
+#endif /* !__MONO_METADATA_W32FILE_UNIX_GLOB_H__ */
diff --git a/mono/metadata/w32file-unix.c b/mono/metadata/w32file-unix.c
new file mode 100644 (file)
index 0000000..ecca05e
--- /dev/null
@@ -0,0 +1,4971 @@
+
+#include <config.h>
+#include <glib.h>
+
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+#if defined(HAVE_SYS_STATFS_H)
+#include <sys/statfs.h>
+#endif
+#if defined(HAVE_SYS_PARAM_H) && defined(HAVE_SYS_MOUNT_H)
+#include <sys/param.h>
+#include <sys/mount.h>
+#endif
+#include <sys/types.h>
+#include <stdio.h>
+#include <utime.h>
+#ifdef __linux__
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#include <mono/utils/linux_magic.h>
+#endif
+#include <sys/time.h>
+#ifdef HAVE_DIRENT_H
+# include <dirent.h>
+#endif
+
+#include "w32file.h"
+#include "w32file-internals.h"
+
+#include "w32file-unix-glob.h"
+#include "w32handle.h"
+#include "utils/mono-io-portability.h"
+#include "utils/mono-logger-internals.h"
+#include "utils/mono-os-mutex.h"
+#include "utils/mono-threads.h"
+#include "utils/mono-threads-api.h"
+#include "utils/strenc.h"
+
+typedef struct {
+       guint64 device;
+       guint64 inode;
+       pid_t opened_by_pid;
+       guint32 sharemode;
+       guint32 access;
+       guint32 handle_refs;
+       guint32 timestamp;
+} FileShare;
+
+/* Currently used for both FILE, CONSOLE and PIPE handle types.
+ * This may have to change in future. */
+typedef struct {
+       gchar *filename;
+       FileShare *share_info;  /* Pointer into shared mem */
+       gint fd;
+       guint32 security_attributes;
+       guint32 fileaccess;
+       guint32 sharemode;
+       guint32 attrs;
+} MonoW32HandleFile;
+
+typedef struct {
+       gchar **namelist;
+       gchar *dir_part;
+       gint num;
+       gsize count;
+} MonoW32HandleFind;
+
+/*
+ * If SHM is disabled, this will point to a hash of FileShare structures, otherwise
+ * it will be NULL. We use this instead of _wapi_fileshare_layout to avoid allocating a
+ * 4MB array.
+ */
+static GHashTable *file_share_table;
+static mono_mutex_t file_share_mutex;
+
+static void
+time_t_to_filetime (time_t timeval, FILETIME *filetime)
+{
+       guint64 ticks;
+       
+       ticks = ((guint64)timeval * 10000000) + 116444736000000000ULL;
+       filetime->dwLowDateTime = ticks & 0xFFFFFFFF;
+       filetime->dwHighDateTime = ticks >> 32;
+}
+
+static void
+file_share_release (FileShare *share_info)
+{
+       /* Prevent new entries racing with us */
+       mono_os_mutex_lock (&file_share_mutex);
+
+       g_assert (share_info->handle_refs > 0);
+       share_info->handle_refs -= 1;
+
+       if (share_info->handle_refs == 0)
+               g_hash_table_remove (file_share_table, share_info);
+
+       mono_os_mutex_unlock (&file_share_mutex);
+}
+
+static gint
+file_share_equal (gconstpointer ka, gconstpointer kb)
+{
+       const FileShare *s1 = (const FileShare *)ka;
+       const FileShare *s2 = (const FileShare *)kb;
+
+       return (s1->device == s2->device && s1->inode == s2->inode) ? 1 : 0;
+}
+
+static guint
+file_share_hash (gconstpointer data)
+{
+       const FileShare *s = (const FileShare *)data;
+
+       return s->inode;
+}
+
+static gboolean
+file_share_get (guint64 device, guint64 inode, guint32 new_sharemode, guint32 new_access,
+       guint32 *old_sharemode, guint32 *old_access, FileShare **share_info)
+{
+       FileShare *file_share;
+       gboolean exists = FALSE;
+
+       /* Prevent new entries racing with us */
+       mono_os_mutex_lock (&file_share_mutex);
+
+       FileShare tmp;
+
+       /*
+        * Instead of allocating a 4MB array, we use a hash table to keep track of this
+        * info. This is needed even if SHM is disabled, to track sharing inside
+        * the current process.
+        */
+       if (!file_share_table)
+               file_share_table = g_hash_table_new_full (file_share_hash, file_share_equal, NULL, g_free);
+
+       tmp.device = device;
+       tmp.inode = inode;
+
+       file_share = (FileShare *)g_hash_table_lookup (file_share_table, &tmp);
+       if (file_share) {
+               *old_sharemode = file_share->sharemode;
+               *old_access = file_share->access;
+               *share_info = file_share;
+
+               g_assert (file_share->handle_refs > 0);
+               file_share->handle_refs += 1;
+
+               exists = TRUE;
+       } else {
+               file_share = g_new0 (FileShare, 1);
+
+               file_share->device = device;
+               file_share->inode = inode;
+               file_share->opened_by_pid = wapi_getpid ();
+               file_share->sharemode = new_sharemode;
+               file_share->access = new_access;
+               file_share->handle_refs = 1;
+               *share_info = file_share;
+
+               g_hash_table_insert (file_share_table, file_share, file_share);
+       }
+
+       mono_os_mutex_unlock (&file_share_mutex);
+
+       return(exists);
+}
+
+static gint
+_wapi_open (const gchar *pathname, gint flags, mode_t mode)
+{
+       gint fd;
+       gchar *located_filename;
+
+       if (flags & O_CREAT) {
+               located_filename = mono_portability_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) && IS_PORTABILITY_SET) {
+                       gint saved_errno = errno;
+                       located_filename = mono_portability_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);
+}
+
+static gint
+_wapi_access (const gchar *pathname, gint mode)
+{
+       gint ret;
+
+       ret = access (pathname, mode);
+       if (ret == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) {
+               gint saved_errno = errno;
+               gchar *located_filename = mono_portability_find_file (pathname, TRUE);
+
+               if (located_filename == NULL) {
+                       errno = saved_errno;
+                       return -1;
+               }
+
+               ret = access (located_filename, mode);
+               g_free (located_filename);
+       }
+
+       return ret;
+}
+
+static gint
+_wapi_chmod (const gchar *pathname, mode_t mode)
+{
+       gint ret;
+
+       ret = chmod (pathname, mode);
+       if (ret == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) {
+               gint saved_errno = errno;
+               gchar *located_filename = mono_portability_find_file (pathname, TRUE);
+
+               if (located_filename == NULL) {
+                       errno = saved_errno;
+                       return -1;
+               }
+
+               ret = chmod (located_filename, mode);
+               g_free (located_filename);
+       }
+
+       return ret;
+}
+
+static gint
+_wapi_utime (const gchar *filename, const struct utimbuf *buf)
+{
+       gint ret;
+
+       ret = utime (filename, buf);
+       if (ret == -1 && errno == ENOENT && IS_PORTABILITY_SET) {
+               gint saved_errno = errno;
+               gchar *located_filename = mono_portability_find_file (filename, TRUE);
+
+               if (located_filename == NULL) {
+                       errno = saved_errno;
+                       return -1;
+               }
+
+               ret = utime (located_filename, buf);
+               g_free (located_filename);
+       }
+
+       return ret;
+}
+
+static gint
+_wapi_unlink (const gchar *pathname)
+{
+       gint ret;
+
+       ret = unlink (pathname);
+       if (ret == -1 && (errno == ENOENT || errno == ENOTDIR || errno == EISDIR) && IS_PORTABILITY_SET) {
+               gint saved_errno = errno;
+               gchar *located_filename = mono_portability_find_file (pathname, TRUE);
+
+               if (located_filename == NULL) {
+                       errno = saved_errno;
+                       return -1;
+               }
+
+               ret = unlink (located_filename);
+               g_free (located_filename);
+       }
+
+       return ret;
+}
+
+static gint
+_wapi_rename (const gchar *oldpath, const gchar *newpath)
+{
+       gint ret;
+       gchar *located_newpath = mono_portability_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) && IS_PORTABILITY_SET) {
+                       gint saved_errno = errno;
+                       gchar *located_oldpath = mono_portability_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;
+}
+
+static gint
+_wapi_stat (const gchar *path, struct stat *buf)
+{
+       gint ret;
+
+       ret = stat (path, buf);
+       if (ret == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) {
+               gint saved_errno = errno;
+               gchar *located_filename = mono_portability_find_file (path, TRUE);
+
+               if (located_filename == NULL) {
+                       errno = saved_errno;
+                       return -1;
+               }
+
+               ret = stat (located_filename, buf);
+               g_free (located_filename);
+       }
+
+       return ret;
+}
+
+static gint
+_wapi_lstat (const gchar *path, struct stat *buf)
+{
+       gint ret;
+
+       ret = lstat (path, buf);
+       if (ret == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) {
+               gint saved_errno = errno;
+               gchar *located_filename = mono_portability_find_file (path, TRUE);
+
+               if (located_filename == NULL) {
+                       errno = saved_errno;
+                       return -1;
+               }
+
+               ret = lstat (located_filename, buf);
+               g_free (located_filename);
+       }
+
+       return ret;
+}
+
+static gint
+_wapi_mkdir (const gchar *pathname, mode_t mode)
+{
+       gint ret;
+       gchar *located_filename = mono_portability_find_file (pathname, FALSE);
+
+       if (located_filename == NULL) {
+               ret = mkdir (pathname, mode);
+       } else {
+               ret = mkdir (located_filename, mode);
+               g_free (located_filename);
+       }
+
+       return ret;
+}
+
+static gint
+_wapi_rmdir (const gchar *pathname)
+{
+       gint ret;
+
+       ret = rmdir (pathname);
+       if (ret == -1 && (errno == ENOENT || errno == ENOTDIR || errno == ENAMETOOLONG) && IS_PORTABILITY_SET) {
+               gint saved_errno = errno;
+               gchar *located_filename = mono_portability_find_file (pathname, TRUE);
+
+               if (located_filename == NULL) {
+                       errno = saved_errno;
+                       return -1;
+               }
+
+               ret = rmdir (located_filename);
+               g_free (located_filename);
+       }
+
+       return ret;
+}
+
+static gint
+_wapi_chdir (const gchar *path)
+{
+       gint ret;
+
+       ret = chdir (path);
+       if (ret == -1 && (errno == ENOENT || errno == ENOTDIR || errno == ENAMETOOLONG) && IS_PORTABILITY_SET) {
+               gint saved_errno = errno;
+               gchar *located_filename = mono_portability_find_file (path, TRUE);
+
+               if (located_filename == NULL) {
+                       errno = saved_errno;
+                       return -1;
+               }
+
+               ret = chdir (located_filename);
+               g_free (located_filename);
+       }
+
+       return ret;
+}
+
+static gchar*
+_wapi_basename (const gchar *filename)
+{
+       gchar *new_filename = g_strdup (filename), *ret;
+
+       if (IS_PORTABILITY_SET) {
+               g_strdelimit (new_filename, "\\", '/');
+       }
+
+       if (IS_PORTABILITY_DRIVE && g_ascii_isalpha (new_filename[0]) && (new_filename[1] == ':')) {
+               gint 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;
+}
+
+static gchar*
+_wapi_dirname (const gchar *filename)
+{
+       gchar *new_filename = g_strdup (filename), *ret;
+
+       if (IS_PORTABILITY_SET) {
+               g_strdelimit (new_filename, "\\", '/');
+       }
+
+       if (IS_PORTABILITY_DRIVE && g_ascii_isalpha (new_filename[0]) && (new_filename[1] == ':')) {
+               gint 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;
+}
+
+static 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) && IS_PORTABILITY_SET) {
+               gchar *located_filename = mono_portability_find_file (path, TRUE);
+               GError *tmp_error = NULL;
+
+               if (located_filename == NULL) {
+                       return(NULL);
+               }
+
+               ret = g_dir_open (located_filename, flags, &tmp_error);
+               g_free (located_filename);
+               if (tmp_error == NULL) {
+                       g_clear_error (error);
+               }
+       }
+
+       return ret;
+}
+
+static gint
+get_errno_from_g_file_error (gint error)
+{
+       switch (error) {
+#ifdef EACCESS
+       case G_FILE_ERROR_ACCES: return EACCES;
+#endif
+#ifdef ENAMETOOLONG
+       case G_FILE_ERROR_NAMETOOLONG: return ENAMETOOLONG;
+#endif
+#ifdef ENOENT
+       case G_FILE_ERROR_NOENT: return ENOENT;
+#endif
+#ifdef ENOTDIR
+       case G_FILE_ERROR_NOTDIR: return ENOTDIR;
+#endif
+#ifdef ENXIO
+       case G_FILE_ERROR_NXIO: return ENXIO;
+#endif
+#ifdef ENODEV
+       case G_FILE_ERROR_NODEV: return ENODEV;
+#endif
+#ifdef EROFS
+       case G_FILE_ERROR_ROFS: return EROFS;
+#endif
+#ifdef ETXTBSY
+       case G_FILE_ERROR_TXTBSY: return ETXTBSY;
+#endif
+#ifdef EFAULT
+       case G_FILE_ERROR_FAULT: return EFAULT;
+#endif
+#ifdef ELOOP
+       case G_FILE_ERROR_LOOP: return ELOOP;
+#endif
+#ifdef ENOSPC
+       case G_FILE_ERROR_NOSPC: return ENOSPC;
+#endif
+#ifdef ENOMEM
+       case G_FILE_ERROR_NOMEM: return ENOMEM;
+#endif
+#ifdef EMFILE
+       case G_FILE_ERROR_MFILE: return EMFILE;
+#endif
+#ifdef ENFILE
+       case G_FILE_ERROR_NFILE: return ENFILE;
+#endif
+#ifdef EBADF
+       case G_FILE_ERROR_BADF: return EBADF;
+#endif
+#ifdef EINVAL
+       case G_FILE_ERROR_INVAL: return EINVAL;
+#endif
+#ifdef EPIPE
+       case G_FILE_ERROR_PIPE: return EPIPE;
+#endif
+#ifdef EAGAIN
+       case G_FILE_ERROR_AGAIN: return EAGAIN;
+#endif
+#ifdef EINTR
+       case G_FILE_ERROR_INTR: return EINTR;
+#endif
+#ifdef EWIO
+       case G_FILE_ERROR_IO: return EIO;
+#endif
+#ifdef EPERM
+       case G_FILE_ERROR_PERM: return EPERM;
+#endif
+       case G_FILE_ERROR_FAILED: return ERROR_INVALID_PARAMETER;
+       default:
+               g_assert_not_reached ();
+       }
+}
+
+static gint
+file_compare (gconstpointer a, gconstpointer b)
+{
+       gchar *astr = *(gchar **) a;
+       gchar *bstr = *(gchar **) b;
+
+       return strcmp (astr, bstr);
+}
+
+/* scandir using glib */
+static gint
+_wapi_io_scandir (const gchar *dirname, const gchar *pattern, gchar ***namelist)
+{
+       GError *error = NULL;
+       GDir *dir;
+       GPtrArray *names;
+       gint result;
+       mono_w32file_unix_glob_t glob_buf;
+       gint flags = 0, i;
+
+       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 &&
+                   !_wapi_access (dirname, F_OK) &&
+                   _wapi_access (dirname, R_OK|X_OK)) {
+                       errnum = EACCES;
+               }
+
+               errno = errnum;
+               return -1;
+       }
+
+       if (IS_PORTABILITY_CASE) {
+               flags = W32FILE_UNIX_GLOB_IGNORECASE;
+       }
+
+       result = mono_w32file_unix_glob (dir, pattern, flags, &glob_buf);
+       if (g_str_has_suffix (pattern, ".*")) {
+               /* Special-case the patterns ending in '.*', as
+                * windows also matches entries with no extension with
+                * this pattern.
+                *
+                * TODO: should this be a MONO_IOMAP option?
+                */
+               gchar *pattern2 = g_strndup (pattern, strlen (pattern) - 2);
+               gint result2;
+
+               g_dir_rewind (dir);
+               result2 = mono_w32file_unix_glob (dir, pattern2, flags | W32FILE_UNIX_GLOB_APPEND | W32FILE_UNIX_GLOB_UNIQUE, &glob_buf);
+
+               g_free (pattern2);
+
+               if (result != 0) {
+                       result = result2;
+               }
+       }
+
+       g_dir_close (dir);
+       if (glob_buf.gl_pathc == 0) {
+               return(0);
+       } else if (result != 0) {
+               return -1;
+       }
+
+       names = g_ptr_array_new ();
+       for (i = 0; i < glob_buf.gl_pathc; i++) {
+               g_ptr_array_add (names, g_strdup (glob_buf.gl_pathv[i]));
+       }
+
+       mono_w32file_unix_globfree (&glob_buf);
+
+       result = names->len;
+       if (result > 0) {
+               g_ptr_array_sort (names, file_compare);
+               g_ptr_array_set_size (names, result + 1);
+
+               *namelist = (gchar **) g_ptr_array_free (names, FALSE);
+       } else {
+               g_ptr_array_free (names, TRUE);
+       }
+
+       return result;
+}
+
+static gboolean
+_wapi_lock_file_region (gint fd, off_t offset, off_t length)
+{
+#if defined(__native_client__)
+       printf("WARNING: %s: fcntl() not available on Native Client!\n", __func__);
+       // behave as below -- locks are not available
+       return TRUE;
+#else
+       struct flock lock_data;
+       gint ret;
+
+       if (offset < 0 || length < 0) {
+               SetLastError (ERROR_INVALID_PARAMETER);
+               return FALSE;
+       }
+
+       lock_data.l_type = F_WRLCK;
+       lock_data.l_whence = SEEK_SET;
+       lock_data.l_start = offset;
+       lock_data.l_len = length;
+
+       do {
+               ret = fcntl (fd, F_SETLK, &lock_data);
+       } while(ret == -1 && errno == EINTR);
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl returns %d", __func__, ret);
+
+       if (ret == -1) {
+               /*
+                * if locks are not available (NFS for example),
+                * ignore the error
+                */
+               if (errno == ENOLCK
+#ifdef EOPNOTSUPP
+                   || errno == EOPNOTSUPP
+#endif
+#ifdef ENOTSUP
+                   || errno == ENOTSUP
+#endif
+                  ) {
+                       return TRUE;
+               }
+
+               SetLastError (ERROR_LOCK_VIOLATION);
+               return FALSE;
+       }
+
+       return TRUE;
+#endif /* __native_client__ */
+}
+
+static gboolean
+_wapi_unlock_file_region (gint fd, off_t offset, off_t length)
+{
+#if defined(__native_client__)
+       printf("WARNING: %s: fcntl() not available on Native Client!\n", __func__);
+       return TRUE;
+#else
+       struct flock lock_data;
+       gint ret;
+
+       lock_data.l_type = F_UNLCK;
+       lock_data.l_whence = SEEK_SET;
+       lock_data.l_start = offset;
+       lock_data.l_len = length;
+
+       do {
+               ret = fcntl (fd, F_SETLK, &lock_data);
+       } while(ret == -1 && errno == EINTR);
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl returns %d", __func__, ret);
+
+       if (ret == -1) {
+               /*
+                * if locks are not available (NFS for example),
+                * ignore the error
+                */
+               if (errno == ENOLCK
+#ifdef EOPNOTSUPP
+                   || errno == EOPNOTSUPP
+#endif
+#ifdef ENOTSUP
+                   || errno == ENOTSUP
+#endif
+                  ) {
+                       return TRUE;
+               }
+
+               SetLastError (ERROR_LOCK_VIOLATION);
+               return FALSE;
+       }
+
+       return TRUE;
+#endif /* __native_client__ */
+}
+
+static void file_close (gpointer handle, gpointer data);
+static void file_details (gpointer data);
+static const gchar* file_typename (void);
+static gsize file_typesize (void);
+static gint file_getfiletype(void);
+static gboolean file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread);
+static gboolean file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten);
+static gboolean file_flush(gpointer handle);
+static guint32 file_seek(gpointer handle, gint32 movedistance,
+                        gint32 *highmovedistance, gint method);
+static gboolean file_setendoffile(gpointer handle);
+static guint32 file_getfilesize(gpointer handle, guint32 *highsize);
+static gboolean file_getfiletime(gpointer handle, FILETIME *create_time,
+                                FILETIME *access_time,
+                                FILETIME *write_time);
+static gboolean file_setfiletime(gpointer handle,
+                                const FILETIME *create_time,
+                                const FILETIME *access_time,
+                                const FILETIME *write_time);
+static guint32 GetDriveTypeFromPath (const gchar *utf8_root_path_name);
+
+/* File handle is only signalled for overlapped IO */
+static MonoW32HandleOps _wapi_file_ops = {
+       file_close,             /* close */
+       NULL,                   /* signal */
+       NULL,                   /* own */
+       NULL,                   /* is_owned */
+       NULL,                   /* special_wait */
+       NULL,                   /* prewait */
+       file_details,   /* details */
+       file_typename,  /* typename */
+       file_typesize,  /* typesize */
+};
+
+static void console_close (gpointer handle, gpointer data);
+static void console_details (gpointer data);
+static const gchar* console_typename (void);
+static gsize console_typesize (void);
+static gint console_getfiletype(void);
+static gboolean console_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread);
+static gboolean console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten);
+
+/* Console is mostly the same as file, except it can block waiting for
+ * input or output
+ */
+static MonoW32HandleOps _wapi_console_ops = {
+       console_close,          /* close */
+       NULL,                   /* signal */
+       NULL,                   /* own */
+       NULL,                   /* is_owned */
+       NULL,                   /* special_wait */
+       NULL,                   /* prewait */
+       console_details,        /* details */
+       console_typename,       /* typename */
+       console_typesize,       /* typesize */
+};
+
+static const gchar* find_typename (void);
+static gsize find_typesize (void);
+
+static MonoW32HandleOps _wapi_find_ops = {
+       NULL,                   /* close */
+       NULL,                   /* signal */
+       NULL,                   /* own */
+       NULL,                   /* is_owned */
+       NULL,                   /* special_wait */
+       NULL,                   /* prewait */
+       NULL,                   /* details */
+       find_typename,  /* typename */
+       find_typesize,  /* typesize */
+};
+
+static void pipe_close (gpointer handle, gpointer data);
+static void pipe_details (gpointer data);
+static const gchar* pipe_typename (void);
+static gsize pipe_typesize (void);
+static gint pipe_getfiletype (void);
+static gboolean pipe_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread);
+static gboolean pipe_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten);
+
+/* Pipe handles
+ */
+static MonoW32HandleOps _wapi_pipe_ops = {
+       pipe_close,             /* close */
+       NULL,                   /* signal */
+       NULL,                   /* own */
+       NULL,                   /* is_owned */
+       NULL,                   /* special_wait */
+       NULL,                   /* prewait */
+       pipe_details,   /* details */
+       pipe_typename,  /* typename */
+       pipe_typesize,  /* typesize */
+};
+
+static const struct {
+       /* File, console and pipe handles */
+       gint (*getfiletype)(void);
+       
+       /* File, console and pipe handles */
+       gboolean (*readfile)(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread);
+       gboolean (*writefile)(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten);
+       gboolean (*flushfile)(gpointer handle);
+       
+       /* File handles */
+       guint32 (*seek)(gpointer handle, gint32 movedistance,
+                       gint32 *highmovedistance, gint method);
+       gboolean (*setendoffile)(gpointer handle);
+       guint32 (*getfilesize)(gpointer handle, guint32 *highsize);
+       gboolean (*getfiletime)(gpointer handle, FILETIME *create_time,
+                               FILETIME *access_time,
+                               FILETIME *write_time);
+       gboolean (*setfiletime)(gpointer handle,
+                               const FILETIME *create_time,
+                               const FILETIME *access_time,
+                               const FILETIME *write_time);
+} io_ops[MONO_W32HANDLE_COUNT]={
+       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+       /* file */
+       {file_getfiletype,
+        file_read, file_write,
+        file_flush, file_seek,
+        file_setendoffile,
+        file_getfilesize,
+        file_getfiletime,
+        file_setfiletime},
+       /* console */
+       {console_getfiletype,
+        console_read,
+        console_write,
+        NULL, NULL, NULL, NULL, NULL, NULL},
+       /* thread */
+       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+       /* sem */
+       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+       /* mutex */
+       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+       /* event */
+       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+       /* socket (will need at least read and write) */
+       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+       /* find */
+       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+       /* process */
+       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+       /* pipe */
+       {pipe_getfiletype,
+        pipe_read,
+        pipe_write,
+        NULL, NULL, NULL, NULL, NULL, NULL},
+};
+
+static gboolean lock_while_writing = FALSE;
+
+/* Some utility functions.
+ */
+
+/*
+ * Check if a file is writable by the current user.
+ *
+ * This is is a best effort kind of thing. It assumes a reasonable sane set
+ * of permissions by the underlying OS.
+ *
+ * We generally assume that basic unix permission bits are authoritative. Which might not
+ * be the case under systems with extended permissions systems (posix ACLs, SELinux, OSX/iOS sandboxing, etc)
+ *
+ * The choice of access as the fallback is due to the expected lower overhead compared to trying to open the file.
+ *
+ * The only expected problem with using access are for root, setuid or setgid programs as access is not consistent
+ * under those situations. It's to be expected that this should not happen in practice as those bits are very dangerous
+ * and should not be used with a dynamic runtime.
+ */
+static gboolean
+is_file_writable (struct stat *st, const gchar *path)
+{
+#if __APPLE__
+       // OS X Finder "locked" or `ls -lO` "uchg".
+       // This only covers one of several cases where an OS X file could be unwritable through special flags.
+       if (st->st_flags & (UF_IMMUTABLE|SF_IMMUTABLE))
+               return 0;
+#endif
+
+       /* Is it globally writable? */
+       if (st->st_mode & S_IWOTH)
+               return 1;
+
+       /* Am I the owner? */
+       if ((st->st_uid == geteuid ()) && (st->st_mode & S_IWUSR))
+               return 1;
+
+       /* Am I in the same group? */
+       if ((st->st_gid == getegid ()) && (st->st_mode & S_IWGRP))
+               return 1;
+
+       /* Fallback to using access(2). It's not ideal as it might not take into consideration euid/egid
+        * but it's the only sane option we have on unix.
+        */
+       return access (path, W_OK) == 0;
+}
+
+
+static guint32 _wapi_stat_to_file_attributes (const gchar *pathname,
+                                             struct stat *buf,
+                                             struct stat *lbuf)
+{
+       guint32 attrs = 0;
+       gchar *filename;
+       
+       /* FIXME: this could definitely be better, but there seems to
+        * be no pattern to the attributes that are set
+        */
+
+       /* Sockets (0140000) != Directory (040000) + Regular file (0100000) */
+       if (S_ISSOCK (buf->st_mode))
+               buf->st_mode &= ~S_IFSOCK; /* don't consider socket protection */
+
+       filename = _wapi_basename (pathname);
+
+       if (S_ISDIR (buf->st_mode)) {
+               attrs = FILE_ATTRIBUTE_DIRECTORY;
+               if (!is_file_writable (buf, pathname)) {
+                       attrs |= FILE_ATTRIBUTE_READONLY;
+               }
+               if (filename[0] == '.') {
+                       attrs |= FILE_ATTRIBUTE_HIDDEN;
+               }
+       } else {
+               if (!is_file_writable (buf, pathname)) {
+                       attrs = FILE_ATTRIBUTE_READONLY;
+
+                       if (filename[0] == '.') {
+                               attrs |= FILE_ATTRIBUTE_HIDDEN;
+                       }
+               } else if (filename[0] == '.') {
+                       attrs = FILE_ATTRIBUTE_HIDDEN;
+               } else {
+                       attrs = FILE_ATTRIBUTE_NORMAL;
+               }
+       }
+
+       if (lbuf != NULL) {
+               if (S_ISLNK (lbuf->st_mode)) {
+                       attrs |= FILE_ATTRIBUTE_REPARSE_POINT;
+               }
+       }
+       
+       g_free (filename);
+       
+       return attrs;
+}
+
+static void
+_wapi_set_last_error_from_errno (void)
+{
+       SetLastError (_wapi_get_win32_file_error (errno));
+}
+
+static void _wapi_set_last_path_error_from_errno (const gchar *dir,
+                                                 const gchar *path)
+{
+       if (errno == ENOENT) {
+               /* Check the path - if it's a missing directory then
+                * we need to set PATH_NOT_FOUND not FILE_NOT_FOUND
+                */
+               gchar *dirname;
+
+
+               if (dir == NULL) {
+                       dirname = _wapi_dirname (path);
+               } else {
+                       dirname = g_strdup (dir);
+               }
+               
+               if (_wapi_access (dirname, F_OK) == 0) {
+                       SetLastError (ERROR_FILE_NOT_FOUND);
+               } else {
+                       SetLastError (ERROR_PATH_NOT_FOUND);
+               }
+
+               g_free (dirname);
+       } else {
+               _wapi_set_last_error_from_errno ();
+       }
+}
+
+/* Handle ops.
+ */
+static void file_close (gpointer handle, gpointer data)
+{
+       MonoW32HandleFile *file_handle = (MonoW32HandleFile *)data;
+       gint fd = file_handle->fd;
+       
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing file handle %p [%s]", __func__, handle,
+                 file_handle->filename);
+
+       if (file_handle->attrs & FILE_FLAG_DELETE_ON_CLOSE)
+               _wapi_unlink (file_handle->filename);
+       
+       g_free (file_handle->filename);
+       
+       if (file_handle->share_info)
+               file_share_release (file_handle->share_info);
+       
+       close (fd);
+}
+
+static void file_details (gpointer data)
+{
+       MonoW32HandleFile *file = (MonoW32HandleFile *)data;
+       
+       g_print ("[%20s] acc: %c%c%c, shr: %c%c%c, attrs: %5u",
+                file->filename,
+                file->fileaccess&GENERIC_READ?'R':'.',
+                file->fileaccess&GENERIC_WRITE?'W':'.',
+                file->fileaccess&GENERIC_EXECUTE?'X':'.',
+                file->sharemode&FILE_SHARE_READ?'R':'.',
+                file->sharemode&FILE_SHARE_WRITE?'W':'.',
+                file->sharemode&FILE_SHARE_DELETE?'D':'.',
+                file->attrs);
+}
+
+static const gchar* file_typename (void)
+{
+       return "File";
+}
+
+static gsize file_typesize (void)
+{
+       return sizeof (MonoW32HandleFile);
+}
+
+static gint file_getfiletype(void)
+{
+       return(FILE_TYPE_DISK);
+}
+
+static gboolean
+file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+{
+       MonoW32HandleFile *file_handle;
+       gboolean ok;
+       gint fd, ret;
+       MonoThreadInfo *info = mono_thread_info_current ();
+       
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+                               (gpointer *)&file_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+
+       fd = file_handle->fd;
+       if(bytesread!=NULL) {
+               *bytesread=0;
+       }
+       
+       if(!(file_handle->fileaccess & GENERIC_READ) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
+                         __func__, handle, file_handle->fileaccess);
+
+               SetLastError (ERROR_ACCESS_DENIED);
+               return(FALSE);
+       }
+
+       do {
+               ret = read (fd, buffer, numbytes);
+       } while (ret == -1 && errno == EINTR &&
+                !mono_thread_info_is_interrupt_state (info));
+                       
+       if(ret==-1) {
+               gint err = errno;
+
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__,
+                         handle, strerror(err));
+               SetLastError (_wapi_get_win32_file_error (err));
+               return(FALSE);
+       }
+               
+       if (bytesread != NULL) {
+               *bytesread = ret;
+       }
+               
+       return(TRUE);
+}
+
+static gboolean
+file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
+{
+       MonoW32HandleFile *file_handle;
+       gboolean ok;
+       gint ret, fd;
+       off_t current_pos = 0;
+       MonoThreadInfo *info = mono_thread_info_current ();
+       
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+                               (gpointer *)&file_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+
+       fd = file_handle->fd;
+       
+       if(byteswritten!=NULL) {
+               *byteswritten=0;
+       }
+       
+       if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+
+               SetLastError (ERROR_ACCESS_DENIED);
+               return(FALSE);
+       }
+       
+       if (lock_while_writing) {
+               /* Need to lock the region we're about to write to,
+                * because we only do advisory locking on POSIX
+                * systems
+                */
+               current_pos = lseek (fd, (off_t)0, SEEK_CUR);
+               if (current_pos == -1) {
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p lseek failed: %s", __func__,
+                                  handle, strerror (errno));
+                       _wapi_set_last_error_from_errno ();
+                       return(FALSE);
+               }
+               
+               if (_wapi_lock_file_region (fd, current_pos,
+                                           numbytes) == FALSE) {
+                       /* The error has already been set */
+                       return(FALSE);
+               }
+       }
+               
+       do {
+               ret = write (fd, buffer, numbytes);
+       } while (ret == -1 && errno == EINTR &&
+                !mono_thread_info_is_interrupt_state (info));
+       
+       if (lock_while_writing) {
+               _wapi_unlock_file_region (fd, current_pos, numbytes);
+       }
+
+       if (ret == -1) {
+               if (errno == EINTR) {
+                       ret = 0;
+               } else {
+                       _wapi_set_last_error_from_errno ();
+                               
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s",
+                                 __func__, handle, strerror(errno));
+
+                       return(FALSE);
+               }
+       }
+       if (byteswritten != NULL) {
+               *byteswritten = ret;
+       }
+       return(TRUE);
+}
+
+static gboolean file_flush(gpointer handle)
+{
+       MonoW32HandleFile *file_handle;
+       gboolean ok;
+       gint ret, fd;
+       
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+                               (gpointer *)&file_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+
+       fd = file_handle->fd;
+
+       if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+
+               SetLastError (ERROR_ACCESS_DENIED);
+               return(FALSE);
+       }
+
+       ret=fsync(fd);
+       if (ret==-1) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fsync of handle %p error: %s", __func__, handle,
+                         strerror(errno));
+
+               _wapi_set_last_error_from_errno ();
+               return(FALSE);
+       }
+       
+       return(TRUE);
+}
+
+static guint32 file_seek(gpointer handle, gint32 movedistance,
+                        gint32 *highmovedistance, gint method)
+{
+       MonoW32HandleFile *file_handle;
+       gboolean ok;
+       gint64 offset, newpos;
+       gint whence, fd;
+       guint32 ret;
+       
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+                               (gpointer *)&file_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(INVALID_SET_FILE_POINTER);
+       }
+       
+       fd = file_handle->fd;
+
+       if(!(file_handle->fileaccess & GENERIC_READ) &&
+          !(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+
+               SetLastError (ERROR_ACCESS_DENIED);
+               return(INVALID_SET_FILE_POINTER);
+       }
+
+       switch(method) {
+       case FILE_BEGIN:
+               whence=SEEK_SET;
+               break;
+       case FILE_CURRENT:
+               whence=SEEK_CUR;
+               break;
+       case FILE_END:
+               whence=SEEK_END;
+               break;
+       default:
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: invalid seek type %d", __func__, method);
+
+               SetLastError (ERROR_INVALID_PARAMETER);
+               return(INVALID_SET_FILE_POINTER);
+       }
+
+#ifdef HAVE_LARGE_FILE_SUPPORT
+       if(highmovedistance==NULL) {
+               offset=movedistance;
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting offset to %lld (low %d)", __func__,
+                         offset, movedistance);
+       } else {
+               offset=((gint64) *highmovedistance << 32) | (guint32)movedistance;
+               
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting offset to %lld 0x%llx (high %d 0x%x, low %d 0x%x)", __func__, offset, offset, *highmovedistance, *highmovedistance, movedistance, movedistance);
+       }
+#else
+       offset=movedistance;
+#endif
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: moving handle %p by %lld bytes from %d", __func__,
+                  handle, (long long)offset, whence);
+
+#ifdef PLATFORM_ANDROID
+       /* bionic doesn't support -D_FILE_OFFSET_BITS=64 */
+       newpos=lseek64(fd, offset, whence);
+#else
+       newpos=lseek(fd, offset, whence);
+#endif
+       if(newpos==-1) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek on handle %p returned error %s",
+                         __func__, handle, strerror(errno));
+
+               _wapi_set_last_error_from_errno ();
+               return(INVALID_SET_FILE_POINTER);
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek returns %lld", __func__, newpos);
+
+#ifdef HAVE_LARGE_FILE_SUPPORT
+       ret=newpos & 0xFFFFFFFF;
+       if(highmovedistance!=NULL) {
+               *highmovedistance=newpos>>32;
+       }
+#else
+       ret=newpos;
+       if(highmovedistance!=NULL) {
+               /* Accurate, but potentially dodgy :-) */
+               *highmovedistance=0;
+       }
+#endif
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: move of handle %p returning %d/%d", __func__,
+                  handle, ret, highmovedistance==NULL?0:*highmovedistance);
+
+       return(ret);
+}
+
+static gboolean file_setendoffile(gpointer handle)
+{
+       MonoW32HandleFile *file_handle;
+       gboolean ok;
+       struct stat statbuf;
+       off_t pos;
+       gint ret, fd;
+       MonoThreadInfo *info = mono_thread_info_current ();
+       
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+                               (gpointer *)&file_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       fd = file_handle->fd;
+       
+       if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+
+               SetLastError (ERROR_ACCESS_DENIED);
+               return(FALSE);
+       }
+
+       /* Find the current file position, and the file length.  If
+        * the file position is greater than the length, write to
+        * extend the file with a hole.  If the file position is less
+        * than the length, truncate the file.
+        */
+       
+       ret=fstat(fd, &statbuf);
+       if(ret==-1) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__,
+                          handle, strerror(errno));
+
+               _wapi_set_last_error_from_errno ();
+               return(FALSE);
+       }
+
+       pos=lseek(fd, (off_t)0, SEEK_CUR);
+       if(pos==-1) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p lseek failed: %s", __func__,
+                         handle, strerror(errno));
+
+               _wapi_set_last_error_from_errno ();
+               return(FALSE);
+       }
+       
+#ifdef FTRUNCATE_DOESNT_EXTEND
+       off_t size = statbuf.st_size;
+       /* I haven't bothered to write the configure.ac stuff for this
+        * because I don't know if any platform needs it.  I'm leaving
+        * this code just in case though
+        */
+       if(pos>size) {
+               /* Extend the file.  Use write() here, because some
+                * manuals say that ftruncate() behaviour is undefined
+                * when the file needs extending.  The POSIX spec says
+                * that on XSI-conformant systems it extends, so if
+                * every system we care about conforms, then we can
+                * drop this write.
+                */
+               do {
+                       ret = write (fd, "", 1);
+               } while (ret == -1 && errno == EINTR &&
+                        !mono_thread_info_is_interrupt_state (info));
+
+               if(ret==-1) {
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p extend write failed: %s", __func__, handle, strerror(errno));
+
+                       _wapi_set_last_error_from_errno ();
+                       return(FALSE);
+               }
+
+               /* And put the file position back after the write */
+               ret = lseek (fd, pos, SEEK_SET);
+               if (ret == -1) {
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p second lseek failed: %s",
+                                  __func__, handle, strerror(errno));
+
+                       _wapi_set_last_error_from_errno ();
+                       return(FALSE);
+               }
+       }
+#endif
+
+/* Native Client has no ftruncate function, even in standalone sel_ldr. */
+#ifndef __native_client__
+       /* always truncate, because the extend write() adds an extra
+        * byte to the end of the file
+        */
+       do {
+               ret=ftruncate(fd, pos);
+       }
+       while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info)); 
+       if(ret==-1) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p ftruncate failed: %s", __func__,
+                         handle, strerror(errno));
+               
+               _wapi_set_last_error_from_errno ();
+               return(FALSE);
+       }
+#endif
+               
+       return(TRUE);
+}
+
+static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
+{
+       MonoW32HandleFile *file_handle;
+       gboolean ok;
+       struct stat statbuf;
+       guint32 size;
+       gint ret;
+       gint fd;
+       
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+                               (gpointer *)&file_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(INVALID_FILE_SIZE);
+       }
+       fd = file_handle->fd;
+       
+       if(!(file_handle->fileaccess & GENERIC_READ) &&
+          !(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+
+               SetLastError (ERROR_ACCESS_DENIED);
+               return(INVALID_FILE_SIZE);
+       }
+
+       /* If the file has a size with the low bits 0xFFFFFFFF the
+        * caller can't tell if this is an error, so clear the error
+        * value
+        */
+       SetLastError (ERROR_SUCCESS);
+       
+       ret = fstat(fd, &statbuf);
+       if (ret == -1) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__,
+                          handle, strerror(errno));
+
+               _wapi_set_last_error_from_errno ();
+               return(INVALID_FILE_SIZE);
+       }
+       
+       /* fstat indicates block devices as zero-length, so go a different path */
+#ifdef BLKGETSIZE64
+       if (S_ISBLK(statbuf.st_mode)) {
+               guint64 bigsize;
+               if (ioctl(fd, BLKGETSIZE64, &bigsize) < 0) {
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p ioctl BLKGETSIZE64 failed: %s",
+                                  __func__, handle, strerror(errno));
+
+                       _wapi_set_last_error_from_errno ();
+                       return(INVALID_FILE_SIZE);
+               }
+               
+               size = bigsize & 0xFFFFFFFF;
+               if (highsize != NULL) {
+                       *highsize = bigsize>>32;
+               }
+
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning block device size %d/%d",
+                          __func__, size, *highsize);
+       
+               return(size);
+       }
+#endif
+       
+#ifdef HAVE_LARGE_FILE_SUPPORT
+       size = statbuf.st_size & 0xFFFFFFFF;
+       if (highsize != NULL) {
+               *highsize = statbuf.st_size>>32;
+       }
+#else
+       if (highsize != NULL) {
+               /* Accurate, but potentially dodgy :-) */
+               *highsize = 0;
+       }
+       size = statbuf.st_size;
+#endif
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning size %d/%d", __func__, size, *highsize);
+       
+       return(size);
+}
+
+static gboolean file_getfiletime(gpointer handle, FILETIME *create_time,
+                                FILETIME *access_time,
+                                FILETIME *write_time)
+{
+       MonoW32HandleFile *file_handle;
+       gboolean ok;
+       struct stat statbuf;
+       guint64 create_ticks, access_ticks, write_ticks;
+       gint ret, fd;
+       
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+                               (gpointer *)&file_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       fd = file_handle->fd;
+
+       if(!(file_handle->fileaccess & GENERIC_READ) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
+                         __func__, handle, file_handle->fileaccess);
+
+               SetLastError (ERROR_ACCESS_DENIED);
+               return(FALSE);
+       }
+       
+       ret=fstat(fd, &statbuf);
+       if(ret==-1) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle,
+                         strerror(errno));
+
+               _wapi_set_last_error_from_errno ();
+               return(FALSE);
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: atime: %ld ctime: %ld mtime: %ld", __func__,
+                 statbuf.st_atime, statbuf.st_ctime,
+                 statbuf.st_mtime);
+
+       /* Try and guess a meaningful create time by using the older
+        * of atime or ctime
+        */
+       /* The magic constant comes from msdn documentation
+        * "Converting a time_t Value to a File Time"
+        */
+       if(statbuf.st_atime < statbuf.st_ctime) {
+               create_ticks=((guint64)statbuf.st_atime*10000000)
+                       + 116444736000000000ULL;
+       } else {
+               create_ticks=((guint64)statbuf.st_ctime*10000000)
+                       + 116444736000000000ULL;
+       }
+       
+       access_ticks=((guint64)statbuf.st_atime*10000000)+116444736000000000ULL;
+       write_ticks=((guint64)statbuf.st_mtime*10000000)+116444736000000000ULL;
+       
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: aticks: %llu cticks: %llu wticks: %llu", __func__,
+                 access_ticks, create_ticks, write_ticks);
+
+       if(create_time!=NULL) {
+               create_time->dwLowDateTime = create_ticks & 0xFFFFFFFF;
+               create_time->dwHighDateTime = create_ticks >> 32;
+       }
+       
+       if(access_time!=NULL) {
+               access_time->dwLowDateTime = access_ticks & 0xFFFFFFFF;
+               access_time->dwHighDateTime = access_ticks >> 32;
+       }
+       
+       if(write_time!=NULL) {
+               write_time->dwLowDateTime = write_ticks & 0xFFFFFFFF;
+               write_time->dwHighDateTime = write_ticks >> 32;
+       }
+
+       return(TRUE);
+}
+
+static gboolean file_setfiletime(gpointer handle,
+                                const FILETIME *create_time G_GNUC_UNUSED,
+                                const FILETIME *access_time,
+                                const FILETIME *write_time)
+{
+       MonoW32HandleFile *file_handle;
+       gboolean ok;
+       struct utimbuf utbuf;
+       struct stat statbuf;
+       guint64 access_ticks, write_ticks;
+       gint ret, fd;
+       
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+                               (gpointer *)&file_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       fd = file_handle->fd;
+       
+       if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+
+               SetLastError (ERROR_ACCESS_DENIED);
+               return(FALSE);
+       }
+
+       if(file_handle->filename == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p unknown filename", __func__, handle);
+
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       
+       /* Get the current times, so we can put the same times back in
+        * the event that one of the FileTime structs is NULL
+        */
+       ret=fstat (fd, &statbuf);
+       if(ret==-1) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle,
+                         strerror(errno));
+
+               SetLastError (ERROR_INVALID_PARAMETER);
+               return(FALSE);
+       }
+
+       if(access_time!=NULL) {
+               access_ticks=((guint64)access_time->dwHighDateTime << 32) +
+                       access_time->dwLowDateTime;
+               /* This is (time_t)0.  We can actually go to INT_MIN,
+                * but this will do for now.
+                */
+               if (access_ticks < 116444736000000000ULL) {
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt to set access time too early",
+                                  __func__);
+                       SetLastError (ERROR_INVALID_PARAMETER);
+                       return(FALSE);
+               }
+
+               if (sizeof (utbuf.actime) == 4 && ((access_ticks - 116444736000000000ULL) / 10000000) > INT_MAX) {
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt to set write time that is too big for a 32bits time_t",
+                                  __func__);
+                       SetLastError (ERROR_INVALID_PARAMETER);
+                       return(FALSE);
+               }
+
+               utbuf.actime=(access_ticks - 116444736000000000ULL) / 10000000;
+       } else {
+               utbuf.actime=statbuf.st_atime;
+       }
+
+       if(write_time!=NULL) {
+               write_ticks=((guint64)write_time->dwHighDateTime << 32) +
+                       write_time->dwLowDateTime;
+               /* This is (time_t)0.  We can actually go to INT_MIN,
+                * but this will do for now.
+                */
+               if (write_ticks < 116444736000000000ULL) {
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt to set write time too early",
+                                  __func__);
+                       SetLastError (ERROR_INVALID_PARAMETER);
+                       return(FALSE);
+               }
+               if (sizeof (utbuf.modtime) == 4 && ((write_ticks - 116444736000000000ULL) / 10000000) > INT_MAX) {
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt to set write time that is too big for a 32bits time_t",
+                                  __func__);
+                       SetLastError (ERROR_INVALID_PARAMETER);
+                       return(FALSE);
+               }
+               
+               utbuf.modtime=(write_ticks - 116444736000000000ULL) / 10000000;
+       } else {
+               utbuf.modtime=statbuf.st_mtime;
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting handle %p access %ld write %ld", __func__,
+                  handle, utbuf.actime, utbuf.modtime);
+
+       ret = _wapi_utime (file_handle->filename, &utbuf);
+       if (ret == -1) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p [%s] utime failed: %s", __func__,
+                          handle, file_handle->filename, strerror(errno));
+
+               SetLastError (ERROR_INVALID_PARAMETER);
+               return(FALSE);
+       }
+       
+       return(TRUE);
+}
+
+static void console_close (gpointer handle, gpointer data)
+{
+       MonoW32HandleFile *console_handle = (MonoW32HandleFile *)data;
+       gint fd = console_handle->fd;
+       
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing console handle %p", __func__, handle);
+
+       g_free (console_handle->filename);
+
+       if (fd > 2) {
+               if (console_handle->share_info)
+                       file_share_release (console_handle->share_info);
+               close (fd);
+       }
+}
+
+static void console_details (gpointer data)
+{
+       file_details (data);
+}
+
+static const gchar* console_typename (void)
+{
+       return "Console";
+}
+
+static gsize console_typesize (void)
+{
+       return sizeof (MonoW32HandleFile);
+}
+
+static gint console_getfiletype(void)
+{
+       return(FILE_TYPE_CHAR);
+}
+
+static gboolean
+console_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+{
+       MonoW32HandleFile *console_handle;
+       gboolean ok;
+       gint ret, fd;
+       MonoThreadInfo *info = mono_thread_info_current ();
+
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
+                               (gpointer *)&console_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up console handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       fd = console_handle->fd;
+       
+       if(bytesread!=NULL) {
+               *bytesread=0;
+       }
+       
+       if(!(console_handle->fileaccess & GENERIC_READ) &&
+          !(console_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
+                          __func__, handle, console_handle->fileaccess);
+
+               SetLastError (ERROR_ACCESS_DENIED);
+               return(FALSE);
+       }
+       
+       do {
+               ret=read(fd, buffer, numbytes);
+       } while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info));
+
+       if(ret==-1) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__, handle,
+                         strerror(errno));
+
+               _wapi_set_last_error_from_errno ();
+               return(FALSE);
+       }
+       
+       if(bytesread!=NULL) {
+               *bytesread=ret;
+       }
+       
+       return(TRUE);
+}
+
+static gboolean
+console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
+{
+       MonoW32HandleFile *console_handle;
+       gboolean ok;
+       gint ret, fd;
+       MonoThreadInfo *info = mono_thread_info_current ();
+       
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
+                               (gpointer *)&console_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up console handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       fd = console_handle->fd;
+       
+       if(byteswritten!=NULL) {
+               *byteswritten=0;
+       }
+       
+       if(!(console_handle->fileaccess & GENERIC_WRITE) &&
+          !(console_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, console_handle->fileaccess);
+
+               SetLastError (ERROR_ACCESS_DENIED);
+               return(FALSE);
+       }
+       
+       do {
+               ret = write(fd, buffer, numbytes);
+       } while (ret == -1 && errno == EINTR &&
+                !mono_thread_info_is_interrupt_state (info));
+
+       if (ret == -1) {
+               if (errno == EINTR) {
+                       ret = 0;
+               } else {
+                       _wapi_set_last_error_from_errno ();
+                       
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s",
+                                  __func__, handle, strerror(errno));
+
+                       return(FALSE);
+               }
+       }
+       if(byteswritten!=NULL) {
+               *byteswritten=ret;
+       }
+       
+       return(TRUE);
+}
+
+static const gchar* find_typename (void)
+{
+       return "Find";
+}
+
+static gsize find_typesize (void)
+{
+       return sizeof (MonoW32HandleFind);
+}
+
+static void pipe_close (gpointer handle, gpointer data)
+{
+       MonoW32HandleFile *pipe_handle = (MonoW32HandleFile*)data;
+       gint fd = pipe_handle->fd;
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing pipe handle %p fd %d", __func__, handle, fd);
+
+       /* No filename with pipe handles */
+
+       if (pipe_handle->share_info)
+               file_share_release (pipe_handle->share_info);
+
+       close (fd);
+}
+
+static void pipe_details (gpointer data)
+{
+       file_details (data);
+}
+
+static const gchar* pipe_typename (void)
+{
+       return "Pipe";
+}
+
+static gsize pipe_typesize (void)
+{
+       return sizeof (MonoW32HandleFile);
+}
+
+static gint pipe_getfiletype(void)
+{
+       return(FILE_TYPE_PIPE);
+}
+
+static gboolean
+pipe_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+{
+       MonoW32HandleFile *pipe_handle;
+       gboolean ok;
+       gint ret, fd;
+       MonoThreadInfo *info = mono_thread_info_current ();
+
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_PIPE,
+                               (gpointer *)&pipe_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up pipe handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       fd = pipe_handle->fd;
+
+       if(bytesread!=NULL) {
+               *bytesread=0;
+       }
+       
+       if(!(pipe_handle->fileaccess & GENERIC_READ) &&
+          !(pipe_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
+                         __func__, handle, pipe_handle->fileaccess);
+
+               SetLastError (ERROR_ACCESS_DENIED);
+               return(FALSE);
+       }
+       
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: reading up to %d bytes from pipe %p", __func__,
+                  numbytes, handle);
+
+       do {
+               ret=read(fd, buffer, numbytes);
+       } while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info));
+               
+       if (ret == -1) {
+               if (errno == EINTR) {
+                       ret = 0;
+               } else {
+                       _wapi_set_last_error_from_errno ();
+                       
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__,
+                                 handle, strerror(errno));
+
+                       return(FALSE);
+               }
+       }
+       
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read %d bytes from pipe %p", __func__, ret, handle);
+
+       if(bytesread!=NULL) {
+               *bytesread=ret;
+       }
+       
+       return(TRUE);
+}
+
+static gboolean
+pipe_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
+{
+       MonoW32HandleFile *pipe_handle;
+       gboolean ok;
+       gint ret, fd;
+       MonoThreadInfo *info = mono_thread_info_current ();
+       
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_PIPE,
+                               (gpointer *)&pipe_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up pipe handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       fd = pipe_handle->fd;
+       
+       if(byteswritten!=NULL) {
+               *byteswritten=0;
+       }
+       
+       if(!(pipe_handle->fileaccess & GENERIC_WRITE) &&
+          !(pipe_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, pipe_handle->fileaccess);
+
+               SetLastError (ERROR_ACCESS_DENIED);
+               return(FALSE);
+       }
+       
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: writing up to %d bytes to pipe %p", __func__, numbytes,
+                  handle);
+
+       do {
+               ret = write (fd, buffer, numbytes);
+       } while (ret == -1 && errno == EINTR &&
+                !mono_thread_info_is_interrupt_state (info));
+
+       if (ret == -1) {
+               if (errno == EINTR) {
+                       ret = 0;
+               } else {
+                       _wapi_set_last_error_from_errno ();
+                       
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s", __func__,
+                                 handle, strerror(errno));
+
+                       return(FALSE);
+               }
+       }
+       if(byteswritten!=NULL) {
+               *byteswritten=ret;
+       }
+       
+       return(TRUE);
+}
+
+static gint convert_flags(guint32 fileaccess, guint32 createmode)
+{
+       gint flags=0;
+       
+       switch(fileaccess) {
+       case GENERIC_READ:
+               flags=O_RDONLY;
+               break;
+       case GENERIC_WRITE:
+               flags=O_WRONLY;
+               break;
+       case GENERIC_READ|GENERIC_WRITE:
+               flags=O_RDWR;
+               break;
+       default:
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown access type 0x%x", __func__,
+                         fileaccess);
+               break;
+       }
+
+       switch(createmode) {
+       case CREATE_NEW:
+               flags|=O_CREAT|O_EXCL;
+               break;
+       case CREATE_ALWAYS:
+               flags|=O_CREAT|O_TRUNC;
+               break;
+       case OPEN_EXISTING:
+               break;
+       case OPEN_ALWAYS:
+               flags|=O_CREAT;
+               break;
+       case TRUNCATE_EXISTING:
+               flags|=O_TRUNC;
+               break;
+       default:
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown create mode 0x%x", __func__,
+                         createmode);
+               break;
+       }
+       
+       return(flags);
+}
+
+#if 0 /* unused */
+static mode_t convert_perms(guint32 sharemode)
+{
+       mode_t perms=0600;
+       
+       if(sharemode&FILE_SHARE_READ) {
+               perms|=044;
+       }
+       if(sharemode&FILE_SHARE_WRITE) {
+               perms|=022;
+       }
+
+       return(perms);
+}
+#endif
+
+static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode,
+                                  guint32 fileaccess,
+                                  FileShare **share_info)
+{
+       gboolean file_already_shared;
+       guint32 file_existing_share, file_existing_access;
+
+       file_already_shared = file_share_get (statbuf->st_dev, statbuf->st_ino, sharemode, fileaccess, &file_existing_share, &file_existing_access, share_info);
+       
+       if (file_already_shared) {
+               /* The reference to this share info was incremented
+                * when we looked it up, so be careful to put it back
+                * if we conclude we can't use this file.
+                */
+               if (file_existing_share == 0) {
+                       /* Quick and easy, no possibility to share */
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing = NONE", __func__, fileaccess);
+
+                       file_share_release (*share_info);
+                       
+                       return(FALSE);
+               }
+
+               if (((file_existing_share == FILE_SHARE_READ) &&
+                    (fileaccess != GENERIC_READ)) ||
+                   ((file_existing_share == FILE_SHARE_WRITE) &&
+                    (fileaccess != GENERIC_WRITE))) {
+                       /* New access mode doesn't match up */
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing: 0x%x", __func__, fileaccess, file_existing_share);
+
+                       file_share_release (*share_info);
+               
+                       return(FALSE);
+               }
+
+               if (((file_existing_access & GENERIC_READ) &&
+                    !(sharemode & FILE_SHARE_READ)) ||
+                   ((file_existing_access & GENERIC_WRITE) &&
+                    !(sharemode & FILE_SHARE_WRITE))) {
+                       /* New share mode doesn't match up */
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Access mode prevents open: requested share: 0x%x, file has access: 0x%x", __func__, sharemode, file_existing_access);
+
+                       file_share_release (*share_info);
+               
+                       return(FALSE);
+               }
+       } else {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: New file!", __func__);
+       }
+
+       return(TRUE);
+}
+
+
+static gboolean
+share_allows_delete (struct stat *statbuf, FileShare **share_info)
+{
+       gboolean file_already_shared;
+       guint32 file_existing_share, file_existing_access;
+
+       file_already_shared = file_share_get (statbuf->st_dev, statbuf->st_ino, FILE_SHARE_DELETE, GENERIC_READ, &file_existing_share, &file_existing_access, share_info);
+
+       if (file_already_shared) {
+               /* The reference to this share info was incremented
+                * when we looked it up, so be careful to put it back
+                * if we conclude we can't use this file.
+                */
+               if (file_existing_share == 0) {
+                       /* Quick and easy, no possibility to share */
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing = NONE", __func__, (*share_info)->access);
+
+                       file_share_release (*share_info);
+
+                       return(FALSE);
+               }
+
+               if (!(file_existing_share & FILE_SHARE_DELETE)) {
+                       /* New access mode doesn't match up */
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing: 0x%x", __func__, (*share_info)->access, file_existing_share);
+
+                       file_share_release (*share_info);
+
+                       return(FALSE);
+               }
+       } else {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: New file!", __func__);
+       }
+
+       return(TRUE);
+}
+
+gpointer
+mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode, guint32 createmode, guint32 attrs)
+{
+       MonoW32HandleFile file_handle = {0};
+       gpointer handle;
+       gint flags=convert_flags(fileaccess, createmode);
+       /*mode_t perms=convert_perms(sharemode);*/
+       /* we don't use sharemode, because that relates to sharing of
+        * the file when the file is open and is already handled by
+        * other code, perms instead are the on-disk permissions and
+        * this is a sane default.
+        */
+       mode_t perms=0666;
+       gchar *filename;
+       gint fd, ret;
+       MonoW32HandleType handle_type;
+       struct stat statbuf;
+
+       if (attrs & FILE_ATTRIBUTE_TEMPORARY)
+               perms = 0600;
+       
+       if (attrs & FILE_ATTRIBUTE_ENCRYPTED){
+               SetLastError (ERROR_ENCRYPTION_FAILED);
+               return INVALID_HANDLE_VALUE;
+       }
+       
+       if (name == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(INVALID_HANDLE_VALUE);
+       }
+
+       filename = mono_unicode_to_external (name);
+       if (filename == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(INVALID_HANDLE_VALUE);
+       }
+       
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening %s with share 0x%x and access 0x%x", __func__,
+                  filename, sharemode, fileaccess);
+       
+       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
+        * EISDIR. However, this is a bit bogus because calls to
+        * manipulate the directory (e.g. mono_w32file_set_times) will still work on
+        * the directory because they use other API calls
+        * (e.g. utime()). Hence, if we failed with the EISDIR error, try
+        * to open the directory again without write permission.
+        */
+       if (fd == -1 && errno == EISDIR)
+       {
+               /* Try again but don't try to make it writable */
+               fd = _wapi_open (filename, flags & ~(O_RDWR|O_WRONLY), perms);
+       }
+       
+       if (fd == -1) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s: %s", __func__, filename,
+                         strerror(errno));
+               _wapi_set_last_path_error_from_errno (NULL, filename);
+               g_free (filename);
+
+               return(INVALID_HANDLE_VALUE);
+       }
+
+       if (fd >= mono_w32handle_fd_reserve) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
+
+               SetLastError (ERROR_TOO_MANY_OPEN_FILES);
+               
+               close (fd);
+               g_free (filename);
+               
+               return(INVALID_HANDLE_VALUE);
+       }
+
+       ret = fstat (fd, &statbuf);
+       if (ret == -1) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fstat error of file %s: %s", __func__,
+                          filename, strerror (errno));
+               _wapi_set_last_error_from_errno ();
+               g_free (filename);
+               close (fd);
+               
+               return(INVALID_HANDLE_VALUE);
+       }
+#ifdef __native_client__
+       /* Workaround: Native Client currently returns the same fake inode
+        * for all files, so do a simple hash on the filename so we don't
+        * use the same share info for each file.
+        */
+       statbuf.st_ino = g_str_hash(filename);
+#endif
+
+       if (share_allows_open (&statbuf, sharemode, fileaccess,
+                        &file_handle.share_info) == FALSE) {
+               SetLastError (ERROR_SHARING_VIOLATION);
+               g_free (filename);
+               close (fd);
+               
+               return (INVALID_HANDLE_VALUE);
+       }
+       if (file_handle.share_info == NULL) {
+               /* No space, so no more files can be opened */
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: No space in the share table", __func__);
+
+               SetLastError (ERROR_TOO_MANY_OPEN_FILES);
+               close (fd);
+               g_free (filename);
+               
+               return(INVALID_HANDLE_VALUE);
+       }
+       
+       file_handle.filename = filename;
+       
+       file_handle.fd = fd;
+       file_handle.fileaccess=fileaccess;
+       file_handle.sharemode=sharemode;
+       file_handle.attrs=attrs;
+
+#ifdef HAVE_POSIX_FADVISE
+       if (attrs & FILE_FLAG_SEQUENTIAL_SCAN)
+               posix_fadvise (fd, 0, 0, POSIX_FADV_SEQUENTIAL);
+       if (attrs & FILE_FLAG_RANDOM_ACCESS)
+               posix_fadvise (fd, 0, 0, POSIX_FADV_RANDOM);
+#endif
+
+#ifdef F_RDAHEAD
+       if (attrs & FILE_FLAG_SEQUENTIAL_SCAN)
+               fcntl(fd, F_RDAHEAD, 1);
+#endif
+
+#ifndef S_ISFIFO
+#define S_ISFIFO(m) ((m & S_IFIFO) != 0)
+#endif
+       if (S_ISFIFO (statbuf.st_mode)) {
+               handle_type = MONO_W32HANDLE_PIPE;
+               /* maintain invariant that pipes have no filename */
+               file_handle.filename = NULL;
+               g_free (filename);
+               filename = NULL;
+       } else if (S_ISCHR (statbuf.st_mode)) {
+               handle_type = MONO_W32HANDLE_CONSOLE;
+       } else {
+               handle_type = MONO_W32HANDLE_FILE;
+       }
+
+       handle = mono_w32handle_new_fd (handle_type, fd, &file_handle);
+       if (handle == INVALID_HANDLE_VALUE) {
+               g_warning ("%s: error creating file handle", __func__);
+               g_free (filename);
+               close (fd);
+               
+               SetLastError (ERROR_GEN_FAILURE);
+               return(INVALID_HANDLE_VALUE);
+       }
+       
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, handle);
+       
+       return(handle);
+}
+
+gboolean mono_w32file_delete(const gunichar2 *name)
+{
+       gchar *filename;
+       gint retval;
+       gboolean ret = FALSE;
+       guint32 attrs;
+#if 0
+       struct stat statbuf;
+       FileShare *shareinfo;
+#endif
+       
+       if(name==NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
+
+       filename=mono_unicode_to_external(name);
+       if(filename==NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
+
+       attrs = mono_w32file_get_attributes (name);
+       if (attrs == INVALID_FILE_ATTRIBUTES) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file attributes error", __func__);
+               /* Error set by mono_w32file_get_attributes() */
+               g_free (filename);
+               return(FALSE);
+       }
+
+#if 0
+       /* Check to make sure sharing allows us to open the file for
+        * writing.  See bug 323389.
+        *
+        * Do the checks that don't need an open file descriptor, for
+        * simplicity's sake.  If we really have to do the full checks
+        * then we can implement that later.
+        */
+       if (_wapi_stat (filename, &statbuf) < 0) {
+               _wapi_set_last_path_error_from_errno (NULL, filename);
+               g_free (filename);
+               return(FALSE);
+       }
+       
+       if (share_allows_open (&statbuf, 0, GENERIC_WRITE,
+                              &shareinfo) == FALSE) {
+               SetLastError (ERROR_SHARING_VIOLATION);
+               g_free (filename);
+               return FALSE;
+       }
+       if (shareinfo)
+               file_share_release (shareinfo);
+#endif
+
+       retval = _wapi_unlink (filename);
+       
+       if (retval == -1) {
+               _wapi_set_last_path_error_from_errno (NULL, filename);
+       } else {
+               ret = TRUE;
+       }
+
+       g_free(filename);
+
+       return(ret);
+}
+
+static gboolean
+MoveFile (gunichar2 *name, gunichar2 *dest_name)
+{
+       gchar *utf8_name, *utf8_dest_name;
+       gint result, errno_copy;
+       struct stat stat_src, stat_dest;
+       gboolean ret = FALSE;
+       FileShare *shareinfo;
+       
+       if(name==NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
+
+       utf8_name = mono_unicode_to_external (name);
+       if (utf8_name == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+               
+               SetLastError (ERROR_INVALID_NAME);
+               return FALSE;
+       }
+       
+       if(dest_name==NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+               g_free (utf8_name);
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
+
+       utf8_dest_name = mono_unicode_to_external (dest_name);
+       if (utf8_dest_name == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+               g_free (utf8_name);
+               SetLastError (ERROR_INVALID_NAME);
+               return FALSE;
+       }
+
+       /*
+        * In C# land we check for the existence of src, but not for dest.
+        * We check it here and return the failure if dest exists and is not
+        * the same file as src.
+        */
+       if (_wapi_stat (utf8_name, &stat_src) < 0) {
+               if (errno != ENOENT || _wapi_lstat (utf8_name, &stat_src) < 0) {
+                       _wapi_set_last_path_error_from_errno (NULL, utf8_name);
+                       g_free (utf8_name);
+                       g_free (utf8_dest_name);
+                       return FALSE;
+               }
+       }
+       
+       if (!_wapi_stat (utf8_dest_name, &stat_dest)) {
+               if (stat_dest.st_dev != stat_src.st_dev ||
+                   stat_dest.st_ino != stat_src.st_ino) {
+                       g_free (utf8_name);
+                       g_free (utf8_dest_name);
+                       SetLastError (ERROR_ALREADY_EXISTS);
+                       return FALSE;
+               }
+       }
+
+       /* Check to make that we have delete sharing permission.
+        * See https://bugzilla.xamarin.com/show_bug.cgi?id=17009
+        *
+        * Do the checks that don't need an open file descriptor, for
+        * simplicity's sake.  If we really have to do the full checks
+        * then we can implement that later.
+        */
+       if (share_allows_delete (&stat_src, &shareinfo) == FALSE) {
+               SetLastError (ERROR_SHARING_VIOLATION);
+               return FALSE;
+       }
+       if (shareinfo)
+               file_share_release (shareinfo);
+
+       result = _wapi_rename (utf8_name, utf8_dest_name);
+       errno_copy = errno;
+       
+       if (result == -1) {
+               switch(errno_copy) {
+               case EEXIST:
+                       SetLastError (ERROR_ALREADY_EXISTS);
+                       break;
+
+               case EXDEV:
+                       /* Ignore here, it is dealt with below */
+                       break;
+
+               case ENOENT:
+                       /* We already know src exists. Must be dest that doesn't exist. */
+                       _wapi_set_last_path_error_from_errno (NULL, utf8_dest_name);
+                       break;
+
+               default:
+                       _wapi_set_last_error_from_errno ();
+               }
+       }
+       
+       g_free (utf8_name);
+       g_free (utf8_dest_name);
+
+       if (result != 0 && errno_copy == EXDEV) {
+               gint32 copy_error;
+
+               if (S_ISDIR (stat_src.st_mode)) {
+                       SetLastError (ERROR_NOT_SAME_DEVICE);
+                       return FALSE;
+               }
+               /* Try a copy to the new location, and delete the source */
+               if (!mono_w32file_copy (name, dest_name, FALSE, &copy_error)) {
+                       /* mono_w32file_copy will set the error */
+                       return(FALSE);
+               }
+               
+               return(mono_w32file_delete (name));
+       }
+
+       if (result == 0) {
+               ret = TRUE;
+       }
+
+       return(ret);
+}
+
+static gboolean
+write_file (gint src_fd, gint dest_fd, struct stat *st_src, gboolean report_errors)
+{
+       gint remain, n;
+       gchar *buf, *wbuf;
+       gint buf_size = st_src->st_blksize;
+       MonoThreadInfo *info = mono_thread_info_current ();
+
+       buf_size = buf_size < 8192 ? 8192 : (buf_size > 65536 ? 65536 : buf_size);
+       buf = (gchar *) g_malloc (buf_size);
+
+       for (;;) {
+               remain = read (src_fd, buf, buf_size);
+               if (remain < 0) {
+                       if (errno == EINTR && !mono_thread_info_is_interrupt_state (info))
+                               continue;
+
+                       if (report_errors)
+                               _wapi_set_last_error_from_errno ();
+
+                       g_free (buf);
+                       return FALSE;
+               }
+               if (remain == 0) {
+                       break;
+               }
+
+               wbuf = buf;
+               while (remain > 0) {
+                       if ((n = write (dest_fd, wbuf, remain)) < 0) {
+                               if (errno == EINTR && !mono_thread_info_is_interrupt_state (info))
+                                       continue;
+
+                               if (report_errors)
+                                       _wapi_set_last_error_from_errno ();
+                               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write failed.", __func__);
+                               g_free (buf);
+                               return FALSE;
+                       }
+
+                       remain -= n;
+                       wbuf += n;
+               }
+       }
+
+       g_free (buf);
+       return TRUE ;
+}
+
+static gboolean
+CopyFile (const gunichar2 *name, const gunichar2 *dest_name, gboolean fail_if_exists)
+{
+       gchar *utf8_src, *utf8_dest;
+       gint src_fd, dest_fd;
+       struct stat st, dest_st;
+       struct utimbuf dest_time;
+       gboolean ret = TRUE;
+       gint ret_utime;
+       
+       if(name==NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
+       
+       utf8_src = mono_unicode_to_external (name);
+       if (utf8_src == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion of source returned NULL",
+                          __func__);
+
+               SetLastError (ERROR_INVALID_PARAMETER);
+               return(FALSE);
+       }
+       
+       if(dest_name==NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: dest is NULL", __func__);
+
+               g_free (utf8_src);
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
+       
+       utf8_dest = mono_unicode_to_external (dest_name);
+       if (utf8_dest == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion of dest returned NULL",
+                          __func__);
+
+               SetLastError (ERROR_INVALID_PARAMETER);
+
+               g_free (utf8_src);
+               
+               return(FALSE);
+       }
+       
+       src_fd = _wapi_open (utf8_src, O_RDONLY, 0);
+       if (src_fd < 0) {
+               _wapi_set_last_path_error_from_errno (NULL, utf8_src);
+               
+               g_free (utf8_src);
+               g_free (utf8_dest);
+               
+               return(FALSE);
+       }
+
+       if (fstat (src_fd, &st) < 0) {
+               _wapi_set_last_error_from_errno ();
+
+               g_free (utf8_src);
+               g_free (utf8_dest);
+               close (src_fd);
+               
+               return(FALSE);
+       }
+
+       /* Before trying to open/create the dest, we need to report a 'file busy'
+        * error if src and dest are actually the same file. We do the check here to take
+        * advantage of the IOMAP capability */
+       if (!_wapi_stat (utf8_dest, &dest_st) && st.st_dev == dest_st.st_dev && 
+                       st.st_ino == dest_st.st_ino) {
+
+               g_free (utf8_src);
+               g_free (utf8_dest);
+               close (src_fd);
+
+               SetLastError (ERROR_SHARING_VIOLATION);
+               return (FALSE);
+       }
+       
+       if (fail_if_exists) {
+               dest_fd = _wapi_open (utf8_dest, O_WRONLY | O_CREAT | O_EXCL, st.st_mode);
+       } else {
+               /* FIXME: it kinda sucks that this code path potentially scans
+                * the directory twice due to the weird SetLastError()
+                * behavior. */
+               dest_fd = _wapi_open (utf8_dest, O_WRONLY | O_TRUNC, st.st_mode);
+               if (dest_fd < 0) {
+                       /* The file does not exist, try creating it */
+                       dest_fd = _wapi_open (utf8_dest, O_WRONLY | O_CREAT | O_TRUNC, st.st_mode);
+               } else {
+                       /* Apparently this error is set if we
+                        * overwrite the dest file
+                        */
+                       SetLastError (ERROR_ALREADY_EXISTS);
+               }
+       }
+       if (dest_fd < 0) {
+               _wapi_set_last_error_from_errno ();
+
+               g_free (utf8_src);
+               g_free (utf8_dest);
+               close (src_fd);
+
+               return(FALSE);
+       }
+
+       if (!write_file (src_fd, dest_fd, &st, TRUE))
+               ret = FALSE;
+
+       close (src_fd);
+       close (dest_fd);
+       
+       dest_time.modtime = st.st_mtime;
+       dest_time.actime = st.st_atime;
+       ret_utime = utime (utf8_dest, &dest_time);
+       if (ret_utime == -1)
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file [%s] utime failed: %s", __func__, utf8_dest, strerror(errno));
+       
+       g_free (utf8_src);
+       g_free (utf8_dest);
+
+       return ret;
+}
+
+static gchar*
+convert_arg_to_utf8 (const gunichar2 *arg, const gchar *arg_name)
+{
+       gchar *utf8_ret;
+
+       if (arg == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s is NULL", __func__, arg_name);
+               SetLastError (ERROR_INVALID_NAME);
+               return NULL;
+       }
+
+       utf8_ret = mono_unicode_to_external (arg);
+       if (utf8_ret == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion of %s returned NULL",
+                          __func__, arg_name);
+               SetLastError (ERROR_INVALID_PARAMETER);
+               return NULL;
+       }
+
+       return utf8_ret;
+}
+
+static gboolean
+ReplaceFile (const gunichar2 *replacedFileName, const gunichar2 *replacementFileName, const gunichar2 *backupFileName, guint32 replaceFlags, gpointer exclude, gpointer reserved)
+{
+       gint result, backup_fd = -1,replaced_fd = -1;
+       gchar *utf8_replacedFileName, *utf8_replacementFileName = NULL, *utf8_backupFileName = NULL;
+       struct stat stBackup;
+       gboolean ret = FALSE;
+
+       if (!(utf8_replacedFileName = convert_arg_to_utf8 (replacedFileName, "replacedFileName")))
+               return FALSE;
+       if (!(utf8_replacementFileName = convert_arg_to_utf8 (replacementFileName, "replacementFileName")))
+               goto replace_cleanup;
+       if (backupFileName != NULL) {
+               if (!(utf8_backupFileName = convert_arg_to_utf8 (backupFileName, "backupFileName")))
+                       goto replace_cleanup;
+       }
+
+       if (utf8_backupFileName) {
+               // Open the backup file for read so we can restore the file if an error occurs.
+               backup_fd = _wapi_open (utf8_backupFileName, O_RDONLY, 0);
+               result = _wapi_rename (utf8_replacedFileName, utf8_backupFileName);
+               if (result == -1)
+                       goto replace_cleanup;
+       }
+
+       result = _wapi_rename (utf8_replacementFileName, utf8_replacedFileName);
+       if (result == -1) {
+               _wapi_set_last_path_error_from_errno (NULL, utf8_replacementFileName);
+               _wapi_rename (utf8_backupFileName, utf8_replacedFileName);
+               if (backup_fd != -1 && !fstat (backup_fd, &stBackup)) {
+                       replaced_fd = _wapi_open (utf8_backupFileName, O_WRONLY | O_CREAT | O_TRUNC,
+                                                 stBackup.st_mode);
+                       
+                       if (replaced_fd == -1)
+                               goto replace_cleanup;
+
+                       write_file (backup_fd, replaced_fd, &stBackup, FALSE);
+               }
+
+               goto replace_cleanup;
+       }
+
+       ret = TRUE;
+
+replace_cleanup:
+       g_free (utf8_replacedFileName);
+       g_free (utf8_replacementFileName);
+       g_free (utf8_backupFileName);
+       if (backup_fd != -1)
+               close (backup_fd);
+       if (replaced_fd != -1)
+               close (replaced_fd);
+       return ret;
+}
+
+static mono_mutex_t stdhandle_mutex;
+
+static gpointer
+_wapi_stdhandle_create (gint fd, const gchar *name)
+{
+       gpointer handle;
+       gint flags;
+       MonoW32HandleFile file_handle = {0};
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating standard handle type %s, fd %d", __func__, name, fd);
+
+#if !defined(__native_client__)
+       /* Check if fd is valid */
+       do {
+               flags = fcntl(fd, F_GETFL);
+       } while (flags == -1 && errno == EINTR);
+
+       if (flags == -1) {
+               /* Invalid fd.  Not really much point checking for EBADF
+                * specifically
+                */
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl error on fd %d: %s", __func__, fd, strerror(errno));
+
+               SetLastError (_wapi_get_win32_file_error (errno));
+               return INVALID_HANDLE_VALUE;
+       }
+
+       switch (flags & (O_RDONLY|O_WRONLY|O_RDWR)) {
+       case O_RDONLY:
+               file_handle.fileaccess = GENERIC_READ;
+               break;
+       case O_WRONLY:
+               file_handle.fileaccess = GENERIC_WRITE;
+               break;
+       case O_RDWR:
+               file_handle.fileaccess = GENERIC_READ | GENERIC_WRITE;
+               break;
+       default:
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't figure out flags 0x%x", __func__, flags);
+               file_handle.fileaccess = 0;
+               break;
+       }
+#else
+       /*
+        * fcntl will return -1 in nacl, as there is no real file system API.
+        * Yet, standard streams are available.
+        */
+       file_handle.fileaccess = (fd == STDIN_FILENO) ? GENERIC_READ : GENERIC_WRITE;
+#endif
+
+       file_handle.fd = fd;
+       file_handle.filename = g_strdup(name);
+       /* some default security attributes might be needed */
+       file_handle.security_attributes = 0;
+
+       /* Apparently input handles can't be written to.  (I don't
+        * know if output or error handles can't be read from.)
+        */
+       if (fd == 0)
+               file_handle.fileaccess &= ~GENERIC_WRITE;
+
+       file_handle.sharemode = 0;
+       file_handle.attrs = 0;
+
+       handle = mono_w32handle_new_fd (MONO_W32HANDLE_CONSOLE, fd, &file_handle);
+       if (handle == INVALID_HANDLE_VALUE) {
+               g_warning ("%s: error creating file handle", __func__);
+               SetLastError (ERROR_GEN_FAILURE);
+               return INVALID_HANDLE_VALUE;
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, handle);
+
+       return handle;
+}
+
+enum {
+       STD_INPUT_HANDLE  = -10,
+       STD_OUTPUT_HANDLE = -11,
+       STD_ERROR_HANDLE  = -12,
+};
+
+static gpointer
+mono_w32file_get_std_handle (gint stdhandle)
+{
+       MonoW32HandleFile *file_handle;
+       gpointer handle;
+       gint fd;
+       const gchar *name;
+       gboolean ok;
+       
+       switch(stdhandle) {
+       case STD_INPUT_HANDLE:
+               fd = 0;
+               name = "<stdin>";
+               break;
+
+       case STD_OUTPUT_HANDLE:
+               fd = 1;
+               name = "<stdout>";
+               break;
+
+       case STD_ERROR_HANDLE:
+               fd = 2;
+               name = "<stderr>";
+               break;
+
+       default:
+               g_assert_not_reached ();
+       }
+
+       handle = GINT_TO_POINTER (fd);
+
+       mono_os_mutex_lock (&stdhandle_mutex);
+
+       ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
+                                 (gpointer *)&file_handle);
+       if (ok == FALSE) {
+               /* Need to create this console handle */
+               handle = _wapi_stdhandle_create (fd, name);
+               
+               if (handle == INVALID_HANDLE_VALUE) {
+                       SetLastError (ERROR_NO_MORE_FILES);
+                       goto done;
+               }
+       } else {
+               /* Add a reference to this handle */
+               mono_w32handle_ref (handle);
+       }
+       
+  done:
+       mono_os_mutex_unlock (&stdhandle_mutex);
+       
+       return(handle);
+}
+
+gboolean
+mono_w32file_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+{
+       MonoW32HandleType type;
+
+       type = mono_w32handle_get_type (handle);
+       
+       if(io_ops[type].readfile==NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       
+       return(io_ops[type].readfile (handle, buffer, numbytes, bytesread));
+}
+
+gboolean
+mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
+{
+       MonoW32HandleType type;
+
+       type = mono_w32handle_get_type (handle);
+       
+       if(io_ops[type].writefile==NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       
+       return(io_ops[type].writefile (handle, buffer, numbytes, byteswritten));
+}
+
+gboolean
+mono_w32file_flush (gpointer handle)
+{
+       MonoW32HandleType type;
+
+       type = mono_w32handle_get_type (handle);
+       
+       if(io_ops[type].flushfile==NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       
+       return(io_ops[type].flushfile (handle));
+}
+
+gboolean
+mono_w32file_truncate (gpointer handle)
+{
+       MonoW32HandleType type;
+
+       type = mono_w32handle_get_type (handle);
+       
+       if (io_ops[type].setendoffile == NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       
+       return(io_ops[type].setendoffile (handle));
+}
+
+guint32
+mono_w32file_seek (gpointer handle, gint32 movedistance, gint32 *highmovedistance, guint32 method)
+{
+       MonoW32HandleType type;
+
+       type = mono_w32handle_get_type (handle);
+       
+       if (io_ops[type].seek == NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(INVALID_SET_FILE_POINTER);
+       }
+       
+       return(io_ops[type].seek (handle, movedistance, highmovedistance,
+                                 method));
+}
+
+gint
+mono_w32file_get_type(gpointer handle)
+{
+       MonoW32HandleType type;
+
+       type = mono_w32handle_get_type (handle);
+       
+       if (io_ops[type].getfiletype == NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FILE_TYPE_UNKNOWN);
+       }
+       
+       return(io_ops[type].getfiletype ());
+}
+
+static guint32
+GetFileSize(gpointer handle, guint32 *highsize)
+{
+       MonoW32HandleType type;
+
+       type = mono_w32handle_get_type (handle);
+       
+       if (io_ops[type].getfilesize == NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(INVALID_FILE_SIZE);
+       }
+       
+       return(io_ops[type].getfilesize (handle, highsize));
+}
+
+gboolean
+mono_w32file_get_times(gpointer handle, FILETIME *create_time, FILETIME *access_time, FILETIME *write_time)
+{
+       MonoW32HandleType type;
+
+       type = mono_w32handle_get_type (handle);
+       
+       if (io_ops[type].getfiletime == NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       
+       return(io_ops[type].getfiletime (handle, create_time, access_time,
+                                        write_time));
+}
+
+gboolean
+mono_w32file_set_times(gpointer handle, const FILETIME *create_time, const FILETIME *access_time, const FILETIME *write_time)
+{
+       MonoW32HandleType type;
+
+       type = mono_w32handle_get_type (handle);
+       
+       if (io_ops[type].setfiletime == NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       
+       return(io_ops[type].setfiletime (handle, create_time, access_time,
+                                        write_time));
+}
+
+/* A tick is a 100-nanosecond interval.  File time epoch is Midnight,
+ * January 1 1601 GMT
+ */
+
+#define TICKS_PER_MILLISECOND 10000L
+#define TICKS_PER_SECOND 10000000L
+#define TICKS_PER_MINUTE 600000000L
+#define TICKS_PER_HOUR 36000000000LL
+#define TICKS_PER_DAY 864000000000LL
+
+#define isleap(y) ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
+
+static const guint16 mon_yday[2][13]={
+       {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
+       {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366},
+};
+
+gboolean
+mono_w32file_filetime_to_systemtime(const FILETIME *file_time, SYSTEMTIME *system_time)
+{
+       gint64 file_ticks, totaldays, rem, y;
+       const guint16 *ip;
+       
+       if(system_time==NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: system_time NULL", __func__);
+
+               SetLastError (ERROR_INVALID_PARAMETER);
+               return(FALSE);
+       }
+       
+       file_ticks=((gint64)file_time->dwHighDateTime << 32) +
+               file_time->dwLowDateTime;
+       
+       /* Really compares if file_ticks>=0x8000000000000000
+        * (LLONG_MAX+1) but we're working with a signed value for the
+        * year and day calculation to work later
+        */
+       if(file_ticks<0) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file_time too big", __func__);
+
+               SetLastError (ERROR_INVALID_PARAMETER);
+               return(FALSE);
+       }
+
+       totaldays=(file_ticks / TICKS_PER_DAY);
+       rem = file_ticks % TICKS_PER_DAY;
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld rem: %lld", __func__, totaldays, rem);
+
+       system_time->wHour=rem/TICKS_PER_HOUR;
+       rem %= TICKS_PER_HOUR;
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Hour: %d rem: %lld", __func__, system_time->wHour, rem);
+       
+       system_time->wMinute = rem / TICKS_PER_MINUTE;
+       rem %= TICKS_PER_MINUTE;
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Minute: %d rem: %lld", __func__, system_time->wMinute,
+                 rem);
+       
+       system_time->wSecond = rem / TICKS_PER_SECOND;
+       rem %= TICKS_PER_SECOND;
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Second: %d rem: %lld", __func__, system_time->wSecond,
+                 rem);
+       
+       system_time->wMilliseconds = rem / TICKS_PER_MILLISECOND;
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Milliseconds: %d", __func__,
+                 system_time->wMilliseconds);
+
+       /* January 1, 1601 was a Monday, according to Emacs calendar */
+       system_time->wDayOfWeek = ((1 + totaldays) % 7) + 1;
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Day of week: %d", __func__, system_time->wDayOfWeek);
+       
+       /* This algorithm to find year and month given days from epoch
+        * from glibc
+        */
+       y=1601;
+       
+#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
+#define LEAPS_THRU_END_OF(y) (DIV(y, 4) - DIV (y, 100) + DIV (y, 400))
+
+       while(totaldays < 0 || totaldays >= (isleap(y)?366:365)) {
+               /* Guess a corrected year, assuming 365 days per year */
+               gint64 yg = y + totaldays / 365 - (totaldays % 365 < 0);
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld yg: %lld y: %lld", __func__,
+                         totaldays, yg,
+                         y);
+               g_message("%s: LEAPS(yg): %lld LEAPS(y): %lld", __func__,
+                         LEAPS_THRU_END_OF(yg-1), LEAPS_THRU_END_OF(y-1));
+               
+               /* Adjust days and y to match the guessed year. */
+               totaldays -= ((yg - y) * 365
+                             + LEAPS_THRU_END_OF (yg - 1)
+                             - LEAPS_THRU_END_OF (y - 1));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld", __func__, totaldays);
+               y = yg;
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: y: %lld", __func__, y);
+       }
+       
+       system_time->wYear = y;
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Year: %d", __func__, system_time->wYear);
+
+       ip = mon_yday[isleap(y)];
+       
+       for(y=11; totaldays < ip[y]; --y) {
+               continue;
+       }
+       totaldays-=ip[y];
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld", __func__, totaldays);
+       
+       system_time->wMonth = y + 1;
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Month: %d", __func__, system_time->wMonth);
+
+       system_time->wDay = totaldays + 1;
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Day: %d", __func__, system_time->wDay);
+       
+       return(TRUE);
+}
+
+gpointer
+mono_w32file_find_first (const gunichar2 *pattern, WIN32_FIND_DATA *find_data)
+{
+       MonoW32HandleFind find_handle = {0};
+       gpointer handle;
+       gchar *utf8_pattern = NULL, *dir_part, *entry_part;
+       gint result;
+       
+       if (pattern == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: pattern is NULL", __func__);
+
+               SetLastError (ERROR_PATH_NOT_FOUND);
+               return(INVALID_HANDLE_VALUE);
+       }
+
+       utf8_pattern = mono_unicode_to_external (pattern);
+       if (utf8_pattern == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+               
+               SetLastError (ERROR_INVALID_NAME);
+               return(INVALID_HANDLE_VALUE);
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: looking for [%s]", __func__, utf8_pattern);
+       
+       /* Figure out which bit of the pattern is the directory */
+       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
+        * really do have metachars in their names (see bug 58116).
+        * FIXME: Figure out a better solution to keep some checks...
+        */
+       if (strchr (dir_part, '*') || strchr (dir_part, '?')) {
+               SetLastError (ERROR_INVALID_NAME);
+               g_free (dir_part);
+               g_free (entry_part);
+               g_free (utf8_pattern);
+               return(INVALID_HANDLE_VALUE);
+       }
+#endif
+
+       /* The pattern can specify a directory or a set of files.
+        *
+        * The pattern can have wildcard characters ? and *, but only
+        * in the section after the last directory delimiter.  (Return
+        * ERROR_INVALID_NAME if there are wildcards in earlier path
+        * sections.)  "*" has the usual 0-or-more chars meaning.  "?" 
+        * means "match one character", "??" seems to mean "match one
+        * or two characters", "???" seems to mean "match one, two or
+        * three characters", etc.  Windows will also try and match
+        * the mangled "short name" of files, so 8 character patterns
+        * with wildcards will show some surprising results.
+        *
+        * All the written documentation I can find says that '?' 
+        * should only match one character, and doesn't mention '??',
+        * '???' etc.  I'm going to assume that the strict behaviour
+        * (ie '???' means three and only three characters) is the
+        * correct one, because that lets me use fnmatch(3) rather
+        * than mess around with regexes.
+        */
+
+       find_handle.namelist = NULL;
+       result = _wapi_io_scandir (dir_part, entry_part,
+                                  &find_handle.namelist);
+       
+       if (result == 0) {
+               /* No files, which windows seems to call
+                * FILE_NOT_FOUND
+                */
+               SetLastError (ERROR_FILE_NOT_FOUND);
+               g_free (utf8_pattern);
+               g_free (entry_part);
+               g_free (dir_part);
+               return (INVALID_HANDLE_VALUE);
+       }
+       
+       if (result < 0) {
+               _wapi_set_last_path_error_from_errno (dir_part, NULL);
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: scandir error: %s", __func__, g_strerror (errno));
+               g_free (utf8_pattern);
+               g_free (entry_part);
+               g_free (dir_part);
+               return (INVALID_HANDLE_VALUE);
+       }
+
+       g_free (utf8_pattern);
+       g_free (entry_part);
+       
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Got %d matches", __func__, result);
+
+       find_handle.dir_part = dir_part;
+       find_handle.num = result;
+       find_handle.count = 0;
+       
+       handle = mono_w32handle_new (MONO_W32HANDLE_FIND, &find_handle);
+       if (handle == INVALID_HANDLE_VALUE) {
+               g_warning ("%s: error creating find handle", __func__);
+               g_free (dir_part);
+               g_free (entry_part);
+               g_free (utf8_pattern);
+               SetLastError (ERROR_GEN_FAILURE);
+               
+               return(INVALID_HANDLE_VALUE);
+       }
+
+       if (handle != INVALID_HANDLE_VALUE &&
+           !mono_w32file_find_next (handle, find_data)) {
+               mono_w32file_find_close (handle);
+               SetLastError (ERROR_NO_MORE_FILES);
+               handle = INVALID_HANDLE_VALUE;
+       }
+
+       return (handle);
+}
+
+gboolean
+mono_w32file_find_next (gpointer handle, WIN32_FIND_DATA *find_data)
+{
+       MonoW32HandleFind *find_handle;
+       gboolean ok;
+       struct stat buf, linkbuf;
+       gint result;
+       gchar *filename;
+       gchar *utf8_filename, *utf8_basename;
+       gunichar2 *utf16_basename;
+       time_t create_time;
+       glong bytes;
+       gboolean ret = FALSE;
+       
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FIND,
+                               (gpointer *)&find_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up find handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+
+       mono_w32handle_lock_handle (handle);
+       
+retry:
+       if (find_handle->count >= find_handle->num) {
+               SetLastError (ERROR_NO_MORE_FILES);
+               goto cleanup;
+       }
+
+       /* stat next match */
+
+       filename = g_build_filename (find_handle->dir_part, find_handle->namelist[find_handle->count ++], NULL);
+
+       result = _wapi_stat (filename, &buf);
+       if (result == -1 && errno == ENOENT) {
+               /* Might be a dangling symlink */
+               result = _wapi_lstat (filename, &buf);
+       }
+       
+       if (result != 0) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: stat failed: %s", __func__, filename);
+
+               g_free (filename);
+               goto retry;
+       }
+
+#ifndef __native_client__
+       result = _wapi_lstat (filename, &linkbuf);
+       if (result != 0) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lstat failed: %s", __func__, filename);
+
+               g_free (filename);
+               goto retry;
+       }
+#endif
+
+       utf8_filename = mono_utf8_from_external (filename);
+       if (utf8_filename == NULL) {
+               /* We couldn't turn this filename into utf8 (eg the
+                * encoding of the name wasn't convertible), so just
+                * ignore it.
+                */
+               g_warning ("%s: Bad encoding for '%s'\nConsider using MONO_EXTERNAL_ENCODINGS\n", __func__, filename);
+               
+               g_free (filename);
+               goto retry;
+       }
+       g_free (filename);
+       
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Found [%s]", __func__, utf8_filename);
+       
+       /* fill data block */
+
+       if (buf.st_mtime < buf.st_ctime)
+               create_time = buf.st_mtime;
+       else
+               create_time = buf.st_ctime;
+       
+#ifdef __native_client__
+       find_data->dwFileAttributes = _wapi_stat_to_file_attributes (utf8_filename, &buf, NULL);
+#else
+       find_data->dwFileAttributes = _wapi_stat_to_file_attributes (utf8_filename, &buf, &linkbuf);
+#endif
+
+       time_t_to_filetime (create_time, &find_data->ftCreationTime);
+       time_t_to_filetime (buf.st_atime, &find_data->ftLastAccessTime);
+       time_t_to_filetime (buf.st_mtime, &find_data->ftLastWriteTime);
+
+       if (find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+               find_data->nFileSizeHigh = 0;
+               find_data->nFileSizeLow = 0;
+       } else {
+               find_data->nFileSizeHigh = buf.st_size >> 32;
+               find_data->nFileSizeLow = buf.st_size & 0xFFFFFFFF;
+       }
+
+       find_data->dwReserved0 = 0;
+       find_data->dwReserved1 = 0;
+
+       utf8_basename = _wapi_basename (utf8_filename);
+       utf16_basename = g_utf8_to_utf16 (utf8_basename, -1, NULL, &bytes,
+                                         NULL);
+       if(utf16_basename==NULL) {
+               g_free (utf8_basename);
+               g_free (utf8_filename);
+               goto retry;
+       }
+       ret = TRUE;
+       
+       /* utf16 is 2 * utf8 */
+       bytes *= 2;
+
+       memset (find_data->cFileName, '\0', (MAX_PATH*2));
+
+       /* Truncating a utf16 string like this might leave the last
+        * gchar incomplete
+        */
+       memcpy (find_data->cFileName, utf16_basename,
+               bytes<(MAX_PATH*2)-2?bytes:(MAX_PATH*2)-2);
+
+       find_data->cAlternateFileName [0] = 0;  /* not used */
+
+       g_free (utf8_basename);
+       g_free (utf8_filename);
+       g_free (utf16_basename);
+
+cleanup:
+       mono_w32handle_unlock_handle (handle);
+       
+       return(ret);
+}
+
+gboolean
+mono_w32file_find_close (gpointer handle)
+{
+       MonoW32HandleFind *find_handle;
+       gboolean ok;
+
+       if (handle == NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FIND,
+                               (gpointer *)&find_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up find handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+
+       mono_w32handle_lock_handle (handle);
+       
+       g_strfreev (find_handle->namelist);
+       g_free (find_handle->dir_part);
+
+       mono_w32handle_unlock_handle (handle);
+       
+       mono_w32handle_unref (handle);
+       
+       return(TRUE);
+}
+
+gboolean
+mono_w32file_create_directory (const gunichar2 *name)
+{
+       gchar *utf8_name;
+       gint result;
+       
+       if (name == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
+       
+       utf8_name = mono_unicode_to_external (name);
+       if (utf8_name == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+       
+               SetLastError (ERROR_INVALID_NAME);
+               return FALSE;
+       }
+
+       result = _wapi_mkdir (utf8_name, 0777);
+
+       if (result == 0) {
+               g_free (utf8_name);
+               return TRUE;
+       }
+
+       _wapi_set_last_path_error_from_errno (NULL, utf8_name);
+       g_free (utf8_name);
+       return FALSE;
+}
+
+gboolean
+mono_w32file_remove_directory (const gunichar2 *name)
+{
+       gchar *utf8_name;
+       gint result;
+       
+       if (name == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
+
+       utf8_name = mono_unicode_to_external (name);
+       if (utf8_name == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+               
+               SetLastError (ERROR_INVALID_NAME);
+               return FALSE;
+       }
+
+       result = _wapi_rmdir (utf8_name);
+       if (result == -1) {
+               _wapi_set_last_path_error_from_errno (NULL, utf8_name);
+               g_free (utf8_name);
+               
+               return(FALSE);
+       }
+       g_free (utf8_name);
+
+       return(TRUE);
+}
+
+guint32
+mono_w32file_get_attributes (const gunichar2 *name)
+{
+       gchar *utf8_name;
+       struct stat buf, linkbuf;
+       gint result;
+       guint32 ret;
+       
+       if (name == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
+       
+       utf8_name = mono_unicode_to_external (name);
+       if (utf8_name == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+               SetLastError (ERROR_INVALID_PARAMETER);
+               return (INVALID_FILE_ATTRIBUTES);
+       }
+
+       result = _wapi_stat (utf8_name, &buf);
+       if (result == -1 && errno == ENOENT) {
+               /* Might be a dangling symlink... */
+               result = _wapi_lstat (utf8_name, &buf);
+       }
+
+       if (result != 0) {
+               _wapi_set_last_path_error_from_errno (NULL, utf8_name);
+               g_free (utf8_name);
+               return (INVALID_FILE_ATTRIBUTES);
+       }
+
+#ifndef __native_client__
+       result = _wapi_lstat (utf8_name, &linkbuf);
+       if (result != 0) {
+               _wapi_set_last_path_error_from_errno (NULL, utf8_name);
+               g_free (utf8_name);
+               return (INVALID_FILE_ATTRIBUTES);
+       }
+#endif
+       
+#ifdef __native_client__
+       ret = _wapi_stat_to_file_attributes (utf8_name, &buf, NULL);
+#else
+       ret = _wapi_stat_to_file_attributes (utf8_name, &buf, &linkbuf);
+#endif
+       
+       g_free (utf8_name);
+
+       return(ret);
+}
+
+gboolean
+mono_w32file_get_attributes_ex (const gunichar2 *name, MonoIOStat *stat)
+{
+       gchar *utf8_name;
+
+       struct stat buf, linkbuf;
+       gint result;
+       
+       if (name == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
+
+       utf8_name = mono_unicode_to_external (name);
+       if (utf8_name == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+               SetLastError (ERROR_INVALID_PARAMETER);
+               return FALSE;
+       }
+
+       result = _wapi_stat (utf8_name, &buf);
+       if (result == -1 && errno == ENOENT) {
+               /* Might be a dangling symlink... */
+               result = _wapi_lstat (utf8_name, &buf);
+       }
+       
+       if (result != 0) {
+               _wapi_set_last_path_error_from_errno (NULL, utf8_name);
+               g_free (utf8_name);
+               return FALSE;
+       }
+
+       result = _wapi_lstat (utf8_name, &linkbuf);
+       if (result != 0) {
+               _wapi_set_last_path_error_from_errno (NULL, utf8_name);
+               g_free (utf8_name);
+               return(FALSE);
+       }
+
+       /* fill stat block */
+
+       stat->attributes = _wapi_stat_to_file_attributes (utf8_name, &buf, &linkbuf);
+       stat->creation_time = (((guint64) (buf.st_mtime < buf.st_ctime ? buf.st_mtime : buf.st_ctime)) * 10 * 1000 * 1000) + 116444736000000000ULL;
+       stat->last_access_time = (((guint64) (buf.st_atime)) * 10 * 1000 * 1000) + 116444736000000000ULL;
+       stat->last_write_time = (((guint64) (buf.st_mtime)) * 10 * 1000 * 1000) + 116444736000000000ULL;
+       stat->length = (stat->attributes & FILE_ATTRIBUTE_DIRECTORY) ? 0 : buf.st_size;
+
+       g_free (utf8_name);
+       return TRUE;
+}
+
+gboolean
+mono_w32file_set_attributes (const gunichar2 *name, guint32 attrs)
+{
+       /* FIXME: think of something clever to do on unix */
+       gchar *utf8_name;
+       struct stat buf;
+       gint result;
+
+       /*
+        * Currently we only handle one *internal* case, with a value that is
+        * not standard: 0x80000000, which means `set executable bit'
+        */
+       
+       if (name == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
+
+       utf8_name = mono_unicode_to_external (name);
+       if (utf8_name == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+               SetLastError (ERROR_INVALID_NAME);
+               return FALSE;
+       }
+
+       result = _wapi_stat (utf8_name, &buf);
+       if (result == -1 && errno == ENOENT) {
+               /* Might be a dangling symlink... */
+               result = _wapi_lstat (utf8_name, &buf);
+       }
+
+       if (result != 0) {
+               _wapi_set_last_path_error_from_errno (NULL, utf8_name);
+               g_free (utf8_name);
+               return FALSE;
+       }
+
+       /* Contrary to the documentation, ms allows NORMAL to be
+        * specified along with other attributes, so dont bother to
+        * catch that case here.
+        */
+       if (attrs & FILE_ATTRIBUTE_READONLY) {
+               result = _wapi_chmod (utf8_name, buf.st_mode & ~(S_IWUSR | S_IWOTH | S_IWGRP));
+       } else {
+               result = _wapi_chmod (utf8_name, buf.st_mode | S_IWUSR);
+       }
+
+       /* Ignore the other attributes for now */
+
+       if (attrs & 0x80000000){
+               mode_t exec_mask = 0;
+
+               if ((buf.st_mode & S_IRUSR) != 0)
+                       exec_mask |= S_IXUSR;
+
+               if ((buf.st_mode & S_IRGRP) != 0)
+                       exec_mask |= S_IXGRP;
+
+               if ((buf.st_mode & S_IROTH) != 0)
+                       exec_mask |= S_IXOTH;
+
+               result = chmod (utf8_name, buf.st_mode | exec_mask);
+       }
+       /* Don't bother to reset executable (might need to change this
+        * policy)
+        */
+       
+       g_free (utf8_name);
+
+       return(TRUE);
+}
+
+guint32
+mono_w32file_get_cwd (guint32 length, gunichar2 *buffer)
+{
+       gunichar2 *utf16_path;
+       glong count;
+       gsize bytes;
+
+#ifdef __native_client__
+       gchar *path = g_get_current_dir ();
+       if (length < strlen(path) + 1 || path == NULL)
+               return 0;
+       memcpy (buffer, path, strlen(path) + 1);
+#else
+       if (getcwd ((gchar*)buffer, length) == NULL) {
+               if (errno == ERANGE) { /*buffer length is not big enough */ 
+                       gchar *path = g_get_current_dir (); /*FIXME g_get_current_dir doesn't work with broken paths and calling it just to know the path length is silly*/
+                       if (path == NULL)
+                               return 0;
+                       utf16_path = mono_unicode_from_external (path, &bytes);
+                       g_free (utf16_path);
+                       g_free (path);
+                       return (bytes/2)+1;
+               }
+               _wapi_set_last_error_from_errno ();
+               return 0;
+       }
+#endif
+
+       utf16_path = mono_unicode_from_external ((gchar*)buffer, &bytes);
+       count = (bytes/2)+1;
+       g_assert (count <= length); /*getcwd must have failed before with ERANGE*/
+
+       /* Add the terminator */
+       memset (buffer, '\0', bytes+2);
+       memcpy (buffer, utf16_path, bytes);
+       
+       g_free (utf16_path);
+
+       return count;
+}
+
+gboolean
+mono_w32file_set_cwd (const gunichar2 *path)
+{
+       gchar *utf8_path;
+       gboolean result;
+
+       if (path == NULL) {
+               SetLastError (ERROR_INVALID_PARAMETER);
+               return(FALSE);
+       }
+       
+       utf8_path = mono_unicode_to_external (path);
+       if (_wapi_chdir (utf8_path) != 0) {
+               _wapi_set_last_error_from_errno ();
+               result = FALSE;
+       }
+       else
+               result = TRUE;
+
+       g_free (utf8_path);
+       return result;
+}
+
+gboolean
+mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size)
+{
+       MonoW32HandleFile pipe_read_handle = {0};
+       MonoW32HandleFile pipe_write_handle = {0};
+       gpointer read_handle;
+       gpointer write_handle;
+       gint filedes[2];
+       gint ret;
+       
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating pipe", __func__);
+
+       ret=pipe (filedes);
+       if(ret==-1) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error creating pipe: %s", __func__,
+                          strerror (errno));
+               
+               _wapi_set_last_error_from_errno ();
+               return(FALSE);
+       }
+
+       if (filedes[0] >= mono_w32handle_fd_reserve ||
+           filedes[1] >= mono_w32handle_fd_reserve) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
+
+               SetLastError (ERROR_TOO_MANY_OPEN_FILES);
+               
+               close (filedes[0]);
+               close (filedes[1]);
+               
+               return(FALSE);
+       }
+       
+       /* filedes[0] is open for reading, filedes[1] for writing */
+
+       pipe_read_handle.fd = filedes [0];
+       pipe_read_handle.fileaccess = GENERIC_READ;
+       read_handle = mono_w32handle_new_fd (MONO_W32HANDLE_PIPE, filedes[0],
+                                          &pipe_read_handle);
+       if (read_handle == INVALID_HANDLE_VALUE) {
+               g_warning ("%s: error creating pipe read handle", __func__);
+               close (filedes[0]);
+               close (filedes[1]);
+               SetLastError (ERROR_GEN_FAILURE);
+               
+               return(FALSE);
+       }
+       
+       pipe_write_handle.fd = filedes [1];
+       pipe_write_handle.fileaccess = GENERIC_WRITE;
+       write_handle = mono_w32handle_new_fd (MONO_W32HANDLE_PIPE, filedes[1],
+                                           &pipe_write_handle);
+       if (write_handle == INVALID_HANDLE_VALUE) {
+               g_warning ("%s: error creating pipe write handle", __func__);
+               mono_w32handle_unref (read_handle);
+               
+               close (filedes[0]);
+               close (filedes[1]);
+               SetLastError (ERROR_GEN_FAILURE);
+               
+               return(FALSE);
+       }
+       
+       *readpipe = read_handle;
+       *writepipe = write_handle;
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning pipe: read handle %p, write handle %p",
+                  __func__, read_handle, write_handle);
+
+       return(TRUE);
+}
+
+#ifdef HAVE_GETFSSTAT
+/* Darwin has getfsstat */
+gint32
+mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf)
+{
+       struct statfs *stats;
+       gint size, n, i;
+       gunichar2 *dir;
+       glong length, total = 0;
+       
+       n = getfsstat (NULL, 0, MNT_NOWAIT);
+       if (n == -1)
+               return 0;
+       size = n * sizeof (struct statfs);
+       stats = (struct statfs *) g_malloc (size);
+       if (stats == NULL)
+               return 0;
+       if (getfsstat (stats, size, MNT_NOWAIT) == -1){
+               g_free (stats);
+               return 0;
+       }
+       for (i = 0; i < n; i++){
+               dir = g_utf8_to_utf16 (stats [i].f_mntonname, -1, NULL, &length, NULL);
+               if (total + length < len){
+                       memcpy (buf + total, dir, sizeof (gunichar2) * length);
+                       buf [total+length] = 0;
+               } 
+               g_free (dir);
+               total += length + 1;
+       }
+       if (total < len)
+               buf [total] = 0;
+       total++;
+       g_free (stats);
+       return total;
+}
+#else
+/* In-place octal sequence replacement */
+static void
+unescape_octal (gchar *str)
+{
+       gchar *rptr;
+       gchar *wptr;
+
+       if (str == NULL)
+               return;
+
+       rptr = wptr = str;
+       while (*rptr != '\0') {
+               if (*rptr == '\\') {
+                       gchar c;
+                       rptr++;
+                       c = (*(rptr++) - '0') << 6;
+                       c += (*(rptr++) - '0') << 3;
+                       c += *(rptr++) - '0';
+                       *wptr++ = c;
+               } else if (wptr != rptr) {
+                       *wptr++ = *rptr++;
+               } else {
+                       rptr++; wptr++;
+               }
+       }
+       *wptr = '\0';
+}
+static gint32 GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf);
+
+#if __linux__
+#define GET_LOGICAL_DRIVE_STRINGS_BUFFER 512
+#define GET_LOGICAL_DRIVE_STRINGS_MOUNTPOINT_BUFFER 512
+#define GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER 64
+
+typedef struct 
+{
+       glong total;
+       guint32 buffer_index;
+       guint32 mountpoint_index;
+       guint32 field_number;
+       guint32 allocated_size;
+       guint32 fsname_index;
+       guint32 fstype_index;
+       gchar mountpoint [GET_LOGICAL_DRIVE_STRINGS_MOUNTPOINT_BUFFER + 1];
+       gchar *mountpoint_allocated;
+       gchar buffer [GET_LOGICAL_DRIVE_STRINGS_BUFFER];
+       gchar fsname [GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER + 1];
+       gchar fstype [GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER + 1];
+       ssize_t nbytes;
+       gchar delimiter;
+       gboolean check_mount_source;
+} LinuxMountInfoParseState;
+
+static gboolean GetLogicalDriveStrings_Mounts (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state);
+static gboolean GetLogicalDriveStrings_MountInfo (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state);
+static void append_to_mountpoint (LinuxMountInfoParseState *state);
+static gboolean add_drive_string (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state);
+
+gint32
+mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf)
+{
+       gint fd;
+       gint32 ret = 0;
+       LinuxMountInfoParseState state;
+       gboolean (*parser)(guint32, gunichar2*, LinuxMountInfoParseState*) = NULL;
+
+       memset (buf, 0, len * sizeof (gunichar2));
+       fd = open ("/proc/self/mountinfo", O_RDONLY);
+       if (fd != -1)
+               parser = GetLogicalDriveStrings_MountInfo;
+       else {
+               fd = open ("/proc/mounts", O_RDONLY);
+               if (fd != -1)
+                       parser = GetLogicalDriveStrings_Mounts;
+       }
+
+       if (!parser) {
+               ret = GetLogicalDriveStrings_Mtab (len, buf);
+               goto done_and_out;
+       }
+
+       memset (&state, 0, sizeof (LinuxMountInfoParseState));
+       state.field_number = 1;
+       state.delimiter = ' ';
+
+       while ((state.nbytes = read (fd, state.buffer, GET_LOGICAL_DRIVE_STRINGS_BUFFER)) > 0) {
+               state.buffer_index = 0;
+
+               while ((*parser)(len, buf, &state)) {
+                       if (state.buffer [state.buffer_index] == '\n') {
+                               gboolean quit = add_drive_string (len, buf, &state);
+                               state.field_number = 1;
+                               state.buffer_index++;
+                               if (state.mountpoint_allocated) {
+                                       g_free (state.mountpoint_allocated);
+                                       state.mountpoint_allocated = NULL;
+                               }
+                               if (quit) {
+                                       ret = state.total;
+                                       goto done_and_out;
+                               }
+                       }
+               }
+       };
+       ret = state.total;
+
+  done_and_out:
+       if (fd != -1)
+               close (fd);
+       return ret;
+}
+
+static gboolean GetLogicalDriveStrings_Mounts (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state)
+{
+       gchar *ptr;
+
+       if (state->field_number == 1)
+               state->check_mount_source = TRUE;
+
+       while (state->buffer_index < (guint32)state->nbytes) {
+               if (state->buffer [state->buffer_index] == state->delimiter) {
+                       state->field_number++;
+                       switch (state->field_number) {
+                               case 2:
+                                       state->mountpoint_index = 0;
+                                       break;
+
+                               case 3:
+                                       if (state->mountpoint_allocated)
+                                               state->mountpoint_allocated [state->mountpoint_index] = 0;
+                                       else
+                                               state->mountpoint [state->mountpoint_index] = 0;
+                                       break;
+
+                               default:
+                                       ptr = (gchar*)memchr (state->buffer + state->buffer_index, '\n', GET_LOGICAL_DRIVE_STRINGS_BUFFER - state->buffer_index);
+                                       if (ptr)
+                                               state->buffer_index = (ptr - (gchar*)state->buffer) - 1;
+                                       else
+                                               state->buffer_index = state->nbytes;
+                                       return TRUE;
+                       }
+                       state->buffer_index++;
+                       continue;
+               } else if (state->buffer [state->buffer_index] == '\n')
+                       return TRUE;
+
+               switch (state->field_number) {
+                       case 1:
+                               if (state->check_mount_source) {
+                                       if (state->fsname_index == 0 && state->buffer [state->buffer_index] == '/') {
+                                               /* We can ignore the rest, it's a device
+                                                * path */
+                                               state->check_mount_source = FALSE;
+                                               state->fsname [state->fsname_index++] = '/';
+                                               break;
+                                       }
+                                       if (state->fsname_index < GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER)
+                                               state->fsname [state->fsname_index++] = state->buffer [state->buffer_index];
+                               }
+                               break;
+
+                       case 2:
+                               append_to_mountpoint (state);
+                               break;
+
+                       case 3:
+                               if (state->fstype_index < GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER)
+                                       state->fstype [state->fstype_index++] = state->buffer [state->buffer_index];
+                               break;
+               }
+
+               state->buffer_index++;
+       }
+
+       return FALSE;
+}
+
+static gboolean GetLogicalDriveStrings_MountInfo (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state)
+{
+       while (state->buffer_index < (guint32)state->nbytes) {
+               if (state->buffer [state->buffer_index] == state->delimiter) {
+                       state->field_number++;
+                       switch (state->field_number) {
+                               case 5:
+                                       state->mountpoint_index = 0;
+                                       break;
+
+                               case 6:
+                                       if (state->mountpoint_allocated)
+                                               state->mountpoint_allocated [state->mountpoint_index] = 0;
+                                       else
+                                               state->mountpoint [state->mountpoint_index] = 0;
+                                       break;
+
+                               case 7:
+                                       state->delimiter = '-';
+                                       break;
+
+                               case 8:
+                                       state->delimiter = ' ';
+                                       break;
+
+                               case 10:
+                                       state->check_mount_source = TRUE;
+                                       break;
+                       }
+                       state->buffer_index++;
+                       continue;
+               } else if (state->buffer [state->buffer_index] == '\n')
+                       return TRUE;
+
+               switch (state->field_number) {
+                       case 5:
+                               append_to_mountpoint (state);
+                               break;
+
+                       case 9:
+                               if (state->fstype_index < GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER)
+                                       state->fstype [state->fstype_index++] = state->buffer [state->buffer_index];
+                               break;
+
+                       case 10:
+                               if (state->check_mount_source) {
+                                       if (state->fsname_index == 0 && state->buffer [state->buffer_index] == '/') {
+                                               /* We can ignore the rest, it's a device
+                                                * path */
+                                               state->check_mount_source = FALSE;
+                                               state->fsname [state->fsname_index++] = '/';
+                                               break;
+                                       }
+                                       if (state->fsname_index < GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER)
+                                               state->fsname [state->fsname_index++] = state->buffer [state->buffer_index];
+                               }
+                               break;
+               }
+
+               state->buffer_index++;
+       }
+
+       return FALSE;
+}
+
+static void
+append_to_mountpoint (LinuxMountInfoParseState *state)
+{
+       gchar ch = state->buffer [state->buffer_index];
+       if (state->mountpoint_allocated) {
+               if (state->mountpoint_index >= state->allocated_size) {
+                       guint32 newsize = (state->allocated_size << 1) + 1;
+                       gchar *newbuf = (gchar *)g_malloc0 (newsize * sizeof (gchar));
+
+                       memcpy (newbuf, state->mountpoint_allocated, state->mountpoint_index);
+                       g_free (state->mountpoint_allocated);
+                       state->mountpoint_allocated = newbuf;
+                       state->allocated_size = newsize;
+               }
+               state->mountpoint_allocated [state->mountpoint_index++] = ch;
+       } else {
+               if (state->mountpoint_index >= GET_LOGICAL_DRIVE_STRINGS_MOUNTPOINT_BUFFER) {
+                       state->allocated_size = (state->mountpoint_index << 1) + 1;
+                       state->mountpoint_allocated = (gchar *)g_malloc0 (state->allocated_size * sizeof (gchar));
+                       memcpy (state->mountpoint_allocated, state->mountpoint, state->mountpoint_index);
+                       state->mountpoint_allocated [state->mountpoint_index++] = ch;
+               } else
+                       state->mountpoint [state->mountpoint_index++] = ch;
+       }
+}
+
+static gboolean
+add_drive_string (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state)
+{
+       gboolean quit = FALSE;
+       gboolean ignore_entry;
+
+       if (state->fsname_index == 1 && state->fsname [0] == '/')
+               ignore_entry = FALSE;
+       else if (memcmp ("overlay", state->fsname, state->fsname_index) == 0 ||
+               memcmp ("aufs", state->fstype, state->fstype_index) == 0) {
+               /* Don't ignore overlayfs and aufs - these might be used on Docker
+                * (https://bugzilla.xamarin.com/show_bug.cgi?id=31021) */
+               ignore_entry = FALSE;
+       } else if (state->fsname_index == 0 || memcmp ("none", state->fsname, state->fsname_index) == 0) {
+               ignore_entry = TRUE;
+       } else if (state->fstype_index >= 5 && memcmp ("fuse.", state->fstype, 5) == 0) {
+               /* Ignore GNOME's gvfs */
+               if (state->fstype_index == 21 && memcmp ("fuse.gvfs-fuse-daemon", state->fstype, state->fstype_index) == 0)
+                       ignore_entry = TRUE;
+               else
+                       ignore_entry = FALSE;
+       } else if (state->fstype_index == 3 && memcmp ("nfs", state->fstype, state->fstype_index) == 0)
+               ignore_entry = FALSE;
+       else
+               ignore_entry = TRUE;
+
+       if (!ignore_entry) {
+               gunichar2 *dir;
+               glong length;
+               gchar *mountpoint = state->mountpoint_allocated ? state->mountpoint_allocated : state->mountpoint;
+
+               unescape_octal (mountpoint);
+               dir = g_utf8_to_utf16 (mountpoint, -1, NULL, &length, NULL);
+               if (state->total + length + 1 > len) {
+                       quit = TRUE;
+                       state->total = len * 2;
+               } else {
+                       length++;
+                       memcpy (buf + state->total, dir, sizeof (gunichar2) * length);
+                       state->total += length;
+               }
+               g_free (dir);
+       }
+       state->fsname_index = 0;
+       state->fstype_index = 0;
+
+       return quit;
+}
+#else
+gint32
+mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf)
+{
+       return GetLogicalDriveStrings_Mtab (len, buf);
+}
+#endif
+static gint32
+GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf)
+{
+       FILE *fp;
+       gunichar2 *ptr, *dir;
+       glong length, total = 0;
+       gchar buffer [512];
+       gchar **splitted;
+
+       memset (buf, 0, sizeof (gunichar2) * (len + 1)); 
+       buf [0] = '/';
+       buf [1] = 0;
+       buf [2] = 0;
+
+       /* Sigh, mntent and friends don't work well.
+        * It stops on the first line that doesn't begin with a '/'.
+        * (linux 2.6.5, libc 2.3.2.ds1-12) - Gonz */
+       fp = fopen ("/etc/mtab", "rt");
+       if (fp == NULL) {
+               fp = fopen ("/etc/mnttab", "rt");
+               if (fp == NULL)
+                       return 1;
+       }
+
+       ptr = buf;
+       while (fgets (buffer, 512, fp) != NULL) {
+               if (*buffer != '/')
+                       continue;
+
+               splitted = g_strsplit (buffer, " ", 0);
+               if (!*splitted || !*(splitted + 1)) {
+                       g_strfreev (splitted);
+                       continue;
+               }
+
+               unescape_octal (*(splitted + 1));
+               dir = g_utf8_to_utf16 (*(splitted + 1), -1, NULL, &length, NULL);
+               g_strfreev (splitted);
+               if (total + length + 1 > len) {
+                       fclose (fp);
+                       g_free (dir);
+                       return len * 2; /* guess */
+               }
+
+               memcpy (ptr + total, dir, sizeof (gunichar2) * length);
+               g_free (dir);
+               total += length + 1;
+       }
+
+       fclose (fp);
+       return total;
+/* Commented out, does not work with my mtab!!! - Gonz */
+#ifdef NOTENABLED /* HAVE_MNTENT_H */
+{
+       FILE *fp;
+       struct mntent *mnt;
+       gunichar2 *ptr, *dir;
+       glong len, total = 0;
+       
+
+       fp = setmntent ("/etc/mtab", "rt");
+       if (fp == NULL) {
+               fp = setmntent ("/etc/mnttab", "rt");
+               if (fp == NULL)
+                       return;
+       }
+
+       ptr = buf;
+       while ((mnt = getmntent (fp)) != NULL) {
+               g_print ("GOT %s\n", mnt->mnt_dir);
+               dir = g_utf8_to_utf16 (mnt->mnt_dir, &len, NULL, NULL, NULL);
+               if (total + len + 1 > len) {
+                       return len * 2; /* guess */
+               }
+
+               memcpy (ptr + total, dir, sizeof (gunichar2) * len);
+               g_free (dir);
+               total += len + 1;
+       }
+
+       endmntent (fp);
+       return total;
+}
+#endif
+}
+#endif
+
+#if defined(HAVE_STATVFS) || defined(HAVE_STATFS)
+gboolean
+mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_bytes_avail, guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes)
+{
+#ifdef HAVE_STATVFS
+       struct statvfs fsstat;
+#elif defined(HAVE_STATFS)
+       struct statfs fsstat;
+#endif
+       gboolean isreadonly;
+       gchar *utf8_path_name;
+       gint ret;
+       unsigned long block_size;
+
+       if (path_name == NULL) {
+               utf8_path_name = g_strdup (g_get_current_dir());
+               if (utf8_path_name == NULL) {
+                       SetLastError (ERROR_DIRECTORY);
+                       return(FALSE);
+               }
+       }
+       else {
+               utf8_path_name = mono_unicode_to_external (path_name);
+               if (utf8_path_name == NULL) {
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+                       SetLastError (ERROR_INVALID_NAME);
+                       return(FALSE);
+               }
+       }
+
+       do {
+#ifdef HAVE_STATVFS
+               ret = statvfs (utf8_path_name, &fsstat);
+               isreadonly = ((fsstat.f_flag & ST_RDONLY) == ST_RDONLY);
+               block_size = fsstat.f_frsize;
+#elif defined(HAVE_STATFS)
+               ret = statfs (utf8_path_name, &fsstat);
+#if defined (MNT_RDONLY)
+               isreadonly = ((fsstat.f_flags & MNT_RDONLY) == MNT_RDONLY);
+#elif defined (MS_RDONLY)
+               isreadonly = ((fsstat.f_flags & MS_RDONLY) == MS_RDONLY);
+#endif
+               block_size = fsstat.f_bsize;
+#endif
+       } while(ret == -1 && errno == EINTR);
+
+       g_free(utf8_path_name);
+
+       if (ret == -1) {
+               _wapi_set_last_error_from_errno ();
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: statvfs failed: %s", __func__, strerror (errno));
+               return(FALSE);
+       }
+
+       /* total number of free bytes for non-root */
+       if (free_bytes_avail != NULL) {
+               if (isreadonly) {
+                       *free_bytes_avail = 0;
+               }
+               else {
+                       *free_bytes_avail = block_size * (guint64)fsstat.f_bavail;
+               }
+       }
+
+       /* total number of bytes available for non-root */
+       if (total_number_of_bytes != NULL) {
+               *total_number_of_bytes = block_size * (guint64)fsstat.f_blocks;
+       }
+
+       /* total number of bytes available for root */
+       if (total_number_of_free_bytes != NULL) {
+               if (isreadonly) {
+                       *total_number_of_free_bytes = 0;
+               }
+               else {
+                       *total_number_of_free_bytes = block_size * (guint64)fsstat.f_bfree;
+               }
+       }
+       
+       return(TRUE);
+}
+#else
+gboolean
+mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_bytes_avail, guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes)
+{
+       if (free_bytes_avail != NULL) {
+               *free_bytes_avail = (guint64) -1;
+       }
+
+       if (total_number_of_bytes != NULL) {
+               *total_number_of_bytes = (guint64) -1;
+       }
+
+       if (total_number_of_free_bytes != NULL) {
+               *total_number_of_free_bytes = (guint64) -1;
+       }
+
+       return(TRUE);
+}
+#endif
+
+/*
+ * General Unix support
+ */
+typedef struct {
+       guint32 drive_type;
+#if __linux__
+       const long fstypeid;
+#endif
+       const gchar* fstype;
+} _wapi_drive_type;
+
+static _wapi_drive_type _wapi_drive_types[] = {
+#if PLATFORM_MACOSX
+       { DRIVE_REMOTE, "afp" },
+       { DRIVE_REMOTE, "autofs" },
+       { DRIVE_CDROM, "cddafs" },
+       { DRIVE_CDROM, "cd9660" },
+       { DRIVE_RAMDISK, "devfs" },
+       { DRIVE_FIXED, "exfat" },
+       { DRIVE_RAMDISK, "fdesc" },
+       { DRIVE_REMOTE, "ftp" },
+       { DRIVE_FIXED, "hfs" },
+       { DRIVE_FIXED, "msdos" },
+       { DRIVE_REMOTE, "nfs" },
+       { DRIVE_FIXED, "ntfs" },
+       { DRIVE_REMOTE, "smbfs" },
+       { DRIVE_FIXED, "udf" },
+       { DRIVE_REMOTE, "webdav" },
+       { DRIVE_UNKNOWN, NULL }
+#elif __linux__
+       { DRIVE_FIXED, ADFS_SUPER_MAGIC, "adfs"},
+       { DRIVE_FIXED, AFFS_SUPER_MAGIC, "affs"},
+       { DRIVE_REMOTE, AFS_SUPER_MAGIC, "afs"},
+       { DRIVE_RAMDISK, AUTOFS_SUPER_MAGIC, "autofs"},
+       { DRIVE_RAMDISK, AUTOFS_SBI_MAGIC, "autofs4"},
+       { DRIVE_REMOTE, CODA_SUPER_MAGIC, "coda" },
+       { DRIVE_RAMDISK, CRAMFS_MAGIC, "cramfs"},
+       { DRIVE_RAMDISK, CRAMFS_MAGIC_WEND, "cramfs"},
+       { DRIVE_REMOTE, CIFS_MAGIC_NUMBER, "cifs"},
+       { DRIVE_RAMDISK, DEBUGFS_MAGIC, "debugfs"},
+       { DRIVE_RAMDISK, SYSFS_MAGIC, "sysfs"},
+       { DRIVE_RAMDISK, SECURITYFS_MAGIC, "securityfs"},
+       { DRIVE_RAMDISK, SELINUX_MAGIC, "selinuxfs"},
+       { DRIVE_RAMDISK, RAMFS_MAGIC, "ramfs"},
+       { DRIVE_FIXED, SQUASHFS_MAGIC, "squashfs"},
+       { DRIVE_FIXED, EFS_SUPER_MAGIC, "efs"},
+       { DRIVE_FIXED, EXT2_SUPER_MAGIC, "ext"},
+       { DRIVE_FIXED, EXT3_SUPER_MAGIC, "ext"},
+       { DRIVE_FIXED, EXT4_SUPER_MAGIC, "ext"},
+       { DRIVE_REMOTE, XENFS_SUPER_MAGIC, "xenfs"},
+       { DRIVE_FIXED, BTRFS_SUPER_MAGIC, "btrfs"},
+       { DRIVE_FIXED, HFS_SUPER_MAGIC, "hfs"},
+       { DRIVE_FIXED, HFSPLUS_SUPER_MAGIC, "hfsplus"},
+       { DRIVE_FIXED, HPFS_SUPER_MAGIC, "hpfs"},
+       { DRIVE_RAMDISK, HUGETLBFS_MAGIC, "hugetlbfs"},
+       { DRIVE_CDROM, ISOFS_SUPER_MAGIC, "iso"},
+       { DRIVE_FIXED, JFFS2_SUPER_MAGIC, "jffs2"},
+       { DRIVE_RAMDISK, ANON_INODE_FS_MAGIC, "anon_inode"},
+       { DRIVE_FIXED, JFS_SUPER_MAGIC, "jfs"},
+       { DRIVE_FIXED, MINIX_SUPER_MAGIC, "minix"},
+       { DRIVE_FIXED, MINIX_SUPER_MAGIC2, "minix v2"},
+       { DRIVE_FIXED, MINIX2_SUPER_MAGIC, "minix2"},
+       { DRIVE_FIXED, MINIX2_SUPER_MAGIC2, "minix2 v2"},
+       { DRIVE_FIXED, MINIX3_SUPER_MAGIC, "minix3"},
+       { DRIVE_FIXED, MSDOS_SUPER_MAGIC, "msdos"},
+       { DRIVE_REMOTE, NCP_SUPER_MAGIC, "ncp"},
+       { DRIVE_REMOTE, NFS_SUPER_MAGIC, "nfs"},
+       { DRIVE_FIXED, NTFS_SB_MAGIC, "ntfs"},
+       { DRIVE_RAMDISK, OPENPROM_SUPER_MAGIC, "openpromfs"},
+       { DRIVE_RAMDISK, PROC_SUPER_MAGIC, "proc"},
+       { DRIVE_FIXED, QNX4_SUPER_MAGIC, "qnx4"},
+       { DRIVE_FIXED, REISERFS_SUPER_MAGIC, "reiserfs"},
+       { DRIVE_RAMDISK, ROMFS_MAGIC, "romfs"},
+       { DRIVE_REMOTE, SMB_SUPER_MAGIC, "samba"},
+       { DRIVE_RAMDISK, CGROUP_SUPER_MAGIC, "cgroupfs"},
+       { DRIVE_RAMDISK, FUTEXFS_SUPER_MAGIC, "futexfs"},
+       { DRIVE_FIXED, SYSV2_SUPER_MAGIC, "sysv2"},
+       { DRIVE_FIXED, SYSV4_SUPER_MAGIC, "sysv4"},
+       { DRIVE_RAMDISK, TMPFS_MAGIC, "tmpfs"},
+       { DRIVE_RAMDISK, DEVPTS_SUPER_MAGIC, "devpts"},
+       { DRIVE_CDROM, UDF_SUPER_MAGIC, "udf"},
+       { DRIVE_FIXED, UFS_MAGIC, "ufs"},
+       { DRIVE_FIXED, UFS_MAGIC_BW, "ufs"},
+       { DRIVE_FIXED, UFS2_MAGIC, "ufs2"},
+       { DRIVE_FIXED, UFS_CIGAM, "ufs"},
+       { DRIVE_RAMDISK, USBDEVICE_SUPER_MAGIC, "usbdev"},
+       { DRIVE_FIXED, XENIX_SUPER_MAGIC, "xenix"},
+       { DRIVE_FIXED, XFS_SB_MAGIC, "xfs"},
+       { DRIVE_RAMDISK, FUSE_SUPER_MAGIC, "fuse"},
+       { DRIVE_FIXED, V9FS_MAGIC, "9p"},
+       { DRIVE_REMOTE, CEPH_SUPER_MAGIC, "ceph"},
+       { DRIVE_RAMDISK, CONFIGFS_MAGIC, "configfs"},
+       { DRIVE_RAMDISK, ECRYPTFS_SUPER_MAGIC, "eCryptfs"},
+       { DRIVE_FIXED, EXOFS_SUPER_MAGIC, "exofs"},
+       { DRIVE_FIXED, VXFS_SUPER_MAGIC, "vxfs"},
+       { DRIVE_FIXED, VXFS_OLT_MAGIC, "vxfs_olt"},
+       { DRIVE_REMOTE, GFS2_MAGIC, "gfs2"},
+       { DRIVE_FIXED, LOGFS_MAGIC_U32, "logfs"},
+       { DRIVE_FIXED, OCFS2_SUPER_MAGIC, "ocfs2"},
+       { DRIVE_FIXED, OMFS_MAGIC, "omfs"},
+       { DRIVE_FIXED, UBIFS_SUPER_MAGIC, "ubifs"},
+       { DRIVE_UNKNOWN, 0, NULL}
+#else
+       { DRIVE_RAMDISK, "ramfs"      },
+       { DRIVE_RAMDISK, "tmpfs"      },
+       { DRIVE_RAMDISK, "proc"       },
+       { DRIVE_RAMDISK, "sysfs"      },
+       { DRIVE_RAMDISK, "debugfs"    },
+       { DRIVE_RAMDISK, "devpts"     },
+       { DRIVE_RAMDISK, "securityfs" },
+       { DRIVE_CDROM,   "iso9660"    },
+       { DRIVE_FIXED,   "ext2"       },
+       { DRIVE_FIXED,   "ext3"       },
+       { DRIVE_FIXED,   "ext4"       },
+       { DRIVE_FIXED,   "sysv"       },
+       { DRIVE_FIXED,   "reiserfs"   },
+       { DRIVE_FIXED,   "ufs"        },
+       { DRIVE_FIXED,   "vfat"       },
+       { DRIVE_FIXED,   "msdos"      },
+       { DRIVE_FIXED,   "udf"        },
+       { DRIVE_FIXED,   "hfs"        },
+       { DRIVE_FIXED,   "hpfs"       },
+       { DRIVE_FIXED,   "qnx4"       },
+       { DRIVE_FIXED,   "ntfs"       },
+       { DRIVE_FIXED,   "ntfs-3g"    },
+       { DRIVE_REMOTE,  "smbfs"      },
+       { DRIVE_REMOTE,  "fuse"       },
+       { DRIVE_REMOTE,  "nfs"        },
+       { DRIVE_REMOTE,  "nfs4"       },
+       { DRIVE_REMOTE,  "cifs"       },
+       { DRIVE_REMOTE,  "ncpfs"      },
+       { DRIVE_REMOTE,  "coda"       },
+       { DRIVE_REMOTE,  "afs"        },
+       { DRIVE_UNKNOWN, NULL         }
+#endif
+};
+
+#if __linux__
+static guint32 _wapi_get_drive_type(long f_type)
+{
+       _wapi_drive_type *current;
+
+       current = &_wapi_drive_types[0];
+       while (current->drive_type != DRIVE_UNKNOWN) {
+               if (current->fstypeid == f_type)
+                       return current->drive_type;
+               current++;
+       }
+
+       return DRIVE_UNKNOWN;
+}
+#else
+static guint32 _wapi_get_drive_type(const gchar* fstype)
+{
+       _wapi_drive_type *current;
+
+       current = &_wapi_drive_types[0];
+       while (current->drive_type != DRIVE_UNKNOWN) {
+               if (strcmp (current->fstype, fstype) == 0)
+                       break;
+
+               current++;
+       }
+       
+       return current->drive_type;
+}
+#endif
+
+#if defined (PLATFORM_MACOSX) || defined (__linux__)
+static guint32
+GetDriveTypeFromPath (const gchar *utf8_root_path_name)
+{
+       struct statfs buf;
+       
+       if (statfs (utf8_root_path_name, &buf) == -1)
+               return DRIVE_UNKNOWN;
+#if PLATFORM_MACOSX
+       return _wapi_get_drive_type (buf.f_fstypename);
+#else
+       return _wapi_get_drive_type (buf.f_type);
+#endif
+}
+#else
+static guint32
+GetDriveTypeFromPath (const gchar *utf8_root_path_name)
+{
+       guint32 drive_type;
+       FILE *fp;
+       gchar buffer [512];
+       gchar **splitted;
+
+       fp = fopen ("/etc/mtab", "rt");
+       if (fp == NULL) {
+               fp = fopen ("/etc/mnttab", "rt");
+               if (fp == NULL) 
+                       return(DRIVE_UNKNOWN);
+       }
+
+       drive_type = DRIVE_NO_ROOT_DIR;
+       while (fgets (buffer, 512, fp) != NULL) {
+               splitted = g_strsplit (buffer, " ", 0);
+               if (!*splitted || !*(splitted + 1) || !*(splitted + 2)) {
+                       g_strfreev (splitted);
+                       continue;
+               }
+
+               /* compare given root_path_name with the one from mtab, 
+                 if length of utf8_root_path_name is zero it must be the root dir */
+               if (strcmp (*(splitted + 1), utf8_root_path_name) == 0 ||
+                   (strcmp (*(splitted + 1), "/") == 0 && strlen (utf8_root_path_name) == 0)) {
+                       drive_type = _wapi_get_drive_type (*(splitted + 2));
+                       /* it is possible this path might be mounted again with
+                          a known type...keep looking */
+                       if (drive_type != DRIVE_UNKNOWN) {
+                               g_strfreev (splitted);
+                               break;
+                       }
+               }
+
+               g_strfreev (splitted);
+       }
+
+       fclose (fp);
+       return drive_type;
+}
+#endif
+
+guint32
+mono_w32file_get_drive_type(const gunichar2 *root_path_name)
+{
+       gchar *utf8_root_path_name;
+       guint32 drive_type;
+
+       if (root_path_name == NULL) {
+               utf8_root_path_name = g_strdup (g_get_current_dir());
+               if (utf8_root_path_name == NULL) {
+                       return(DRIVE_NO_ROOT_DIR);
+               }
+       }
+       else {
+               utf8_root_path_name = mono_unicode_to_external (root_path_name);
+               if (utf8_root_path_name == NULL) {
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+                       return(DRIVE_NO_ROOT_DIR);
+               }
+               
+               /* strip trailing slash for compare below */
+               if (g_str_has_suffix(utf8_root_path_name, "/") && utf8_root_path_name [1] != 0) {
+                       utf8_root_path_name[strlen(utf8_root_path_name) - 1] = 0;
+               }
+       }
+       drive_type = GetDriveTypeFromPath (utf8_root_path_name);
+       g_free (utf8_root_path_name);
+
+       return (drive_type);
+}
+
+#if defined (PLATFORM_MACOSX) || defined (__linux__) || defined(PLATFORM_BSD) || defined(__native_client__) || defined(__FreeBSD_kernel__)
+static gchar*
+get_fstypename (gchar *utfpath)
+{
+#if defined (PLATFORM_MACOSX) || defined (__linux__)
+       struct statfs stat;
+#if __linux__
+       _wapi_drive_type *current;
+#endif
+       if (statfs (utfpath, &stat) == -1)
+               return NULL;
+#if PLATFORM_MACOSX
+       return g_strdup (stat.f_fstypename);
+#else
+       current = &_wapi_drive_types[0];
+       while (current->drive_type != DRIVE_UNKNOWN) {
+               if (stat.f_type == current->fstypeid)
+                       return g_strdup (current->fstype);
+               current++;
+       }
+       return NULL;
+#endif
+#else
+       return NULL;
+#endif
+}
+
+/* Linux has struct statfs which has a different layout */
+gboolean
+mono_w32file_get_volume_information (const gunichar2 *path, gunichar2 *volumename, gint volumesize, gint *outserial, gint *maxcomp, gint *fsflags, gunichar2 *fsbuffer, gint fsbuffersize)
+{
+       gchar *utfpath;
+       gchar *fstypename;
+       gboolean status = FALSE;
+       glong len;
+       
+       // We only support getting the file system type
+       if (fsbuffer == NULL)
+               return 0;
+       
+       utfpath = mono_unicode_to_external (path);
+       if ((fstypename = get_fstypename (utfpath)) != NULL){
+               gunichar2 *ret = g_utf8_to_utf16 (fstypename, -1, NULL, &len, NULL);
+               if (ret != NULL && len < fsbuffersize){
+                       memcpy (fsbuffer, ret, len * sizeof (gunichar2));
+                       fsbuffer [len] = 0;
+                       status = TRUE;
+               }
+               if (ret != NULL)
+                       g_free (ret);
+               g_free (fstypename);
+       }
+       g_free (utfpath);
+       return status;
+}
+#endif
+
+static gboolean
+LockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 length_low, guint32 length_high)
+{
+       MonoW32HandleFile *file_handle;
+       off_t offset, length;
+
+       if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, (gpointer *)&file_handle)) {
+               g_warning ("%s: error looking up file handle %p", __func__, handle);
+               SetLastError (ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       if (!(file_handle->fileaccess & GENERIC_READ) && !(file_handle->fileaccess & GENERIC_WRITE) && !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+               SetLastError (ERROR_ACCESS_DENIED);
+               return FALSE;
+       }
+
+#ifdef HAVE_LARGE_FILE_SUPPORT
+       offset = ((gint64)offset_high << 32) | offset_low;
+       length = ((gint64)length_high << 32) | length_low;
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking handle %p, offset %lld, length %lld", __func__, handle, offset, length);
+#else
+       if (offset_high > 0 || length_high > 0) {
+               SetLastError (ERROR_INVALID_PARAMETER);
+               return FALSE;
+       }
+       offset = offset_low;
+       length = length_low;
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking handle %p, offset %ld, length %ld", __func__, handle, offset, length);
+#endif
+
+       return _wapi_lock_file_region (GPOINTER_TO_UINT(handle), offset, length);
+}
+
+static gboolean
+UnlockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 length_low, guint32 length_high)
+{
+       MonoW32HandleFile *file_handle;
+       off_t offset, length;
+
+       if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, (gpointer *)&file_handle)) {
+               g_warning ("%s: error looking up file handle %p", __func__, handle);
+               SetLastError (ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       if (!(file_handle->fileaccess & GENERIC_READ) && !(file_handle->fileaccess & GENERIC_WRITE) && !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+               SetLastError (ERROR_ACCESS_DENIED);
+               return FALSE;
+       }
+
+#ifdef HAVE_LARGE_FILE_SUPPORT
+       offset = ((gint64)offset_high << 32) | offset_low;
+       length = ((gint64)length_high << 32) | length_low;
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking handle %p, offset %lld, length %lld", __func__, handle, offset, length);
+#else
+       offset = offset_low;
+       length = length_low;
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking handle %p, offset %ld, length %ld", __func__, handle, offset, length);
+#endif
+
+       return _wapi_unlock_file_region (GPOINTER_TO_UINT(handle), offset, length);
+}
+
+void
+mono_w32file_init (void)
+{
+       mono_os_mutex_init (&stdhandle_mutex);
+       mono_os_mutex_init (&file_share_mutex);
+
+       mono_w32handle_register_ops (MONO_W32HANDLE_FILE,    &_wapi_file_ops);
+       mono_w32handle_register_ops (MONO_W32HANDLE_CONSOLE, &_wapi_console_ops);
+       mono_w32handle_register_ops (MONO_W32HANDLE_FIND,    &_wapi_find_ops);
+       mono_w32handle_register_ops (MONO_W32HANDLE_PIPE,    &_wapi_pipe_ops);
+
+/*     mono_w32handle_register_capabilities (MONO_W32HANDLE_FILE, */
+/*                                         MONO_W32HANDLE_CAP_WAIT); */
+/*     mono_w32handle_register_capabilities (MONO_W32HANDLE_CONSOLE, */
+/*                                         MONO_W32HANDLE_CAP_WAIT); */
+
+       if (g_getenv ("MONO_STRICT_IO_EMULATION"))
+               lock_while_writing = TRUE;
+}
+
+void
+mono_w32file_cleanup (void)
+{
+       mono_os_mutex_destroy (&file_share_mutex);
+
+       if (file_share_table)
+               g_hash_table_destroy (file_share_table);
+}
+
+gboolean
+mono_w32file_move (gunichar2 *path, gunichar2 *dest, gint32 *error)
+{
+       gboolean result;
+
+       MONO_ENTER_GC_SAFE;
+
+       result = MoveFile (path, dest);
+       if (!result)
+               *error = GetLastError ();
+
+       MONO_EXIT_GC_SAFE;
+
+       return result;
+}
+
+gboolean
+mono_w32file_copy (gunichar2 *path, gunichar2 *dest, gboolean overwrite, gint32 *error)
+{
+       gboolean result;
+
+       MONO_ENTER_GC_SAFE;
+
+       result = CopyFile (path, dest, !overwrite);
+       if (!result)
+               *error = GetLastError ();
+
+       MONO_EXIT_GC_SAFE;
+
+       return result;
+}
+
+gboolean
+mono_w32file_replace (gunichar2 *destinationFileName, gunichar2 *sourceFileName, gunichar2 *destinationBackupFileName, guint32 flags, gint32 *error)
+{
+       gboolean result;
+
+       MONO_ENTER_GC_SAFE;
+
+       result = ReplaceFile (destinationFileName, sourceFileName, destinationBackupFileName, flags, NULL, NULL);
+       if (!result)
+               *error = GetLastError ();
+
+       MONO_EXIT_GC_SAFE;
+
+       return result;
+}
+
+gint64
+mono_w32file_get_file_size (gpointer handle, gint32 *error)
+{
+       gint64 length;
+       guint32 length_hi;
+
+       MONO_ENTER_GC_SAFE;
+
+       length = GetFileSize (handle, &length_hi);
+       if(length==INVALID_FILE_SIZE) {
+               *error=GetLastError ();
+       }
+
+       MONO_EXIT_GC_SAFE;
+
+       return length | ((gint64)length_hi << 32);
+}
+
+gboolean
+mono_w32file_lock (gpointer handle, gint64 position, gint64 length, gint32 *error)
+{
+       gboolean result;
+
+       MONO_ENTER_GC_SAFE;
+
+       result = LockFile (handle, position & 0xFFFFFFFF, position >> 32, length & 0xFFFFFFFF, length >> 32);
+       if (!result)
+               *error = GetLastError ();
+
+       MONO_EXIT_GC_SAFE;
+
+       return result;
+}
+
+gboolean
+mono_w32file_unlock (gpointer handle, gint64 position, gint64 length, gint32 *error)
+{
+       gboolean result;
+
+       MONO_ENTER_GC_SAFE;
+
+       result = UnlockFile (handle, position & 0xFFFFFFFF, position >> 32, length & 0xFFFFFFFF, length >> 32);
+       if (!result)
+               *error = GetLastError ();
+
+       MONO_EXIT_GC_SAFE;
+
+       return result;
+}
+
+gpointer
+mono_w32file_get_console_input (void)
+{
+       gpointer handle;
+
+       MONO_ENTER_GC_SAFE;
+       handle = mono_w32file_get_std_handle (STD_INPUT_HANDLE);
+       MONO_EXIT_GC_SAFE;
+
+       return handle;
+}
+
+gpointer
+mono_w32file_get_console_output (void)
+{
+       gpointer handle;
+
+       MONO_ENTER_GC_SAFE;
+       handle = mono_w32file_get_std_handle (STD_OUTPUT_HANDLE);
+       MONO_EXIT_GC_SAFE;
+
+       return handle;
+}
+
+gpointer
+mono_w32file_get_console_error (void)
+{
+       gpointer handle;
+
+       MONO_ENTER_GC_SAFE;
+       handle = mono_w32file_get_std_handle (STD_ERROR_HANDLE);
+       MONO_EXIT_GC_SAFE;
+
+       return handle;
+}
diff --git a/mono/metadata/w32file-win32-internals.h b/mono/metadata/w32file-win32-internals.h
new file mode 100644 (file)
index 0000000..0c7c97f
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#ifndef _MONO_METADATA_W32FILE_WIN32_INTERNALS_H_
+#define _MONO_METADATA_W32FILE_WIN32_INTERNALS_H_
+
+#include <config.h>
+#include <glib.h>
+
+#ifdef HOST_WIN32
+#include "mono/metadata/w32file.h"
+#include "mono/metadata/w32file-internals.h"
+#endif /* HOST_WIN32 */
+#endif /* _MONO_METADATA_W32FILE_WIN32_INTERNALS_H_ */
diff --git a/mono/metadata/w32file-win32-uwp.c b/mono/metadata/w32file-win32-uwp.c
new file mode 100644 (file)
index 0000000..15062f0
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * w32file-win32-uwp.c: UWP w32file support for Mono.
+ *
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+*/
+#include <config.h>
+#include <glib.h>
+#include "mono/utils/mono-compiler.h"
+
+#if G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT)
+#include <windows.h>
+#include "mono/metadata/w32file-win32-internals.h"
+
+gboolean
+mono_w32file_move (gunichar2 *path, gunichar2 *dest, gint32 *error)
+{
+       gboolean result = FALSE;
+       MONO_ENTER_GC_SAFE;
+
+       result = MoveFileEx (path, dest, MOVEFILE_COPY_ALLOWED);
+       if (result == FALSE) {
+               *error=GetLastError ();
+       }
+
+       MONO_EXIT_GC_SAFE;
+       return result;
+}
+
+gboolean
+mono_w32file_replace (gunichar2 *destinationFileName, gunichar2 *sourceFileName,
+                          gunichar2 *destinationBackupFileName, guint32 flags, gint32 *error)
+{
+       gboolean result = FALSE;
+       MONO_ENTER_GC_SAFE;
+
+       result = ReplaceFile (destinationFileName, sourceFileName, destinationBackupFileName, flags, NULL, NULL);
+       if (result == FALSE) {
+               *error=GetLastError ();
+       }
+
+       MONO_EXIT_GC_SAFE;
+       return result;
+}
+
+gboolean
+mono_w32file_copy (gunichar2 *path, gunichar2 *dest, gboolean overwrite, gint32 *error)
+{
+       gboolean                                                result = FALSE;
+       COPYFILE2_EXTENDED_PARAMETERS   copy_param = {0};
+
+       copy_param.dwSize = sizeof (COPYFILE2_EXTENDED_PARAMETERS);
+       copy_param.dwCopyFlags = (!overwrite) ? COPY_FILE_FAIL_IF_EXISTS : 0;
+
+       MONO_ENTER_GC_SAFE;
+
+       result = SUCCEEDED (CopyFile2 (path, dest, &copy_param));
+       if (result == FALSE) {
+               *error=GetLastError ();
+       }
+
+       MONO_EXIT_GC_SAFE;
+       return result;
+}
+
+gint64
+mono_w32file_get_file_size (HANDLE handle, gint32 *error)
+{
+       LARGE_INTEGER length;
+
+       MONO_ENTER_GC_SAFE;
+
+       if (!GetFileSizeEx (handle, &length)) {
+               *error=GetLastError ();
+               length.QuadPart = INVALID_FILE_SIZE;
+       }
+
+       MONO_EXIT_GC_SAFE;
+       return length.QuadPart;
+}
+
+gboolean
+mono_w32file_lock (HANDLE handle, gint64 position, gint64 length, gint32 *error)
+{
+       gboolean result = FALSE;
+       MONO_ENTER_GC_SAFE;
+
+       result = LockFile (handle, position & 0xFFFFFFFF, position >> 32,
+                          length & 0xFFFFFFFF, length >> 32);
+
+       if (result == FALSE) {
+               *error = GetLastError ();
+       }
+
+       MONO_EXIT_GC_SAFE;
+       return result;
+}
+
+gboolean
+mono_w32file_unlock (HANDLE handle, gint64 position, gint64 length, gint32 *error)
+{
+       gboolean result = FALSE;
+       MONO_ENTER_GC_SAFE;
+
+       result = UnlockFile (handle, position & 0xFFFFFFFF, position >> 32,
+                            length & 0xFFFFFFFF, length >> 32);
+
+       if (result == FALSE) {
+               *error = GetLastError ();
+       }
+
+       MONO_EXIT_GC_SAFE;
+       return result;
+}
+
+HANDLE
+mono_w32file_get_console_output (void)
+{
+       MonoError mono_error;
+       mono_error_init (&mono_error);
+
+       g_unsupported_api ("GetStdHandle (STD_OUTPUT_HANDLE)");
+
+       mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "GetStdHandle (STD_OUTPUT_HANDLE)");
+       mono_error_set_pending_exception (&mono_error);
+
+       SetLastError (ERROR_NOT_SUPPORTED);
+
+       return INVALID_HANDLE_VALUE;
+}
+
+HANDLE
+mono_w32file_get_console_input (void)
+{
+       MonoError mono_error;
+       mono_error_init (&mono_error);
+
+       g_unsupported_api ("GetStdHandle (STD_INPUT_HANDLE)");
+
+       mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "GetStdHandle (STD_INPUT_HANDLE)");
+       mono_error_set_pending_exception (&mono_error);
+
+       SetLastError (ERROR_NOT_SUPPORTED);
+
+       return INVALID_HANDLE_VALUE;
+}
+
+HANDLE
+mono_w32file_get_console_error (void)
+{
+       MonoError mono_error;
+       mono_error_init (&mono_error);
+
+       g_unsupported_api ("GetStdHandle (STD_ERROR_HANDLE)");
+
+       mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "GetStdHandle (STD_ERROR_HANDLE)");
+       mono_error_set_pending_exception (&mono_error);
+
+       SetLastError (ERROR_NOT_SUPPORTED);
+
+       return INVALID_HANDLE_VALUE;
+}
+
+#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
+
+MONO_EMPTY_SOURCE_FILE (file_io_windows_uwp);
+#endif /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
diff --git a/mono/metadata/w32file-win32.c b/mono/metadata/w32file-win32.c
new file mode 100644 (file)
index 0000000..7a5478c
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * w32file-win32.c: Windows File IO internal calls.
+ *
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#include <config.h>
+#include <glib.h>
+
+#include <winsock2.h>
+#include <windows.h>
+#include "mono/metadata/w32file-win32-internals.h"
+
+void
+mono_w32file_init (void)
+{
+}
+
+void
+mono_w32file_cleanup (void)
+{
+}
+
+gunichar2
+ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
+{
+       return (gunichar2) ':'; /* colon */
+}
+
+gunichar2
+ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
+{
+       return (gunichar2) '\\';        /* backslash */
+}
+
+gunichar2
+ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
+{
+       return (gunichar2) '/'; /* forward slash */
+}
+
+gunichar2
+ves_icall_System_IO_MonoIO_get_PathSeparator ()
+{
+       return (gunichar2) ';'; /* semicolon */
+}
+
+void ves_icall_System_IO_MonoIO_DumpHandles (void)
+{
+       return;
+}
+
+gpointer
+mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode, guint32 createmode, guint32 attrs)
+{
+       return CreateFile (name, fileaccess, sharemode, NULL, createmode, attrs, NULL);
+}
+
+gboolean
+mono_w32file_delete (const gunichar2 *name)
+{
+       return DeleteFile (name);
+}
+
+gboolean
+mono_w32file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+{
+       return ReadFile (handle, buffer, numbytes, bytesread, NULL);
+}
+
+gboolean
+mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
+{
+       return WriteFile (handle, buffer, numbytes, byteswritten, NULL);
+}
+
+gboolean
+mono_w32file_flush (gpointer handle)
+{
+       return FlushFileBuffers (handle);
+}
+
+gboolean
+mono_w32file_truncate (gpointer handle)
+{
+       return SetEndOfFile (handle);
+}
+
+guint32
+mono_w32file_seek (gpointer handle, gint32 movedistance, gint32 *highmovedistance, guint32 method)
+{
+       return SetFilePointer (handle, movedistance, highmovedistance, method);
+}
+
+gint
+mono_w32file_get_type (gpointer handle)
+{
+       return GetFileType (handle);
+}
+
+gboolean
+mono_w32file_get_times (gpointer handle, FILETIME *create_time, FILETIME *access_time, FILETIME *write_time)
+{
+       return GetFileTime (handle, create_time, access_time, write_time);
+}
+
+gboolean
+mono_w32file_set_times (gpointer handle, const FILETIME *create_time, const FILETIME *access_time, const FILETIME *write_time)
+{
+       return SetFileTime (handle, create_time, access_time, write_time);
+}
+
+gboolean
+mono_w32file_filetime_to_systemtime (const FILETIME *file_time, SYSTEMTIME *system_time)
+{
+       return FileTimeToSystemTime (file_time, system_time);
+}
+
+gpointer
+mono_w32file_find_first (const gunichar2 *pattern, WIN32_FIND_DATA *find_data)
+{
+       return FindFirstFile (pattern, find_data);
+}
+
+gboolean
+mono_w32file_find_next (gpointer handle, WIN32_FIND_DATA *find_data)
+{
+       return FindNextFile (handle, find_data);
+}
+
+gboolean
+mono_w32file_find_close (gpointer handle)
+{
+       return FindClose (handle);
+}
+
+gboolean
+mono_w32file_create_directory (const gunichar2 *name)
+{
+       return CreateDirectory (name, NULL);
+}
+
+gboolean
+mono_w32file_remove_directory (const gunichar2 *name)
+{
+       return RemoveDirectory (name);
+}
+
+guint32
+mono_w32file_get_attributes (const gunichar2 *name)
+{
+       return GetFileAttributes (name);
+}
+
+gboolean
+mono_w32file_get_attributes_ex (const gunichar2 *name, MonoIOStat *stat)
+{
+       gboolean result;
+       WIN32_FILE_ATTRIBUTE_DATA data;
+
+       result = GetFileAttributesEx (name, GetFileExInfoStandard, &data);
+       if (result) {
+               stat->attributes = data.dwFileAttributes;
+               stat->creation_time = (gint64) ((((guint64) data.ftCreationTime.dwHighDateTime) << 32) + data.ftCreationTime.dwLowDateTime);
+               stat->last_access_time = (gint64) ((((guint64) data.ftLastAccessTime.dwHighDateTime) << 32) + data.ftLastAccessTime.dwLowDateTime);
+               stat->last_write_time = (gint64) ((((guint64) data.ftLastWriteTime.dwHighDateTime) << 32) + data.ftLastWriteTime.dwLowDateTime);
+               stat->length = ((gint64)data.nFileSizeHigh << 32) | data.nFileSizeLow;
+       }
+
+       return result;
+}
+
+gboolean
+mono_w32file_set_attributes (const gunichar2 *name, guint32 attrs)
+{
+       return SetFileAttributes (name, attrs);
+}
+
+guint32
+mono_w32file_get_cwd (guint32 length, gunichar2 *buffer)
+{
+       return GetCurrentDirectory (length, buffer);
+}
+
+gboolean
+mono_w32file_set_cwd (const gunichar2 *path)
+{
+       return SetCurrentDirectory (path);
+}
+
+gboolean
+mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size)
+{
+       SECURITY_ATTRIBUTES attr;
+       attr.nLength = sizeof(SECURITY_ATTRIBUTES);
+       attr.bInheritHandle = TRUE;
+       attr.lpSecurityDescriptor = NULL;
+       return CreatePipe (readpipe, writepipe, &attr, size);
+}
+
+gboolean
+mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_bytes_avail, guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes)
+{
+       gboolean result;
+       ULARGE_INTEGER *wapi_free_bytes_avail;
+       ULARGE_INTEGER *wapi_total_number_of_bytes;
+       ULARGE_INTEGER *wapi_total_number_of_free_bytes;
+
+       result = GetDiskFreeSpaceEx (path_name, wapi_free_bytes_avail, wapi_total_number_of_bytes, wapi_total_number_of_free_bytes);
+       if (result) {
+               if (free_bytes_avail)
+                       *free_bytes_avail = wapi_free_bytes_avail->QuadPart;
+               if (total_number_of_bytes)
+                       *total_number_of_bytes = wapi_total_number_of_bytes->QuadPart;
+               if (total_number_of_free_bytes)
+                       *total_number_of_free_bytes = wapi_total_number_of_free_bytes->QuadPart;
+       }
+
+       return result;
+}
+
+gboolean
+mono_w32file_get_volume_information (const gunichar2 *path, gunichar2 *volumename, gint volumesize, gint *outserial, gint *maxcomp, gint *fsflags, gunichar2 *fsbuffer, gint fsbuffersize)
+{
+       return GetVolumeInformation (path, volumename, volumesize, outserial, maxcomp, fsflags, fsbuffer, fsbuffersize);
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+
+gboolean
+mono_w32file_move (gunichar2 *path, gunichar2 *dest, gint32 *error)
+{
+       gboolean result;
+
+       MONO_ENTER_GC_SAFE;
+
+       result = MoveFile (path, dest);
+       if (!result)
+               *error = GetLastError ();
+
+       MONO_EXIT_GC_SAFE;
+
+       return result;
+}
+
+gboolean
+mono_w32file_replace (gunichar2 *destinationFileName, gunichar2 *sourceFileName, gunichar2 *destinationBackupFileName, guint32 flags, gint32 *error)
+{
+       gboolean result;
+
+       MONO_ENTER_GC_SAFE;
+
+       result = ReplaceFile (destinationFileName, sourceFileName, destinationBackupFileName, flags, NULL, NULL);
+       if (!result)
+               *error = GetLastError ();
+
+       MONO_EXIT_GC_SAFE;
+
+       return result;
+}
+
+gboolean
+mono_w32file_copy (gunichar2 *path, gunichar2 *dest, gboolean overwrite, gint32 *error)
+{
+       gboolean result;
+
+       MONO_ENTER_GC_SAFE;
+
+       result = CopyFile (path, dest, !overwrite);
+       if (!result)
+               *error = GetLastError ();
+
+       MONO_EXIT_GC_SAFE;
+
+       return result;
+}
+
+gboolean
+mono_w32file_lock (gpointer handle, gint64 position, gint64 length, gint32 *error)
+{
+       gboolean result;
+
+       MONO_ENTER_GC_SAFE;
+
+       result = LockFile (handle, position & 0xFFFFFFFF, position >> 32, length & 0xFFFFFFFF, length >> 32);
+       if (!result)
+               *error = GetLastError ();
+
+       MONO_EXIT_GC_SAFE;
+
+       return result;
+}
+
+gboolean
+mono_w32file_unlock (gpointer handle, gint64 position, gint64 length, gint32 *error)
+{
+       gboolean result;
+
+       MONO_ENTER_GC_SAFE;
+
+       result = UnlockFile (handle, position & 0xFFFFFFFF, position >> 32, length & 0xFFFFFFFF, length >> 32);
+       if (!result)
+               *error = GetLastError ();
+
+       MONO_EXIT_GC_SAFE;
+
+       return result;
+}
+
+HANDLE
+mono_w32file_get_console_input (void)
+{
+       return GetStdHandle (STD_INPUT_HANDLE);
+}
+
+HANDLE
+mono_w32file_get_console_output (void)
+{
+       return GetStdHandle (STD_OUTPUT_HANDLE);
+}
+
+HANDLE
+mono_w32file_get_console_error (void)
+{
+       return GetStdHandle (STD_ERROR_HANDLE);
+}
+
+gint64
+mono_w32file_get_file_size (gpointer handle, gint32 *error)
+{
+       gint64 length;
+       guint32 length_hi;
+
+       MONO_ENTER_GC_SAFE;
+
+       length = GetFileSize (handle, &length_hi);
+       if(length==INVALID_FILE_SIZE) {
+               *error=GetLastError ();
+       }
+
+       MONO_EXIT_GC_SAFE;
+
+       return length | ((gint64)length_hi << 32);
+}
+
+guint32
+mono_w32file_get_drive_type (const gunichar2 *root_path_name)
+{
+       return GetDriveType (root_path_name);
+}
+
+gint32
+mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf)
+{
+       return GetLogicalDriveStrings (len, buf);
+}
+
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
diff --git a/mono/metadata/w32file.c b/mono/metadata/w32file.c
new file mode 100644 (file)
index 0000000..8aabbc5
--- /dev/null
@@ -0,0 +1,1248 @@
+/*
+ * w32file.c: File IO internal calls
+ *
+ * Author:
+ *     Dick Porter (dick@ximian.com)
+ *     Gonzalo Paniagua Javier (gonzalo@ximian.com)
+ *
+ * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
+ * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <string.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <mono/metadata/object.h>
+#include <mono/io-layer/io-layer.h>
+#include <mono/metadata/w32file.h>
+#include <mono/metadata/w32file-internals.h>
+#include <mono/metadata/exception.h>
+#include <mono/metadata/appdomain.h>
+#include <mono/metadata/marshal.h>
+#include <mono/utils/strenc.h>
+#include <utils/mono-io-portability.h>
+#include <mono/metadata/w32handle.h>
+
+#undef DEBUG
+
+/* conversion functions */
+
+static guint32 convert_mode(MonoFileMode mono_mode)
+{
+       guint32 mode;
+
+       switch(mono_mode) {
+       case FileMode_CreateNew:
+               mode=CREATE_NEW;
+               break;
+       case FileMode_Create:
+               mode=CREATE_ALWAYS;
+               break;
+       case FileMode_Open:
+               mode=OPEN_EXISTING;
+               break;
+       case FileMode_OpenOrCreate:
+               mode=OPEN_ALWAYS;
+               break;
+       case FileMode_Truncate:
+               mode=TRUNCATE_EXISTING;
+               break;
+       case FileMode_Append:
+               mode=OPEN_ALWAYS;
+               break;
+       default:
+               g_warning("System.IO.FileMode has unknown value 0x%x",
+                         mono_mode);
+               /* Safe fallback */
+               mode=OPEN_EXISTING;
+       }
+       
+       return(mode);
+}
+
+static guint32 convert_access(MonoFileAccess mono_access)
+{
+       guint32 access;
+       
+       switch(mono_access) {
+       case FileAccess_Read:
+               access=GENERIC_READ;
+               break;
+       case FileAccess_Write:
+               access=GENERIC_WRITE;
+               break;
+       case FileAccess_ReadWrite:
+               access=GENERIC_READ|GENERIC_WRITE;
+               break;
+       default:
+               g_warning("System.IO.FileAccess has unknown value 0x%x",
+                         mono_access);
+               /* Safe fallback */
+               access=GENERIC_READ;
+       }
+       
+       return(access);
+}
+
+static guint32 convert_share(MonoFileShare mono_share)
+{
+       guint32 share = 0;
+       
+       if (mono_share & FileShare_Read) {
+               share |= FILE_SHARE_READ;
+       }
+       if (mono_share & FileShare_Write) {
+               share |= FILE_SHARE_WRITE;
+       }
+       if (mono_share & FileShare_Delete) {
+               share |= FILE_SHARE_DELETE;
+       }
+       
+       if (mono_share & ~(FileShare_Read|FileShare_Write|FileShare_Delete)) {
+               g_warning("System.IO.FileShare has unknown value 0x%x",
+                         mono_share);
+               /* Safe fallback */
+               share=0;
+       }
+
+       return(share);
+}
+
+#if 0
+static guint32 convert_stdhandle(guint32 fd)
+{
+       guint32 stdhandle;
+       
+       switch(fd) {
+       case 0:
+               stdhandle=STD_INPUT_HANDLE;
+               break;
+       case 1:
+               stdhandle=STD_OUTPUT_HANDLE;
+               break;
+       case 2:
+               stdhandle=STD_ERROR_HANDLE;
+               break;
+       default:
+               g_warning("unknown standard file descriptor %d", fd);
+               stdhandle=STD_INPUT_HANDLE;
+       }
+       
+       return(stdhandle);
+}
+#endif
+
+static guint32 convert_seekorigin(MonoSeekOrigin origin)
+{
+       guint32 w32origin;
+       
+       switch(origin) {
+       case SeekOrigin_Begin:
+               w32origin=FILE_BEGIN;
+               break;
+       case SeekOrigin_Current:
+               w32origin=FILE_CURRENT;
+               break;
+       case SeekOrigin_End:
+               w32origin=FILE_END;
+               break;
+       default:
+               g_warning("System.IO.SeekOrigin has unknown value 0x%x",
+                         origin);
+               /* Safe fallback */
+               w32origin=FILE_CURRENT;
+       }
+       
+       return(w32origin);
+}
+
+static gint64 convert_filetime (const FILETIME *filetime)
+{
+       return (gint64) ((((guint64) filetime->dwHighDateTime) << 32) + filetime->dwLowDateTime);
+}
+
+/* Managed file attributes have nearly but not quite the same values
+ * as the w32 equivalents.
+ */
+static guint32 convert_attrs(MonoFileAttributes attrs)
+{
+       if(attrs & FileAttributes_Encrypted) {
+               attrs = (MonoFileAttributes)(attrs | FILE_ATTRIBUTE_ENCRYPTED);
+       }
+       
+       return(attrs);
+}
+
+/*
+ * On Win32, mono_w32file_get_attributes|_ex () seems to try opening the file,
+ * which might lead to sharing violation errors, whereas mono_w32file_find_first
+ * always succeeds. These 2 wrappers resort to mono_w32file_find_first if
+ * mono_w32file_get_attributes|_ex () has failed.
+ */
+static guint32
+get_file_attributes (const gunichar2 *path)
+{
+       guint32 res;
+       WIN32_FIND_DATA find_data;
+       HANDLE find_handle;
+       gint32 error;
+
+       res = mono_w32file_get_attributes (path);
+       if (res != -1)
+               return res;
+
+       error = GetLastError ();
+
+       if (error != ERROR_SHARING_VIOLATION)
+               return res;
+
+       find_handle = mono_w32file_find_first (path, &find_data);
+
+       if (find_handle == INVALID_HANDLE_VALUE)
+               return res;
+
+       mono_w32file_find_close (find_handle);
+
+       return find_data.dwFileAttributes;
+}
+
+static gboolean
+get_file_attributes_ex (const gunichar2 *path, MonoIOStat *stat)
+{
+       gboolean res;
+       WIN32_FIND_DATA find_data;
+       HANDLE find_handle;
+       gint32 error;
+
+       res = mono_w32file_get_attributes_ex (path, stat);
+       if (res)
+               return TRUE;
+
+       error = GetLastError ();
+       if (error != ERROR_SHARING_VIOLATION)
+               return FALSE;
+
+       find_handle = mono_w32file_find_first (path, &find_data);
+
+       if (find_handle == INVALID_HANDLE_VALUE)
+               return FALSE;
+
+       mono_w32file_find_close (find_handle);
+       
+       stat->attributes = find_data.dwFileAttributes;
+       stat->creation_time = convert_filetime (&find_data.ftCreationTime);
+       stat->last_access_time = convert_filetime (&find_data.ftLastAccessTime);
+       stat->last_write_time = convert_filetime (&find_data.ftLastWriteTime);
+       stat->length = ((gint64)find_data.nFileSizeHigh << 32) | find_data.nFileSizeLow;
+       return TRUE;
+}
+
+/* System.IO.MonoIO internal calls */
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error)
+{
+       gboolean ret;
+       MONO_ENTER_GC_SAFE;
+       
+       *error=ERROR_SUCCESS;
+       
+       ret=mono_w32file_create_directory (mono_string_chars (path));
+       if(ret==FALSE) {
+               *error=GetLastError ();
+       }
+
+       MONO_EXIT_GC_SAFE;
+       return(ret);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error)
+{
+       gboolean ret;
+       MONO_ENTER_GC_SAFE;
+       
+       *error=ERROR_SUCCESS;
+       
+       ret=mono_w32file_remove_directory (mono_string_chars (path));
+       if(ret==FALSE) {
+               *error=GetLastError ();
+       }
+
+       MONO_EXIT_GC_SAFE;
+       return(ret);
+}
+
+static gchar *
+get_search_dir (const gunichar2 *pattern)
+{
+       gchar *p;
+       gchar *result;
+
+       p = g_utf16_to_utf8 (pattern, -1, NULL, NULL, NULL);
+       result = g_path_get_dirname (p);
+       g_free (p);
+       return result;
+}
+
+static GPtrArray *
+get_filesystem_entries (const gunichar2 *path,
+                                                const gunichar2 *path_with_pattern,
+                                                gint attrs, gint mask,
+                                                gint32 *error)
+{
+       int i;
+       WIN32_FIND_DATA data;
+       HANDLE find_handle;
+       GPtrArray *names = NULL;
+       gchar *utf8_path = NULL, *utf8_result, *full_name;
+       gint32 attributes;
+
+       mask = convert_attrs ((MonoFileAttributes)mask);
+       attributes = get_file_attributes (path);
+       if (attributes != -1) {
+               if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
+                       *error = ERROR_INVALID_NAME;
+                       goto fail;
+               }
+       } else {
+               *error = GetLastError ();
+               goto fail;
+       }
+       
+       find_handle = mono_w32file_find_first (path_with_pattern, &data);
+       if (find_handle == INVALID_HANDLE_VALUE) {
+               gint32 find_error = GetLastError ();
+               
+               if (find_error == ERROR_FILE_NOT_FOUND || find_error == ERROR_NO_MORE_FILES) {
+                       /* No files, so just return an empty array */
+                       goto fail;
+               }
+               
+               *error = find_error;
+               goto fail;
+       }
+
+       utf8_path = get_search_dir (path_with_pattern);
+       names = g_ptr_array_new ();
+
+       do {
+               if ((data.cFileName[0] == '.' && data.cFileName[1] == 0) ||
+                   (data.cFileName[0] == '.' && data.cFileName[1] == '.' && data.cFileName[2] == 0)) {
+                       continue;
+               }
+               
+               if ((data.dwFileAttributes & mask) == attrs) {
+                       utf8_result = g_utf16_to_utf8 (data.cFileName, -1, NULL, NULL, NULL);
+                       if (utf8_result == NULL) {
+                               continue;
+                       }
+                       
+                       full_name = g_build_filename (utf8_path, utf8_result, NULL);
+                       g_ptr_array_add (names, full_name);
+
+                       g_free (utf8_result);
+               }
+       } while(mono_w32file_find_next (find_handle, &data));
+
+       if (mono_w32file_find_close (find_handle) == FALSE) {
+               *error = GetLastError ();
+               goto fail;
+       }
+
+       g_free (utf8_path);
+       return names;
+fail:
+       if (names) {
+               for (i = 0; i < names->len; i++)
+                       g_free (g_ptr_array_index (names, i));
+               g_ptr_array_free (names, TRUE);
+       }
+       g_free (utf8_path);
+       return FALSE;
+}
+
+
+MonoArray *
+ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
+                                                MonoString *path_with_pattern,
+                                                gint attrs, gint mask,
+                                                gint32 *ioerror)
+{
+       MonoError error;
+       MonoDomain *domain = mono_domain_get ();
+       MonoArray *result;
+       int i;
+       GPtrArray *names;
+       
+       *ioerror = ERROR_SUCCESS;
+
+       MONO_ENTER_GC_SAFE;
+       names = get_filesystem_entries (mono_string_chars (path), mono_string_chars (path_with_pattern), attrs, mask, ioerror);
+       MONO_EXIT_GC_SAFE;
+
+       if (!names) {
+               // If there's no array and no error, then return an empty array.
+               if (*ioerror == ERROR_SUCCESS) {
+                       MonoArray *arr = mono_array_new_checked (domain, mono_defaults.string_class, 0, &error);
+                       mono_error_set_pending_exception (&error);
+                       return arr;
+               }
+               return NULL;
+       }
+
+       result = mono_array_new_checked (domain, mono_defaults.string_class, names->len, &error);
+       if (mono_error_set_pending_exception (&error))
+               goto leave;
+       for (i = 0; i < names->len; i++) {
+               mono_array_setref (result, i, mono_string_new (domain, (const char *)g_ptr_array_index (names, i)));
+               g_free (g_ptr_array_index (names, i));
+       }
+leave:
+       g_ptr_array_free (names, TRUE);
+       return result;
+}
+
+typedef struct {
+       MonoDomain *domain;
+       gchar *utf8_path;
+       HANDLE find_handle;
+} IncrementalFind;
+       
+static gboolean
+incremental_find_check_match (IncrementalFind *handle, WIN32_FIND_DATA *data, MonoString **result)
+{
+       gchar *utf8_result;
+       gchar *full_name;
+       
+       if ((data->cFileName[0] == '.' && data->cFileName[1] == 0) || (data->cFileName[0] == '.' && data->cFileName[1] == '.' && data->cFileName[2] == 0))
+               return FALSE;
+
+       utf8_result = g_utf16_to_utf8 (data->cFileName, -1, NULL, NULL, NULL);
+       if (utf8_result == NULL) 
+               return FALSE;
+       
+       full_name = g_build_filename (handle->utf8_path, utf8_result, NULL);
+       g_free (utf8_result);
+       *result = mono_string_new (mono_domain_get (), full_name);
+       g_free (full_name);
+       
+       return TRUE;
+}
+
+HANDLE
+ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path_with_pattern, MonoString **file_name, gint32 *file_attr, gint32 *ioerror)
+{
+       HANDLE hnd;
+       WIN32_FIND_DATA data;
+       MonoError error;
+
+       hnd = mono_w32file_find_first (mono_string_chars (path_with_pattern), &data);
+
+       if (hnd == INVALID_HANDLE_VALUE) {
+               *file_name = NULL;
+               *file_attr = 0;
+               *ioerror = GetLastError ();
+               return hnd;
+       }
+
+       mono_gc_wbarrier_generic_store (file_name, (MonoObject*) mono_string_from_utf16_checked (data.cFileName, &error));
+       mono_error_set_pending_exception (&error);
+
+       *file_attr = data.dwFileAttributes;
+       *ioerror = ERROR_SUCCESS;
+
+       return hnd;
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_FindNextFile (HANDLE hnd, MonoString **file_name, gint32 *file_attr, gint32 *ioerror)
+{
+       MonoBoolean res;
+       WIN32_FIND_DATA data;
+       MonoError error;
+
+       res = mono_w32file_find_next (hnd, &data);
+
+       if (res == FALSE) {
+               *file_name = NULL;
+               *file_attr = 0;
+               *ioerror = GetLastError ();
+               return res;
+       }
+
+       mono_gc_wbarrier_generic_store (file_name, (MonoObject*) mono_string_from_utf16_checked (data.cFileName, &error));
+       mono_error_set_pending_exception (&error);
+
+       *file_attr = data.dwFileAttributes;
+       *ioerror = ERROR_SUCCESS;
+
+       return res;
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_FindCloseFile (HANDLE hnd)
+{
+       return mono_w32file_find_close (hnd);
+}
+
+/* FIXME make gc suspendable */
+MonoString *
+ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
+                                     MonoString *path_with_pattern,
+                                     gint32 *result_attr, gint32 *ioerror,
+                                     gpointer *handle)
+{
+       MonoError error;
+       WIN32_FIND_DATA data;
+       HANDLE find_handle;
+       IncrementalFind *ifh;
+       MonoString *result;
+       
+       *ioerror = ERROR_SUCCESS;
+       
+       find_handle = mono_w32file_find_first (mono_string_chars (path_with_pattern), &data);
+       
+       if (find_handle == INVALID_HANDLE_VALUE) {
+               gint32 find_error = GetLastError ();
+               *handle = NULL;
+               
+               if (find_error == ERROR_FILE_NOT_FOUND) 
+                       return NULL;
+               
+               *ioerror = find_error;
+               return NULL;
+       }
+
+       ifh = g_new (IncrementalFind, 1);
+       ifh->find_handle = find_handle;
+       ifh->utf8_path = mono_string_to_utf8_checked (path, &error);
+       if (mono_error_set_pending_exception (&error)) {
+               MONO_ENTER_GC_SAFE;
+               mono_w32file_find_close (find_handle);
+               MONO_EXIT_GC_SAFE;
+               g_free (ifh);
+               return NULL;
+       }
+       ifh->domain = mono_domain_get ();
+       *handle = ifh;
+
+       while (incremental_find_check_match (ifh, &data, &result) == 0){
+               if (mono_w32file_find_next (find_handle, &data) == FALSE){
+                       int e = GetLastError ();
+                       if (e != ERROR_NO_MORE_FILES)
+                               *ioerror = e;
+                       return NULL;
+               }
+       }
+       *result_attr = data.dwFileAttributes;
+       
+       return result;
+}
+
+/* FIXME make gc suspendable */
+MonoString *
+ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_attr, gint32 *error)
+{
+       IncrementalFind *ifh = (IncrementalFind *)handle;
+       WIN32_FIND_DATA data;
+       MonoString *result;
+
+       *error = ERROR_SUCCESS;
+       do {
+               if (mono_w32file_find_next (ifh->find_handle, &data) == FALSE){
+                       int e = GetLastError ();
+                       if (e != ERROR_NO_MORE_FILES)
+                               *error = e;
+                       return NULL;
+               }
+       } while (incremental_find_check_match (ifh, &data, &result) == 0);
+
+       *result_attr = data.dwFileAttributes;
+       return result;
+}
+
+int
+ves_icall_System_IO_MonoIO_FindClose (gpointer handle)
+{
+       IncrementalFind *ifh = (IncrementalFind *)handle;
+       gint32 error;
+
+       MONO_ENTER_GC_SAFE;
+       if (mono_w32file_find_close (ifh->find_handle) == FALSE){
+               error = GetLastError ();
+       } else
+               error = ERROR_SUCCESS;
+       g_free (ifh->utf8_path);
+       g_free (ifh);
+       MONO_EXIT_GC_SAFE;
+
+       return error;
+}
+
+MonoString *
+ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *io_error)
+{
+       MonoError error;
+       MonoString *result;
+       gunichar2 *buf;
+       int len, res_len;
+
+       len = MAX_PATH + 1; /*FIXME this is too smal under most unix systems.*/
+       buf = g_new (gunichar2, len);
+       
+       mono_error_init (&error);
+       *io_error=ERROR_SUCCESS;
+       result = NULL;
+
+       res_len = mono_w32file_get_cwd (len, buf);
+       if (res_len > len) { /*buf is too small.*/
+               int old_res_len = res_len;
+               g_free (buf);
+               buf = g_new (gunichar2, res_len);
+               res_len = mono_w32file_get_cwd (res_len, buf) == old_res_len;
+       }
+       
+       if (res_len) {
+               len = 0;
+               while (buf [len])
+                       ++ len;
+
+               result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
+       } else {
+               *io_error=GetLastError ();
+       }
+
+       g_free (buf);
+       mono_error_set_pending_exception (&error);
+       return result;
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString *path,
+                                               gint32 *error)
+{
+       gboolean ret;
+       
+       *error=ERROR_SUCCESS;
+       
+       ret=mono_w32file_set_cwd (mono_string_chars (path));
+       if(ret==FALSE) {
+               *error=GetLastError ();
+       }
+       
+       return(ret);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest, gint32 *error)
+{
+       *error=ERROR_SUCCESS;
+       return mono_w32file_move (mono_string_chars (path), mono_string_chars (dest), error);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *destinationFileName,
+                                       MonoString *destinationBackupFileName, MonoBoolean ignoreMetadataErrors,
+                                       gint32 *error)
+{
+       gunichar2 *utf16_sourceFileName = NULL, *utf16_destinationFileName = NULL, *utf16_destinationBackupFileName = NULL;
+       guint32 replaceFlags = REPLACEFILE_WRITE_THROUGH;
+
+       if (sourceFileName)
+               utf16_sourceFileName = mono_string_chars (sourceFileName);
+       if (destinationFileName)
+               utf16_destinationFileName = mono_string_chars (destinationFileName);
+       if (destinationBackupFileName)
+               utf16_destinationBackupFileName = mono_string_chars (destinationBackupFileName);
+
+       *error = ERROR_SUCCESS;
+       if (ignoreMetadataErrors)
+               replaceFlags |= REPLACEFILE_IGNORE_MERGE_ERRORS;
+
+       /* FIXME: source and destination file names must not be NULL, but apparently they might be! */
+       return mono_w32file_replace (utf16_destinationFileName, utf16_sourceFileName,
+                                         utf16_destinationBackupFileName, replaceFlags, error);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest,
+                                    MonoBoolean overwrite, gint32 *error)
+{
+       *error=ERROR_SUCCESS;
+       return mono_w32file_copy (mono_string_chars (path), mono_string_chars (dest), overwrite, error);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error)
+{
+       gboolean ret;
+       MONO_ENTER_GC_SAFE;
+       
+       *error=ERROR_SUCCESS;
+       
+       ret=mono_w32file_delete (mono_string_chars (path));
+       if(ret==FALSE) {
+               *error=GetLastError ();
+       }
+       
+       MONO_EXIT_GC_SAFE;
+       return(ret);
+}
+
+gint32 
+ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
+{
+       gint32 ret;
+       MONO_ENTER_GC_SAFE;
+
+       *error=ERROR_SUCCESS;
+       
+       ret=get_file_attributes (mono_string_chars (path));
+
+       /* 
+        * The definition of INVALID_FILE_ATTRIBUTES in the cygwin win32
+        * headers is wrong, hence this temporary workaround.
+        * See
+        * http://cygwin.com/ml/cygwin/2003-09/msg01771.html
+        */
+       if (ret==-1) {
+         /* if(ret==INVALID_FILE_ATTRIBUTES) { */
+               *error=GetLastError ();
+       }
+       
+       MONO_EXIT_GC_SAFE;
+       return(ret);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
+                                             gint32 *error)
+{
+       gboolean ret;
+       MONO_ENTER_GC_SAFE;
+       
+       *error=ERROR_SUCCESS;
+       
+       ret=mono_w32file_set_attributes (mono_string_chars (path),
+               convert_attrs ((MonoFileAttributes)attrs));
+       if(ret==FALSE) {
+               *error=GetLastError ();
+       }
+
+       MONO_EXIT_GC_SAFE;
+       return(ret);
+}
+
+gint32
+ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
+{
+       gboolean ret;
+       MONO_ENTER_GC_SAFE;
+
+       *error=ERROR_SUCCESS;
+       
+       ret=mono_w32file_get_type (handle);
+       if(ret==FILE_TYPE_UNKNOWN) {
+               /* Not necessarily an error, but the caller will have
+                * to decide based on the error value.
+                */
+               *error=GetLastError ();
+       }
+       
+       MONO_EXIT_GC_SAFE;
+       return(ret);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat, gint32 *error)
+{
+       gboolean result;
+       MONO_ENTER_GC_SAFE;
+
+       *error=ERROR_SUCCESS;
+       
+       result = get_file_attributes_ex (mono_string_chars (path), stat);
+
+       if (!result) {
+               *error=GetLastError ();
+               memset (stat, 0, sizeof (MonoIOStat));
+       }
+
+       MONO_EXIT_GC_SAFE;
+       return result;
+}
+
+HANDLE 
+ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
+                                gint32 access_mode, gint32 share, gint32 options,
+                                gint32 *error)
+{
+       HANDLE ret;
+       int attributes, attrs;
+       gunichar2 *chars;
+       MONO_ENTER_GC_SAFE;
+
+       chars = mono_string_chars (filename);   
+       *error=ERROR_SUCCESS;
+
+       if (options != 0){
+               if (options & FileOptions_Encrypted)
+                       attributes = FILE_ATTRIBUTE_ENCRYPTED;
+               else
+                       attributes = FILE_ATTRIBUTE_NORMAL;
+               if (options & FileOptions_DeleteOnClose)
+                       attributes |= FILE_FLAG_DELETE_ON_CLOSE;
+               if (options & FileOptions_SequentialScan)
+                       attributes |= FILE_FLAG_SEQUENTIAL_SCAN;
+               if (options & FileOptions_RandomAccess)
+                       attributes |= FILE_FLAG_RANDOM_ACCESS;
+
+               if (options & FileOptions_Temporary)
+                       attributes |= FILE_ATTRIBUTE_TEMPORARY;
+               
+               if (options & FileOptions_WriteThrough)
+                       attributes |= FILE_FLAG_WRITE_THROUGH;
+       } else
+               attributes = FILE_ATTRIBUTE_NORMAL;
+
+       /* If we're opening a directory we need to set the extra flag
+        */
+       attrs = get_file_attributes (chars);
+       if (attrs != INVALID_FILE_ATTRIBUTES) {
+               if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
+                       attributes |= FILE_FLAG_BACKUP_SEMANTICS;
+               }
+       }
+       
+       ret=mono_w32file_create (chars, convert_access ((MonoFileAccess)access_mode), convert_share ((MonoFileShare)share), convert_mode ((MonoFileMode)mode), attributes);
+       if(ret==INVALID_HANDLE_VALUE) {
+               *error=GetLastError ();
+       } 
+       
+       MONO_EXIT_GC_SAFE;
+       return(ret);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error)
+{
+       gboolean ret;
+       MONO_ENTER_GC_SAFE;
+
+       *error=ERROR_SUCCESS;
+       
+       ret=CloseHandle (handle);
+       if(ret==FALSE) {
+               *error=GetLastError ();
+       }
+       
+       MONO_EXIT_GC_SAFE;
+       return(ret);
+}
+
+gint32 
+ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArray *dest,
+                                gint32 dest_offset, gint32 count,
+                                gint32 *error)
+{
+       guchar *buffer;
+       gboolean result;
+       guint32 n;
+
+       *error=ERROR_SUCCESS;
+
+       MONO_CHECK_ARG_NULL (dest, 0);
+
+       if (dest_offset > mono_array_length (dest) - count) {
+               mono_set_pending_exception (mono_get_exception_argument ("array", "array too small. numBytes/offset wrong."));
+               return 0;
+       }
+
+       buffer = mono_array_addr (dest, guchar, dest_offset);
+
+       MONO_ENTER_GC_SAFE;
+       result = mono_w32file_read (handle, buffer, count, &n);
+       MONO_EXIT_GC_SAFE;
+
+       if (!result) {
+               *error=GetLastError ();
+               return -1;
+       }
+
+       return (gint32)n;
+}
+
+gint32 
+ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArray *src,
+                                 gint32 src_offset, gint32 count,
+                                 gint32 *error)
+{
+       guchar *buffer;
+       gboolean result;
+       guint32 n;
+
+       *error=ERROR_SUCCESS;
+
+       MONO_CHECK_ARG_NULL (src, 0);
+       
+       if (src_offset > mono_array_length (src) - count) {
+               mono_set_pending_exception (mono_get_exception_argument ("array", "array too small. numBytes/offset wrong."));
+               return 0;
+       }
+       
+       buffer = mono_array_addr (src, guchar, src_offset);
+       MONO_ENTER_GC_SAFE;
+       result = mono_w32file_write (handle, buffer, count, &n);
+       MONO_EXIT_GC_SAFE;
+
+       if (!result) {
+               *error=GetLastError ();
+               return -1;
+       }
+
+       return (gint32)n;
+}
+
+gint64 
+ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
+                                gint32 *error)
+{
+       gint32 offset_hi;
+       MONO_ENTER_GC_SAFE;
+
+       *error=ERROR_SUCCESS;
+       
+       offset_hi = offset >> 32;
+       offset = mono_w32file_seek (handle, (gint32) (offset & 0xFFFFFFFF), &offset_hi,
+                                convert_seekorigin ((MonoSeekOrigin)origin));
+
+       if(offset==INVALID_SET_FILE_POINTER) {
+               *error=GetLastError ();
+       }
+
+       MONO_EXIT_GC_SAFE;
+       return offset | ((gint64)offset_hi << 32);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
+{
+       gboolean ret;
+       MONO_ENTER_GC_SAFE;
+
+       *error=ERROR_SUCCESS;
+       
+       ret=mono_w32file_flush (handle);
+       if(ret==FALSE) {
+               *error=GetLastError ();
+       }
+       
+       MONO_EXIT_GC_SAFE;
+       return(ret);
+}
+
+gint64
+ves_icall_System_IO_MonoIO_GetLength (HANDLE handle, gint32 *error)
+{
+       *error=ERROR_SUCCESS;
+       return mono_w32file_get_file_size (handle, error);
+}
+
+/* FIXME make gc suspendable */
+MonoBoolean
+ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length,
+                                     gint32 *error)
+{
+       gint64 offset, offset_set;
+       gint32 offset_hi;
+       gint32 length_hi;
+       gboolean result;
+
+       *error=ERROR_SUCCESS;
+       
+       /* save file pointer */
+
+       offset_hi = 0;
+       offset = mono_w32file_seek (handle, 0, &offset_hi, FILE_CURRENT);
+       if(offset==INVALID_SET_FILE_POINTER) {
+               *error=GetLastError ();
+               return(FALSE);
+       }
+
+       /* extend or truncate */
+
+       length_hi = length >> 32;
+       offset_set=mono_w32file_seek (handle, length & 0xFFFFFFFF, &length_hi,
+                                  FILE_BEGIN);
+       if(offset_set==INVALID_SET_FILE_POINTER) {
+               *error=GetLastError ();
+               return(FALSE);
+       }
+
+       result = mono_w32file_truncate (handle);
+       if(result==FALSE) {
+               *error=GetLastError ();
+               return(FALSE);
+       }
+
+       /* restore file pointer */
+
+       offset_set=mono_w32file_seek (handle, offset & 0xFFFFFFFF, &offset_hi,
+                                  FILE_BEGIN);
+       if(offset_set==INVALID_SET_FILE_POINTER) {
+               *error=GetLastError ();
+               return(FALSE);
+       }
+
+       return result;
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
+                                       gint64 last_access_time,
+                                       gint64 last_write_time, gint32 *error)
+{
+       gboolean ret;
+       const FILETIME *creation_filetime;
+       const FILETIME *access_filetime;
+       const FILETIME *write_filetime;
+       MONO_ENTER_GC_SAFE;
+
+       *error=ERROR_SUCCESS;
+       
+       if (creation_time < 0)
+               creation_filetime = NULL;
+       else
+               creation_filetime = (FILETIME *)&creation_time;
+
+       if (last_access_time < 0)
+               access_filetime = NULL;
+       else
+               access_filetime = (FILETIME *)&last_access_time;
+
+       if (last_write_time < 0)
+               write_filetime = NULL;
+       else
+               write_filetime = (FILETIME *)&last_write_time;
+
+       ret=mono_w32file_set_times (handle, creation_filetime, access_filetime, write_filetime);
+       if(ret==FALSE) {
+               *error=GetLastError ();
+       }
+
+       MONO_EXIT_GC_SAFE;
+       return(ret);
+}
+
+HANDLE 
+ves_icall_System_IO_MonoIO_get_ConsoleOutput ()
+{
+       return mono_w32file_get_console_output ();
+}
+
+HANDLE 
+ves_icall_System_IO_MonoIO_get_ConsoleInput ()
+{
+       return mono_w32file_get_console_input ();
+}
+
+HANDLE 
+ves_icall_System_IO_MonoIO_get_ConsoleError ()
+{
+       return mono_w32file_get_console_error ();
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle, HANDLE *write_handle, gint32 *error)
+{
+       gboolean ret;
+
+       MONO_ENTER_GC_SAFE;
+       ret=mono_w32file_create_pipe (read_handle, write_handle, 0);
+       MONO_EXIT_GC_SAFE;
+
+       if(ret==FALSE) {
+               *error = GetLastError ();
+               /* FIXME: throw an exception? */
+               return(FALSE);
+       }
+       
+       return(TRUE);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_handle, HANDLE source_handle,
+               HANDLE target_process_handle, HANDLE *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error)
+{
+       /* This is only used on Windows */
+       gboolean ret;
+       
+       MONO_ENTER_GC_SAFE;
+#ifdef HOST_WIN32
+       ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options);
+#else
+       mono_w32handle_ref (source_handle);
+       *target_handle = source_handle;
+       ret = TRUE;
+#endif
+       MONO_EXIT_GC_SAFE;
+
+       if(ret==FALSE) {
+               *error = GetLastError ();
+               /* FIXME: throw an exception? */
+               return(FALSE);
+       }
+       
+       return(TRUE);
+}
+
+#ifndef HOST_WIN32
+gunichar2 
+ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
+{
+       return (gunichar2) '/'; /* forward slash */
+}
+
+gunichar2 
+ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
+{
+       return (gunichar2) '/'; /* forward slash */
+}
+
+gunichar2 
+ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
+{
+       if (IS_PORTABILITY_SET)
+               return (gunichar2) '\\';        /* backslash */
+       else
+               return (gunichar2) '/'; /* forward slash */
+}
+
+gunichar2 
+ves_icall_System_IO_MonoIO_get_PathSeparator ()
+{
+       return (gunichar2) ':'; /* colon */
+}
+#endif /* !HOST_WIN32 */
+
+static const gunichar2
+invalid_path_chars [] = {
+#if defined (TARGET_WIN32)
+       0x0022,                         /* double quote, which seems allowed in MS.NET but should be rejected */
+       0x003c,                         /* less than */
+       0x003e,                         /* greater than */
+       0x007c,                         /* pipe */
+       0x0008,
+       0x0010,
+       0x0011,
+       0x0012,
+       0x0014,
+       0x0015,
+       0x0016,
+       0x0017,
+       0x0018,
+       0x0019,
+#endif
+       0x0000                          /* null */
+};
+
+MonoArray *
+ves_icall_System_IO_MonoIO_get_InvalidPathChars ()
+{
+       MonoError error;
+       MonoArray *chars;
+       MonoDomain *domain;
+       int i, n;
+
+       domain = mono_domain_get ();
+       n = sizeof (invalid_path_chars) / sizeof (gunichar2);
+       chars = mono_array_new_checked (domain, mono_defaults.char_class, n, &error);
+       if (mono_error_set_pending_exception (&error))
+               return NULL;
+
+       for (i = 0; i < n; ++ i)
+               mono_array_set (chars, gunichar2, i, invalid_path_chars [i]);
+       
+       return chars;
+}
+
+void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position,
+                                     gint64 length, gint32 *error)
+{
+       *error=ERROR_SUCCESS;
+       mono_w32file_lock (handle, position, length, error);
+}
+
+void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position,
+                                       gint64 length, gint32 *error)
+{
+       *error=ERROR_SUCCESS;
+       mono_w32file_unlock (handle, position, length, error);
+}
+
+//Support for io-layer free mmap'd files.
+
+#if defined (TARGET_IOS) || defined (TARGET_ANDROID)
+
+gint64
+mono_filesize_from_path (MonoString *string)
+{
+       MonoError error;
+       struct stat buf;
+       gint64 res;
+       char *path = mono_string_to_utf8_checked (string, &error);
+       mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */
+
+       MONO_ENTER_GC_SAFE;
+       if (stat (path, &buf) == -1)
+               res = -1;
+       else
+               res = (gint64)buf.st_size;
+
+       g_free (path);
+
+       MONO_EXIT_GC_SAFE;
+       return res;
+}
+
+gint64
+mono_filesize_from_fd (int fd)
+{
+       struct stat buf;
+       int res;
+
+       MONO_ENTER_GC_SAFE;
+       res = fstat (fd, &buf);
+       MONO_EXIT_GC_SAFE;
+       
+       if (res == -1)
+               return (gint64)-1;
+
+       return (gint64)buf.st_size;
+}
+
+#endif
+
+#ifndef HOST_WIN32
+void mono_w32handle_dump (void);
+
+void ves_icall_System_IO_MonoIO_DumpHandles (void)
+{
+       mono_w32handle_dump ();
+}
+#endif /* !HOST_WIN32 */
diff --git a/mono/metadata/w32file.h b/mono/metadata/w32file.h
new file mode 100644 (file)
index 0000000..05bfe9f
--- /dev/null
@@ -0,0 +1,497 @@
+/*
+ * w32file.h: File IO internal calls
+ *
+ * Authors:
+ *     Dick Porter (dick@ximian.com)
+ *     Dan Lewis (dihlewis@yahoo.co.uk)
+ *
+ * (C) 2001 Ximian, Inc.
+ * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#ifndef _MONO_METADATA_W32FILE_H_
+#define _MONO_METADATA_W32FILE_H_
+
+#include <config.h>
+#include <glib.h>
+
+#include "io-layer/io-layer.h"
+#include <mono/metadata/object-internals.h>
+#include <mono/utils/mono-compiler.h>
+
+G_BEGIN_DECLS
+
+/* This is a copy of System.IO.FileAccess */
+typedef enum {
+       FileAccess_Read=0x01,
+       FileAccess_Write=0x02,
+       FileAccess_ReadWrite=FileAccess_Read|FileAccess_Write
+} MonoFileAccess;
+
+/* This is a copy of System.IO.FileMode */
+typedef enum {
+       FileMode_CreateNew=1,
+       FileMode_Create=2,
+       FileMode_Open=3,
+       FileMode_OpenOrCreate=4,
+       FileMode_Truncate=5,
+       FileMode_Append=6
+} MonoFileMode;
+
+/* This is a copy of System.IO.FileShare */
+typedef enum {
+       FileShare_None=0x0,
+       FileShare_Read=0x01,
+       FileShare_Write=0x02,
+       FileShare_ReadWrite=FileShare_Read|FileShare_Write,
+       FileShare_Delete=0x04
+} MonoFileShare;
+
+/* This is a copy of System.IO.FileOptions */
+typedef enum {
+       FileOptions_None = 0,
+       FileOptions_Temporary = 1,              // Internal.   See note in System.IO.FileOptions
+       FileOptions_Encrypted = 0x4000,
+       FileOptions_DeleteOnClose = 0x4000000,
+       FileOptions_SequentialScan = 0x8000000,
+       FileOptions_RandomAccess = 0x10000000,
+       FileOptions_Asynchronous = 0x40000000,
+       FileOptions_WriteThrough = 0x80000000
+} MonoFileOptions;
+
+/* This is a copy of System.IO.SeekOrigin */
+typedef enum {
+       SeekOrigin_Begin=0,
+       SeekOrigin_Current=1,
+       SeekOrigin_End=2
+} MonoSeekOrigin;
+
+/* This is a copy of System.IO.MonoIOStat */
+typedef struct _MonoIOStat {
+       gint32 attributes;
+       gint64 length;
+       gint64 creation_time;
+       gint64 last_access_time;
+       gint64 last_write_time;
+} MonoIOStat;
+
+/* This is a copy of System.IO.FileAttributes */
+typedef enum {
+       FileAttributes_ReadOnly=0x00001,
+       FileAttributes_Hidden=0x00002,
+       FileAttributes_System=0x00004,
+       FileAttributes_Directory=0x00010,
+       FileAttributes_Archive=0x00020,
+       FileAttributes_Device=0x00040,
+       FileAttributes_Normal=0x00080,
+       FileAttributes_Temporary=0x00100,
+       FileAttributes_SparseFile=0x00200,
+       FileAttributes_ReparsePoint=0x00400,
+       FileAttributes_Compressed=0x00800,
+       FileAttributes_Offline=0x01000,
+       FileAttributes_NotContentIndexed=0x02000,
+       FileAttributes_Encrypted=0x04000,
+       FileAttributes_MonoExecutable= (int) 0x80000000
+} MonoFileAttributes;
+/* This is not used anymore
+typedef struct _MonoFSAsyncResult {
+       MonoObject obj;
+       MonoObject *state;
+       MonoBoolean completed;
+       MonoBoolean done;
+       MonoException *exc;
+       MonoWaitHandle *wait_handle;
+       MonoDelegate *async_callback;
+       MonoBoolean completed_synch;
+       MonoArray *buffer;
+       gint offset;
+       gint count;
+       gint original_count;
+       gint bytes_read;
+       MonoDelegate *real_cb;
+} MonoFSAsyncResult;
+*/
+/* System.IO.MonoIO */
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error);
+
+MonoArray *
+ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
+                                                MonoString *path_with_pattern,
+                                                gint mask, gint attrs,
+                                                gint32 *error);
+
+extern gpointer
+ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path_with_pattern,
+                                               MonoString **file_name,
+                                               gint32 *file_attr,
+                                               gint32 *ioerror);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_FindNextFile (gpointer hnd,
+                                               MonoString **file_name,
+                                               gint32 *file_attr,
+                                               gint32 *ioerror);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_FindCloseFile (gpointer hnd);
+
+extern MonoString *
+ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
+                                     MonoString *path_with_pattern,
+                                     gint32 *result_mask,
+                                     gint32 *error,
+                                     gpointer *handle);
+extern MonoString *
+ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_mask, gint32 *error);
+
+extern int
+ves_icall_System_IO_MonoIO_FindClose (gpointer handle);
+
+extern MonoString *
+ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString *path,
+                                               gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest,
+                                    gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest,
+                                    MonoBoolean overwrite, gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error);
+
+extern gint32 
+ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
+                                             gint32 *error);
+
+extern gint32
+ves_icall_System_IO_MonoIO_GetFileType (gpointer handle, gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat,
+                                       gint32 *error);
+
+extern gpointer 
+ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
+                                gint32 access_mode, gint32 share, gint32 options,
+                                gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_Close (gpointer handle, gint32 *error);
+
+extern gint32 
+ves_icall_System_IO_MonoIO_Read (gpointer handle, MonoArray *dest,
+                                gint32 dest_offset, gint32 count,
+                                gint32 *error);
+
+extern gint32 
+ves_icall_System_IO_MonoIO_Write (gpointer handle, MonoArray *src,
+                                 gint32 src_offset, gint32 count,
+                                 gint32 *error);
+
+extern gint64 
+ves_icall_System_IO_MonoIO_Seek (gpointer handle, gint64 offset, gint32 origin,
+                                gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_Flush (gpointer handle, gint32 *error);
+
+extern gint64 
+ves_icall_System_IO_MonoIO_GetLength (gpointer handle, gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_SetLength (gpointer handle, gint64 length,
+                                     gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_SetFileTime (gpointer handle, gint64 creation_time,
+                                       gint64 last_access_time,
+                                       gint64 last_write_time, gint32 *error);
+
+extern gpointer 
+ves_icall_System_IO_MonoIO_get_ConsoleOutput (void);
+
+extern gpointer 
+ves_icall_System_IO_MonoIO_get_ConsoleInput (void);
+
+extern gpointer 
+ves_icall_System_IO_MonoIO_get_ConsoleError (void);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_CreatePipe (gpointer *read_handle, gpointer *write_handle, gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_DuplicateHandle (gpointer source_process_handle, gpointer source_handle,
+               gpointer target_process_handle, gpointer *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error);
+
+extern gunichar2 
+ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar (void);
+
+extern gunichar2 
+ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar (void);
+
+extern gunichar2 
+ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar (void);
+
+extern gunichar2 
+ves_icall_System_IO_MonoIO_get_PathSeparator (void);
+
+extern MonoArray *
+ves_icall_System_IO_MonoIO_get_InvalidPathChars (void);
+
+extern void ves_icall_System_IO_MonoIO_Lock (gpointer handle, gint64 position,
+                                            gint64 length, gint32 *error);
+extern void ves_icall_System_IO_MonoIO_Unlock (gpointer handle, gint64 position,
+                                              gint64 length, gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *destinationFileName,
+                                       MonoString *destinationBackupFileName, MonoBoolean ignoreMetadataErrors,
+                                       gint32 *error);
+
+#if defined (TARGET_IOS) || defined (TARGET_ANDROID)
+
+MONO_RT_EXTERNAL_ONLY
+extern gint64
+mono_filesize_from_path (MonoString *path);
+
+extern gint64
+mono_filesize_from_fd (int fd);
+
+#endif
+
+void
+ves_icall_System_IO_MonoIO_DumpHandles (void);
+
+#if !defined(HOST_WIN32)
+
+#define GENERIC_READ    0x80000000
+#define GENERIC_WRITE   0x40000000
+#define GENERIC_EXECUTE 0x20000000
+#define GENERIC_ALL     0x10000000
+
+#define FILE_SHARE_READ   0x00000001
+#define FILE_SHARE_WRITE  0x00000002
+#define FILE_SHARE_DELETE 0x00000004
+
+#define CREATE_NEW        1
+#define CREATE_ALWAYS     2
+#define OPEN_EXISTING     3
+#define OPEN_ALWAYS       4
+#define TRUNCATE_EXISTING 5
+
+#define FILE_ATTRIBUTE_READONLY            0x00000001
+#define FILE_ATTRIBUTE_HIDDEN              0x00000002
+#define FILE_ATTRIBUTE_SYSTEM              0x00000004
+#define FILE_ATTRIBUTE_DIRECTORY           0x00000010
+#define FILE_ATTRIBUTE_ARCHIVE             0x00000020
+#define FILE_ATTRIBUTE_ENCRYPTED           0x00000040
+#define FILE_ATTRIBUTE_NORMAL              0x00000080
+#define FILE_ATTRIBUTE_TEMPORARY           0x00000100
+#define FILE_ATTRIBUTE_SPARSE_FILE         0x00000200
+#define FILE_ATTRIBUTE_REPARSE_POINT       0x00000400
+#define FILE_ATTRIBUTE_COMPRESSED          0x00000800
+#define FILE_ATTRIBUTE_OFFLINE             0x00001000
+#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
+#define FILE_FLAG_OPEN_NO_RECALL           0x00100000
+#define FILE_FLAG_OPEN_REPARSE_POINT       0x00200000
+#define FILE_FLAG_POSIX_SEMANTICS          0x01000000
+#define FILE_FLAG_BACKUP_SEMANTICS         0x02000000
+#define FILE_FLAG_DELETE_ON_CLOSE          0x04000000
+#define FILE_FLAG_SEQUENTIAL_SCAN          0x08000000
+#define FILE_FLAG_RANDOM_ACCESS            0x10000000
+#define FILE_FLAG_NO_BUFFERING             0x20000000
+#define FILE_FLAG_OVERLAPPED               0x40000000
+#define FILE_FLAG_WRITE_THROUGH            0x80000000
+
+#define REPLACEFILE_WRITE_THROUGH       0x00000001
+#define REPLACEFILE_IGNORE_MERGE_ERRORS 0x00000002
+
+#define MAX_PATH 260
+
+#define INVALID_SET_FILE_POINTER ((guint32) 0xFFFFFFFF)
+#define INVALID_FILE_SIZE        ((guint32) 0xFFFFFFFF)
+#define INVALID_FILE_ATTRIBUTES  ((guint32) 0xFFFFFFFF)
+
+#define FILE_TYPE_UNKNOWN 0x0000
+#define FILE_TYPE_DISK    0x0001
+#define FILE_TYPE_CHAR    0x0002
+#define FILE_TYPE_PIPE    0x0003
+#define FILE_TYPE_REMOTE  0x8000
+
+#define FILE_BEGIN   0
+#define FILE_CURRENT 1
+#define FILE_END     2
+
+#define DRIVE_UNKNOWN     0
+#define DRIVE_NO_ROOT_DIR 1
+#define DRIVE_REMOVABLE   2
+#define DRIVE_FIXED       3
+#define DRIVE_REMOTE      4
+#define DRIVE_CDROM       5
+#define DRIVE_RAMDISK     6
+
+typedef struct {
+       guint16 wYear;
+       guint16 wMonth;
+       guint16 wDayOfWeek;
+       guint16 wDay;
+       guint16 wHour;
+       guint16 wMinute;
+       guint16 wSecond;
+       guint16 wMilliseconds;
+} SYSTEMTIME;
+
+typedef struct {
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+       guint32 dwHighDateTime;
+       guint32 dwLowDateTime;
+#else
+       guint32 dwLowDateTime;
+       guint32 dwHighDateTime;
+#endif
+} FILETIME;
+
+typedef struct {
+       guint32 dwFileAttributes;
+       FILETIME ftCreationTime;
+       FILETIME ftLastAccessTime;
+       FILETIME ftLastWriteTime;
+       guint32 nFileSizeHigh;
+       guint32 nFileSizeLow;
+       guint32 dwReserved0;
+       guint32 dwReserved1;
+       gunichar2 cFileName [MAX_PATH];
+       gunichar2 cAlternateFileName [14];
+} WIN32_FIND_DATA;
+
+#endif /* !defined(HOST_WIN32) */
+
+void
+mono_w32file_init (void);
+
+void
+mono_w32file_cleanup (void);
+
+gpointer
+mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode, guint32 createmode, guint32 attrs);
+
+gboolean
+mono_w32file_delete (const gunichar2 *name);
+
+gboolean
+mono_w32file_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread);
+
+gboolean
+mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten);
+
+gboolean
+mono_w32file_flush (gpointer handle);
+
+gboolean
+mono_w32file_truncate (gpointer handle);
+
+guint32
+mono_w32file_seek (gpointer handle, gint32 movedistance, gint32 *highmovedistance, guint32 method);
+
+gboolean
+mono_w32file_move (gunichar2 *path, gunichar2 *dest, gint32 *error);
+
+gboolean
+mono_w32file_copy (gunichar2 *path, gunichar2 *dest, gboolean overwrite, gint32 *error);
+
+gboolean
+mono_w32file_lock (gpointer handle, gint64 position, gint64 length, gint32 *error);
+
+gboolean
+mono_w32file_replace (gunichar2 *destinationFileName, gunichar2 *sourceFileName, gunichar2 *destinationBackupFileName, guint32 flags, gint32 *error);
+
+gboolean
+mono_w32file_unlock (gpointer handle, gint64 position, gint64 length, gint32 *error);
+
+gpointer
+mono_w32file_get_console_output (void);
+
+gpointer
+mono_w32file_get_console_error (void);
+
+gpointer
+mono_w32file_get_console_input (void);
+
+gint64
+mono_w32file_get_file_size (gpointer handle, gint32 *error);
+
+gint
+mono_w32file_get_type (gpointer handle);
+
+gboolean
+mono_w32file_get_times (gpointer handle, FILETIME *create_time, FILETIME *access_time, FILETIME *write_time);
+
+gboolean
+mono_w32file_set_times (gpointer handle, const FILETIME *create_time, const FILETIME *access_time, const FILETIME *write_time);
+
+gboolean
+mono_w32file_filetime_to_systemtime (const FILETIME *file_time, SYSTEMTIME *system_time);
+
+gpointer
+mono_w32file_find_first (const gunichar2 *pattern, WIN32_FIND_DATA *find_data);
+
+gboolean
+mono_w32file_find_next (gpointer handle, WIN32_FIND_DATA *find_data);
+
+gboolean
+mono_w32file_find_close (gpointer handle);
+
+gboolean
+mono_w32file_create_directory (const gunichar2 *name);
+
+gboolean
+mono_w32file_remove_directory (const gunichar2 *name);
+
+guint32
+mono_w32file_get_attributes (const gunichar2 *name);
+
+gboolean
+mono_w32file_get_attributes_ex (const gunichar2 *name, MonoIOStat *stat);
+
+gboolean
+mono_w32file_set_attributes (const gunichar2 *name, guint32 attrs);
+
+guint32
+mono_w32file_get_cwd (guint32 length, gunichar2 *buffer);
+
+gboolean
+mono_w32file_set_cwd (const gunichar2 *path);
+
+gboolean
+mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size);
+
+gint32
+mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf);
+
+gboolean
+mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_bytes_avail, guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes);
+
+guint32
+mono_w32file_get_drive_type (const gunichar2 *root_path_name);
+
+gboolean
+mono_w32file_get_volume_information (const gunichar2 *path, gunichar2 *volumename, gint volumesize, gint *outserial, gint *maxcomp, gint *fsflags, gunichar2 *fsbuffer, gint fsbuffersize);
+
+G_END_DECLS
+
+#endif /* _MONO_METADATA_W32FILE_H_ */
index d4fae9dd09e1543bca9224dce1aa1ab07e27cf39..248bf1b316f00a7920a2f7618d15fe152b5af99b 100644 (file)
@@ -250,7 +250,7 @@ mono_w32handle_unlock_handle (gpointer handle)
 }
 
 /*
- * wapi_init:
+ * mono_w32handle_init:
  *
  *   Initialize the io-layer.
  */
index a39f5ca276163804a73af82022d485a634a10562..faf8ac6eea97da61a84fa9d36b6c5c3051ee6782 100644 (file)
@@ -18,6 +18,8 @@
 #include "mono/utils/mono-threads.h"
 #include "mono/metadata/w32handle.h"
 
+#define MAX_PATH 260
+
 typedef struct {
        MonoNativeThreadId tid;
        guint32 recursion;
index 8be10017ab641acb152459bc03e20bc9febda9b0..e81b50a1acfebfd7e4ec759ecb0068639626b606 100644 (file)
@@ -58,6 +58,7 @@
 #include <mono/metadata/exception.h>
 #include <mono/io-layer/io-layer.h>
 #include <mono/metadata/w32handle.h>
+#include <mono/metadata/w32file.h>
 #include <mono/utils/mono-membar.h>
 #include <mono/utils/mono-logger-internals.h>
 #include <mono/utils/strenc.h>
@@ -68,6 +69,7 @@
 #include <mono/utils/mono-time.h>
 #include <mono/utils/mono-mmap.h>
 #include <mono/utils/strenc.h>
+#include <mono/utils/mono-io-portability.h>
 
 #ifndef MAXPATHLEN
 #define MAXPATHLEN 242
@@ -1886,9 +1888,9 @@ process_create (const gunichar2 *appname, const gunichar2 *cmdline,
                out_fd = GPOINTER_TO_UINT (startup_handles->output);
                err_fd = GPOINTER_TO_UINT (startup_handles->error);
        } else {
-               in_fd = GPOINTER_TO_UINT (GetStdHandle (STD_INPUT_HANDLE));
-               out_fd = GPOINTER_TO_UINT (GetStdHandle (STD_OUTPUT_HANDLE));
-               err_fd = GPOINTER_TO_UINT (GetStdHandle (STD_ERROR_HANDLE));
+               in_fd = GPOINTER_TO_UINT (mono_w32file_get_console_input ());
+               out_fd = GPOINTER_TO_UINT (mono_w32file_get_console_output ());
+               err_fd = GPOINTER_TO_UINT (mono_w32file_get_console_error ());
        }
 
        /*
@@ -2961,14 +2963,37 @@ map_pe_file (gunichar2 *filename, gint32 *map_size, void **handle)
                return(NULL);
        }
 
-       fd = _wapi_open (filename_ext, O_RDONLY, 0);
-       if (fd == -1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s: %s", __func__, filename_ext, strerror (errno));
+       fd = open (filename_ext, O_RDONLY, 0);
+       if (fd == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) {
+               gint saved_errno;
+               gchar *located_filename;
 
-               SetLastError (_wapi_get_win32_file_error (errno));
-               g_free (filename_ext);
+               saved_errno = errno;
 
-               return(NULL);
+               located_filename = mono_portability_find_file (filename_ext, TRUE);
+               if (!located_filename) {
+                       errno = saved_errno;
+
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s (1): %s", __func__, filename_ext, strerror (errno));
+
+                       g_free (filename_ext);
+
+                       SetLastError (_wapi_get_win32_file_error (errno));
+                       return NULL;
+               }
+
+               fd = open (located_filename, O_RDONLY, 0);
+               if (fd == -1) {
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s (2): %s", __func__, filename_ext, strerror (errno));
+
+                       g_free (filename_ext);
+                       g_free (located_filename);
+
+                       SetLastError (_wapi_get_win32_file_error (errno));
+                       return NULL;
+               }
+
+               g_free (located_filename);
        }
 
        if (fstat (fd, &statbuf) == -1) {
index e4a8a755ff239519c28b9021447d8df43087ad47..78a622af6531296c1e25710931a85a77c00742ca 100644 (file)
@@ -4,6 +4,7 @@
 #include "w32process.h"
 #include "w32process-internals.h"
 #include "w32process-win32-internals.h"
+#include "w32file.h"
 #include "object.h"
 #include "object-internals.h"
 #include "class.h"
index bcecd8cb558381ea08df99bb5e3bc3e0ba8b5528..0e88d94abe7de1618f94469f6f30486657a9e84c 100644 (file)
@@ -14,6 +14,8 @@
 #include "mono/utils/mono-logger-internals.h"
 #include "mono/metadata/w32handle.h"
 
+#define MAX_PATH 260
+
 typedef struct {
        guint32 val;
        gint32 max;
index dd4c61129d0ad726c1f7b7e07b3159017ed48852..02f5fe108443eb9b61a4b1e79d203c7fe9cecff9 100644 (file)
@@ -33,16 +33,6 @@ typedef struct {
        gpointer buf;
 } WSABUF;
 
-typedef struct {
-       guint32 Internal;
-       guint32 InternalHigh;
-       guint32 Offset;
-       guint32 OffsetHigh;
-       gpointer hEvent;
-       gpointer handle1;
-       gpointer handle2;
-} OVERLAPPED;
-
 typedef struct {
        gpointer Head;
        guint32 HeadLength;
@@ -57,6 +47,16 @@ typedef struct {
        guint8 Data4[8];
 } GUID;
 
+typedef struct {
+       guint32 Internal;
+       guint32 InternalHigh;
+       guint32 Offset;
+       guint32 OffsetHigh;
+       gpointer hEvent;
+       gpointer handle1;
+       gpointer handle2;
+} OVERLAPPED;
+
 typedef BOOL (WINAPI *LPFN_DISCONNECTEX)(SOCKET, OVERLAPPED*, guint32, guint32);
 typedef BOOL (WINAPI *LPFN_TRANSMITFILE)(SOCKET, HANDLE, guint32, guint32, OVERLAPPED*, TRANSMIT_FILE_BUFFERS*, guint32);
 
index 9d45ddac9215782b7a090e9f2fc785ba1ade4271..ba9156eb48b8042374b532fc05d6ec6774e5d845 100644 (file)
@@ -50,7 +50,7 @@
 #include <mono/metadata/exception.h>
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/appdomain.h>
-#include <mono/metadata/file-io.h>
+#include <mono/metadata/w32file.h>
 #include <mono/metadata/threads.h>
 #include <mono/metadata/threads-types.h>
 #include <mono/metadata/threadpool-io.h>
index 6c94d1ff21e1fdfebad47c3634bf9bd1819de0bb..0f4d0703b7b097bf9ddc053b4bd34d5d2e287748 100644 (file)
@@ -29,7 +29,7 @@
     <ClCompile Include="..\mono\metadata\console-win32.c" />\r
     <ClCompile Include="..\mono\metadata\property-bag.c" />\r
     <ClCompile Include="..\mono\metadata\w32socket-win32.c" />\r
-    <ClCompile Include="..\mono\metadata\file-io-windows.c" />\r
+    <ClCompile Include="..\mono\metadata\w32file-win32.c" />\r
     <ClCompile Include="..\mono\metadata\icall-windows.c" />\r
     <ClCompile Include="..\mono\metadata\marshal-windows.c" />\r
     <ClCompile Include="..\mono\metadata\mono-security-windows.c" />\r
@@ -49,7 +49,7 @@
     <ClCompile Include="..\mono\metadata\domain.c" />\r
     <ClCompile Include="..\mono\metadata\environment.c" />\r
     <ClCompile Include="..\mono\metadata\exception.c" />\r
-    <ClCompile Include="..\mono\metadata\file-io.c" />\r
+    <ClCompile Include="..\mono\metadata\w32file.c" />\r
     <ClCompile Include="..\mono\metadata\file-mmap-windows.c" />\r
     <ClCompile Include="..\mono\metadata\filewatcher.c" />\r
     <ClCompile Include="..\mono\metadata\gc-stats.c" />\r
     <ClInclude Include="..\mono\metadata\dynamic-stream-internals.h" />\r
     <ClInclude Include="..\mono\metadata\environment.h" />\r
     <ClInclude Include="..\mono\metadata\exception.h" />\r
-    <ClInclude Include="..\mono\metadata\file-io-internals.h" />\r
-    <ClInclude Include="..\mono\metadata\file-io-windows-internals.h" />\r
-    <ClInclude Include="..\mono\metadata\file-io.h" />\r
+    <ClInclude Include="..\mono\metadata\w32file-internals.h" />\r
+    <ClInclude Include="..\mono\metadata\w32file-win32-internals.h" />\r
+    <ClInclude Include="..\mono\metadata\w32file.h" />\r
     <ClInclude Include="..\mono\metadata\filewatcher.h" />\r
     <ClInclude Include="..\mono\metadata\gc-internals.h" />\r
     <ClInclude Include="..\mono\metadata\handle.h" />\r
index 8de9920a9ea5b71ce137255db089e3949d93924a..bc9a0c35fb6b1e791ff78fc70dcc1577a393ec02 100644 (file)
@@ -46,7 +46,7 @@
     <ClCompile Include="..\mono\metadata\exception.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\mono\metadata\file-io.c">\r
+    <ClCompile Include="..\mono\metadata\w32file.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\mono\metadata\file-mmap-windows.c">\r
     <ClCompile Include="..\mono\metadata\w32socket-win32.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\mono\metadata\file-io-windows.c">\r
+    <ClCompile Include="..\mono\metadata\w32file-win32.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\mono\metadata\icall-windows.c">\r
     <ClInclude Include="..\mono\metadata\exception.h">\r
       <Filter>Header Files</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\mono\metadata\file-io.h">\r
+    <ClInclude Include="..\mono\metadata\w32file.h">\r
       <Filter>Header Files</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\mono\metadata\filewatcher.h">\r
     <ClInclude Include="..\mono\metadata\console-win32-internals.h">\r
       <Filter>Header Files</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\mono\metadata\file-io-windows-internals.h">\r
+    <ClInclude Include="..\mono\metadata\w32file-win32-internals.h">\r
       <Filter>Header Files</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\mono\metadata\file-io-internals.h">\r
+    <ClInclude Include="..\mono\metadata\w32file-internals.h">\r
       <Filter>Header Files</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\mono\metadata\icall-internals.h">\r
index e997a22ae4b7fcee570b6990bbe19e477a24c8d5..57b84fab14f852b834a27a8e7aaa201d7820348e 100644 (file)
     <ClCompile Include="..\mono\metadata\console-win32.c" />\r
     <ClCompile Include="..\mono\metadata\domain.c" />\r
     <ClCompile Include="..\mono\metadata\environment.c" />\r
-    <ClCompile Include="..\mono\metadata\file-io-windows.c" />\r
-    <ClCompile Include="..\mono\metadata\file-io.c" />\r
+    <ClCompile Include="..\mono\metadata\w32file-win32.c" />\r
+    <ClCompile Include="..\mono\metadata\w32file.c" />\r
     <ClCompile Include="..\mono\metadata\filewatcher.c" />\r
     <ClCompile Include="..\mono\metadata\gc.c" />\r
     <ClCompile Include="..\mono\metadata\icall-windows.c" />\r
index c7f55c9b0d13f29c955a1a0f1f879f8f99ee8e35..9f25b8211b54c2eb19c449415c191d7e0399619c 100644 (file)
@@ -22,7 +22,7 @@
     <ClCompile Include="..\mono\metadata\environment.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\mono\metadata\file-io.c">\r
+    <ClCompile Include="..\mono\metadata\w32file.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\mono\metadata\filewatcher.c">\r
     <ClCompile Include="..\mono\metadata\icall-windows.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\mono\metadata\file-io-windows.c">\r
+    <ClCompile Include="..\mono\metadata\w32file-win32.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
   </ItemGroup>\r