1 /**
2  * \file
3  * Unix/Windows implementation for filemap.
4  *
5  * Author:
6  *   Paolo Molaro (lupus@ximian.com)
7  *
8  * Copyright 2008-2008 Novell, Inc.
9  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
10  */
11 
12 #include "config.h"
13 
14 #if HAVE_SYS_STAT_H
15 #include <sys/stat.h>
16 #endif
17 #include <fcntl.h>
18 #include <string.h>
19 #ifdef HAVE_UNISTD_H
20 #include <unistd.h>
21 #endif
22 #include <stdlib.h>
23 #include <stdio.h>
24 
25 #include "mono-mmap.h"
26 
27 MonoFileMap *
mono_file_map_open(const char * name)28 mono_file_map_open (const char* name)
29 {
30 #ifdef WIN32
31 	gunichar2 *wname = g_utf8_to_utf16 (name, -1, 0, 0, 0);
32 	MonoFileMap *result;
33 
34 	if (wname == NULL)
35 		return NULL;
36 	result = (MonoFileMap *) _wfopen ((wchar_t *) wname, L"rb");
37 	g_free (wname);
38 	return result;
39 #else
40 	int fd = open (name, O_RDONLY);
41 	if (fd < 0)
42 		return NULL;
43 	return (MonoFileMap *)(size_t)fd;
44 #endif
45 }
46 
47 guint64
mono_file_map_size(MonoFileMap * fmap)48 mono_file_map_size (MonoFileMap *fmap)
49 {
50 	struct stat stat_buf;
51 	if (fstat (mono_file_map_fd (fmap), &stat_buf) < 0)
52 		return 0;
53 	return stat_buf.st_size;
54 }
55 
56 int
mono_file_map_fd(MonoFileMap * fmap)57 mono_file_map_fd (MonoFileMap *fmap)
58 {
59 #ifdef WIN32
60 	return fileno ((FILE*)fmap);
61 #else
62 	return (int)(size_t)fmap;
63 #endif
64 }
65 
66 int
mono_file_map_close(MonoFileMap * fmap)67 mono_file_map_close (MonoFileMap *fmap)
68 {
69 #ifdef WIN32
70 	return fclose ((FILE*)fmap);
71 #else
72 	return close (mono_file_map_fd (fmap));
73 #endif
74 }
75 
76 #if !defined (HOST_WIN32)
77 
78 static mono_file_map_alloc_fn alloc_fn = (mono_file_map_alloc_fn) malloc;
79 static mono_file_map_release_fn release_fn = (mono_file_map_release_fn) free;
80 
81 void
mono_file_map_set_allocator(mono_file_map_alloc_fn alloc,mono_file_map_release_fn release)82 mono_file_map_set_allocator (mono_file_map_alloc_fn alloc, mono_file_map_release_fn release)
83 {
84 	alloc_fn = alloc == NULL     ? (mono_file_map_alloc_fn) malloc : alloc;
85 	release_fn = release == NULL ? (mono_file_map_release_fn) free : release;
86 }
87 
88 void *
mono_file_map_fileio(size_t length,int flags,int fd,guint64 offset,void ** ret_handle)89 mono_file_map_fileio (size_t length, int flags, int fd, guint64 offset, void **ret_handle)
90 {
91 	guint64 cur_offset;
92 	size_t bytes_read;
93 	void *ptr = (*alloc_fn) (length);
94 	if (!ptr)
95 		return NULL;
96 	cur_offset = lseek (fd, 0, SEEK_CUR);
97 	if (lseek (fd, offset, SEEK_SET) != offset) {
98 		(*release_fn) (ptr);
99 		return NULL;
100 	}
101 	bytes_read = read (fd, ptr, length);
102 	if (bytes_read != length)
103 		return NULL;
104 	lseek (fd, cur_offset, SEEK_SET);
105 	*ret_handle = NULL;
106 	return ptr;
107 }
108 
109 int
mono_file_unmap_fileio(void * addr,void * handle)110 mono_file_unmap_fileio (void *addr, void *handle)
111 {
112 	(*release_fn) (addr);
113 	return 0;
114 }
115 #if !defined(HAVE_MMAP)
116 void *
mono_file_map(size_t length,int flags,int fd,guint64 offset,void ** ret_handle)117 mono_file_map (size_t length, int flags, int fd, guint64 offset, void **ret_handle)
118 {
119 	return mono_file_map_fileio (length, flags, fd, offset, ret_handle);
120 }
121 
122 int
mono_file_unmap(void * addr,void * handle)123 mono_file_unmap (void *addr, void *handle)
124 {
125 	return mono_file_unmap_fileio(addr, handle);
126 }
127 #endif
128 #endif
129