X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fw32file-unix.c;h=a3ac2264f6da7addaebd76807e466a43745ce499;hb=537a24f852eed5bb612e5713497970d5836962fc;hp=be8b5f70502c4777e5e428c943e711ad8856c64d;hpb=3b2913ca03f284906f55606c9b36540890b7572a;p=mono.git diff --git a/mono/metadata/w32file-unix.c b/mono/metadata/w32file-unix.c index be8b5f70502..a3ac2264f6d 100644 --- a/mono/metadata/w32file-unix.c +++ b/mono/metadata/w32file-unix.c @@ -1,3 +1,6 @@ +/** + * \file + */ #include #include @@ -37,6 +40,7 @@ #include "w32file-unix-glob.h" #include "w32handle.h" #include "w32error.h" +#include "fdhandle.h" #include "utils/mono-io-portability.h" #include "utils/mono-logger-internals.h" #include "utils/mono-os-mutex.h" @@ -56,14 +60,14 @@ typedef struct { /* Currently used for both FILE, CONSOLE and PIPE handle types. * This may have to change in future. */ typedef struct { + MonoFDHandle fdhandle; gchar *filename; FileShare *share_info; /* Pointer into shared mem */ - gint fd; guint32 security_attributes; guint32 fileaccess; guint32 sharemode; guint32 attrs; -} MonoW32HandleFile; +} FileHandle; typedef struct { gchar **namelist; @@ -78,7 +82,7 @@ typedef struct { * 4MB array. */ static GHashTable *file_share_table; -static mono_mutex_t file_share_mutex; +static MonoCoopMutex file_share_mutex; static void time_t_to_filetime (time_t timeval, FILETIME *filetime) @@ -90,19 +94,78 @@ time_t_to_filetime (time_t timeval, FILETIME *filetime) filetime->dwHighDateTime = ticks >> 32; } +static FileHandle* +file_data_create (MonoFDType type, gint fd) +{ + FileHandle *filehandle; + + filehandle = g_new0 (FileHandle, 1); + mono_fdhandle_init ((MonoFDHandle*) filehandle, type, fd); + + return filehandle; +} + +static gint +_wapi_unlink (const gchar *pathname); + +static void +file_share_release (FileShare *share_info); + +static void +file_data_close (MonoFDHandle *fdhandle) +{ + FileHandle* filehandle; + + filehandle = (FileHandle*) fdhandle; + g_assert (filehandle); + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing fd %d", __func__, ((MonoFDHandle*) filehandle)->fd); + + if (((MonoFDHandle*) filehandle)->type == MONO_FDTYPE_FILE && (filehandle->attrs & FILE_FLAG_DELETE_ON_CLOSE)) { + _wapi_unlink (filehandle->filename); + } + + if (((MonoFDHandle*) filehandle)->type != MONO_FDTYPE_CONSOLE || ((MonoFDHandle*) filehandle)->fd > 2) { + if (filehandle->share_info) { + file_share_release (filehandle->share_info); + filehandle->share_info = NULL; + } + + MONO_ENTER_GC_SAFE; + close (((MonoFDHandle*) filehandle)->fd); + MONO_EXIT_GC_SAFE; + } +} + +static void +file_data_destroy (MonoFDHandle *fdhandle) +{ + FileHandle *filehandle; + + filehandle = (FileHandle*) fdhandle; + g_assert (filehandle); + + if (filehandle->filename) + g_free (filehandle->filename); + + g_free (filehandle); +} + static void file_share_release (FileShare *share_info) { /* Prevent new entries racing with us */ - mono_os_mutex_lock (&file_share_mutex); + mono_coop_mutex_lock (&file_share_mutex); g_assert (share_info->handle_refs > 0); share_info->handle_refs -= 1; - if (share_info->handle_refs == 0) + if (share_info->handle_refs == 0) { g_hash_table_remove (file_share_table, share_info); + // g_free (share_info); + } - mono_os_mutex_unlock (&file_share_mutex); + mono_coop_mutex_unlock (&file_share_mutex); } static gint @@ -130,7 +193,7 @@ file_share_get (guint64 device, guint64 inode, guint32 new_sharemode, guint32 ne gboolean exists = FALSE; /* Prevent new entries racing with us */ - mono_os_mutex_lock (&file_share_mutex); + mono_coop_mutex_lock (&file_share_mutex); FileShare tmp; @@ -168,7 +231,7 @@ file_share_get (guint64 device, guint64 inode, guint32 new_sharemode, guint32 ne g_hash_table_insert (file_share_table, file_share, file_share); } - mono_os_mutex_unlock (&file_share_mutex); + mono_coop_mutex_unlock (&file_share_mutex); return(exists); } @@ -182,13 +245,19 @@ _wapi_open (const gchar *pathname, gint flags, mode_t mode) if (flags & O_CREAT) { located_filename = mono_portability_find_file (pathname, FALSE); if (located_filename == NULL) { + MONO_ENTER_GC_SAFE; fd = open (pathname, flags, mode); + MONO_EXIT_GC_SAFE; } else { + MONO_ENTER_GC_SAFE; fd = open (located_filename, flags, mode); + MONO_EXIT_GC_SAFE; g_free (located_filename); } } else { + MONO_ENTER_GC_SAFE; fd = open (pathname, flags, mode); + MONO_EXIT_GC_SAFE; if (fd == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) { gint saved_errno = errno; located_filename = mono_portability_find_file (pathname, TRUE); @@ -198,7 +267,9 @@ _wapi_open (const gchar *pathname, gint flags, mode_t mode) return -1; } + MONO_ENTER_GC_SAFE; fd = open (located_filename, flags, mode); + MONO_EXIT_GC_SAFE; g_free (located_filename); } } @@ -211,7 +282,9 @@ _wapi_access (const gchar *pathname, gint mode) { gint ret; + MONO_ENTER_GC_SAFE; ret = access (pathname, mode); + MONO_EXIT_GC_SAFE; if (ret == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) { gint saved_errno = errno; gchar *located_filename = mono_portability_find_file (pathname, TRUE); @@ -221,7 +294,9 @@ _wapi_access (const gchar *pathname, gint mode) return -1; } + MONO_ENTER_GC_SAFE; ret = access (located_filename, mode); + MONO_EXIT_GC_SAFE; g_free (located_filename); } @@ -233,7 +308,9 @@ _wapi_chmod (const gchar *pathname, mode_t mode) { gint ret; + MONO_ENTER_GC_SAFE; ret = chmod (pathname, mode); + MONO_EXIT_GC_SAFE; if (ret == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) { gint saved_errno = errno; gchar *located_filename = mono_portability_find_file (pathname, TRUE); @@ -243,7 +320,9 @@ _wapi_chmod (const gchar *pathname, mode_t mode) return -1; } + MONO_ENTER_GC_SAFE; ret = chmod (located_filename, mode); + MONO_EXIT_GC_SAFE; g_free (located_filename); } @@ -255,7 +334,9 @@ _wapi_utime (const gchar *filename, const struct utimbuf *buf) { gint ret; + MONO_ENTER_GC_SAFE; ret = utime (filename, buf); + MONO_EXIT_GC_SAFE; if (ret == -1 && errno == ENOENT && IS_PORTABILITY_SET) { gint saved_errno = errno; gchar *located_filename = mono_portability_find_file (filename, TRUE); @@ -265,7 +346,9 @@ _wapi_utime (const gchar *filename, const struct utimbuf *buf) return -1; } + MONO_ENTER_GC_SAFE; ret = utime (located_filename, buf); + MONO_EXIT_GC_SAFE; g_free (located_filename); } @@ -277,7 +360,9 @@ _wapi_unlink (const gchar *pathname) { gint ret; + MONO_ENTER_GC_SAFE; ret = unlink (pathname); + MONO_EXIT_GC_SAFE; 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); @@ -287,7 +372,9 @@ _wapi_unlink (const gchar *pathname) return -1; } + MONO_ENTER_GC_SAFE; ret = unlink (located_filename); + MONO_EXIT_GC_SAFE; g_free (located_filename); } @@ -301,9 +388,13 @@ _wapi_rename (const gchar *oldpath, const gchar *newpath) gchar *located_newpath = mono_portability_find_file (newpath, FALSE); if (located_newpath == NULL) { + MONO_ENTER_GC_SAFE; ret = rename (oldpath, newpath); + MONO_EXIT_GC_SAFE; } else { + MONO_ENTER_GC_SAFE; ret = rename (oldpath, located_newpath); + MONO_EXIT_GC_SAFE; if (ret == -1 && (errno == EISDIR || errno == ENAMETOOLONG || errno == ENOENT || errno == ENOTDIR || errno == EXDEV) && IS_PORTABILITY_SET) { gint saved_errno = errno; @@ -317,7 +408,9 @@ _wapi_rename (const gchar *oldpath, const gchar *newpath) return -1; } + MONO_ENTER_GC_SAFE; ret = rename (located_oldpath, located_newpath); + MONO_EXIT_GC_SAFE; g_free (located_oldpath); } g_free (located_newpath); @@ -331,7 +424,9 @@ _wapi_stat (const gchar *path, struct stat *buf) { gint ret; + MONO_ENTER_GC_SAFE; ret = stat (path, buf); + MONO_EXIT_GC_SAFE; if (ret == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) { gint saved_errno = errno; gchar *located_filename = mono_portability_find_file (path, TRUE); @@ -341,7 +436,9 @@ _wapi_stat (const gchar *path, struct stat *buf) return -1; } + MONO_ENTER_GC_SAFE; ret = stat (located_filename, buf); + MONO_EXIT_GC_SAFE; g_free (located_filename); } @@ -353,7 +450,9 @@ _wapi_lstat (const gchar *path, struct stat *buf) { gint ret; + MONO_ENTER_GC_SAFE; ret = lstat (path, buf); + MONO_EXIT_GC_SAFE; if (ret == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) { gint saved_errno = errno; gchar *located_filename = mono_portability_find_file (path, TRUE); @@ -377,9 +476,13 @@ _wapi_mkdir (const gchar *pathname, mode_t mode) gchar *located_filename = mono_portability_find_file (pathname, FALSE); if (located_filename == NULL) { + MONO_ENTER_GC_SAFE; ret = mkdir (pathname, mode); + MONO_EXIT_GC_SAFE; } else { + MONO_ENTER_GC_SAFE; ret = mkdir (located_filename, mode); + MONO_EXIT_GC_SAFE; g_free (located_filename); } @@ -391,7 +494,9 @@ _wapi_rmdir (const gchar *pathname) { gint ret; + MONO_ENTER_GC_SAFE; ret = rmdir (pathname); + MONO_EXIT_GC_SAFE; 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); @@ -401,7 +506,9 @@ _wapi_rmdir (const gchar *pathname) return -1; } + MONO_ENTER_GC_SAFE; ret = rmdir (located_filename); + MONO_EXIT_GC_SAFE; g_free (located_filename); } @@ -413,7 +520,9 @@ _wapi_chdir (const gchar *path) { gint ret; + MONO_ENTER_GC_SAFE; ret = chdir (path); + MONO_EXIT_GC_SAFE; 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); @@ -423,7 +532,9 @@ _wapi_chdir (const gchar *path) return -1; } + MONO_ENTER_GC_SAFE; ret = chdir (located_filename); + MONO_EXIT_GC_SAFE; g_free (located_filename); } @@ -479,7 +590,9 @@ _wapi_g_dir_open (const gchar *path, guint flags, GError **error) { GDir *ret; + MONO_ENTER_GC_SAFE; ret = g_dir_open (path, flags, error); + MONO_EXIT_GC_SAFE; 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; @@ -488,7 +601,9 @@ _wapi_g_dir_open (const gchar *path, guint flags, GError **error) return(NULL); } + MONO_ENTER_GC_SAFE; ret = g_dir_open (located_filename, flags, &tmp_error); + MONO_EXIT_GC_SAFE; g_free (located_filename); if (tmp_error == NULL) { g_clear_error (error); @@ -502,7 +617,7 @@ static gint get_errno_from_g_file_error (gint error) { switch (error) { -#ifdef EACCESS +#ifdef EACCES case G_FILE_ERROR_ACCES: return EACCES; #endif #ifdef ENAMETOOLONG @@ -559,7 +674,7 @@ get_errno_from_g_file_error (gint error) #ifdef EINTR case G_FILE_ERROR_INTR: return EINTR; #endif -#ifdef EWIO +#ifdef EIO case G_FILE_ERROR_IO: return EIO; #endif #ifdef EPERM @@ -622,7 +737,9 @@ _wapi_io_scandir (const gchar *dirname, const gchar *pattern, gchar ***namelist) gchar *pattern2 = g_strndup (pattern, strlen (pattern) - 2); gint result2; + MONO_ENTER_GC_SAFE; g_dir_rewind (dir); + MONO_EXIT_GC_SAFE; result2 = mono_w32file_unix_glob (dir, pattern2, flags | W32FILE_UNIX_GLOB_APPEND | W32FILE_UNIX_GLOB_UNIQUE, &glob_buf); g_free (pattern2); @@ -632,7 +749,9 @@ _wapi_io_scandir (const gchar *dirname, const gchar *pattern, gchar ***namelist) } } + MONO_ENTER_GC_SAFE; g_dir_close (dir); + MONO_EXIT_GC_SAFE; if (glob_buf.gl_pathc == 0) { return(0); } else if (result != 0) { @@ -662,11 +781,6 @@ _wapi_io_scandir (const gchar *dirname, const gchar *pattern, gchar ***namelist) 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; @@ -707,16 +821,11 @@ _wapi_lock_file_region (gint fd, off_t offset, off_t length) } 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; @@ -752,68 +861,17 @@ _wapi_unlock_file_region (gint fd, off_t offset, off_t length) } 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) +{ + return "Find"; +} -static const gchar* find_typename (void); -static gsize find_typesize (void); +static gsize find_typesize (void) +{ + return sizeof (MonoW32HandleFind); +} static MonoW32HandleOps _wapi_find_ops = { NULL, /* close */ @@ -827,85 +885,6 @@ static MonoW32HandleOps _wapi_find_ops = { 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. @@ -1039,98 +1018,34 @@ static void _wapi_set_last_path_error_from_errno (const gchar *dir, } } -/* 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) +file_read(FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *bytesread) { - MonoW32HandleFile *file_handle; - gboolean ok; - gint fd, ret; + gint 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); - mono_w32error_set_last (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); + if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); } do { - ret = read (fd, buffer, numbytes); + MONO_ENTER_GC_SAFE; + ret = read (((MonoFDHandle*) filehandle)->fd, buffer, numbytes); + MONO_EXIT_GC_SAFE; } 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)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(err)); mono_w32error_set_last (mono_w32error_unix_to_win32 (err)); return(FALSE); } @@ -1143,32 +1058,18 @@ file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread } static gboolean -file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten) +file_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten) { - MonoW32HandleFile *file_handle; - gboolean ok; - gint ret, fd; + gint ret; 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); - mono_w32error_set_last (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); + if(!(filehandle->fileaccess & GENERIC_WRITE) && !(filehandle->fileaccess & GENERIC_ALL)) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); @@ -1179,28 +1080,30 @@ file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byt * because we only do advisory locking on POSIX * systems */ - current_pos = lseek (fd, (off_t)0, SEEK_CUR); + MONO_ENTER_GC_SAFE; + current_pos = lseek (((MonoFDHandle*) filehandle)->fd, (off_t)0, SEEK_CUR); + MONO_EXIT_GC_SAFE; if (current_pos == -1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p lseek failed: %s", __func__, - handle, strerror (errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d lseek failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror (errno)); _wapi_set_last_error_from_errno (); return(FALSE); } - if (_wapi_lock_file_region (fd, current_pos, - numbytes) == FALSE) { + if (_wapi_lock_file_region (((MonoFDHandle*) filehandle)->fd, current_pos, numbytes) == FALSE) { /* The error has already been set */ return(FALSE); } } do { - ret = write (fd, buffer, numbytes); + MONO_ENTER_GC_SAFE; + ret = write (((MonoFDHandle*) filehandle)->fd, buffer, numbytes); + MONO_EXIT_GC_SAFE; } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (lock_while_writing) { - _wapi_unlock_file_region (fd, current_pos, numbytes); + _wapi_unlock_file_region (((MonoFDHandle*) filehandle)->fd, current_pos, numbytes); } if (ret == -1) { @@ -1209,8 +1112,7 @@ file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byt } 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)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); return(FALSE); } @@ -1221,35 +1123,22 @@ file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byt return(TRUE); } -static gboolean file_flush(gpointer handle) +static gboolean file_flush(FileHandle *filehandle) { - 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); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); - } - - fd = file_handle->fd; + gint ret; - 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); + if(!(filehandle->fileaccess & (GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); } - ret=fsync(fd); + MONO_ENTER_GC_SAFE; + ret=fsync(((MonoFDHandle*) filehandle)->fd); + MONO_EXIT_GC_SAFE; if (ret==-1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fsync of handle %p error: %s", __func__, handle, - strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fsync of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(FALSE); @@ -1258,30 +1147,15 @@ static gboolean file_flush(gpointer handle) return(TRUE); } -static guint32 file_seek(gpointer handle, gint32 movedistance, +static guint32 file_seek(FileHandle *filehandle, gint32 movedistance, gint32 *highmovedistance, gint method) { - MonoW32HandleFile *file_handle; - gboolean ok; gint64 offset, newpos; - gint whence, fd; + gint whence; 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); - mono_w32error_set_last (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); + if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(INVALID_SET_FILE_POINTER); @@ -1307,35 +1181,38 @@ static guint32 file_seek(gpointer handle, gint32 movedistance, #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__, + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting offset to %" G_GINT64_FORMAT " (low %" G_GINT32_FORMAT ")", __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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting offset to %" G_GINT64_FORMAT " 0x%" PRIx64 " (high %" G_GINT32_FORMAT " 0x%" PRIx32 ", low %" G_GINT32_FORMAT " 0x%" PRIx32 ")", + __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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: moving fd %d by %" G_GINT64_FORMAT " bytes from %d", __func__, ((MonoFDHandle*) filehandle)->fd, offset, whence); #ifdef PLATFORM_ANDROID /* bionic doesn't support -D_FILE_OFFSET_BITS=64 */ - newpos=lseek64(fd, offset, whence); + MONO_ENTER_GC_SAFE; + newpos=lseek64(((MonoFDHandle*) filehandle)->fd, offset, whence); + MONO_EXIT_GC_SAFE; #else - newpos=lseek(fd, offset, whence); + MONO_ENTER_GC_SAFE; + newpos=lseek(((MonoFDHandle*) filehandle)->fd, offset, whence); + MONO_EXIT_GC_SAFE; #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)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek on fd %d returned error %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek returns %" G_GINT64_FORMAT, __func__, newpos); #ifdef HAVE_LARGE_FILE_SUPPORT ret=newpos & 0xFFFFFFFF; @@ -1350,34 +1227,20 @@ static guint32 file_seek(gpointer handle, gint32 movedistance, } #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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: move of fd %d returning %" G_GUINT32_FORMAT "/%" G_GINT32_FORMAT, __func__, ((MonoFDHandle*) filehandle)->fd, ret, highmovedistance==NULL?0:*highmovedistance); return(ret); } -static gboolean file_setendoffile(gpointer handle) +static gboolean file_setendoffile(FileHandle *filehandle) { - MonoW32HandleFile *file_handle; - gboolean ok; struct stat statbuf; off_t pos; - gint ret, fd; + gint 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); - mono_w32error_set_last (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); + if(!(filehandle->fileaccess & (GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); @@ -1389,19 +1252,21 @@ static gboolean file_setendoffile(gpointer handle) * than the length, truncate the file. */ - ret=fstat(fd, &statbuf); + MONO_ENTER_GC_SAFE; + ret=fstat(((MonoFDHandle*) filehandle)->fd, &statbuf); + MONO_EXIT_GC_SAFE; if(ret==-1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, - handle, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d fstat failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(FALSE); } - pos=lseek(fd, (off_t)0, SEEK_CUR); + MONO_ENTER_GC_SAFE; + pos=lseek(((MonoFDHandle*) filehandle)->fd, (off_t)0, SEEK_CUR); + MONO_EXIT_GC_SAFE; if(pos==-1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p lseek failed: %s", __func__, - handle, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d lseek failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(FALSE); @@ -1422,22 +1287,25 @@ static gboolean file_setendoffile(gpointer handle) * drop this write. */ do { - ret = write (fd, "", 1); + MONO_ENTER_GC_SAFE; + ret = write (((MonoFDHandle*) filehandle)->fd, "", 1); + MONO_EXIT_GC_SAFE; } 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)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d extend write failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_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); + MONO_ENTER_GC_SAFE; + ret = lseek (((MonoFDHandle*) filehandle)->fd, pos, SEEK_SET); + MONO_EXIT_GC_SAFE; if (ret == -1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p second lseek failed: %s", - __func__, handle, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d second lseek failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(FALSE); @@ -1445,50 +1313,33 @@ static gboolean file_setendoffile(gpointer handle) } #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); + MONO_ENTER_GC_SAFE; + ret=ftruncate(((MonoFDHandle*) filehandle)->fd, pos); + MONO_EXIT_GC_SAFE; } 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)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d ftruncate failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(FALSE); } -#endif return(TRUE); } -static guint32 file_getfilesize(gpointer handle, guint32 *highsize) +static guint32 file_getfilesize(FileHandle *filehandle, 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); - mono_w32error_set_last (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); + if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(INVALID_FILE_SIZE); @@ -1500,10 +1351,11 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize) */ mono_w32error_set_last (ERROR_SUCCESS); - ret = fstat(fd, &statbuf); + MONO_ENTER_GC_SAFE; + ret = fstat(((MonoFDHandle*) filehandle)->fd, &statbuf); + MONO_EXIT_GC_SAFE; if (ret == -1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, - handle, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d fstat failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(INVALID_FILE_SIZE); @@ -1513,9 +1365,12 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize) #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)); + gint res; + MONO_ENTER_GC_SAFE; + res = ioctl (((MonoFDHandle*) filehandle)->fd, BLKGETSIZE64, &bigsize); + MONO_EXIT_GC_SAFE; + if (res < 0) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d ioctl BLKGETSIZE64 failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(INVALID_FILE_SIZE); @@ -1526,7 +1381,7 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize) *highsize = bigsize>>32; } - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning block device size %d/%d", + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning block device size %" G_GUINT32_FORMAT "/%" G_GUINT32_FORMAT, __func__, size, *highsize); return(size); @@ -1546,44 +1401,31 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize) size = statbuf.st_size; #endif - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning size %d/%d", __func__, size, *highsize); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning size %" G_GUINT32_FORMAT "/%" G_GUINT32_FORMAT, __func__, size, *highsize); return(size); } -static gboolean file_getfiletime(gpointer handle, FILETIME *create_time, +static gboolean file_getfiletime(FileHandle *filehandle, 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); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); - } - fd = file_handle->fd; + gint ret; - 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); + if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); } - ret=fstat(fd, &statbuf); + MONO_ENTER_GC_SAFE; + ret=fstat(((MonoFDHandle*) filehandle)->fd, &statbuf); + MONO_EXIT_GC_SAFE; if(ret==-1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle, - strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d fstat failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(FALSE); @@ -1610,7 +1452,7 @@ static gboolean file_getfiletime(gpointer handle, FILETIME *create_time, 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__, + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: aticks: %" G_GUINT64_FORMAT " cticks: %" G_GUINT64_FORMAT " wticks: %" G_GUINT64_FORMAT, __func__, access_ticks, create_ticks, write_ticks); if(create_time!=NULL) { @@ -1631,38 +1473,26 @@ static gboolean file_getfiletime(gpointer handle, FILETIME *create_time, return(TRUE); } -static gboolean file_setfiletime(gpointer handle, +static gboolean file_setfiletime(FileHandle *filehandle, 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; + gint 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); - mono_w32error_set_last (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); + if(!(filehandle->fileaccess & (GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (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); + if(filehandle->filename == NULL) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d unknown filename", __func__, ((MonoFDHandle*) filehandle)->fd); mono_w32error_set_last (ERROR_INVALID_HANDLE); return(FALSE); @@ -1671,10 +1501,11 @@ static gboolean file_setfiletime(gpointer handle, /* 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); + MONO_ENTER_GC_SAFE; + ret=fstat (((MonoFDHandle*) filehandle)->fd, &statbuf); + MONO_EXIT_GC_SAFE; if(ret==-1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle, - strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d fstat failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); mono_w32error_set_last (ERROR_INVALID_PARAMETER); return(FALSE); @@ -1729,13 +1560,12 @@ static gboolean file_setfiletime(gpointer handle, 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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting fd %d access %ld write %ld", __func__, + ((MonoFDHandle*) filehandle)->fd, utbuf.actime, utbuf.modtime); - ret = _wapi_utime (file_handle->filename, &utbuf); + ret = _wapi_utime (filehandle->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)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d [%s] utime failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->filename, g_strerror(errno)); mono_w32error_set_last (ERROR_INVALID_PARAMETER); return(FALSE); @@ -1744,80 +1574,31 @@ static gboolean file_setfiletime(gpointer handle, 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) +console_read(FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *bytesread) { - MonoW32HandleFile *console_handle; - gboolean ok; - gint ret, fd; + gint ret; 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); - mono_w32error_set_last (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); + if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); } do { - ret=read(fd, buffer, numbytes); + MONO_ENTER_GC_SAFE; + ret=read(((MonoFDHandle*) filehandle)->fd, buffer, numbytes); + MONO_EXIT_GC_SAFE; } 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)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(FALSE); @@ -1831,37 +1612,26 @@ console_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesr } static gboolean -console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten) +console_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten) { - MonoW32HandleFile *console_handle; - gboolean ok; - gint ret, fd; + gint ret; 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); - mono_w32error_set_last (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); + if(!(filehandle->fileaccess & (GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); } do { - ret = write(fd, buffer, numbytes); + MONO_ENTER_GC_SAFE; + ret = write(((MonoFDHandle*) filehandle)->fd, buffer, numbytes); + MONO_EXIT_GC_SAFE; } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); @@ -1871,8 +1641,7 @@ console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 * } 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)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); return(FALSE); } @@ -1884,87 +1653,29 @@ console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 * 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) +pipe_read (FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *bytesread) { - MonoW32HandleFile *pipe_handle; - gboolean ok; - gint ret, fd; + gint ret; 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); - mono_w32error_set_last (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); + if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: reading up to %" G_GUINT32_FORMAT " bytes from pipe %d", __func__, numbytes, ((MonoFDHandle*) filehandle)->fd); do { - ret=read(fd, buffer, numbytes); + MONO_ENTER_GC_SAFE; + ret=read(((MonoFDHandle*) filehandle)->fd, buffer, numbytes); + MONO_EXIT_GC_SAFE; } while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info)); if (ret == -1) { @@ -1973,14 +1684,13 @@ pipe_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesrea } 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)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of fd %d error: %s", __func__,((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); return(FALSE); } } - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read %d bytes from pipe %p", __func__, ret, handle); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read %d bytes from pipe %d", __func__, ret, ((MonoFDHandle*) filehandle)->fd); if(bytesread!=NULL) { *bytesread=ret; @@ -1990,40 +1700,28 @@ pipe_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesrea } static gboolean -pipe_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten) +pipe_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten) { - MonoW32HandleFile *pipe_handle; - gboolean ok; - gint ret, fd; + gint ret; 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); - mono_w32error_set_last (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); + if(!(filehandle->fileaccess & (GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: writing up to %" G_GUINT32_FORMAT " bytes to pipe %d", __func__, numbytes, ((MonoFDHandle*) filehandle)->fd); do { - ret = write (fd, buffer, numbytes); + MONO_ENTER_GC_SAFE; + ret = write (((MonoFDHandle*) filehandle)->fd, buffer, numbytes); + MONO_EXIT_GC_SAFE; } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); @@ -2033,8 +1731,7 @@ pipe_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byt } 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)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of fd %d error: %s", __func__,((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); return(FALSE); } @@ -2061,7 +1758,7 @@ static gint convert_flags(guint32 fileaccess, guint32 createmode) flags=O_RDWR; break; default: - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown access type 0x%x", __func__, + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown access type 0x%" PRIx32, __func__, fileaccess); break; } @@ -2082,7 +1779,7 @@ static gint convert_flags(guint32 fileaccess, guint32 createmode) flags|=O_TRUNC; break; default: - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown create mode 0x%x", __func__, + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown create mode 0x%" PRIx32, __func__, createmode); break; } @@ -2122,9 +1819,10 @@ static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode, */ 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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%" PRIx32 ", file has sharing = NONE", __func__, fileaccess); file_share_release (*share_info); + *share_info = NULL; return(FALSE); } @@ -2134,9 +1832,10 @@ 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 */ - 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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%" PRIx32 ", file has sharing: 0x%" PRIx32, __func__, fileaccess, file_existing_share); file_share_release (*share_info); + *share_info = NULL; return(FALSE); } @@ -2146,9 +1845,10 @@ 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 */ - 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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Access mode prevents open: requested share: 0x%" PRIx32 ", file has access: 0x%" PRIx32, __func__, sharemode, file_existing_access); file_share_release (*share_info); + *share_info = NULL; return(FALSE); } @@ -2175,18 +1875,20 @@ share_allows_delete (struct stat *statbuf, FileShare **share_info) */ 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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%" PRIx32 ", file has sharing = NONE", __func__, (*share_info)->access); file_share_release (*share_info); + *share_info = NULL; 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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%" PRIx32 ", file has sharing: 0x%" PRIx32, __func__, (*share_info)->access, file_existing_share); file_share_release (*share_info); + *share_info = NULL; return(FALSE); } @@ -2200,8 +1902,8 @@ share_allows_delete (struct stat *statbuf, FileShare **share_info) gpointer mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode, guint32 createmode, guint32 attrs) { - MonoW32HandleFile file_handle = {0}; - gpointer handle; + FileHandle *filehandle; + MonoFDType type; gint flags=convert_flags(fileaccess, createmode); /*mode_t perms=convert_perms(sharemode);*/ /* we don't use sharemode, because that relates to sharing of @@ -2212,7 +1914,6 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode mode_t perms=0666; gchar *filename; gint fd, ret; - MonoW32HandleType handle_type; struct stat statbuf; if (attrs & FILE_ATTRIBUTE_TEMPORARY) @@ -2238,7 +1939,7 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode 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__, + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening %s with share 0x%" PRIx32 " and access 0x%" PRIx32, __func__, filename, sharemode, fileaccess); fd = _wapi_open (filename, flags, perms); @@ -2258,115 +1959,105 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode } if (fd == -1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s: %s", __func__, filename, - strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s: %s", __func__, filename, g_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__); - - mono_w32error_set_last (ERROR_TOO_MANY_OPEN_FILES); - - close (fd); - g_free (filename); - - return(INVALID_HANDLE_VALUE); - } - + MONO_ENTER_GC_SAFE; ret = fstat (fd, &statbuf); + MONO_EXIT_GC_SAFE; if (ret == -1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fstat error of file %s: %s", __func__, - filename, strerror (errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fstat error of file %s: %s", __func__, filename, g_strerror (errno)); _wapi_set_last_error_from_errno (); - g_free (filename); + MONO_ENTER_GC_SAFE; close (fd); - + MONO_EXIT_GC_SAFE; + 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); + +#ifndef S_ISFIFO +#define S_ISFIFO(m) ((m & S_IFIFO) != 0) #endif + if (S_ISFIFO (statbuf.st_mode)) { + type = MONO_FDTYPE_PIPE; + /* maintain invariant that pipes have no filename */ + g_free (filename); + filename = NULL; + } else if (S_ISCHR (statbuf.st_mode)) { + type = MONO_FDTYPE_CONSOLE; + } else { + type = MONO_FDTYPE_FILE; + } + + filehandle = file_data_create (type, fd); + filehandle->filename = filename; + filehandle->fileaccess = fileaccess; + filehandle->sharemode = sharemode; + filehandle->attrs = attrs; - if (share_allows_open (&statbuf, sharemode, fileaccess, - &file_handle.share_info) == FALSE) { + if (!share_allows_open (&statbuf, filehandle->sharemode, filehandle->fileaccess, &filehandle->share_info)) { mono_w32error_set_last (ERROR_SHARING_VIOLATION); - g_free (filename); - close (fd); + MONO_ENTER_GC_SAFE; + close (((MonoFDHandle*) filehandle)->fd); + MONO_EXIT_GC_SAFE; + mono_fdhandle_unref ((MonoFDHandle*) filehandle); return (INVALID_HANDLE_VALUE); } - if (file_handle.share_info == NULL) { + if (!filehandle->share_info) { /* 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__); mono_w32error_set_last (ERROR_TOO_MANY_OPEN_FILES); - close (fd); - g_free (filename); + MONO_ENTER_GC_SAFE; + close (((MonoFDHandle*) filehandle)->fd); + MONO_EXIT_GC_SAFE; + mono_fdhandle_unref ((MonoFDHandle*) filehandle); 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); + if (attrs & FILE_FLAG_SEQUENTIAL_SCAN) { + MONO_ENTER_GC_SAFE; + posix_fadvise (((MonoFDHandle*) filehandle)->fd, 0, 0, POSIX_FADV_SEQUENTIAL); + MONO_EXIT_GC_SAFE; + } + if (attrs & FILE_FLAG_RANDOM_ACCESS) { + MONO_ENTER_GC_SAFE; + posix_fadvise (((MonoFDHandle*) filehandle)->fd, 0, 0, POSIX_FADV_RANDOM); + MONO_EXIT_GC_SAFE; + } #endif #ifdef F_RDAHEAD - if (attrs & FILE_FLAG_SEQUENTIAL_SCAN) - fcntl(fd, F_RDAHEAD, 1); + if (attrs & FILE_FLAG_SEQUENTIAL_SCAN) { + MONO_ENTER_GC_SAFE; + fcntl(((MonoFDHandle*) filehandle)->fd, F_RDAHEAD, 1); + MONO_EXIT_GC_SAFE; + } #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; - } + mono_fdhandle_insert ((MonoFDHandle*) filehandle); - 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); - - mono_w32error_set_last (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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) filehandle)->fd)); + + return GINT_TO_POINTER(((MonoFDHandle*) filehandle)->fd); } gboolean mono_w32file_close (gpointer handle) { - return mono_w32handle_close (handle); + if (!mono_fdhandle_close (GPOINTER_TO_INT (handle))) { + mono_w32error_set_last (ERROR_INVALID_HANDLE); + return FALSE; + } + + return TRUE; } gboolean mono_w32file_delete(const gunichar2 *name) @@ -2374,7 +2065,6 @@ gboolean mono_w32file_delete(const gunichar2 *name) gchar *filename; gint retval; gboolean ret = FALSE; - guint32 attrs; #if 0 struct stat statbuf; FileShare *shareinfo; @@ -2395,14 +2085,6 @@ gboolean mono_w32file_delete(const gunichar2 *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. @@ -2430,6 +2112,19 @@ gboolean mono_w32file_delete(const gunichar2 *name) retval = _wapi_unlink (filename); if (retval == -1) { + /* On linux, calling unlink on an non-existing file in a read-only mount will fail with EROFS. + * The expected behavior is for this function to return FALSE and not trigger an exception. + * To work around this behavior, we stat the file on failure. + * + * This was supposedly fixed on kernel 3.0 [1] but we could reproduce it with Ubuntu 16.04 which has kernel 4.4. + * We can't remove this workaround until the early 2020's when most Android deviced will have a fix. + * [1] https://github.com/torvalds/linux/commit/50338b889dc504c69e0cb316ac92d1b9e51f3c8a + */ + if (errno == EROFS) { + MonoIOStat stat; + if (mono_w32file_get_attributes_ex (name, &stat)) //The file exists, so must be due the RO file system + errno = EROFS; + } _wapi_set_last_path_error_from_errno (NULL, filename); } else { ret = TRUE; @@ -2516,8 +2211,10 @@ MoveFile (gunichar2 *name, gunichar2 *dest_name) mono_w32error_set_last (ERROR_SHARING_VIOLATION); return FALSE; } - if (shareinfo) + if (shareinfo) { file_share_release (shareinfo); + shareinfo = NULL; + } result = _wapi_rename (utf8_name, utf8_dest_name); errno_copy = errno; @@ -2580,7 +2277,9 @@ write_file (gint src_fd, gint dest_fd, struct stat *st_src, gboolean report_erro buf = (gchar *) g_malloc (buf_size); for (;;) { + MONO_ENTER_GC_SAFE; remain = read (src_fd, buf, buf_size); + MONO_EXIT_GC_SAFE; if (remain < 0) { if (errno == EINTR && !mono_thread_info_is_interrupt_state (info)) continue; @@ -2597,7 +2296,10 @@ write_file (gint src_fd, gint dest_fd, struct stat *st_src, gboolean report_erro wbuf = buf; while (remain > 0) { - if ((n = write (dest_fd, wbuf, remain)) < 0) { + MONO_ENTER_GC_SAFE; + n = write (dest_fd, wbuf, remain); + MONO_EXIT_GC_SAFE; + if (n < 0) { if (errno == EINTR && !mono_thread_info_is_interrupt_state (info)) continue; @@ -2626,6 +2328,7 @@ CopyFile (const gunichar2 *name, const gunichar2 *dest_name, gboolean fail_if_ex struct utimbuf dest_time; gboolean ret = TRUE; gint ret_utime; + gint syscall_res; if(name==NULL) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__); @@ -2673,12 +2376,17 @@ CopyFile (const gunichar2 *name, const gunichar2 *dest_name, gboolean fail_if_ex return(FALSE); } - if (fstat (src_fd, &st) < 0) { + MONO_ENTER_GC_SAFE; + syscall_res = fstat (src_fd, &st); + MONO_EXIT_GC_SAFE; + if (syscall_res < 0) { _wapi_set_last_error_from_errno (); g_free (utf8_src); g_free (utf8_dest); + MONO_ENTER_GC_SAFE; close (src_fd); + MONO_EXIT_GC_SAFE; return(FALSE); } @@ -2691,7 +2399,9 @@ CopyFile (const gunichar2 *name, const gunichar2 *dest_name, gboolean fail_if_ex g_free (utf8_src); g_free (utf8_dest); + MONO_ENTER_GC_SAFE; close (src_fd); + MONO_EXIT_GC_SAFE; mono_w32error_set_last (ERROR_SHARING_VIOLATION); return (FALSE); @@ -2719,7 +2429,9 @@ CopyFile (const gunichar2 *name, const gunichar2 *dest_name, gboolean fail_if_ex g_free (utf8_src); g_free (utf8_dest); + MONO_ENTER_GC_SAFE; close (src_fd); + MONO_EXIT_GC_SAFE; return(FALSE); } @@ -2732,9 +2444,11 @@ CopyFile (const gunichar2 *name, const gunichar2 *dest_name, gboolean fail_if_ex dest_time.modtime = st.st_mtime; dest_time.actime = st.st_atime; + MONO_ENTER_GC_SAFE; ret_utime = utime (utf8_dest, &dest_time); + MONO_EXIT_GC_SAFE; 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)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file [%s] utime failed: %s", __func__, utf8_dest, g_strerror(errno)); g_free (utf8_src); g_free (utf8_dest); @@ -2812,25 +2526,27 @@ replace_cleanup: g_free (utf8_replacedFileName); g_free (utf8_replacementFileName); g_free (utf8_backupFileName); - if (backup_fd != -1) + if (backup_fd != -1) { + MONO_ENTER_GC_SAFE; close (backup_fd); - if (replaced_fd != -1) + MONO_EXIT_GC_SAFE; + } + if (replaced_fd != -1) { + MONO_ENTER_GC_SAFE; close (replaced_fd); + MONO_EXIT_GC_SAFE; + } 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}; + FileHandle *filehandle; 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); @@ -2840,59 +2556,52 @@ _wapi_stdhandle_create (gint fd, const gchar *name) /* 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)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl error on fd %d: %s", __func__, fd, g_strerror(errno)); mono_w32error_set_last (mono_w32error_unix_to_win32 (errno)); return INVALID_HANDLE_VALUE; } + filehandle = file_data_create (MONO_FDTYPE_CONSOLE, fd); + filehandle->filename = g_strdup(name); + switch (flags & (O_RDONLY|O_WRONLY|O_RDWR)) { case O_RDONLY: - file_handle.fileaccess = GENERIC_READ; + filehandle->fileaccess = GENERIC_READ; break; case O_WRONLY: - file_handle.fileaccess = GENERIC_WRITE; + filehandle->fileaccess = GENERIC_WRITE; break; case O_RDWR: - file_handle.fileaccess = GENERIC_READ | GENERIC_WRITE; + filehandle->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; + filehandle->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; + filehandle->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; + filehandle->fileaccess &= ~GENERIC_WRITE; - file_handle.sharemode = 0; - file_handle.attrs = 0; + filehandle->sharemode = 0; + filehandle->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__); - mono_w32error_set_last (ERROR_GEN_FAILURE); - return INVALID_HANDLE_VALUE; + if (!mono_fdhandle_try_insert ((MonoFDHandle*) filehandle)) { + /* we raced between 2 invocations of _wapi_stdhandle_create */ + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return GINT_TO_POINTER(fd); } - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, handle); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) filehandle)->fd)); - return handle; + return GINT_TO_POINTER(((MonoFDHandle*) filehandle)->fd); } enum { @@ -2904,11 +2613,9 @@ enum { static gpointer mono_w32file_get_std_handle (gint stdhandle) { - MonoW32HandleFile *file_handle; - gpointer handle; + FileHandle **filehandle; gint fd; const gchar *name; - gboolean ok; switch(stdhandle) { case STD_INPUT_HANDLE: @@ -2930,167 +2637,260 @@ mono_w32file_get_std_handle (gint stdhandle) g_assert_not_reached (); } - handle = GINT_TO_POINTER (fd); - - mono_os_mutex_lock (&stdhandle_mutex); + if (!mono_fdhandle_lookup_and_ref(fd, (MonoFDHandle**) &filehandle)) { + gpointer handle; - 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) { mono_w32error_set_last (ERROR_NO_MORE_FILES); - goto done; + return INVALID_HANDLE_VALUE; } - } else { - /* Add a reference to this handle */ - mono_w32handle_ref (handle); } - - done: - mono_os_mutex_unlock (&stdhandle_mutex); - - return(handle); + + return GINT_TO_POINTER (fd); } gboolean mono_w32file_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread) { - MonoW32HandleType type; + FileHandle *filehandle; + gboolean ret; - type = mono_w32handle_get_type (handle); - - if(io_ops[type].readfile==NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); + return FALSE; } - - return(io_ops[type].readfile (handle, buffer, numbytes, bytesread)); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = file_read(filehandle, buffer, numbytes, bytesread); + break; + case MONO_FDTYPE_CONSOLE: + ret = console_read(filehandle, buffer, numbytes, bytesread); + break; + case MONO_FDTYPE_PIPE: + ret = pipe_read(filehandle, buffer, numbytes, bytesread); + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return FALSE; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } gboolean mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten) { - MonoW32HandleType type; + FileHandle *filehandle; + gboolean ret; - type = mono_w32handle_get_type (handle); - - if(io_ops[type].writefile==NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); + return FALSE; } - - return(io_ops[type].writefile (handle, buffer, numbytes, byteswritten)); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = file_write(filehandle, buffer, numbytes, byteswritten); + break; + case MONO_FDTYPE_CONSOLE: + ret = console_write(filehandle, buffer, numbytes, byteswritten); + break; + case MONO_FDTYPE_PIPE: + ret = pipe_write(filehandle, buffer, numbytes, byteswritten); + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return FALSE; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } gboolean mono_w32file_flush (gpointer handle) { - MonoW32HandleType type; + FileHandle *filehandle; + gboolean ret; - type = mono_w32handle_get_type (handle); - - if(io_ops[type].flushfile==NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); + return FALSE; } - - return(io_ops[type].flushfile (handle)); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = file_flush(filehandle); + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return FALSE; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } gboolean mono_w32file_truncate (gpointer handle) { - MonoW32HandleType type; + FileHandle *filehandle; + gboolean ret; - type = mono_w32handle_get_type (handle); - - if (io_ops[type].setendoffile == NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); + return FALSE; } - - return(io_ops[type].setendoffile (handle)); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = file_setendoffile(filehandle); + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return FALSE; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } guint32 mono_w32file_seek (gpointer handle, gint32 movedistance, gint32 *highmovedistance, guint32 method) { - MonoW32HandleType type; + FileHandle *filehandle; + guint32 ret; - type = mono_w32handle_get_type (handle); - - if (io_ops[type].seek == NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(INVALID_SET_FILE_POINTER); + return INVALID_SET_FILE_POINTER; } - - return(io_ops[type].seek (handle, movedistance, highmovedistance, - method)); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = file_seek(filehandle, movedistance, highmovedistance, method); + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return INVALID_SET_FILE_POINTER; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } gint mono_w32file_get_type(gpointer handle) { - MonoW32HandleType type; + FileHandle *filehandle; + gint ret; - type = mono_w32handle_get_type (handle); - - if (io_ops[type].getfiletype == NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FILE_TYPE_UNKNOWN); + return FILE_TYPE_UNKNOWN; } - - return(io_ops[type].getfiletype ()); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = FILE_TYPE_DISK; + break; + case MONO_FDTYPE_CONSOLE: + ret = FILE_TYPE_CHAR; + break; + case MONO_FDTYPE_PIPE: + ret = FILE_TYPE_PIPE; + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return FILE_TYPE_UNKNOWN; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } static guint32 GetFileSize(gpointer handle, guint32 *highsize) { - MonoW32HandleType type; + FileHandle *filehandle; + guint32 ret; - type = mono_w32handle_get_type (handle); - - if (io_ops[type].getfilesize == NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(INVALID_FILE_SIZE); + return INVALID_FILE_SIZE; } - - return(io_ops[type].getfilesize (handle, highsize)); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = file_getfilesize(filehandle, highsize); + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return INVALID_FILE_SIZE; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } gboolean mono_w32file_get_times(gpointer handle, FILETIME *create_time, FILETIME *access_time, FILETIME *write_time) { - MonoW32HandleType type; + FileHandle *filehandle; + gboolean ret; - type = mono_w32handle_get_type (handle); - - if (io_ops[type].getfiletime == NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); + return FALSE; } - - return(io_ops[type].getfiletime (handle, create_time, access_time, - write_time)); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = file_getfiletime(filehandle, create_time, access_time, write_time); + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return FALSE; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } gboolean mono_w32file_set_times(gpointer handle, const FILETIME *create_time, const FILETIME *access_time, const FILETIME *write_time) { - MonoW32HandleType type; + FileHandle *filehandle; + gboolean ret; - type = mono_w32handle_get_type (handle); - - if (io_ops[type].setfiletime == NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); + return FALSE; } - - return(io_ops[type].setfiletime (handle, create_time, access_time, - write_time)); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = file_setfiletime(filehandle, create_time, access_time, write_time); + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return FALSE; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } /* A tick is a 100-nanosecond interval. File time epoch is Midnight, @@ -3139,21 +2939,23 @@ mono_w32file_filetime_to_systemtime(const FILETIME *file_time, SYSTEMTIME *syste 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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %" G_GINT64_FORMAT " rem: %" G_GINT64_FORMAT, __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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Hour: %d rem: %" G_GINT64_FORMAT, __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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Minute: %d rem: %" G_GINT64_FORMAT, __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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Second: %d rem: %" G_GINT64_FORMAT, __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__, @@ -3174,19 +2976,19 @@ mono_w32file_filetime_to_systemtime(const FILETIME *file_time, SYSTEMTIME *syste 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__, + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %" G_GINT64_FORMAT " yg: %" G_GINT64_FORMAT " y: %" G_GINT64_FORMAT, __func__, + totaldays, yg, y); + g_message("%s: LEAPS(yg): %li LEAPS(y): %li", __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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %" G_GINT64_FORMAT, + __func__, totaldays); y = yg; - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: y: %lld", __func__, y); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: y: %" G_GINT64_FORMAT, __func__, y); } system_time->wYear = y; @@ -3198,7 +3000,7 @@ mono_w32file_filetime_to_systemtime(const FILETIME *file_time, SYSTEMTIME *syste continue; } totaldays-=ip[y]; - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld", __func__, totaldays); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %" G_GINT64_FORMAT, __func__, totaldays); system_time->wMonth = y + 1; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Month: %d", __func__, system_time->wMonth); @@ -3374,7 +3176,6 @@ retry: 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); @@ -3382,7 +3183,6 @@ retry: g_free (filename); goto retry; } -#endif utf8_filename = mono_utf8_from_external (filename); if (utf8_filename == NULL) { @@ -3406,11 +3206,7 @@ retry: 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); @@ -3487,7 +3283,9 @@ mono_w32file_find_close (gpointer handle) mono_w32handle_unlock_handle (handle); - mono_w32handle_unref (handle); + MONO_ENTER_GC_SAFE; + mono_w32handle_close (handle); + MONO_EXIT_GC_SAFE; return(TRUE); } @@ -3582,7 +3380,7 @@ mono_w32file_get_attributes (const gunichar2 *name) } result = _wapi_stat (utf8_name, &buf); - if (result == -1 && errno == ENOENT) { + if (result == -1 && (errno == ENOENT || errno == ELOOP)) { /* Might be a dangling symlink... */ result = _wapi_lstat (utf8_name, &buf); } @@ -3593,20 +3391,14 @@ mono_w32file_get_attributes (const gunichar2 *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); @@ -3731,7 +3523,9 @@ mono_w32file_set_attributes (const gunichar2 *name, guint32 attrs) if ((buf.st_mode & S_IROTH) != 0) exec_mask |= S_IXOTH; + MONO_ENTER_GC_SAFE; result = chmod (utf8_name, buf.st_mode | exec_mask); + MONO_EXIT_GC_SAFE; } /* Don't bother to reset executable (might need to change this * policy) @@ -3749,12 +3543,6 @@ mono_w32file_get_cwd (guint32 length, gunichar2 *buffer) 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*/ @@ -3768,7 +3556,6 @@ mono_w32file_get_cwd (guint32 length, gunichar2 *buffer) _wapi_set_last_error_from_errno (); return 0; } -#endif utf16_path = mono_unicode_from_external ((gchar*)buffer, &bytes); count = (bytes/2)+1; @@ -3809,71 +3596,39 @@ mono_w32file_set_cwd (const gunichar2 *path) 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; + FileHandle *read_filehandle, *write_filehandle; gint filedes[2]; gint ret; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating pipe", __func__); + MONO_ENTER_GC_SAFE; ret=pipe (filedes); - if(ret==-1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error creating pipe: %s", __func__, - strerror (errno)); - + MONO_EXIT_GC_SAFE; + if (ret==-1) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error creating pipe: (%d) %s", + __func__, errno, g_strerror (errno)); + _wapi_set_last_error_from_errno (); - return(FALSE); + 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__); - - mono_w32error_set_last (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]); - mono_w32error_set_last (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]); - mono_w32error_set_last (ERROR_GEN_FAILURE); - - return(FALSE); - } - - *readpipe = read_handle; - *writepipe = write_handle; + read_filehandle = file_data_create (MONO_FDTYPE_PIPE, filedes[0]); + read_filehandle->fileaccess = GENERIC_READ; + + write_filehandle = file_data_create (MONO_FDTYPE_PIPE, filedes[1]); + write_filehandle->fileaccess = GENERIC_WRITE; + + mono_fdhandle_insert ((MonoFDHandle*) read_filehandle); + mono_fdhandle_insert ((MonoFDHandle*) write_filehandle); + + *readpipe = GINT_TO_POINTER(((MonoFDHandle*) read_filehandle)->fd); + *writepipe = GINT_TO_POINTER(((MonoFDHandle*) write_filehandle)->fd); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning pipe: read handle %p, write handle %p", - __func__, read_handle, write_handle); + __func__, GINT_TO_POINTER(((MonoFDHandle*) read_filehandle)->fd), GINT_TO_POINTER(((MonoFDHandle*) write_filehandle)->fd)); return(TRUE); } @@ -3887,15 +3642,21 @@ mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf) gint size, n, i; gunichar2 *dir; glong length, total = 0; - + gint syscall_res; + + MONO_ENTER_GC_SAFE; n = getfsstat (NULL, 0, MNT_NOWAIT); + MONO_EXIT_GC_SAFE; 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){ + MONO_ENTER_GC_SAFE; + syscall_res = getfsstat (stats, size, MNT_NOWAIT); + MONO_EXIT_GC_SAFE; + if (syscall_res == -1){ g_free (stats); return 0; } @@ -3982,11 +3743,15 @@ mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf) gboolean (*parser)(guint32, gunichar2*, LinuxMountInfoParseState*) = NULL; memset (buf, 0, len * sizeof (gunichar2)); + MONO_ENTER_GC_SAFE; fd = open ("/proc/self/mountinfo", O_RDONLY); + MONO_EXIT_GC_SAFE; if (fd != -1) parser = GetLogicalDriveStrings_MountInfo; else { + MONO_ENTER_GC_SAFE; fd = open ("/proc/mounts", O_RDONLY); + MONO_EXIT_GC_SAFE; if (fd != -1) parser = GetLogicalDriveStrings_Mounts; } @@ -4000,7 +3765,12 @@ mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf) state.field_number = 1; state.delimiter = ' '; - while ((state.nbytes = read (fd, state.buffer, GET_LOGICAL_DRIVE_STRINGS_BUFFER)) > 0) { + while (1) { + MONO_ENTER_GC_SAFE; + state.nbytes = read (fd, state.buffer, GET_LOGICAL_DRIVE_STRINGS_BUFFER); + MONO_EXIT_GC_SAFE; + if (!(state.nbytes > 0)) + break; state.buffer_index = 0; while ((*parser)(len, buf, &state)) { @@ -4022,8 +3792,11 @@ mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf) ret = state.total; done_and_out: - if (fd != -1) + if (fd != -1) { + MONO_ENTER_GC_SAFE; close (fd); + MONO_EXIT_GC_SAFE; + } return ret; } @@ -4256,15 +4029,25 @@ GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf) /* 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 */ + MONO_ENTER_GC_SAFE; fp = fopen ("/etc/mtab", "rt"); + MONO_EXIT_GC_SAFE; if (fp == NULL) { + MONO_ENTER_GC_SAFE; fp = fopen ("/etc/mnttab", "rt"); + MONO_EXIT_GC_SAFE; if (fp == NULL) return 1; } ptr = buf; - while (fgets (buffer, 512, fp) != NULL) { + while (1) { + gchar *fgets_res; + MONO_ENTER_GC_SAFE; + fgets_res = fgets (buffer, 512, fp); + MONO_EXIT_GC_SAFE; + if (!fgets_res) + break; if (*buffer != '/') continue; @@ -4278,7 +4061,9 @@ GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf) dir = g_utf8_to_utf16 (*(splitted + 1), -1, NULL, &length, NULL); g_strfreev (splitted); if (total + length + 1 > len) { + MONO_ENTER_GC_SAFE; fclose (fp); + MONO_EXIT_GC_SAFE; g_free (dir); return len * 2; /* guess */ } @@ -4288,7 +4073,9 @@ GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf) total += length + 1; } + MONO_ENTER_GC_SAFE; fclose (fp); + MONO_EXIT_GC_SAFE; return total; /* Commented out, does not work with my mtab!!! - Gonz */ #ifdef NOTENABLED /* HAVE_MNTENT_H */ @@ -4299,18 +4086,30 @@ GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf) glong len, total = 0; + MONO_ENTER_GC_SAFE; fp = setmntent ("/etc/mtab", "rt"); + MONO_EXIT_GC_SAFE; if (fp == NULL) { + MONO_ENTER_GC_SAFE; fp = setmntent ("/etc/mnttab", "rt"); + MONO_EXIT_GC_SAFE; if (fp == NULL) return; } ptr = buf; - while ((mnt = getmntent (fp)) != NULL) { + while (1) { + MONO_ENTER_GC_SAFE; + mnt = getmntent (fp); + MONO_EXIT_GC_SAFE; + if (mnt == NULL) + break; 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) { + MONO_ENTER_GC_SAFE; + endmntent (fp); + MONO_EXIT_GC_SAFE; return len * 2; /* guess */ } @@ -4319,7 +4118,9 @@ GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf) total += len + 1; } + MONO_ENTER_GC_SAFE; endmntent (fp); + MONO_EXIT_GC_SAFE; return total; } #endif @@ -4359,11 +4160,15 @@ mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_byte do { #ifdef HAVE_STATVFS + MONO_ENTER_GC_SAFE; ret = statvfs (utf8_path_name, &fsstat); + MONO_EXIT_GC_SAFE; isreadonly = ((fsstat.f_flag & ST_RDONLY) == ST_RDONLY); block_size = fsstat.f_frsize; #elif defined(HAVE_STATFS) + MONO_ENTER_GC_SAFE; ret = statfs (utf8_path_name, &fsstat); + MONO_EXIT_GC_SAFE; #if defined (MNT_RDONLY) isreadonly = ((fsstat.f_flags & MNT_RDONLY) == MNT_RDONLY); #elif defined (MS_RDONLY) @@ -4377,7 +4182,7 @@ mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_byte 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)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: statvfs failed: %s", __func__, g_strerror (errno)); return(FALSE); } @@ -4450,6 +4255,7 @@ static _wapi_drive_type _wapi_drive_types[] = { { DRIVE_RAMDISK, "fdesc" }, { DRIVE_REMOTE, "ftp" }, { DRIVE_FIXED, "hfs" }, + { DRIVE_FIXED, "apfs" }, { DRIVE_FIXED, "msdos" }, { DRIVE_REMOTE, "nfs" }, { DRIVE_FIXED, "ntfs" }, @@ -4601,8 +4407,12 @@ static guint32 GetDriveTypeFromPath (const gchar *utf8_root_path_name) { struct statfs buf; - - if (statfs (utf8_root_path_name, &buf) == -1) + gint res; + + MONO_ENTER_GC_SAFE; + res = statfs (utf8_root_path_name, &buf); + MONO_EXIT_GC_SAFE; + if (res == -1) return DRIVE_UNKNOWN; #if PLATFORM_MACOSX return _wapi_get_drive_type (buf.f_fstypename); @@ -4619,15 +4429,25 @@ GetDriveTypeFromPath (const gchar *utf8_root_path_name) gchar buffer [512]; gchar **splitted; + MONO_ENTER_GC_SAFE; fp = fopen ("/etc/mtab", "rt"); + MONO_EXIT_GC_SAFE; if (fp == NULL) { + MONO_ENTER_GC_SAFE; fp = fopen ("/etc/mnttab", "rt"); + MONO_EXIT_GC_SAFE; if (fp == NULL) return(DRIVE_UNKNOWN); } drive_type = DRIVE_NO_ROOT_DIR; - while (fgets (buffer, 512, fp) != NULL) { + while (1) { + gchar *fgets_res; + MONO_ENTER_GC_SAFE; + fgets_res = fgets (buffer, 512, fp); + MONO_EXIT_GC_SAFE; + if (fgets_res == NULL) + break; splitted = g_strsplit (buffer, " ", 0); if (!*splitted || !*(splitted + 1) || !*(splitted + 2)) { g_strfreev (splitted); @@ -4650,7 +4470,9 @@ GetDriveTypeFromPath (const gchar *utf8_root_path_name) g_strfreev (splitted); } + MONO_ENTER_GC_SAFE; fclose (fp); + MONO_EXIT_GC_SAFE; return drive_type; } #endif @@ -4685,7 +4507,7 @@ mono_w32file_get_drive_type(const gunichar2 *root_path_name) return (drive_type); } -#if defined (PLATFORM_MACOSX) || defined (__linux__) || defined(PLATFORM_BSD) || defined(__native_client__) || defined(__FreeBSD_kernel__) +#if defined (PLATFORM_MACOSX) || defined (__linux__) || defined(PLATFORM_BSD) || defined(__FreeBSD_kernel__) || defined(__HAIKU__) static gchar* get_fstypename (gchar *utfpath) { @@ -4694,7 +4516,11 @@ get_fstypename (gchar *utfpath) #if __linux__ _wapi_drive_type *current; #endif - if (statfs (utfpath, &stat) == -1) + gint statfs_res; + MONO_ENTER_GC_SAFE; + statfs_res = statfs (utfpath, &stat); + MONO_EXIT_GC_SAFE; + if (statfs_res == -1) return NULL; #if PLATFORM_MACOSX return g_strdup (stat.f_fstypename); @@ -4745,18 +4571,25 @@ mono_w32file_get_volume_information (const gunichar2 *path, gunichar2 *volumenam static gboolean LockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 length_low, guint32 length_high) { - MonoW32HandleFile *file_handle; + FileHandle *filehandle; + gboolean ret; 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); + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { + mono_w32error_set_last (ERROR_INVALID_HANDLE); + return FALSE; + } + + if (((MonoFDHandle*) filehandle)->type != MONO_FDTYPE_FILE) { mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); 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); + if (!(filehandle->fileaccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); return FALSE; } @@ -4764,36 +4597,48 @@ LockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 leng 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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking fd %d, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__, ((MonoFDHandle*) filehandle)->fd, (gint64) offset, (gint64) length); #else if (offset_high > 0 || length_high > 0) { mono_w32error_set_last (ERROR_INVALID_PARAMETER); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); 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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking fd %d, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__, ((MonoFDHandle*) filehandle)->fd, (gint64) offset, (gint64) length); #endif - return _wapi_lock_file_region (GPOINTER_TO_UINT(handle), offset, length); + ret = _wapi_lock_file_region (((MonoFDHandle*) filehandle)->fd, offset, length); + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } static gboolean UnlockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 length_low, guint32 length_high) { - MonoW32HandleFile *file_handle; + FileHandle *filehandle; + gboolean ret; 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); + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { + mono_w32error_set_last (ERROR_INVALID_HANDLE); + return FALSE; + } + + if (((MonoFDHandle*) filehandle)->type != MONO_FDTYPE_FILE) { mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); 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); + if (!(filehandle->fileaccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); return FALSE; } @@ -4801,41 +4646,44 @@ UnlockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 le 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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking fd %d, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__, ((MonoFDHandle*) filehandle)->fd, (gint64) offset, (gint64) 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); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking fd %p, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__, ((MonoFDHandle*) filehandle)->fd, (gint64) offset, (gint64) length); #endif - return _wapi_unlock_file_region (GPOINTER_TO_UINT(handle), offset, length); + ret = _wapi_unlock_file_region (((MonoFDHandle*) filehandle)->fd, offset, length); + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } void mono_w32file_init (void) { - mono_os_mutex_init (&stdhandle_mutex); - mono_os_mutex_init (&file_share_mutex); + MonoFDHandleCallback file_data_callbacks = { + .close = file_data_close, + .destroy = file_data_destroy + }; - 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_fdhandle_register (MONO_FDTYPE_FILE, &file_data_callbacks); + mono_fdhandle_register (MONO_FDTYPE_CONSOLE, &file_data_callbacks); + mono_fdhandle_register (MONO_FDTYPE_PIPE, &file_data_callbacks); -/* mono_w32handle_register_capabilities (MONO_W32HANDLE_FILE, */ -/* MONO_W32HANDLE_CAP_WAIT); */ -/* mono_w32handle_register_capabilities (MONO_W32HANDLE_CONSOLE, */ -/* MONO_W32HANDLE_CAP_WAIT); */ + mono_coop_mutex_init (&file_share_mutex); - if (g_getenv ("MONO_STRICT_IO_EMULATION")) + mono_w32handle_register_ops (MONO_W32HANDLE_FIND, &_wapi_find_ops); + + if (g_hasenv ("MONO_STRICT_IO_EMULATION")) lock_while_writing = TRUE; } void mono_w32file_cleanup (void) { - mono_os_mutex_destroy (&file_share_mutex); + mono_coop_mutex_destroy (&file_share_mutex); if (file_share_table) g_hash_table_destroy (file_share_table); @@ -4846,14 +4694,9 @@ mono_w32file_move (gunichar2 *path, gunichar2 *dest, gint32 *error) { gboolean result; - MONO_ENTER_GC_SAFE; - result = MoveFile (path, dest); if (!result) *error = mono_w32error_get_last (); - - MONO_EXIT_GC_SAFE; - return result; } @@ -4862,14 +4705,10 @@ mono_w32file_copy (gunichar2 *path, gunichar2 *dest, gboolean overwrite, gint32 { gboolean result; - MONO_ENTER_GC_SAFE; - result = CopyFile (path, dest, !overwrite); if (!result) *error = mono_w32error_get_last (); - MONO_EXIT_GC_SAFE; - return result; } @@ -4878,14 +4717,9 @@ mono_w32file_replace (gunichar2 *destinationFileName, gunichar2 *sourceFileName, { gboolean result; - MONO_ENTER_GC_SAFE; - result = ReplaceFile (destinationFileName, sourceFileName, destinationBackupFileName, flags, NULL, NULL); if (!result) *error = mono_w32error_get_last (); - - MONO_EXIT_GC_SAFE; - return result; } @@ -4895,15 +4729,11 @@ 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=mono_w32error_get_last (); } - MONO_EXIT_GC_SAFE; - return length | ((gint64)length_hi << 32); } @@ -4912,14 +4742,9 @@ mono_w32file_lock (gpointer handle, gint64 position, gint64 length, gint32 *erro { gboolean result; - MONO_ENTER_GC_SAFE; - result = LockFile (handle, position & 0xFFFFFFFF, position >> 32, length & 0xFFFFFFFF, length >> 32); if (!result) *error = mono_w32error_get_last (); - - MONO_EXIT_GC_SAFE; - return result; } @@ -4928,49 +4753,26 @@ mono_w32file_unlock (gpointer handle, gint64 position, gint64 length, gint32 *er { gboolean result; - MONO_ENTER_GC_SAFE; - result = UnlockFile (handle, position & 0xFFFFFFFF, position >> 32, length & 0xFFFFFFFF, length >> 32); if (!result) *error = mono_w32error_get_last (); - - 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; + return mono_w32file_get_std_handle (STD_INPUT_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; + return mono_w32file_get_std_handle (STD_OUTPUT_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; + return mono_w32file_get_std_handle (STD_ERROR_HANDLE); }