Merge pull request #1624 from esdrubal/getprocesstimes
[mono.git] / mono / metadata / file-io.c
index c0ed5de44936919449bbcde49d1450bf97972e1f..c4bb6df67659c364a42f5a2a2c47943bea43b63c 100644 (file)
@@ -269,16 +269,16 @@ MonoBoolean
 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);
 }
 
@@ -286,16 +286,16 @@ MonoBoolean
 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);
 }
 
@@ -311,37 +311,29 @@ get_search_dir (MonoString *pattern)
        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;
 
-       result = NULL;
-       *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;
-                       goto leave;
+                       goto fail;
                }
        } else {
                *error = GetLastError ();
-               goto leave;
+               goto fail;
        }
        
        find_handle = FindFirstFile (mono_string_chars (path_with_pattern), &data);
@@ -350,11 +342,11 @@ ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
                
                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);
@@ -381,25 +373,52 @@ ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
 
        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 (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);
        return result;
 }
 
@@ -430,6 +449,7 @@ incremental_find_check_match (IncrementalFind *handle, WIN32_FIND_DATA *data, Mo
        return TRUE;
 }
 
+/* FIXME make gc suspendable */
 MonoString *
 ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
                                      MonoString *path_with_pattern,
@@ -475,6 +495,7 @@ ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
        return result;
 }
 
+/* FIXME make gc suspendable */
 MonoString *
 ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_attr, gint32 *error)
 {
@@ -482,7 +503,7 @@ ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_attr, gint3
        WIN32_FIND_DATA data;
        MonoString *result;
 
-       error = ERROR_SUCCESS;
+       *error = ERROR_SUCCESS;
        do {
                if (FindNextFile (ifh->find_handle, &data) == FALSE){
                        int e = GetLastError ();
@@ -501,13 +522,15 @@ ves_icall_System_IO_MonoIO_FindClose (gpointer handle)
 {
        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;
 }
@@ -519,8 +542,6 @@ ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *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);
        
@@ -555,8 +576,6 @@ ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString *path,
 {
        gboolean ret;
        
-       MONO_ARCH_SAVE_REGS;
-
        *error=ERROR_SUCCESS;
        
        ret=SetCurrentDirectory (mono_string_chars (path));
@@ -572,16 +591,16 @@ ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest,
                                     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);
 }
 
@@ -593,8 +612,7 @@ ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *
        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);
@@ -607,11 +625,13 @@ ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *
        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;
 }
 
@@ -620,9 +640,8 @@ ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest,
                                     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);
@@ -630,6 +649,7 @@ ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest,
                *error=GetLastError ();
        }
        
+       MONO_FINISH_BLOCKING
        return(ret);
 }
 
@@ -637,9 +657,8 @@ MonoBoolean
 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));
@@ -647,6 +666,7 @@ ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error)
                *error=GetLastError ();
        }
        
+       MONO_FINISH_BLOCKING
        return(ret);
 }
 
@@ -654,8 +674,7 @@ gint32
 ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
 {
        gint32 ret;
-       
-       MONO_ARCH_SAVE_REGS;
+       MONO_PREPARE_BLOCKING
 
        *error=ERROR_SUCCESS;
        
@@ -672,6 +691,7 @@ ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
                *error=GetLastError ();
        }
        
+       MONO_FINISH_BLOCKING
        return(ret);
 }
 
@@ -680,9 +700,8 @@ ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
                                              gint32 *error)
 {
        gboolean ret;
+       MONO_PREPARE_BLOCKING
        
-       MONO_ARCH_SAVE_REGS;
-
        *error=ERROR_SUCCESS;
        
        ret=SetFileAttributes (mono_string_chars (path),
@@ -690,7 +709,8 @@ ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
        if(ret==FALSE) {
                *error=GetLastError ();
        }
-       
+
+       MONO_FINISH_BLOCKING
        return(ret);
 }
 
@@ -698,8 +718,7 @@ gint32
 ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
 {
        gboolean ret;
-       
-       MONO_ARCH_SAVE_REGS;
+       MONO_PREPARE_BLOCKING
 
        *error=ERROR_SUCCESS;
        
@@ -711,6 +730,7 @@ ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
                *error=GetLastError ();
        }
        
+       MONO_FINISH_BLOCKING
        return(ret);
 }
 
@@ -720,8 +740,7 @@ ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat,
 {
        gboolean result;
        WIN32_FILE_ATTRIBUTE_DATA data;
-
-       MONO_ARCH_SAVE_REGS;
+       MONO_PREPARE_BLOCKING
 
        *error=ERROR_SUCCESS;
        
@@ -734,6 +753,7 @@ ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat,
                memset (stat, 0, sizeof (MonoIOStat));
        }
 
+       MONO_FINISH_BLOCKING
        return result;
 }
 
@@ -744,10 +764,10 @@ ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
 {
        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){
@@ -790,6 +810,7 @@ ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
                *error=GetLastError ();
        } 
        
+       MONO_FINISH_BLOCKING
        return(ret);
 }
 
@@ -797,8 +818,7 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error)
 {
        gboolean ret;
-       
-       MONO_ARCH_SAVE_REGS;
+       MONO_PREPARE_BLOCKING
 
        *error=ERROR_SUCCESS;
        
@@ -807,6 +827,7 @@ ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error)
                *error=GetLastError ();
        }
        
+       MONO_FINISH_BLOCKING
        return(ret);
 }
 
@@ -819,17 +840,20 @@ ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArray *dest,
        gboolean result;
        guint32 n;
 
-       MONO_ARCH_SAVE_REGS;
-
        *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 ();
@@ -848,17 +872,19 @@ ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArray *src,
        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 > 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 ();
@@ -873,8 +899,7 @@ ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
                                 gint32 *error)
 {
        gint32 offset_hi;
-
-       MONO_ARCH_SAVE_REGS;
+       MONO_PREPARE_BLOCKING
 
        *error=ERROR_SUCCESS;
        
@@ -885,7 +910,8 @@ ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
        if(offset==INVALID_SET_FILE_POINTER) {
                *error=GetLastError ();
        }
-       
+
+       MONO_FINISH_BLOCKING
        return offset | ((gint64)offset_hi << 32);
 }
 
@@ -893,8 +919,7 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
 {
        gboolean ret;
-       
-       MONO_ARCH_SAVE_REGS;
+       MONO_PREPARE_BLOCKING
 
        *error=ERROR_SUCCESS;
        
@@ -903,6 +928,7 @@ ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
                *error=GetLastError ();
        }
        
+       MONO_FINISH_BLOCKING
        return(ret);
 }
 
@@ -911,8 +937,7 @@ ves_icall_System_IO_MonoIO_GetLength (HANDLE handle, gint32 *error)
 {
        gint64 length;
        guint32 length_hi;
-
-       MONO_ARCH_SAVE_REGS;
+       MONO_PREPARE_BLOCKING
 
        *error=ERROR_SUCCESS;
        
@@ -921,9 +946,11 @@ ves_icall_System_IO_MonoIO_GetLength (HANDLE handle, gint32 *error)
                *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)
@@ -933,8 +960,6 @@ ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length,
        gint32 length_hi;
        gboolean result;
 
-       MONO_ARCH_SAVE_REGS;
-
        *error=ERROR_SUCCESS;
        
        /* save file pointer */
@@ -983,8 +1008,7 @@ ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
        const FILETIME *creation_filetime;
        const FILETIME *last_access_filetime;
        const FILETIME *last_write_filetime;
-
-       MONO_ARCH_SAVE_REGS;
+       MONO_PREPARE_BLOCKING
 
        *error=ERROR_SUCCESS;
        
@@ -1007,31 +1031,26 @@ ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
        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);
 }
 
@@ -1042,13 +1061,14 @@ ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_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);
@@ -1064,9 +1084,10 @@ MonoBoolean ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_ha
        /* 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);
@@ -1146,8 +1167,6 @@ ves_icall_System_IO_MonoIO_get_InvalidPathChars ()
        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);
@@ -1164,6 +1183,7 @@ ves_icall_System_IO_MonoIO_GetTempPath (MonoString **mono_name)
        gunichar2 *name;
        int ret;
 
+       MONO_PREPARE_BLOCKING
        name=g_new0 (gunichar2, 256);
        
        ret=GetTempPath (256, name);
@@ -1173,6 +1193,7 @@ ves_icall_System_IO_MonoIO_GetTempPath (MonoString **mono_name)
                name=g_new0 (gunichar2, ret+2); /* include the terminator */
                ret=GetTempPath (ret, name);
        }
+       MONO_FINISH_BLOCKING
        
        if(ret>0) {
 #ifdef DEBUG
@@ -1192,6 +1213,7 @@ void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position,
                                      gint64 length, gint32 *error)
 {
        gboolean ret;
+       MONO_PREPARE_BLOCKING
        
        *error=ERROR_SUCCESS;
        
@@ -1200,12 +1222,15 @@ void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position,
        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;
        
@@ -1214,6 +1239,8 @@ void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position,
        if (ret == FALSE) {
                *error = GetLastError ();
        }
+
+       MONO_FINISH_BLOCKING
 }
 
 //Support for io-layer free mmap'd files.
@@ -1226,13 +1253,16 @@ 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;
 }
 
@@ -1240,8 +1270,13 @@ gint64
 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;