+/**
+ * \file
+ */
#include <config.h>
#include <glib.h>
#ifdef EINTR
case G_FILE_ERROR_INTR: return EINTR;
#endif
-#ifdef EWIO
+#ifdef EIO
case G_FILE_ERROR_IO: return EIO;
#endif
#ifdef EPERM
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;
}
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;
}
return TRUE;
-#endif /* __native_client__ */
}
static void file_close (gpointer handle, gpointer data);
}
#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
*/
_wapi_set_last_error_from_errno ();
return(FALSE);
}
-#endif
return(TRUE);
}
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_allows_open (&statbuf, sharemode, fileaccess,
&file_handle.share_info) == FALSE) {
gchar *filename;
gint retval;
gboolean ret = FALSE;
- guint32 attrs;
#if 0
struct stat statbuf;
FileShare *shareinfo;
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.
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;
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);
file_handle.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);
mono_w32error_set_last (ERROR_NO_MORE_FILES);
goto done;
}
- } else {
- /* Add a reference to this handle */
- mono_w32handle_ref (handle);
}
done:
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);
g_free (filename);
goto retry;
}
-#endif
utf8_filename = mono_utf8_from_external (filename);
if (utf8_filename == NULL) {
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);
}
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);
}
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);
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*/
_wapi_set_last_error_from_errno ();
return 0;
}
-#endif
utf16_path = mono_unicode_from_external ((gchar*)buffer, &bytes);
count = (bytes/2)+1;
return (drive_type);
}
-#if defined (PLATFORM_MACOSX) || defined (__linux__) || defined(PLATFORM_BSD) || defined(__native_client__) || defined(__FreeBSD_kernel__) || defined(__HAIKU__)
+#if defined (PLATFORM_MACOSX) || defined (__linux__) || defined(PLATFORM_BSD) || defined(__FreeBSD_kernel__) || defined(__HAIKU__)
static gchar*
get_fstypename (gchar *utfpath)
{
/* mono_w32handle_register_capabilities (MONO_W32HANDLE_CONSOLE, */
/* MONO_W32HANDLE_CAP_WAIT); */
- if (g_getenv ("MONO_STRICT_IO_EMULATION"))
+ if (g_hasenv ("MONO_STRICT_IO_EMULATION"))
lock_while_writing = TRUE;
}