예제 #1
0
int
mono_mmap_map (void *handle, gint64 offset, gint64 *size, int access, void **mmap_handle, void **base_address)
{
	gint64 mmap_offset = 0;
	MmapHandle *fh = (MmapHandle *)handle;
	MmapInstance res = { 0 };
	size_t eff_size = *size;
	struct stat buf = { 0 };
	fstat (fh->fd, &buf); //FIXME error handling

	*mmap_handle = NULL;
	*base_address = NULL;

	if (offset > buf.st_size || ((eff_size + offset) > buf.st_size && !is_special_zero_size_file (&buf)))
		return ACCESS_DENIED;
	/**
	  * 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 = align_up_to_page_size (buf.st_size) - offset;
	*size = eff_size;

	mmap_offset = align_down_to_page_size (offset);
	eff_size += (offset - mmap_offset);
	//FIXME translate some interesting errno values
	res.address = mono_file_map ((size_t)eff_size, acess_to_mmap_flags (access), fh->fd, mmap_offset, &res.free_handle);
	res.length = eff_size;

	if (res.address) {
		*mmap_handle = g_memdup (&res, sizeof (MmapInstance));
		*base_address = (char*)res.address + (offset - mmap_offset);
		return 0;
	}

	return COULD_NOT_MAP_MEMORY;
}
예제 #2
0
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;
}
예제 #3
0
/*
XXX implement options
*/
static void*
open_file_map (MonoString *path, int input_fd, int mode, gint64 *capacity, int access, int options, int *error)
{
	struct stat buf;
	char *c_path = path ? mono_string_to_utf8 (path) : NULL;
	MmapHandle *handle = NULL;
	int result, fd;

	if (path)
		result = stat (c_path, &buf);
	else
		result = fstat (input_fd, &buf);

	if (mode == FILE_MODE_TRUNCATE || mode == FILE_MODE_APPEND || mode == FILE_MODE_OPEN) {
		if (result == -1) { //XXX translate errno?
			*error = FILE_NOT_FOUND;
			goto done;
		}
	}

	if (mode == FILE_MODE_CREATE_NEW && result == 0) {
		*error = FILE_ALREADY_EXISTS;
		goto done;
	}

	if (result == 0) {
		if (*capacity == 0) {
			/**
			 * Special files such as FIFOs, sockets, and devices can have a size of 0. Specifying a capacity for these
			 * also makes little sense, so don't do the check if th file is one of these.
			 */
			if (buf.st_size == 0 && !is_special_zero_size_file (&buf)) {
				*error = CAPACITY_SMALLER_THAN_FILE_SIZE;
				goto done;
			}
			*capacity = buf.st_size;
		} else if (*capacity < buf.st_size) {
			*error = CAPACITY_SMALLER_THAN_FILE_SIZE;
			goto done;
		}
	} else {
		if (mode == FILE_MODE_CREATE_NEW && *capacity == 0) {
			*error = CAPACITY_SMALLER_THAN_FILE_SIZE;
			goto done;
		}
	}

	if (path) //FIXME use io portability?
		fd = open (c_path, file_mode_to_unix (mode) | access_mode_to_unix (access), DEFAULT_FILEMODE);
	else
		fd = dup (input_fd);

	if (fd == -1) { //XXX translate errno?
		*error = COULD_NOT_OPEN;
		goto done;
	}

	*capacity = align_up_to_page_size ((size_t)*capacity);

	if (*capacity > buf.st_size) {
		int unused G_GNUC_UNUSED = ftruncate (fd, (off_t)*capacity);
	}

	handle = g_new0 (MmapHandle, 1);
	handle->ref_count = 1;
	handle->capacity = *capacity;
	handle->fd = fd;

done:
	g_free (c_path);
	return (void*)handle;
}
예제 #4
0
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;
}