void * mono_mmap_open_file (MonoString *path, int mode, MonoString *mapName, gint64 *capacity, int access, int options, int *error) { g_assert (path || mapName); if (!mapName) return open_file_map (path, -1, mode, capacity, access, options, error); if (path) { 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; } else { handle = 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); } } named_regions_unlock (); g_free (c_mapName); return handle; } return open_memory_map (mapName, mode, capacity, access, options, error); }
/* this is an icall */ void * mono_mmap_open_handle (void *input_fd, MonoString *mapName, gint64 *capacity, int access, int options, int *ioerror) { MonoError error; MmapHandle *handle; if (!mapName) { handle = (MmapHandle *)open_file_map (NULL, GPOINTER_TO_INT (input_fd), FILE_MODE_OPEN, capacity, access, options, ioerror); } else { char *c_mapName = mono_string_to_utf8_checked (mapName, &error); if (mono_error_set_pending_exception (&error)) return NULL; named_regions_lock (); handle = (MmapHandle*)g_hash_table_lookup (named_regions, c_mapName); if (handle) { *ioerror = 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, ioerror); 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; named_regions_lock (); --handle->ref_count; if (handle->ref_count == 0) { if (handle->name) g_hash_table_remove (named_regions, handle->name); g_free (handle->name); close (handle->fd); g_free (handle); } named_regions_unlock (); }
/* This is an icall */ void * mono_mmap_open_file (MonoString *path, int mode, MonoString *mapName, gint64 *capacity, int access, int options, int *ioerror) { MonoError error; MmapHandle *handle = NULL; g_assert (path || mapName); if (!mapName) { char * c_path = mono_string_to_utf8_checked (path, &error); if (mono_error_set_pending_exception (&error)) return NULL; handle = open_file_map (c_path, -1, mode, capacity, access, options, ioerror); g_free (c_path); return handle; } char *c_mapName = mono_string_to_utf8_checked (mapName, &error); if (mono_error_set_pending_exception (&error)) return NULL; if (path) { named_regions_lock (); handle = (MmapHandle*)g_hash_table_lookup (named_regions, c_mapName); if (handle) { *ioerror = FILE_ALREADY_EXISTS; handle = NULL; } else { char *c_path = mono_string_to_utf8_checked (path, &error); if (is_ok (&error)) { handle = (MmapHandle *)open_file_map (c_path, -1, mode, capacity, access, options, ioerror); if (handle) { handle->name = g_strdup (c_mapName); g_hash_table_insert (named_regions, handle->name, handle); } } else { handle = NULL; } g_free (c_path); } named_regions_unlock (); } else handle = open_memory_map (c_mapName, mode, capacity, access, options, ioerror); g_free (c_mapName); return handle; }
static void* open_memory_map (MonoString *mapName, int mode, gint64 *capacity, int access, int options, int *error) { char *c_mapName; MmapHandle *handle; if (*capacity <= 1) { *error = CAPACITY_MUST_BE_POSITIVE; return NULL; } if (!(mode == FILE_MODE_CREATE_NEW || mode == FILE_MODE_OPEN_OR_CREATE || mode == FILE_MODE_OPEN)) { *error = INVALID_FILE_MODE; return NULL; } c_mapName = mono_string_to_utf8 (mapName); named_regions_lock (); handle = (MmapHandle*)g_hash_table_lookup (named_regions, c_mapName); if (handle) { if (mode == FILE_MODE_CREATE_NEW) { *error = FILE_ALREADY_EXISTS; goto done; } handle->ref_count++; //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; if (mode == FILE_MODE_OPEN) { *error = FILE_NOT_FOUND; goto done; } *capacity = align_up_to_page_size (*capacity); strcpy (file_name, MONO_ANON_FILE_TEMPLATE); fd = mkstemp (file_name); if (fd == -1) { *error = COULD_NOT_MAP_MEMORY; goto done; } unlink (file_name); unused = ftruncate (fd, (off_t)*capacity); handle = g_new0 (MmapHandle, 1); handle->ref_count = 1; handle->capacity = *capacity; handle->fd = fd; handle->name = g_strdup (c_mapName); g_hash_table_insert (named_regions, handle->name, handle); } done: named_regions_unlock (); g_free (c_mapName); return handle; }
static void* open_memory_map (const char *c_mapName, int mode, gint64 *capacity, int access, int options, int *ioerror) { MmapHandle *handle; if (*capacity <= 0) { *ioerror = CAPACITY_MUST_BE_POSITIVE; return NULL; } #if SIZEOF_VOID_P == 4 if (*capacity > UINT32_MAX) { *ioerror = CAPACITY_LARGER_THAN_LOGICAL_ADDRESS_SPACE; return NULL; } #endif if (!(mode == FILE_MODE_CREATE_NEW || mode == FILE_MODE_OPEN_OR_CREATE || mode == FILE_MODE_OPEN)) { *ioerror = INVALID_FILE_MODE; return NULL; } named_regions_lock (); handle = (MmapHandle*)g_hash_table_lookup (named_regions, c_mapName); if (handle) { if (mode == FILE_MODE_CREATE_NEW) { *ioerror = FILE_ALREADY_EXISTS; goto done; } handle->ref_count++; //XXX should we ftruncate if the file is smaller than capacity? } else { int fd; char *file_name; const char *tmp_dir; int unused G_GNUC_UNUSED, alloc_size; if (mode == FILE_MODE_OPEN) { *ioerror = FILE_NOT_FOUND; goto done; } *capacity = align_up_to_page_size (*capacity); 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 *ioerror = 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) { *ioerror = COULD_NOT_MAP_MEMORY; goto done; } unlink (file_name); unused = ftruncate (fd, (off_t)*capacity); handle = g_new0 (MmapHandle, 1); handle->ref_count = 1; handle->capacity = *capacity; handle->fd = fd; handle->name = g_strdup (c_mapName); g_hash_table_insert (named_regions, handle->name, handle); } done: named_regions_unlock (); return handle; }