NaCl runtime fixes
[mono.git] / mono / io-layer / io.c
index a046d1a5e0add7ecb7822f78f04ec67bd76542c8..a3e5ad15b56aaa87d2e9c89b1266c7bd1753a363 100755 (executable)
@@ -708,6 +708,8 @@ 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
         */
@@ -722,6 +724,7 @@ static gboolean file_setendoffile(gpointer handle)
                _wapi_set_last_error_from_errno ();
                return(FALSE);
        }
+#endif
                
        return(TRUE);
 }
@@ -1512,6 +1515,13 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
                
                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);
+#endif
 
        if (share_check (&statbuf, sharemode, fileaccess,
                         &file_handle.share_info, fd) == FALSE) {
@@ -2746,6 +2756,7 @@ retry:
                goto retry;
        }
 
+#ifndef __native_client__
        result = _wapi_lstat (filename, &linkbuf);
        if (result != 0) {
                DEBUG ("%s: lstat failed: %s", __func__, filename);
@@ -2753,6 +2764,7 @@ retry:
                g_free (filename);
                goto retry;
        }
+#endif
 
        utf8_filename = mono_utf8_from_external (filename);
        if (utf8_filename == NULL) {
@@ -2776,7 +2788,11 @@ 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
 
        _wapi_time_t_to_filetime (create_time, &find_data->ftCreationTime);
        _wapi_time_t_to_filetime (buf.st_atime, &find_data->ftLastAccessTime);
@@ -2999,14 +3015,20 @@ guint32 GetFileAttributes (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);
 
@@ -3203,6 +3225,12 @@ extern guint32 GetCurrentDirectory (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 ((char*)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*/
@@ -3216,6 +3244,7 @@ extern guint32 GetCurrentDirectory (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;
@@ -4126,8 +4155,12 @@ GetDriveTypeFromPath (const gchar *utf8_root_path_name)
                if (strcmp (*(splitted + 1), utf8_root_path_name) == 0 ||
                    (strcmp (*(splitted + 1), "/") == 0 && strlen (utf8_root_path_name) == 0)) {
                        drive_type = _wapi_get_drive_type (*(splitted + 2));
-                       g_strfreev (splitted);
-                       break;
+                       /* it is possible this path might be mounted again with
+                          a known type...keep looking */
+                       if (drive_type != DRIVE_UNKNOWN) {
+                               g_strfreev (splitted);
+                               break;
+                       }
                }
 
                g_strfreev (splitted);
@@ -4167,7 +4200,7 @@ guint32 GetDriveType(const gunichar2 *root_path_name)
        return (drive_type);
 }
 
-static const gchar*
+static gchar*
 get_fstypename (gchar *utfpath)
 {
 #if defined (PLATFORM_MACOSX) || defined (__linux__)
@@ -4178,12 +4211,12 @@ get_fstypename (gchar *utfpath)
        if (statfs (utfpath, &stat) == -1)
                return NULL;
 #if PLATFORM_MACOSX
-       return stat.f_fstypename;
+       return g_strdup (stat.f_fstypename);
 #else
        current = &_wapi_drive_types[0];
        while (current->drive_type != DRIVE_UNKNOWN) {
                if (stat.f_type == current->fstypeid)
-                       return current->fstype;
+                       return g_strdup (current->fstype);
                current++;
        }
        return NULL;
@@ -4199,7 +4232,7 @@ gboolean
 GetVolumeInformation (const gunichar2 *path, gunichar2 *volumename, int volumesize, int *outserial, int *maxcomp, int *fsflags, gunichar2 *fsbuffer, int fsbuffersize)
 {
        gchar *utfpath;
-       const gchar *fstypename;
+       gchar *fstypename;
        gboolean status = FALSE;
        glong len;
        
@@ -4217,6 +4250,7 @@ GetVolumeInformation (const gunichar2 *path, gunichar2 *volumename, int volumesi
                }
                if (ret != NULL)
                        g_free (ret);
+               g_free (fstypename);
        }
        g_free (utfpath);
        return status;