Merge pull request #2543 from ermshiperete/Xamarin-31021
[mono.git] / mono / io-layer / io.c
index bc09631baa282db90ba688cc1c61a1daf10411ec..b751134d7045aa6a2cae4e3fc3ba186fedbd66c1 100644 (file)
 #include <mono/io-layer/timefuncs-private.h>
 #include <mono/io-layer/thread-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>
-
-#if 0
-#define DEBUG(...) g_message(__VA_ARGS__)
-#define DEBUG_ENABLED 1
-#else
-#define DEBUG(...)
-#endif
+#include <mono/utils/mono-logger-internals.h>
 
 static void file_close (gpointer handle, gpointer data);
 static WapiFileType file_getfiletype(void);
@@ -245,7 +240,7 @@ static void io_ops_init (void)
  * This is is a best effort kind of thing. It assumes a reasonable sane set
  * of permissions by the underlying OS.
  *
- * We assume that basic unix permission bits are authoritative. Which might not
+ * 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.
@@ -257,6 +252,13 @@ static void io_ops_init (void)
 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;
@@ -367,7 +369,7 @@ static void file_close (gpointer handle, gpointer data)
        struct _WapiHandle_file *file_handle = (struct _WapiHandle_file *)data;
        int fd = file_handle->fd;
        
-       DEBUG("%s: closing file handle %p [%s]", __func__, handle,
+       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)
@@ -410,7 +412,7 @@ static gboolean file_read(gpointer handle, gpointer buffer,
        
        if(!(file_handle->fileaccess & GENERIC_READ) &&
           !(file_handle->fileaccess & GENERIC_ALL)) {
-               DEBUG("%s: handle %p doesn't have GENERIC_READ access: %u",
+               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);
@@ -425,7 +427,7 @@ static gboolean file_read(gpointer handle, gpointer buffer,
        if(ret==-1) {
                gint err = errno;
 
-               DEBUG("%s: read of handle %p error: %s", __func__,
+               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);
@@ -464,7 +466,7 @@ static gboolean file_write(gpointer handle, gconstpointer buffer,
        
        if(!(file_handle->fileaccess & GENERIC_WRITE) &&
           !(file_handle->fileaccess & GENERIC_ALL)) {
-               DEBUG("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+               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);
@@ -477,7 +479,7 @@ static gboolean file_write(gpointer handle, gconstpointer buffer,
                 */
                current_pos = lseek (fd, (off_t)0, SEEK_CUR);
                if (current_pos == -1) {
-                       DEBUG ("%s: handle %p lseek failed: %s", __func__,
+                       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);
@@ -505,7 +507,7 @@ static gboolean file_write(gpointer handle, gconstpointer buffer,
                } else {
                        _wapi_set_last_error_from_errno ();
                                
-                       DEBUG("%s: write of handle %p error: %s",
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s",
                                  __func__, handle, strerror(errno));
 
                        return(FALSE);
@@ -536,7 +538,7 @@ static gboolean file_flush(gpointer handle)
 
        if(!(file_handle->fileaccess & GENERIC_WRITE) &&
           !(file_handle->fileaccess & GENERIC_ALL)) {
-               DEBUG("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+               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);
@@ -544,7 +546,7 @@ static gboolean file_flush(gpointer handle)
 
        ret=fsync(fd);
        if (ret==-1) {
-               DEBUG("%s: fsync of handle %p error: %s", __func__, handle,
+               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 ();
@@ -577,7 +579,7 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
        if(!(file_handle->fileaccess & GENERIC_READ) &&
           !(file_handle->fileaccess & GENERIC_WRITE) &&
           !(file_handle->fileaccess & GENERIC_ALL)) {
-               DEBUG ("%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+               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);
@@ -594,7 +596,7 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
                whence=SEEK_END;
                break;
        default:
-               DEBUG("%s: invalid seek type %d", __func__, method);
+               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);
@@ -603,18 +605,18 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
 #ifdef HAVE_LARGE_FILE_SUPPORT
        if(highmovedistance==NULL) {
                offset=movedistance;
-               DEBUG("%s: setting offset to %lld (low %d)", __func__,
+               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;
                
-               DEBUG("%s: setting offset to %lld 0x%llx (high %d 0x%x, low %d 0x%x)", __func__, offset, offset, *highmovedistance, *highmovedistance, movedistance, 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
 
-       DEBUG ("%s: moving handle %p by %lld bytes from %d", __func__,
+       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
@@ -624,14 +626,14 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
        newpos=lseek(fd, offset, whence);
 #endif
        if(newpos==-1) {
-               DEBUG("%s: lseek on handle %p returned error %s",
+               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);
        }
 
-       DEBUG ("%s: lseek returns %lld", __func__, newpos);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek returns %lld", __func__, newpos);
 
 #ifdef HAVE_LARGE_FILE_SUPPORT
        ret=newpos & 0xFFFFFFFF;
@@ -646,7 +648,7 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
        }
 #endif
 
-       DEBUG ("%s: move of handle %p returning %d/%d", __func__,
+       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);
@@ -672,7 +674,7 @@ static gboolean file_setendoffile(gpointer handle)
        
        if(!(file_handle->fileaccess & GENERIC_WRITE) &&
           !(file_handle->fileaccess & GENERIC_ALL)) {
-               DEBUG("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+               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);
@@ -686,7 +688,7 @@ static gboolean file_setendoffile(gpointer handle)
        
        ret=fstat(fd, &statbuf);
        if(ret==-1) {
-               DEBUG ("%s: handle %p fstat failed: %s", __func__,
+               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 ();
@@ -695,7 +697,7 @@ static gboolean file_setendoffile(gpointer handle)
 
        pos=lseek(fd, (off_t)0, SEEK_CUR);
        if(pos==-1) {
-               DEBUG("%s: handle %p lseek failed: %s", __func__,
+               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 ();
@@ -722,7 +724,7 @@ static gboolean file_setendoffile(gpointer handle)
                         !_wapi_thread_cur_apc_pending());
 
                if(ret==-1) {
-                       DEBUG("%s: handle %p extend write failed: %s", __func__, handle, strerror(errno));
+                       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);
@@ -731,7 +733,7 @@ static gboolean file_setendoffile(gpointer handle)
                /* And put the file position back after the write */
                ret = lseek (fd, pos, SEEK_SET);
                if (ret == -1) {
-                       DEBUG ("%s: handle %p second lseek failed: %s",
+                       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 ();
@@ -750,7 +752,7 @@ static gboolean file_setendoffile(gpointer handle)
        }
        while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); 
        if(ret==-1) {
-               DEBUG("%s: handle %p ftruncate failed: %s", __func__,
+               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 ();
@@ -783,7 +785,7 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
        if(!(file_handle->fileaccess & GENERIC_READ) &&
           !(file_handle->fileaccess & GENERIC_WRITE) &&
           !(file_handle->fileaccess & GENERIC_ALL)) {
-               DEBUG("%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+               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);
@@ -797,7 +799,7 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
        
        ret = fstat(fd, &statbuf);
        if (ret == -1) {
-               DEBUG ("%s: handle %p fstat failed: %s", __func__,
+               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 ();
@@ -809,7 +811,7 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
        if (S_ISBLK(statbuf.st_mode)) {
                guint64 bigsize;
                if (ioctl(fd, BLKGETSIZE64, &bigsize) < 0) {
-                       DEBUG ("%s: handle %p ioctl BLKGETSIZE64 failed: %s",
+                       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 ();
@@ -821,7 +823,7 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
                        *highsize = bigsize>>32;
                }
 
-               DEBUG ("%s: Returning block device size %d/%d",
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning block device size %d/%d",
                           __func__, size, *highsize);
        
                return(size);
@@ -841,7 +843,7 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
        size = statbuf.st_size;
 #endif
 
-       DEBUG ("%s: Returning size %d/%d", __func__, size, *highsize);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning size %d/%d", __func__, size, *highsize);
        
        return(size);
 }
@@ -868,7 +870,7 @@ static gboolean file_getfiletime(gpointer handle, WapiFileTime *create_time,
 
        if(!(file_handle->fileaccess & GENERIC_READ) &&
           !(file_handle->fileaccess & GENERIC_ALL)) {
-               DEBUG("%s: handle %p doesn't have GENERIC_READ access: %u",
+               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);
@@ -877,14 +879,14 @@ static gboolean file_getfiletime(gpointer handle, WapiFileTime *create_time,
        
        ret=fstat(fd, &statbuf);
        if(ret==-1) {
-               DEBUG("%s: handle %p fstat failed: %s", __func__, handle,
+               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);
        }
 
-       DEBUG("%s: atime: %ld ctime: %ld mtime: %ld", __func__,
+       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);
 
@@ -905,7 +907,7 @@ static gboolean file_getfiletime(gpointer handle, WapiFileTime *create_time,
        access_ticks=((guint64)statbuf.st_atime*10000000)+116444736000000000ULL;
        write_ticks=((guint64)statbuf.st_mtime*10000000)+116444736000000000ULL;
        
-       DEBUG("%s: aticks: %llu cticks: %llu wticks: %llu", __func__,
+       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) {
@@ -950,14 +952,14 @@ static gboolean file_setfiletime(gpointer handle,
        
        if(!(file_handle->fileaccess & GENERIC_WRITE) &&
           !(file_handle->fileaccess & GENERIC_ALL)) {
-               DEBUG("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+               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) {
-               DEBUG("%s: handle %p unknown filename", __func__, handle);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p unknown filename", __func__, handle);
 
                SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
@@ -968,7 +970,7 @@ static gboolean file_setfiletime(gpointer handle,
         */
        ret=fstat (fd, &statbuf);
        if(ret==-1) {
-               DEBUG("%s: handle %p fstat failed: %s", __func__, handle,
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle,
                          strerror(errno));
 
                SetLastError (ERROR_INVALID_PARAMETER);
@@ -982,7 +984,7 @@ static gboolean file_setfiletime(gpointer handle,
                 * but this will do for now.
                 */
                if (access_ticks < 116444736000000000ULL) {
-                       DEBUG ("%s: attempt to set access time too early",
+                       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);
@@ -1000,7 +1002,7 @@ static gboolean file_setfiletime(gpointer handle,
                 * but this will do for now.
                 */
                if (write_ticks < 116444736000000000ULL) {
-                       DEBUG ("%s: attempt to set write time too early",
+                       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);
@@ -1011,12 +1013,12 @@ static gboolean file_setfiletime(gpointer handle,
                utbuf.modtime=statbuf.st_mtime;
        }
 
-       DEBUG ("%s: setting handle %p access %ld write %ld", __func__,
+       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) {
-               DEBUG ("%s: handle %p [%s] utime failed: %s", __func__,
+               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);
@@ -1031,12 +1033,15 @@ static void console_close (gpointer handle, gpointer data)
        struct _WapiHandle_file *console_handle = (struct _WapiHandle_file *)data;
        int fd = console_handle->fd;
        
-       DEBUG("%s: closing console handle %p", __func__, handle);
+       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 (fd > 2) {
+               if (console_handle->share_info)
+                       _wapi_handle_share_release (console_handle->share_info);
                close (fd);
+       }
 }
 
 static WapiFileType console_getfiletype(void)
@@ -1068,7 +1073,7 @@ static gboolean console_read(gpointer handle, gpointer buffer,
        
        if(!(console_handle->fileaccess & GENERIC_READ) &&
           !(console_handle->fileaccess & GENERIC_ALL)) {
-               DEBUG ("%s: handle %p doesn't have GENERIC_READ access: %u",
+               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);
@@ -1080,7 +1085,7 @@ static gboolean console_read(gpointer handle, gpointer buffer,
        } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
 
        if(ret==-1) {
-               DEBUG("%s: read of handle %p error: %s", __func__, handle,
+               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 ();
@@ -1118,7 +1123,7 @@ static gboolean console_write(gpointer handle, gconstpointer buffer,
        
        if(!(console_handle->fileaccess & GENERIC_WRITE) &&
           !(console_handle->fileaccess & GENERIC_ALL)) {
-               DEBUG("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, console_handle->fileaccess);
+               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);
@@ -1135,7 +1140,7 @@ static gboolean console_write(gpointer handle, gconstpointer buffer,
                } else {
                        _wapi_set_last_error_from_errno ();
                        
-                       DEBUG ("%s: write of handle %p error: %s",
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s",
                                   __func__, handle, strerror(errno));
 
                        return(FALSE);
@@ -1153,10 +1158,13 @@ static void pipe_close (gpointer handle, gpointer data)
        struct _WapiHandle_file *pipe_handle = (struct _WapiHandle_file*)data;
        int fd = pipe_handle->fd;
 
-       DEBUG("%s: closing pipe handle %p", __func__, handle);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing pipe handle %p", __func__, handle);
 
        /* No filename with pipe handles */
 
+       if (pipe_handle->share_info)
+               _wapi_handle_share_release (pipe_handle->share_info);
+
        close (fd);
 }
 
@@ -1189,14 +1197,14 @@ static gboolean pipe_read (gpointer handle, gpointer buffer,
        
        if(!(pipe_handle->fileaccess & GENERIC_READ) &&
           !(pipe_handle->fileaccess & GENERIC_ALL)) {
-               DEBUG("%s: handle %p doesn't have GENERIC_READ access: %u",
+               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);
        }
        
-       DEBUG ("%s: reading up to %d bytes from pipe %p", __func__,
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: reading up to %d bytes from pipe %p", __func__,
                   numbytes, handle);
 
        do {
@@ -1209,14 +1217,14 @@ static gboolean pipe_read (gpointer handle, gpointer buffer,
                } else {
                        _wapi_set_last_error_from_errno ();
                        
-                       DEBUG("%s: read of handle %p error: %s", __func__,
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__,
                                  handle, strerror(errno));
 
                        return(FALSE);
                }
        }
        
-       DEBUG ("%s: read %d bytes from pipe", __func__, ret);
+       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;
@@ -1249,13 +1257,13 @@ static gboolean pipe_write(gpointer handle, gconstpointer buffer,
        
        if(!(pipe_handle->fileaccess & GENERIC_WRITE) &&
           !(pipe_handle->fileaccess & GENERIC_ALL)) {
-               DEBUG("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, pipe_handle->fileaccess);
+               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);
        }
        
-       DEBUG ("%s: writing up to %d bytes to pipe %p", __func__, numbytes,
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: writing up to %d bytes to pipe %p", __func__, numbytes,
                   handle);
 
        do {
@@ -1269,7 +1277,7 @@ static gboolean pipe_write(gpointer handle, gconstpointer buffer,
                } else {
                        _wapi_set_last_error_from_errno ();
                        
-                       DEBUG("%s: write of handle %p error: %s", __func__,
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s", __func__,
                                  handle, strerror(errno));
 
                        return(FALSE);
@@ -1297,7 +1305,7 @@ static int convert_flags(guint32 fileaccess, guint32 createmode)
                flags=O_RDWR;
                break;
        default:
-               DEBUG("%s: Unknown access type 0x%x", __func__,
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown access type 0x%x", __func__,
                          fileaccess);
                break;
        }
@@ -1318,7 +1326,7 @@ static int convert_flags(guint32 fileaccess, guint32 createmode)
                flags|=O_TRUNC;
                break;
        default:
-               DEBUG("%s: Unknown create mode 0x%x", __func__,
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown create mode 0x%x", __func__,
                          createmode);
                break;
        }
@@ -1358,7 +1366,7 @@ static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode,
                 */
                if (file_existing_share == 0) {
                        /* Quick and easy, no possibility to share */
-                       DEBUG ("%s: Share mode prevents open: requested access: 0x%x, file has sharing = NONE", __func__, fileaccess);
+                       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);
                        
@@ -1370,7 +1378,7 @@ static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode,
                    ((file_existing_share == FILE_SHARE_WRITE) &&
                     (fileaccess != GENERIC_WRITE))) {
                        /* New access mode doesn't match up */
-                       DEBUG ("%s: Share mode prevents open: requested access: 0x%x, file has sharing: 0x%x", __func__, fileaccess, file_existing_share);
+                       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);
                
@@ -1382,14 +1390,14 @@ static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode,
                    ((file_existing_access & GENERIC_WRITE) &&
                     !(sharemode & FILE_SHARE_WRITE))) {
                        /* New share mode doesn't match up */
-                       DEBUG ("%s: Access mode prevents open: requested share: 0x%x, file has access: 0x%x", __func__, sharemode, file_existing_access);
+                       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 {
-               DEBUG ("%s: New file!", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: New file!", __func__);
        }
 
        return(TRUE);
@@ -1411,7 +1419,7 @@ share_allows_delete (struct stat *statbuf, struct _WapiFileShare **share_info)
                 */
                if (file_existing_share == 0) {
                        /* Quick and easy, no possibility to share */
-                       DEBUG ("%s: Share mode prevents open: requested access: 0x%x, file has sharing = NONE", __func__, fileaccess);
+                       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);
 
@@ -1420,14 +1428,14 @@ share_allows_delete (struct stat *statbuf, struct _WapiFileShare **share_info)
 
                if (!(file_existing_share & FILE_SHARE_DELETE)) {
                        /* New access mode doesn't match up */
-                       DEBUG ("%s: Share mode prevents open: requested access: 0x%x, file has sharing: 0x%x", __func__, fileaccess, file_existing_share);
+                       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 {
-               DEBUG ("%s: New file!", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: New file!", __func__);
        }
 
        return(TRUE);
@@ -1454,14 +1462,6 @@ static gboolean share_check (struct stat *statbuf, guint32 sharemode,
                               share_info) == TRUE) {
                return (TRUE);
        }
-       
-       /* Still violating.  It's possible that a process crashed
-        * while still holding a file handle, and that a non-mono
-        * process has the file open.  (For example, C-c mcs while
-        * editing a source file.)  As a last resort, run a handle
-        * collection, which will remove stale share entries.
-        */
-       _wapi_handle_collect ();
 
        return(share_allows_open (statbuf, sharemode, fileaccess, share_info));
 }
@@ -1522,7 +1522,7 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
        }
        
        if (name == NULL) {
-               DEBUG ("%s: name is NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
 
                SetLastError (ERROR_INVALID_NAME);
                return(INVALID_HANDLE_VALUE);
@@ -1530,13 +1530,13 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
 
        filename = mono_unicode_to_external (name);
        if (filename == NULL) {
-               DEBUG("%s: unicode conversion returned NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
 
                SetLastError (ERROR_INVALID_NAME);
                return(INVALID_HANDLE_VALUE);
        }
        
-       DEBUG ("%s: Opening %s with share 0x%x and access 0x%x", __func__,
+       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);
@@ -1556,7 +1556,7 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
        }
        
        if (fd == -1) {
-               DEBUG("%s: Error opening file %s: %s", __func__, filename,
+               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);
@@ -1565,7 +1565,7 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
        }
 
        if (fd >= _wapi_fd_reserve) {
-               DEBUG ("%s: File descriptor is too big", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
 
                SetLastError (ERROR_TOO_MANY_OPEN_FILES);
                
@@ -1577,7 +1577,7 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
 
        ret = fstat (fd, &statbuf);
        if (ret == -1) {
-               DEBUG ("%s: fstat error of file %s: %s", __func__,
+               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);
@@ -1603,7 +1603,7 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
        }
        if (file_handle.share_info == NULL) {
                /* No space, so no more files can be opened */
-               DEBUG ("%s: No space in the share table", __func__);
+               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);
@@ -1636,6 +1636,10 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
 #endif
        if (S_ISFIFO (statbuf.st_mode)) {
                handle_type = WAPI_HANDLE_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 = WAPI_HANDLE_CONSOLE;
        } else {
@@ -1652,7 +1656,7 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
                return(INVALID_HANDLE_VALUE);
        }
        
-       DEBUG("%s: returning handle %p", __func__, handle);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, handle);
        
        return(handle);
 }
@@ -1678,7 +1682,7 @@ gboolean DeleteFile(const gunichar2 *name)
 #endif
        
        if(name==NULL) {
-               DEBUG("%s: name is NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
 
                SetLastError (ERROR_INVALID_NAME);
                return(FALSE);
@@ -1686,7 +1690,7 @@ gboolean DeleteFile(const gunichar2 *name)
 
        filename=mono_unicode_to_external(name);
        if(filename==NULL) {
-               DEBUG("%s: unicode conversion returned NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
 
                SetLastError (ERROR_INVALID_NAME);
                return(FALSE);
@@ -1694,7 +1698,7 @@ gboolean DeleteFile(const gunichar2 *name)
 
        attrs = GetFileAttributes (name);
        if (attrs == INVALID_FILE_ATTRIBUTES) {
-               DEBUG ("%s: file attributes error", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file attributes error", __func__);
                /* Error set by GetFileAttributes() */
                g_free (filename);
                return(FALSE);
@@ -1759,7 +1763,7 @@ gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_name)
        struct _WapiFileShare *shareinfo;
        
        if(name==NULL) {
-               DEBUG("%s: name is NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
 
                SetLastError (ERROR_INVALID_NAME);
                return(FALSE);
@@ -1767,14 +1771,14 @@ gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_name)
 
        utf8_name = mono_unicode_to_external (name);
        if (utf8_name == NULL) {
-               DEBUG ("%s: unicode conversion returned NULL", __func__);
+               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) {
-               DEBUG("%s: name is NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
 
                g_free (utf8_name);
                SetLastError (ERROR_INVALID_NAME);
@@ -1783,7 +1787,7 @@ gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_name)
 
        utf8_dest_name = mono_unicode_to_external (dest_name);
        if (utf8_dest_name == NULL) {
-               DEBUG ("%s: unicode conversion returned NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
 
                g_free (utf8_name);
                SetLastError (ERROR_INVALID_NAME);
@@ -1904,7 +1908,7 @@ write_file (int src_fd, int dest_fd, struct stat *st_src, gboolean report_errors
 
                                if (report_errors)
                                        _wapi_set_last_error_from_errno ();
-                               DEBUG ("%s: write failed.", __func__);
+                               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write failed.", __func__);
                                free (buf);
                                return FALSE;
                        }
@@ -1941,7 +1945,7 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name,
        int ret_utime;
        
        if(name==NULL) {
-               DEBUG("%s: name is NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
 
                SetLastError (ERROR_INVALID_NAME);
                return(FALSE);
@@ -1949,7 +1953,7 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name,
        
        utf8_src = mono_unicode_to_external (name);
        if (utf8_src == NULL) {
-               DEBUG ("%s: unicode conversion of source returned NULL",
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion of source returned NULL",
                           __func__);
 
                SetLastError (ERROR_INVALID_PARAMETER);
@@ -1957,7 +1961,7 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name,
        }
        
        if(dest_name==NULL) {
-               DEBUG("%s: dest is NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: dest is NULL", __func__);
 
                g_free (utf8_src);
                SetLastError (ERROR_INVALID_NAME);
@@ -1966,7 +1970,7 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name,
        
        utf8_dest = mono_unicode_to_external (dest_name);
        if (utf8_dest == NULL) {
-               DEBUG ("%s: unicode conversion of dest returned NULL",
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion of dest returned NULL",
                           __func__);
 
                SetLastError (ERROR_INVALID_PARAMETER);
@@ -2047,7 +2051,7 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name,
        dest_time.actime = st.st_atime;
        ret_utime = utime (utf8_dest, &dest_time);
        if (ret_utime == -1)
-               DEBUG ("%s: file [%s] utime failed: %s", __func__, utf8_dest, strerror(errno));
+               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);
@@ -2061,14 +2065,14 @@ convert_arg_to_utf8 (const gunichar2 *arg, const gchar *arg_name)
        gchar *utf8_ret;
 
        if (arg == NULL) {
-               DEBUG ("%s: %s is NULL", __func__, arg_name);
+               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) {
-               DEBUG ("%s: unicode conversion of %s returned 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;
@@ -2171,7 +2175,7 @@ gpointer GetStdHandle(WapiStdHandle stdhandle)
                break;
 
        default:
-               DEBUG("%s: unknown standard handle type", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unknown standard handle type", __func__);
 
                SetLastError (ERROR_INVALID_PARAMETER);
                return(INVALID_HANDLE_VALUE);
@@ -2557,7 +2561,7 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
        const guint16 *ip;
        
        if(system_time==NULL) {
-               DEBUG("%s: system_time NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: system_time NULL", __func__);
 
                SetLastError (ERROR_INVALID_PARAMETER);
                return(FALSE);
@@ -2571,7 +2575,7 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
         * year and day calculation to work later
         */
        if(file_ticks<0) {
-               DEBUG("%s: file_time too big", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file_time too big", __func__);
 
                SetLastError (ERROR_INVALID_PARAMETER);
                return(FALSE);
@@ -2579,29 +2583,29 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
 
        totaldays=(file_ticks / TICKS_PER_DAY);
        rem = file_ticks % TICKS_PER_DAY;
-       DEBUG("%s: totaldays: %lld rem: %lld", __func__, totaldays, rem);
+       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;
-       DEBUG("%s: Hour: %d rem: %lld", __func__, system_time->wHour, rem);
+       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;
-       DEBUG("%s: Minute: %d rem: %lld", __func__, system_time->wMinute,
+       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;
-       DEBUG("%s: Second: %d rem: %lld", __func__, system_time->wSecond,
+       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;
-       DEBUG("%s: Milliseconds: %d", __func__,
+       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;
-       DEBUG("%s: Day of week: %d", __func__, system_time->wDayOfWeek);
+       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
@@ -2614,7 +2618,7 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
        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);
-               DEBUG("%s: totaldays: %lld yg: %lld y: %lld", __func__,
+               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__,
@@ -2624,13 +2628,13 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
                totaldays -= ((yg - y) * 365
                              + LEAPS_THRU_END_OF (yg - 1)
                              - LEAPS_THRU_END_OF (y - 1));
-               DEBUG("%s: totaldays: %lld", __func__, totaldays);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld", __func__, totaldays);
                y = yg;
-               DEBUG("%s: y: %lld", __func__, y);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: y: %lld", __func__, y);
        }
        
        system_time->wYear = y;
-       DEBUG("%s: Year: %d", __func__, system_time->wYear);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Year: %d", __func__, system_time->wYear);
 
        ip = mon_yday[isleap(y)];
        
@@ -2638,13 +2642,13 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
                continue;
        }
        totaldays-=ip[y];
-       DEBUG("%s: totaldays: %lld", __func__, totaldays);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld", __func__, totaldays);
        
        system_time->wMonth = y + 1;
-       DEBUG("%s: Month: %d", __func__, system_time->wMonth);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Month: %d", __func__, system_time->wMonth);
 
        system_time->wDay = totaldays + 1;
-       DEBUG("%s: Day: %d", __func__, system_time->wDay);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Day: %d", __func__, system_time->wDay);
        
        return(TRUE);
 }
@@ -2657,7 +2661,7 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
        int result;
        
        if (pattern == NULL) {
-               DEBUG ("%s: pattern is NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: pattern is NULL", __func__);
 
                SetLastError (ERROR_PATH_NOT_FOUND);
                return(INVALID_HANDLE_VALUE);
@@ -2665,13 +2669,13 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
 
        utf8_pattern = mono_unicode_to_external (pattern);
        if (utf8_pattern == NULL) {
-               DEBUG ("%s: unicode conversion returned NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
                
                SetLastError (ERROR_INVALID_NAME);
                return(INVALID_HANDLE_VALUE);
        }
 
-       DEBUG ("%s: looking for [%s]", __func__, utf8_pattern);
+       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);
@@ -2727,12 +2731,8 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
        }
        
        if (result < 0) {
-#ifdef DEBUG_ENABLED
-               gint errnum = errno;
-#endif
                _wapi_set_last_path_error_from_errno (dir_part, NULL);
-               DEBUG ("%s: scandir error: %s", __func__,
-                          g_strerror (errnum));
+               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);
@@ -2742,7 +2742,7 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
        g_free (utf8_pattern);
        g_free (entry_part);
        
-       DEBUG ("%s: Got %d matches", __func__, result);
+       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;
@@ -2812,7 +2812,7 @@ retry:
        }
        
        if (result != 0) {
-               DEBUG ("%s: stat failed: %s", __func__, filename);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: stat failed: %s", __func__, filename);
 
                g_free (filename);
                goto retry;
@@ -2821,7 +2821,7 @@ retry:
 #ifndef __native_client__
        result = _wapi_lstat (filename, &linkbuf);
        if (result != 0) {
-               DEBUG ("%s: lstat failed: %s", __func__, filename);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lstat failed: %s", __func__, filename);
 
                g_free (filename);
                goto retry;
@@ -2841,7 +2841,7 @@ retry:
        }
        g_free (filename);
        
-       DEBUG ("%s: Found [%s]", __func__, utf8_filename);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Found [%s]", __func__, utf8_filename);
        
        /* fill data block */
 
@@ -2964,7 +2964,7 @@ gboolean CreateDirectory (const gunichar2 *name,
        int result;
        
        if (name == NULL) {
-               DEBUG("%s: name is NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
 
                SetLastError (ERROR_INVALID_NAME);
                return(FALSE);
@@ -2972,7 +2972,7 @@ gboolean CreateDirectory (const gunichar2 *name,
        
        utf8_name = mono_unicode_to_external (name);
        if (utf8_name == NULL) {
-               DEBUG ("%s: unicode conversion returned NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
        
                SetLastError (ERROR_INVALID_NAME);
                return FALSE;
@@ -3005,7 +3005,7 @@ gboolean RemoveDirectory (const gunichar2 *name)
        int result;
        
        if (name == NULL) {
-               DEBUG("%s: name is NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
 
                SetLastError (ERROR_INVALID_NAME);
                return(FALSE);
@@ -3013,7 +3013,7 @@ gboolean RemoveDirectory (const gunichar2 *name)
 
        utf8_name = mono_unicode_to_external (name);
        if (utf8_name == NULL) {
-               DEBUG ("%s: unicode conversion returned NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
                
                SetLastError (ERROR_INVALID_NAME);
                return FALSE;
@@ -3047,7 +3047,7 @@ guint32 GetFileAttributes (const gunichar2 *name)
        guint32 ret;
        
        if (name == NULL) {
-               DEBUG("%s: name is NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
 
                SetLastError (ERROR_INVALID_NAME);
                return(FALSE);
@@ -3055,7 +3055,7 @@ guint32 GetFileAttributes (const gunichar2 *name)
        
        utf8_name = mono_unicode_to_external (name);
        if (utf8_name == NULL) {
-               DEBUG ("%s: unicode conversion returned NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
 
                SetLastError (ERROR_INVALID_PARAMETER);
                return (INVALID_FILE_ATTRIBUTES);
@@ -3113,7 +3113,7 @@ gboolean GetFileAttributesEx (const gunichar2 *name, WapiGetFileExInfoLevels lev
        int result;
        
        if (level != GetFileExInfoStandard) {
-               DEBUG ("%s: info level %d not supported.", __func__,
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: info level %d not supported.", __func__,
                           level);
 
                SetLastError (ERROR_INVALID_PARAMETER);
@@ -3121,7 +3121,7 @@ gboolean GetFileAttributesEx (const gunichar2 *name, WapiGetFileExInfoLevels lev
        }
        
        if (name == NULL) {
-               DEBUG("%s: name is NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
 
                SetLastError (ERROR_INVALID_NAME);
                return(FALSE);
@@ -3129,7 +3129,7 @@ gboolean GetFileAttributesEx (const gunichar2 *name, WapiGetFileExInfoLevels lev
 
        utf8_name = mono_unicode_to_external (name);
        if (utf8_name == NULL) {
-               DEBUG ("%s: unicode conversion returned NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
 
                SetLastError (ERROR_INVALID_PARAMETER);
                return FALSE;
@@ -3207,7 +3207,7 @@ extern gboolean SetFileAttributes (const gunichar2 *name, guint32 attrs)
         */
        
        if (name == NULL) {
-               DEBUG("%s: name is NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
 
                SetLastError (ERROR_INVALID_NAME);
                return(FALSE);
@@ -3215,7 +3215,7 @@ extern gboolean SetFileAttributes (const gunichar2 *name, guint32 attrs)
 
        utf8_name = mono_unicode_to_external (name);
        if (utf8_name == NULL) {
-               DEBUG ("%s: unicode conversion returned NULL", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
 
                SetLastError (ERROR_INVALID_NAME);
                return FALSE;
@@ -3359,11 +3359,11 @@ gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe,
        
        mono_once (&io_ops_once, io_ops_init);
        
-       DEBUG ("%s: Creating pipe", __func__);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating pipe", __func__);
 
        ret=pipe (filedes);
        if(ret==-1) {
-               DEBUG ("%s: Error creating pipe: %s", __func__,
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error creating pipe: %s", __func__,
                           strerror (errno));
                
                _wapi_set_last_error_from_errno ();
@@ -3372,7 +3372,7 @@ gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe,
 
        if (filedes[0] >= _wapi_fd_reserve ||
            filedes[1] >= _wapi_fd_reserve) {
-               DEBUG ("%s: File descriptor is too big", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
 
                SetLastError (ERROR_TOO_MANY_OPEN_FILES);
                
@@ -3415,7 +3415,7 @@ gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe,
        *readpipe = read_handle;
        *writepipe = write_handle;
 
-       DEBUG ("%s: Returning pipe: read handle %p, write handle %p",
+       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);
@@ -3733,9 +3733,14 @@ add_drive_string (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state)
 
        if (state->fsname_index == 1 && state->fsname [0] == '/')
                ignore_entry = FALSE;
-       else if (state->fsname_index == 0 || memcmp ("none", state->fsname, state->fsname_index) == 0)
+       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) {
+       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;
@@ -3887,7 +3892,7 @@ gboolean GetDiskFreeSpaceEx(const gunichar2 *path_name, WapiULargeInteger *free_
        else {
                utf8_path_name = mono_unicode_to_external (path_name);
                if (utf8_path_name == NULL) {
-                       DEBUG("%s: unicode conversion returned NULL", __func__);
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
 
                        SetLastError (ERROR_INVALID_NAME);
                        return(FALSE);
@@ -3914,7 +3919,7 @@ gboolean GetDiskFreeSpaceEx(const gunichar2 *path_name, WapiULargeInteger *free_
 
        if (ret == -1) {
                _wapi_set_last_error_from_errno ();
-               DEBUG ("%s: statvfs failed: %s", __func__, strerror (errno));
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: statvfs failed: %s", __func__, strerror (errno));
                return(FALSE);
        }
 
@@ -4207,7 +4212,7 @@ guint32 GetDriveType(const gunichar2 *root_path_name)
        else {
                utf8_root_path_name = mono_unicode_to_external (root_path_name);
                if (utf8_root_path_name == NULL) {
-                       DEBUG("%s: unicode conversion returned NULL", __func__);
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
                        return(DRIVE_NO_ROOT_DIR);
                }