* Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
* Copyright 2004-2009 Novell, Inc (http://www.novell.com)
* Copyright 2012 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <config.h>
static guint32 convert_attrs(MonoFileAttributes attrs)
{
if(attrs & FileAttributes_Encrypted) {
- attrs |= FILE_ATTRIBUTE_ENCRYPTED;
+ attrs = (MonoFileAttributes)(attrs | FILE_ATTRIBUTE_ENCRYPTED);
}
return(attrs);
ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error)
{
gboolean ret;
+ MONO_PREPARE_BLOCKING;
*error=ERROR_SUCCESS;
if(ret==FALSE) {
*error=GetLastError ();
}
-
+
+ MONO_FINISH_BLOCKING;
return(ret);
}
ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error)
{
gboolean ret;
+ MONO_PREPARE_BLOCKING;
*error=ERROR_SUCCESS;
if(ret==FALSE) {
*error=GetLastError ();
}
-
+
+ MONO_FINISH_BLOCKING;
return(ret);
}
static gchar *
-get_search_dir (MonoString *pattern)
+get_search_dir (const gunichar2 *pattern)
{
gchar *p;
gchar *result;
- p = mono_string_to_utf8 (pattern);
+ p = g_utf16_to_utf8 (pattern, -1, NULL, NULL, NULL);
result = g_path_get_dirname (p);
g_free (p);
return result;
}
-MonoArray *
-ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
- MonoString *path_with_pattern,
+static GPtrArray *
+get_filesystem_entries (const gunichar2 *path,
+ const gunichar2 *path_with_pattern,
gint attrs, gint mask,
gint32 *error)
{
- MonoDomain *domain;
- MonoArray *result;
int i;
WIN32_FIND_DATA data;
HANDLE find_handle;
- GPtrArray *names;
- gchar *utf8_path, *utf8_result, *full_name;
+ GPtrArray *names = NULL;
+ gchar *utf8_path = NULL, *utf8_result, *full_name;
gint32 attributes;
-
- result = NULL;
- *error = ERROR_SUCCESS;
- domain = mono_domain_get ();
- mask = convert_attrs (mask);
- attributes = get_file_attributes (mono_string_chars (path));
+ mask = convert_attrs ((MonoFileAttributes)mask);
+ attributes = get_file_attributes (path);
if (attributes != -1) {
if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
*error = ERROR_INVALID_NAME;
- goto leave;
+ goto fail;
}
} else {
*error = GetLastError ();
- goto leave;
+ goto fail;
}
- find_handle = FindFirstFile (mono_string_chars (path_with_pattern), &data);
+ find_handle = FindFirstFile (path_with_pattern, &data);
if (find_handle == INVALID_HANDLE_VALUE) {
gint32 find_error = GetLastError ();
if (find_error == ERROR_FILE_NOT_FOUND || find_error == ERROR_NO_MORE_FILES) {
/* No files, so just return an empty array */
- goto leave;
+ goto fail;
}
*error = find_error;
- goto leave;
+ goto fail;
}
utf8_path = get_search_dir (path_with_pattern);
if (FindClose (find_handle) == FALSE) {
*error = GetLastError ();
- result = NULL;
- } else {
- result = mono_array_new (domain, mono_defaults.string_class, names->len);
- for (i = 0; i < names->len; i++) {
- mono_array_setref (result, i, mono_string_new (domain, g_ptr_array_index (names, i)));
- }
+ goto fail;
}
- for (i = 0; i < names->len; i++) {
- g_free (g_ptr_array_index (names, i));
+ g_free (utf8_path);
+ return names;
+fail:
+ if (names) {
+ for (i = 0; i < names->len; i++)
+ g_free (g_ptr_array_index (names, i));
+ g_ptr_array_free (names, TRUE);
}
- g_ptr_array_free (names, TRUE);
g_free (utf8_path);
+ return FALSE;
+}
-leave:
- // If there's no array and no error, then return an empty array.
- if (result == NULL && *error == ERROR_SUCCESS)
- result = mono_array_new (domain, mono_defaults.string_class, 0);
+MonoArray *
+ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
+ MonoString *path_with_pattern,
+ gint attrs, gint mask,
+ gint32 *error)
+{
+ MonoDomain *domain = mono_domain_get ();
+ MonoArray *result;
+ int i;
+ GPtrArray *names;
+
+ *error = ERROR_SUCCESS;
+
+ MONO_PREPARE_BLOCKING;
+ names = get_filesystem_entries (mono_string_chars (path), mono_string_chars (path_with_pattern), attrs, mask, error);
+ MONO_FINISH_BLOCKING;
+
+ if (!names) {
+ // If there's no array and no error, then return an empty array.
+ if (*error == ERROR_SUCCESS)
+ return mono_array_new (domain, mono_defaults.string_class, 0);
+ return NULL;
+ }
+
+ result = mono_array_new (domain, mono_defaults.string_class, names->len);
+ for (i = 0; i < names->len; i++) {
+ mono_array_setref (result, i, mono_string_new (domain, (const char *)g_ptr_array_index (names, i)));
+ g_free (g_ptr_array_index (names, i));
+ }
+ g_ptr_array_free (names, TRUE);
return result;
}
return TRUE;
}
+/* FIXME make gc suspendable */
MonoString *
ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
MonoString *path_with_pattern,
return result;
}
+/* FIXME make gc suspendable */
MonoString *
ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_attr, gint32 *error)
{
- IncrementalFind *ifh = handle;
+ IncrementalFind *ifh = (IncrementalFind *)handle;
WIN32_FIND_DATA data;
MonoString *result;
int
ves_icall_System_IO_MonoIO_FindClose (gpointer handle)
{
- IncrementalFind *ifh = handle;
+ IncrementalFind *ifh = (IncrementalFind *)handle;
gint32 error;
-
+
+ MONO_PREPARE_BLOCKING;
if (FindClose (ifh->find_handle) == FALSE){
error = GetLastError ();
} else
error = ERROR_SUCCESS;
g_free (ifh->utf8_path);
g_free (ifh);
+ MONO_FINISH_BLOCKING;
return error;
}
MonoString *
-ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *error)
+ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *io_error)
{
+ MonoError error;
MonoString *result;
gunichar2 *buf;
int len, res_len;
len = MAX_PATH + 1; /*FIXME this is too smal under most unix systems.*/
buf = g_new (gunichar2, len);
- *error=ERROR_SUCCESS;
+ mono_error_init (&error);
+ *io_error=ERROR_SUCCESS;
result = NULL;
res_len = GetCurrentDirectory (len, buf);
while (buf [len])
++ len;
- result = mono_string_new_utf16 (mono_domain_get (), buf, len);
+ result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
} else {
- *error=GetLastError ();
+ *io_error=GetLastError ();
}
g_free (buf);
+ mono_error_raise_exception (&error);
return result;
}
gint32 *error)
{
gboolean ret;
+ MONO_PREPARE_BLOCKING;
*error=ERROR_SUCCESS;
-
+
ret=MoveFile (mono_string_chars (path), mono_string_chars (dest));
if(ret==FALSE) {
*error=GetLastError ();
}
-
+
+ MONO_FINISH_BLOCKING;
return(ret);
}
gboolean ret;
gunichar2 *utf16_sourceFileName = NULL, *utf16_destinationFileName = NULL, *utf16_destinationBackupFileName = NULL;
guint32 replaceFlags = REPLACEFILE_WRITE_THROUGH;
+ MONO_PREPARE_BLOCKING;
if (sourceFileName)
utf16_sourceFileName = mono_string_chars (sourceFileName);
if (ret == FALSE)
*error = GetLastError ();
+ MONO_FINISH_BLOCKING;
return ret;
}
MonoBoolean overwrite, gint32 *error)
{
gboolean ret;
+ MONO_PREPARE_BLOCKING;
*error=ERROR_SUCCESS;
*error=GetLastError ();
}
+ MONO_FINISH_BLOCKING;
return(ret);
}
ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error)
{
gboolean ret;
+ MONO_PREPARE_BLOCKING;
*error=ERROR_SUCCESS;
*error=GetLastError ();
}
+ MONO_FINISH_BLOCKING;
return(ret);
}
ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
{
gint32 ret;
-
+ MONO_PREPARE_BLOCKING;
+
*error=ERROR_SUCCESS;
ret=get_file_attributes (mono_string_chars (path));
*error=GetLastError ();
}
+ MONO_FINISH_BLOCKING;
return(ret);
}
gint32 *error)
{
gboolean ret;
+ MONO_PREPARE_BLOCKING;
*error=ERROR_SUCCESS;
ret=SetFileAttributes (mono_string_chars (path),
- convert_attrs (attrs));
+ convert_attrs ((MonoFileAttributes)attrs));
if(ret==FALSE) {
*error=GetLastError ();
}
-
+
+ MONO_FINISH_BLOCKING;
return(ret);
}
ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
{
gboolean ret;
-
+ MONO_PREPARE_BLOCKING;
+
*error=ERROR_SUCCESS;
ret=GetFileType (handle);
*error=GetLastError ();
}
+ MONO_FINISH_BLOCKING;
return(ret);
}
{
gboolean result;
WIN32_FILE_ATTRIBUTE_DATA data;
+ MONO_PREPARE_BLOCKING;
*error=ERROR_SUCCESS;
memset (stat, 0, sizeof (MonoIOStat));
}
+ MONO_FINISH_BLOCKING;
return result;
}
{
HANDLE ret;
int attributes, attrs;
- gunichar2 *chars = mono_string_chars (filename);
-
+ gunichar2 *chars;
+ MONO_PREPARE_BLOCKING;
+
+ chars = mono_string_chars (filename);
*error=ERROR_SUCCESS;
if (options != 0){
}
}
- ret=CreateFile (chars, convert_access (access_mode),
- convert_share (share), NULL, convert_mode (mode),
+ ret=CreateFile (chars, convert_access ((MonoFileAccess)access_mode),
+ convert_share ((MonoFileShare)share), NULL, convert_mode ((MonoFileMode)mode),
attributes, NULL);
if(ret==INVALID_HANDLE_VALUE) {
*error=GetLastError ();
}
+ MONO_FINISH_BLOCKING;
return(ret);
}
ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error)
{
gboolean ret;
-
+ MONO_PREPARE_BLOCKING;
+
*error=ERROR_SUCCESS;
ret=CloseHandle (handle);
*error=GetLastError ();
}
+ MONO_FINISH_BLOCKING;
return(ret);
}
*error=ERROR_SUCCESS;
- MONO_CHECK_ARG_NULL (dest);
+ MONO_CHECK_ARG_NULL (dest, 0);
- if (dest_offset > mono_array_length (dest) - count)
- mono_raise_exception (mono_get_exception_argument ("array", "array too small. numBytes/offset wrong."));
+ if (dest_offset > mono_array_length (dest) - count) {
+ mono_set_pending_exception (mono_get_exception_argument ("array", "array too small. numBytes/offset wrong."));
+ return 0;
+ }
buffer = mono_array_addr (dest, guchar, dest_offset);
+
+ MONO_PREPARE_BLOCKING;
result = ReadFile (handle, buffer, count, &n, NULL);
+ MONO_FINISH_BLOCKING;
if (!result) {
*error=GetLastError ();
*error=ERROR_SUCCESS;
- MONO_CHECK_ARG_NULL (src);
+ MONO_CHECK_ARG_NULL (src, 0);
- if (src_offset > mono_array_length (src) - count)
- mono_raise_exception (mono_get_exception_argument ("array", "array too small. numBytes/offset wrong."));
+ if (src_offset > mono_array_length (src) - count) {
+ mono_set_pending_exception (mono_get_exception_argument ("array", "array too small. numBytes/offset wrong."));
+ return 0;
+ }
buffer = mono_array_addr (src, guchar, src_offset);
+ MONO_PREPARE_BLOCKING;
result = WriteFile (handle, buffer, count, &n, NULL);
+ MONO_FINISH_BLOCKING;
if (!result) {
*error=GetLastError ();
gint32 *error)
{
gint32 offset_hi;
+ MONO_PREPARE_BLOCKING;
*error=ERROR_SUCCESS;
offset_hi = offset >> 32;
offset = SetFilePointer (handle, (gint32) (offset & 0xFFFFFFFF), &offset_hi,
- convert_seekorigin (origin));
+ convert_seekorigin ((MonoSeekOrigin)origin));
if(offset==INVALID_SET_FILE_POINTER) {
*error=GetLastError ();
}
-
+
+ MONO_FINISH_BLOCKING;
return offset | ((gint64)offset_hi << 32);
}
ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
{
gboolean ret;
-
+ MONO_PREPARE_BLOCKING;
+
*error=ERROR_SUCCESS;
ret=FlushFileBuffers (handle);
*error=GetLastError ();
}
+ MONO_FINISH_BLOCKING;
return(ret);
}
{
gint64 length;
guint32 length_hi;
+ MONO_PREPARE_BLOCKING;
*error=ERROR_SUCCESS;
*error=GetLastError ();
}
+ MONO_FINISH_BLOCKING;
return length | ((gint64)length_hi << 32);
}
+/* FIXME make gc suspendable */
MonoBoolean
ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length,
gint32 *error)
const FILETIME *creation_filetime;
const FILETIME *last_access_filetime;
const FILETIME *last_write_filetime;
+ MONO_PREPARE_BLOCKING;
*error=ERROR_SUCCESS;
if(ret==FALSE) {
*error=GetLastError ();
}
-
+
+ MONO_FINISH_BLOCKING;
return(ret);
}
}
MonoBoolean
-ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle,
- HANDLE *write_handle)
+ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle, HANDLE *write_handle, gint32 *error)
{
SECURITY_ATTRIBUTES attr;
gboolean ret;
attr.nLength=sizeof(SECURITY_ATTRIBUTES);
attr.bInheritHandle=TRUE;
attr.lpSecurityDescriptor=NULL;
-
+
+ MONO_PREPARE_BLOCKING;
ret=CreatePipe (read_handle, write_handle, &attr, 0);
+ MONO_FINISH_BLOCKING;
+
if(ret==FALSE) {
+ *error = GetLastError ();
/* FIXME: throw an exception? */
return(FALSE);
}
return(TRUE);
}
-MonoBoolean ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_handle,
- HANDLE source_handle, HANDLE target_process_handle, HANDLE *target_handle,
- gint32 access, gint32 inherit, gint32 options)
+MonoBoolean
+ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_handle, HANDLE source_handle,
+ HANDLE target_process_handle, HANDLE *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error)
{
/* This is only used on Windows */
gboolean ret;
+ MONO_PREPARE_BLOCKING;
ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options);
+ MONO_FINISH_BLOCKING;
+
if(ret==FALSE) {
+ *error = GetLastError ();
/* FIXME: throw an exception? */
return(FALSE);
}
return chars;
}
-gint32
-ves_icall_System_IO_MonoIO_GetTempPath (MonoString **mono_name)
-{
- gunichar2 *name;
- int ret;
-
- name=g_new0 (gunichar2, 256);
-
- ret=GetTempPath (256, name);
- if(ret>255) {
- /* Buffer was too short. Try again... */
- g_free (name);
- name=g_new0 (gunichar2, ret+2); /* include the terminator */
- ret=GetTempPath (ret, name);
- }
-
- if(ret>0) {
-#ifdef DEBUG
- g_message ("%s: Temp path is [%s] (len %d)", __func__, name, ret);
-#endif
-
- mono_gc_wbarrier_generic_store ((gpointer) mono_name,
- (MonoObject*) mono_string_new_utf16 (mono_domain_get (), name, ret));
- }
-
- g_free (name);
-
- return(ret);
-}
-
void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position,
gint64 length, gint32 *error)
{
gboolean ret;
+ MONO_PREPARE_BLOCKING;
*error=ERROR_SUCCESS;
if (ret == FALSE) {
*error = GetLastError ();
}
+
+ MONO_FINISH_BLOCKING;
}
void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position,
gint64 length, gint32 *error)
{
gboolean ret;
+ MONO_PREPARE_BLOCKING;
*error=ERROR_SUCCESS;
if (ret == FALSE) {
*error = GetLastError ();
}
+
+ MONO_FINISH_BLOCKING;
}
//Support for io-layer free mmap'd files.
struct stat buf;
gint64 res;
char *path = mono_string_to_utf8 (string);
-
+
+ MONO_PREPARE_BLOCKING;
if (stat (path, &buf) == -1)
res = -1;
else
res = (gint64)buf.st_size;
g_free (path);
+
+ MONO_FINISH_BLOCKING;
return res;
}
mono_filesize_from_fd (int fd)
{
struct stat buf;
+ int res;
- if (fstat (fd, &buf) == -1)
+ MONO_PREPARE_BLOCKING;
+ res = fstat (fd, &buf);
+ MONO_FINISH_BLOCKING;
+
+ if (res == -1)
return (gint64)-1;
return (gint64)buf.st_size;
}
#endif
+
+void _wapi_handle_dump (void);
+
+void ves_icall_System_IO_MonoIO_DumpHandles (void)
+{
+#ifndef HOST_WIN32
+ _wapi_handle_dump ();
+#endif
+}