First set of licensing changes
[mono.git] / mono / metadata / file-mmap-posix.c
index 0ef54ab82fcd7a73ea8dbdf0e3112b6fc258a867..efa5547f6e485fa3a5f81522dc9fddc2153194c9 100644 (file)
@@ -5,11 +5,12 @@
  *     Rodrigo Kumpera
  *
  * Copyright 2014 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>
 
-#ifndef TARGET_WIN32
+#ifndef HOST_WIN32
 
 #include <glib.h>
 #include <string.h>
@@ -36,6 +37,8 @@
 #include <mono/utils/atomic.h>
 #include <mono/utils/mono-memory-model.h>
 #include <mono/utils/mono-mmap.h>
+#include <mono/utils/mono-coop-mutex.h>
+#include <mono/utils/mono-threads.h>
 
 typedef struct {
        int kind;
@@ -81,14 +84,14 @@ enum {
        MMAP_FILE_ACCESS_READ_WRITE_EXECUTE = 5,
 };
 
-#ifdef PLATFORM_ANDROID
-#define DEFAULT_FILEMODE 0666
-#else
+#ifdef DEFFILEMODE
 #define DEFAULT_FILEMODE DEFFILEMODE
+#else
+#define DEFAULT_FILEMODE 0666
 #endif
 
 static int mmap_init_state;
-static mono_mutex_t named_regions_mutex;
+static MonoCoopMutex named_regions_mutex;
 static GHashTable *named_regions;
 
 
@@ -115,14 +118,14 @@ retry:
                if (InterlockedCompareExchange (&mmap_init_state, 1, 0) != 0)
                        goto retry;
                named_regions = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
-               mono_mutex_init (&named_regions_mutex);
+               mono_coop_mutex_init (&named_regions_mutex);
 
                mono_atomic_store_release (&mmap_init_state, 2);
                break;
 
        case 1:
                do {
-                       g_usleep (1000); /* Been init'd by other threads, this is very rare. */
+                       mono_thread_info_sleep (1, NULL); /* Been init'd by other threads, this is very rare. */
                } while (mmap_init_state != 2);
                break;
        case 2:
@@ -136,13 +139,13 @@ static void
 named_regions_lock (void)
 {
        file_mmap_init ();
-       mono_mutex_lock (&named_regions_mutex);
+       mono_coop_mutex_lock (&named_regions_mutex);
 }
 
 static void
 named_regions_unlock (void)
 {
-       mono_mutex_unlock (&named_regions_mutex);       
+       mono_coop_mutex_unlock (&named_regions_mutex);
 }
 
 
@@ -280,9 +283,7 @@ open_file_map (MonoString *path, int input_fd, int mode, gint64 *capacity, int a
                goto done;
        }
 
-       *capacity = align_up_to_page_size ((size_t)*capacity);
-
-       if (*capacity > buf.st_size) {
+       if (result != 0 || *capacity > buf.st_size) {
                int unused G_GNUC_UNUSED = ftruncate (fd, (off_t)*capacity);
        }
 
@@ -296,7 +297,7 @@ done:
        return (void*)handle;
 }
 
-#define MONO_ANON_FILE_TEMPLATE "/tmp/mono.anonmap.XXXXXXXXX"
+#define MONO_ANON_FILE_TEMPLATE "/mono.anonmap.XXXXXXXXX"
 static void*
 open_memory_map (MonoString *mapName, int mode, gint64 *capacity, int access, int options, int *error)
 {
@@ -326,8 +327,9 @@ open_memory_map (MonoString *mapName, int mode, gint64 *capacity, int access, in
                //XXX should we ftruncate if the file is smaller than capacity?
        } else {
                int fd;
-               char file_name [sizeof (MONO_ANON_FILE_TEMPLATE) + 1];
-               int unused G_GNUC_UNUSED;
+               char *file_name;
+               const char *tmp_dir;
+               int unused G_GNUC_UNUSED, alloc_size;
 
                if (mode == FILE_MODE_OPEN) {
                        *error = FILE_NOT_FOUND;
@@ -335,7 +337,16 @@ open_memory_map (MonoString *mapName, int mode, gint64 *capacity, int access, in
                }
                *capacity = align_up_to_page_size (*capacity);
 
-               strcpy (file_name, MONO_ANON_FILE_TEMPLATE);
+               tmp_dir = g_get_tmp_dir ();
+               alloc_size = strlen (tmp_dir) + strlen (MONO_ANON_FILE_TEMPLATE) + 1;
+               if (alloc_size > 1024) {//rather fail that stack overflow
+                       *error = COULD_NOT_MAP_MEMORY;
+                       goto done;
+               }
+               file_name = (char *)alloca (alloc_size);
+               strcpy (file_name, tmp_dir);
+               strcat (file_name, MONO_ANON_FILE_TEMPLATE);
+
                fd = mkstemp (file_name);
                if (fd == -1) {
                        *error = COULD_NOT_MAP_MEMORY;
@@ -381,7 +392,7 @@ mono_mmap_open_file (MonoString *path, int mode, MonoString *mapName, gint64 *ca
                        *error = FILE_ALREADY_EXISTS;
                        handle = NULL;
                } else {
-                       handle = open_file_map (path, -1, mode, capacity, access, options, error);
+                       handle = (MmapHandle *)open_file_map (path, -1, mode, capacity, access, options, error);
                        if (handle) {
                                handle->name = g_strdup (c_mapName);
                                g_hash_table_insert (named_regions, handle->name, handle);
@@ -400,29 +411,33 @@ void *
 mono_mmap_open_handle (void *input_fd, MonoString *mapName, gint64 *capacity, int access, int options, int *error)
 {
        MmapHandle *handle;
-       char *c_mapName = mono_string_to_utf8 (mapName);
-
-       named_regions_lock ();
-       handle = (MmapHandle*)g_hash_table_lookup (named_regions, c_mapName);
-       if (handle) {
-               *error = FILE_ALREADY_EXISTS;
-               handle = NULL;
+       if (!mapName) {
+               handle = (MmapHandle *)open_file_map (NULL, GPOINTER_TO_INT (input_fd), FILE_MODE_OPEN, capacity, access, options, error);
        } else {
-               //XXX we're exploiting wapi HANDLE == FD equivalence. THIS IS FRAGILE, create a _wapi_handle_to_fd call
-               handle = open_file_map (NULL, GPOINTER_TO_INT (input_fd), FILE_MODE_OPEN, capacity, access, options, error);
-               handle->name = g_strdup (c_mapName);
-               g_hash_table_insert (named_regions, handle->name, handle);
-       }
-       named_regions_unlock ();
+               char *c_mapName = mono_string_to_utf8 (mapName);
 
-       g_free (c_mapName);
+               named_regions_lock ();
+               handle = (MmapHandle*)g_hash_table_lookup (named_regions, c_mapName);
+               if (handle) {
+                       *error = FILE_ALREADY_EXISTS;
+                       handle = NULL;
+               } else {
+                       //XXX we're exploiting wapi HANDLE == FD equivalence. THIS IS FRAGILE, create a _wapi_handle_to_fd call
+                       handle = (MmapHandle *)open_file_map (NULL, GPOINTER_TO_INT (input_fd), FILE_MODE_OPEN, capacity, access, options, error);
+                       handle->name = g_strdup (c_mapName);
+                       g_hash_table_insert (named_regions, handle->name, handle);
+               }
+               named_regions_unlock ();
+
+               g_free (c_mapName);
+       }
        return handle;
 }
 
 void
 mono_mmap_close (void *mmap_handle)
 {
-       MmapHandle *handle = mmap_handle;
+       MmapHandle *handle = (MmapHandle *)mmap_handle;
 
        named_regions_lock ();
        --handle->ref_count;
@@ -440,7 +455,7 @@ mono_mmap_close (void *mmap_handle)
 void
 mono_mmap_configure_inheritability (void *mmap_handle, gboolean inheritability)
 {
-       MmapHandle *h = mmap_handle;
+       MmapHandle *h = (MmapHandle *)mmap_handle;
        int fd, flags;
 
        fd = h->fd;
@@ -455,7 +470,7 @@ mono_mmap_configure_inheritability (void *mmap_handle, gboolean inheritability)
 void
 mono_mmap_flush (void *mmap_handle)
 {
-       MmapInstance *h = mmap_handle;
+       MmapInstance *h = (MmapInstance *)mmap_handle;
 
        if (h)
                msync (h->address, h->length, MS_SYNC);
@@ -465,19 +480,21 @@ int
 mono_mmap_map (void *handle, gint64 offset, gint64 *size, int access, void **mmap_handle, void **base_address)
 {
        gint64 mmap_offset = 0;
-       MmapHandle *fh = handle;
+       MmapHandle *fh = (MmapHandle *)handle;
        MmapInstance res = { 0 };
        size_t eff_size = *size;
        struct stat buf = { 0 };
        fstat (fh->fd, &buf); //FIXME error handling
 
+       if (offset > buf.st_size || ((eff_size + offset) > buf.st_size && !is_special_zero_size_file (&buf)))
+               goto error;
        /**
          * We use the file size if one of the following conditions is true:
          *  -input size is zero
          *  -input size is bigger than the file and the file is not a magical zero size file such as /dev/mem.
          */
-       if (eff_size == 0 || (eff_size > buf.st_size && !is_special_zero_size_file (&buf)))
-               eff_size = buf.st_size;
+       if (eff_size == 0)
+               eff_size = align_up_to_page_size (buf.st_size) - offset;
        *size = eff_size;
 
        mmap_offset = align_down_to_page_size (offset);
@@ -492,6 +509,7 @@ mono_mmap_map (void *handle, gint64 offset, gint64 *size, int access, void **mma
                return 0;
        }
 
+error:
        *mmap_handle = NULL;
        *base_address = NULL;
        return COULD_NOT_MAP_MEMORY;
@@ -501,7 +519,7 @@ gboolean
 mono_mmap_unmap (void *mmap_handle)
 {
        int res = 0;
-       MmapInstance *h = mmap_handle;
+       MmapInstance *h = (MmapInstance *)mmap_handle;
 
        res = mono_file_unmap (h->address, h->free_handle);