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