• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2007-2010 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 ** GNU General Public License for more details.
11 */
12 
13 /*
14  * Contains implementation of routines that implement platform-independent
15  * file I/O.
16  */
17 
18 #include "stddef.h"
19 #include "sys/types.h"
20 #include "errno.h"
21 #ifdef  WIN32
22 #include "windows.h"
23 #else   // WIN32
24 #include <sys/mman.h>
25 #endif  // WIN32
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 
30 #include "mapfile.h"
31 
32 MapFile*
mapfile_open(const char * path,int oflag,int share_mode)33 mapfile_open(const char* path, int oflag, int share_mode)
34 {
35 #ifdef WIN32
36     DWORD win32_share;
37     DWORD win32_desired_access = GENERIC_READ;
38     DWORD win32_disposition = OPEN_EXISTING;
39     DWORD win32_flags;
40 
41     /* Convert to Win32 desired access. */
42     if ((oflag & O_RDWR) == O_RDWR) {
43         win32_desired_access = GENERIC_READ | GENERIC_WRITE;
44     } else if ((oflag & O_ACCMODE) == O_RDONLY) {
45         win32_desired_access = GENERIC_READ;
46     } else if ((oflag & O_WRONLY) == O_WRONLY) {
47         win32_desired_access = GENERIC_WRITE;
48     }
49 
50     /* Convert to Win32 sharing. */
51     win32_share = 0;
52     if ((share_mode & S_IWRITE) != 0) {
53         win32_share |= FILE_SHARE_WRITE;
54     }
55     if ((share_mode & S_IREAD) != 0) {
56         win32_share |= FILE_SHARE_READ;
57     }
58 
59     /* Convert to Win32 disposition. */
60     if ((oflag & O_CREAT) == O_CREAT) {
61         if ((oflag & O_EXCL) == O_EXCL) {
62             win32_disposition = CREATE_NEW;
63         } else {
64             win32_disposition = OPEN_ALWAYS;
65         }
66     } if ((oflag & O_TRUNC) == O_TRUNC) {
67         win32_desired_access = TRUNCATE_EXISTING;
68     } else {
69         win32_disposition = OPEN_EXISTING;
70     }
71 
72     /* Convert to Win32 flags. */
73     win32_flags = 0;
74 #if defined(O_DSYNC)
75     if ((oflag & O_DSYNC) == O_DSYNC ||
76         (oflag & O_RSYNC) == O_RSYNC ||
77         (oflag & O_RSYNC) == O_SYNC) {
78         win32_flags |= FILE_FLAG_WRITE_THROUGH;
79     }
80 #endif  // O_DSYNC
81 
82     HANDLE file_handle = CreateFile(path, win32_desired_access, win32_share,
83                                     NULL, win32_disposition, win32_flags, NULL);
84     if (file_handle == INVALID_HANDLE_VALUE) {
85         errno = GetLastError();
86     }
87 #else   // WIN32
88     int file_handle = open(path, oflag, share_mode);
89 #endif  // WIN32
90 
91     return (MapFile*)(ptrdiff_t)file_handle;
92 }
93 
94 int
mapfile_close(MapFile * handle)95 mapfile_close(MapFile* handle)
96 {
97 #ifdef WIN32
98     if (CloseHandle(handle)) {
99         return 0;
100     } else {
101         errno = GetLastError();
102         return -1;
103     }
104 #else   // WIN32
105     return close((int)(ptrdiff_t)handle);
106 #endif  // WIN32
107 }
108 
109 ssize_t
mapfile_read(MapFile * handle,void * buf,size_t nbyte)110 mapfile_read(MapFile* handle, void* buf, size_t nbyte)
111 {
112 #ifdef WIN32
113     ssize_t ret_bytes;
114     DWORD read_bytes;
115     if (ReadFile(handle, buf, nbyte, &read_bytes, NULL)) {
116         ret_bytes = (ssize_t)read_bytes;
117     } else {
118         errno = GetLastError();
119         ret_bytes = -1;
120     }
121     return ret_bytes;
122 #else   // WIN32
123     ssize_t ret;
124     do {
125         ret = read((int)(ptrdiff_t)handle, buf, nbyte);
126     } while (ret < 0 && errno == EINTR);
127     return ret;
128 #endif  // WIN32
129 }
130 
131 ssize_t
mapfile_read_at(MapFile * handle,size_t offset,void * buf,size_t nbyte)132 mapfile_read_at(MapFile* handle, size_t offset, void* buf, size_t nbyte)
133 {
134 #ifdef WIN32
135     LARGE_INTEGER convert;
136     convert.QuadPart = offset;
137     if ((SetFilePointer(handle, convert.LowPart, &convert.HighPart,
138                         FILE_BEGIN) == INVALID_SET_FILE_POINTER) &&
139             (GetLastError() != NO_ERROR)) {
140         errno = GetLastError();
141         return -1;
142     }
143     return mapfile_read(handle, buf, nbyte);
144 #else   // WIN32
145     ssize_t res = lseek((int)(ptrdiff_t)handle, offset, SEEK_SET);
146     return res >= 0 ? mapfile_read(handle, buf, nbyte) : res;
147 #endif  // WIN32
148 }
149 
150 void*
mapfile_map(MapFile * handle,size_t offset,size_t size,int prot,void ** mapped_offset,size_t * mapped_size)151 mapfile_map(MapFile* handle,
152             size_t offset,
153             size_t size,
154             int prot,
155             void** mapped_offset,
156             size_t* mapped_size)
157 {
158     void* mapped_at = NULL;
159     size_t align_mask;
160     size_t map_offset;
161     size_t map_size;
162 
163   /* Get the mask for mapping offset alignment. */
164 #ifdef  WIN32
165     DWORD win32_prot;
166     DWORD win32_map;
167     HANDLE map_handle;
168     LARGE_INTEGER converter;
169     SYSTEM_INFO sys_info;
170     GetSystemInfo(&sys_info);
171     align_mask = sys_info.dwAllocationGranularity - 1;
172 #else   // WIN32
173     align_mask = getpagesize() - 1;
174 #endif  // WIN32
175 
176     /* Adjust mapping offset and mapping size accordingly to
177      * the mapping alignment requirements. */
178     map_offset = offset & ~align_mask;
179     map_size = (size_t)(offset - map_offset + size);
180 
181     /* Make sure mapping size doesn't exceed 4G. */
182     if (map_size < size) {
183         errno = EFBIG;
184         return NULL;
185     }
186 
187     /* Map the section. */
188 #ifdef  WIN32
189     /* Convert to Win32 page protection and mapping type. */
190     win32_prot = PAGE_READONLY;
191     win32_map = FILE_MAP_READ;
192     if (prot != PROT_NONE) {
193         if ((prot & (PROT_WRITE | PROT_EXEC)) == 0) {
194             win32_prot = PAGE_READONLY;
195             win32_map = FILE_MAP_READ;
196         } else if ((prot & (PROT_WRITE | PROT_EXEC)) ==
197                    (PROT_WRITE | PROT_EXEC)) {
198             win32_prot = PAGE_EXECUTE_READWRITE;
199             win32_map = FILE_MAP_WRITE;
200         } else if ((prot & PROT_WRITE) == PROT_WRITE) {
201             win32_prot = PAGE_READWRITE;
202             win32_map = FILE_MAP_WRITE;
203         } else if ((prot & PROT_EXEC) == PROT_EXEC) {
204             win32_prot = PAGE_EXECUTE_READ;
205             win32_map = FILE_MAP_READ;
206         }
207     }
208 
209     converter.QuadPart = map_offset + map_size;
210     map_handle = CreateFileMapping(handle, NULL, win32_prot,
211                                    converter.HighPart, converter.LowPart, NULL);
212     if (map_handle != NULL) {
213         converter.QuadPart = map_offset;
214         mapped_at = MapViewOfFile(map_handle, win32_map, converter.HighPart,
215                                   converter.LowPart, map_size);
216         /* Memory mapping (if successful) will hold extra references to the
217         * mapping, so we can close it right after we mapped file view. */
218         CloseHandle(map_handle);
219     }
220     if (mapped_at == NULL) {
221         errno = GetLastError();
222         return NULL;
223     }
224 #else   // WIN32
225     mapped_at =
226         mmap(0, map_size, PROT_READ, MAP_SHARED, (int)(ptrdiff_t)handle, map_offset);
227     if (mapped_at == MAP_FAILED) {
228         return NULL;
229     }
230 #endif  // WIN32
231 
232     *mapped_offset = (char*)mapped_at + (offset - map_offset);
233     *mapped_size = size;
234 
235     return mapped_at;
236 }
237 
238 int
mapfile_unmap(void * mapped_at,size_t len)239 mapfile_unmap(void* mapped_at, size_t len)
240 {
241 #ifdef WIN32
242     if (!UnmapViewOfFile(mapped_at)) {
243         errno = GetLastError();
244         return -1;
245     }
246     return 0;
247 #else   // WIN32
248     return munmap(mapped_at, len);
249 #endif  // WIN32
250 }
251