*
* 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)
*/
#include <config.h>
return (gint64)ticks;
}
-static void convert_win32_file_attribute_data (const WIN32_FILE_ATTRIBUTE_DATA *data, const gunichar2 *name, MonoIOStat *stat)
+static void convert_win32_file_attribute_data (const WIN32_FILE_ATTRIBUTE_DATA *data, MonoIOStat *stat)
{
- int len;
-
stat->attributes = data->dwFileAttributes;
stat->creation_time = convert_filetime (&data->ftCreationTime);
stat->last_access_time = convert_filetime (&data->ftLastAccessTime);
stat->last_write_time = convert_filetime (&data->ftLastWriteTime);
stat->length = ((gint64)data->nFileSizeHigh << 32) | data->nFileSizeLow;
-
- len = 0;
- while (name [len])
- ++ len;
-
- MONO_STRUCT_SETREF (stat, name, mono_string_new_utf16 (mono_domain_get (), name, len));
}
/* Managed file attributes have nearly but not quite the same values
ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error)
{
gboolean ret;
+ MONO_PREPARE_BLOCKING
- MONO_ARCH_SAVE_REGS;
-
*error=ERROR_SUCCESS;
ret=CreateDirectory (mono_string_chars (path), NULL);
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
- MONO_ARCH_SAVE_REGS;
-
*error=ERROR_SUCCESS;
ret=RemoveDirectory (mono_string_chars (path));
if(ret==FALSE) {
*error=GetLastError ();
}
-
+
+ MONO_FINISH_BLOCKING
return(ret);
}
return result;
}
-MonoArray *
-ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
+static GPtrArray *
+get_filesystem_entries (MonoString *path,
MonoString *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;
-
- MONO_ARCH_SAVE_REGS;
-
- *error = ERROR_SUCCESS;
- domain = mono_domain_get ();
mask = convert_attrs (mask);
attributes = get_file_attributes (mono_string_chars (path));
if (attributes != -1) {
if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
*error = ERROR_INVALID_NAME;
- return (NULL);
+ goto fail;
}
} else {
*error = GetLastError ();
- return (NULL);
+ goto fail;
}
find_handle = FindFirstFile (mono_string_chars (path_with_pattern), &data);
if (find_error == ERROR_FILE_NOT_FOUND || find_error == ERROR_NO_MORE_FILES) {
/* No files, so just return an empty array */
- result = mono_array_new (domain,
- mono_defaults.string_class,
- 0);
-
- return(result);
+ goto fail;
}
*error = find_error;
- return(NULL);
+ 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;
}
+ g_free (utf8_path);
+ return names;
+fail:
+ if (names) {
+ for (i = 0; i < names->len; i++)
+ g_free (g_ptr_array_index (names, i));
+ g_ptr_array_free (names, TRUE);
+ }
+ g_free (utf8_path);
+ return FALSE;
+}
+
+
+MonoArray *
+ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
+ MonoString *path_with_pattern,
+ gint attrs, gint mask,
+ gint32 *error)
+{
+ MonoDomain *domain = mono_domain_get ();
+ MonoArray *result;
+ int i;
+ GPtrArray *names;
+
+ *error = ERROR_SUCCESS;
+
+ MONO_PREPARE_BLOCKING
+ names = get_filesystem_entries (path, 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, g_ptr_array_index (names, i)));
g_free (g_ptr_array_index (names, i));
}
g_ptr_array_free (names, TRUE);
- g_free (utf8_path);
-
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)
{
WIN32_FIND_DATA data;
MonoString *result;
- error = ERROR_SUCCESS;
+ *error = ERROR_SUCCESS;
do {
if (FindNextFile (ifh->find_handle, &data) == FALSE){
int e = GetLastError ();
{
IncrementalFind *ifh = 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;
}
gunichar2 *buf;
int len, res_len;
- MONO_ARCH_SAVE_REGS;
-
len = MAX_PATH + 1; /*FIXME this is too smal under most unix systems.*/
buf = g_new (gunichar2, len);
{
gboolean ret;
- MONO_ARCH_SAVE_REGS;
-
*error=ERROR_SUCCESS;
ret=SetCurrentDirectory (mono_string_chars (path));
gint32 *error)
{
gboolean ret;
+ MONO_PREPARE_BLOCKING
- MONO_ARCH_SAVE_REGS;
-
*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_ARCH_SAVE_REGS;
+ MONO_PREPARE_BLOCKING
if (sourceFileName)
utf16_sourceFileName = mono_string_chars (sourceFileName);
if (ignoreMetadataErrors)
replaceFlags |= REPLACEFILE_IGNORE_MERGE_ERRORS;
+ /* FIXME: source and destination file names must not be NULL, but apparently they might be! */
ret = ReplaceFile (utf16_destinationFileName, utf16_sourceFileName, utf16_destinationBackupFileName,
replaceFlags, NULL, NULL);
if (ret == FALSE)
*error = GetLastError ();
+ MONO_FINISH_BLOCKING
return ret;
}
MonoBoolean overwrite, gint32 *error)
{
gboolean ret;
+ MONO_PREPARE_BLOCKING
- MONO_ARCH_SAVE_REGS;
-
*error=ERROR_SUCCESS;
ret=CopyFile (mono_string_chars (path), mono_string_chars (dest), !overwrite);
*error=GetLastError ();
}
+ MONO_FINISH_BLOCKING
return(ret);
}
ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error)
{
gboolean ret;
+ MONO_PREPARE_BLOCKING
- MONO_ARCH_SAVE_REGS;
-
*error=ERROR_SUCCESS;
ret=DeleteFile (mono_string_chars (path));
*error=GetLastError ();
}
+ MONO_FINISH_BLOCKING
return(ret);
}
ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
{
gint32 ret;
-
- MONO_ARCH_SAVE_REGS;
+ MONO_PREPARE_BLOCKING
*error=ERROR_SUCCESS;
*error=GetLastError ();
}
+ MONO_FINISH_BLOCKING
return(ret);
}
gint32 *error)
{
gboolean ret;
+ MONO_PREPARE_BLOCKING
- MONO_ARCH_SAVE_REGS;
-
*error=ERROR_SUCCESS;
ret=SetFileAttributes (mono_string_chars (path),
if(ret==FALSE) {
*error=GetLastError ();
}
-
+
+ MONO_FINISH_BLOCKING
return(ret);
}
ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
{
gboolean ret;
-
- MONO_ARCH_SAVE_REGS;
+ MONO_PREPARE_BLOCKING
*error=ERROR_SUCCESS;
*error=GetLastError ();
}
+ MONO_FINISH_BLOCKING
return(ret);
}
{
gboolean result;
WIN32_FILE_ATTRIBUTE_DATA data;
-
- MONO_ARCH_SAVE_REGS;
+ MONO_PREPARE_BLOCKING
*error=ERROR_SUCCESS;
result = get_file_attributes_ex (mono_string_chars (path), &data);
if (result) {
- convert_win32_file_attribute_data (&data,
- mono_string_chars (path),
- stat);
+ convert_win32_file_attribute_data (&data, stat);
} else {
*error=GetLastError ();
memset (stat, 0, sizeof (MonoIOStat));
}
+ MONO_FINISH_BLOCKING
return result;
}
{
HANDLE ret;
int attributes, attrs;
- gunichar2 *chars = mono_string_chars (filename);
-
- MONO_ARCH_SAVE_REGS;
+ gunichar2 *chars;
+ MONO_PREPARE_BLOCKING
+ chars = mono_string_chars (filename);
*error=ERROR_SUCCESS;
if (options != 0){
*error=GetLastError ();
}
+ MONO_FINISH_BLOCKING
return(ret);
}
ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error)
{
gboolean ret;
-
- MONO_ARCH_SAVE_REGS;
+ MONO_PREPARE_BLOCKING
*error=ERROR_SUCCESS;
*error=GetLastError ();
}
+ MONO_FINISH_BLOCKING
return(ret);
}
gboolean result;
guint32 n;
- MONO_ARCH_SAVE_REGS;
-
*error=ERROR_SUCCESS;
- MONO_CHECK_ARG_NULL (dest);
-
- if (dest_offset + count > mono_array_length (dest))
+ MONO_CHECK_ARG_NULL (dest, 0);
+
+ if (dest_offset > mono_array_length (dest) - count) {
+ mono_set_pending_exception (mono_get_exception_argument ("array", "array too small. numBytes/offset wrong."));
return 0;
+ }
buffer = mono_array_addr (dest, guchar, dest_offset);
+
+ MONO_PREPARE_BLOCKING
result = ReadFile (handle, buffer, count, &n, NULL);
+ MONO_FINISH_BLOCKING
if (!result) {
*error=GetLastError ();
gboolean result;
guint32 n;
- MONO_ARCH_SAVE_REGS;
-
*error=ERROR_SUCCESS;
- MONO_CHECK_ARG_NULL (src);
+ MONO_CHECK_ARG_NULL (src, 0);
- if (src_offset + count > mono_array_length (src))
+ 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_ARCH_SAVE_REGS;
+ MONO_PREPARE_BLOCKING
*error=ERROR_SUCCESS;
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_ARCH_SAVE_REGS;
+ MONO_PREPARE_BLOCKING
*error=ERROR_SUCCESS;
*error=GetLastError ();
}
+ MONO_FINISH_BLOCKING
return(ret);
}
{
gint64 length;
guint32 length_hi;
-
- MONO_ARCH_SAVE_REGS;
+ 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)
gint32 length_hi;
gboolean result;
- MONO_ARCH_SAVE_REGS;
-
*error=ERROR_SUCCESS;
/* save file pointer */
const FILETIME *creation_filetime;
const FILETIME *last_access_filetime;
const FILETIME *last_write_filetime;
-
- MONO_ARCH_SAVE_REGS;
+ MONO_PREPARE_BLOCKING
*error=ERROR_SUCCESS;
if(ret==FALSE) {
*error=GetLastError ();
}
-
+
+ MONO_FINISH_BLOCKING
return(ret);
}
HANDLE
ves_icall_System_IO_MonoIO_get_ConsoleOutput ()
{
- MONO_ARCH_SAVE_REGS;
-
return GetStdHandle (STD_OUTPUT_HANDLE);
}
HANDLE
ves_icall_System_IO_MonoIO_get_ConsoleInput ()
{
- MONO_ARCH_SAVE_REGS;
-
return GetStdHandle (STD_INPUT_HANDLE);
}
HANDLE
ves_icall_System_IO_MonoIO_get_ConsoleError ()
{
- MONO_ARCH_SAVE_REGS;
-
return GetStdHandle (STD_ERROR_HANDLE);
}
SECURITY_ATTRIBUTES attr;
gboolean ret;
- MONO_ARCH_SAVE_REGS;
-
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) {
/* FIXME: throw an exception? */
return(FALSE);
/* This is only used on Windows */
gboolean ret;
- MONO_ARCH_SAVE_REGS;
-
+ MONO_PREPARE_BLOCKING
ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options);
+ MONO_FINISH_BLOCKING
+
if(ret==FALSE) {
/* FIXME: throw an exception? */
return(FALSE);
MonoDomain *domain;
int i, n;
- MONO_ARCH_SAVE_REGS;
-
domain = mono_domain_get ();
n = sizeof (invalid_path_chars) / sizeof (gunichar2);
chars = mono_array_new (domain, mono_defaults.char_class, n);
gunichar2 *name;
int ret;
+ MONO_PREPARE_BLOCKING
name=g_new0 (gunichar2, 256);
ret=GetTempPath (256, name);
name=g_new0 (gunichar2, ret+2); /* include the terminator */
ret=GetTempPath (ret, name);
}
+ MONO_FINISH_BLOCKING
if(ret>0) {
#ifdef DEBUG
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.
-#if (defined (__MACH__) && defined (TARGET_ARM)) || defined (TARGET_ANDROID)
+#if defined (TARGET_IOS) || defined (TARGET_ANDROID)
gint64
mono_filesize_from_path (MonoString *string)
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;