1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3 * Copyright 2010 Couchbase, Inc
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <stdint.h>
21 #include <fcntl.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <string.h>
25
26 #include "filemgr.h"
27 #include "filemgr_ops.h"
28
29 #if defined(WIN32) || defined(_WIN32)
30 #include <windows.h>
31 #include <io.h>
32
handle_to_win(int fd)33 static inline HANDLE handle_to_win(int fd)
34 {
35 return (HANDLE)_get_osfhandle(fd);
36 }
37
_filemgr_win_open(const char *pathname, int flags, mode_t mode)38 int _filemgr_win_open(const char *pathname, int flags, mode_t mode)
39 {
40 #ifdef _MSC_VER
41 int fd = _open(pathname, flags, mode);
42 if (fd < 0) {
43 errno_t err;
44 _get_errno(&err);
45 return (int) convert_errno_to_fdb_status(err, FDB_RESULT_OPEN_FAIL);
46 }
47 return fd;
48 #else
49 int fd;
50 do {
51 fd = open(pathname, flags | O_LARGEFILE, mode);
52 } while (fd == -1 && errno == EINTR);
53
54 if (fd < 0) {
55 return (int) convert_errno_to_fdb_status(errno, FDB_RESULT_OPEN_FAIL)
56 }
57 return fd;
58 #endif
59 }
60
_filemgr_win_pwrite(int fd, void *buf, size_t count, cs_off_t offset)61 ssize_t _filemgr_win_pwrite(int fd, void *buf, size_t count, cs_off_t offset)
62 {
63 HANDLE file = handle_to_win(fd);
64 BOOL rv;
65 DWORD byteswritten;
66 OVERLAPPED winoffs;
67 memset(&winoffs, 0, sizeof(winoffs));
68 winoffs.Offset = offset & 0xFFFFFFFF;
69 winoffs.OffsetHigh = ((uint64_t)offset >> 32) & 0x7FFFFFFF;
70 rv = WriteFile(file, buf, count, &byteswritten, &winoffs);
71 if(!rv) {
72 #ifdef _MSC_VER
73 errno_t err;
74 _get_errno(&err);
75 return (ssize_t) convert_errno_to_fdb_status(err, FDB_RESULT_WRITE_FAIL);
76 #else
77 return (sszie_t) convert_errno_to_fdb_status(errno, FDB_RESULT_WRITE_FAIL);
78 #endif
79 }
80 return (ssize_t) byteswritten;
81 }
82
_filemgr_win_pread(int fd, void *buf, size_t count, cs_off_t offset)83 ssize_t _filemgr_win_pread(int fd, void *buf, size_t count, cs_off_t offset)
84 {
85 HANDLE file = handle_to_win(fd);
86 BOOL rv;
87 DWORD bytesread;
88 OVERLAPPED winoffs;
89 memset(&winoffs, 0, sizeof(winoffs));
90 winoffs.Offset = offset & 0xFFFFFFFF;
91 winoffs.OffsetHigh = ((uint64_t)offset >> 32) & 0x7FFFFFFF;
92 rv = ReadFile(file, buf, count, &bytesread, &winoffs);
93 if(!rv) {
94 #ifdef _MSC_VER
95 errno_t err;
96 _get_errno(&err);
97 return (ssize_t) convert_errno_to_fdb_status(err, FDB_RESULT_READ_FAIL);
98 #else
99 return (ssize_t) convert_errno_to_fdb_status(errno, FDB_RESULT_READ_FAIL);
100 #endif
101 }
102 return (ssize_t) bytesread;
103 }
104
_filemgr_win_close(int fd)105 int _filemgr_win_close(int fd)
106 {
107 #ifdef _MSC_VER
108 int rv = 0;
109 if (fd != -1) {
110 rv = _close(fd);
111 }
112
113 if (rv < 0) {
114 errno_t err;
115 _get_errno(&err);
116 return (int) convert_errno_to_fdb_status(err, FDB_RESULT_CLOSE_FAIL);
117 }
118 return FDB_RESULT_SUCCESS;
119 #else
120 int rv = 0;
121 if (fd != -1) {
122 do {
123 rv = close(fd);
124 } while (rv == -1 && errno == EINTR);
125 }
126
127 if (rv < 0) {
128 return (int) convert_errno_to_fdb_status(errno, FDB_RESULT_CLOSE_FAIL);
129 }
130 return FDB_RESULT_SUCCESS;
131 #endif
132 }
133
_filemgr_win_goto_eof(int fd)134 cs_off_t _filemgr_win_goto_eof(int fd)
135 {
136 #ifdef _MSC_VER
137 cs_off_t rv = _lseeki64(fd, 0, SEEK_END);
138 if (rv < 0) {
139 errno_t err;
140 _get_errno(&err);
141 return (cs_off_t) convert_errno_to_fdb_status(err, FDB_RESULT_SEEK_FAIL);
142 }
143 return rv;
144 #else
145 cs_off_t rv = lseek(fd, 0, SEEK_END);
146 if (rv < 0) {
147 return (cs_off_t) convert_errno_to_fdb_status(errno, FDB_RESULT_SEEK_FAIL);
148 }
149 return rv;
150 #endif
151 }
152
_filemgr_win_file_size(const char *filename)153 cs_off_t _filemgr_win_file_size(const char *filename)
154 {
155 #ifdef _MSC_VER
156 struct _stat st;
157 if (_stat(filename, &st) == -1) {
158 errno_t err;
159 _get_errno(&err);
160 return (cs_off_t) convert_errno_to_fdb_status(err, FDB_RESULT_READ_FAIL);
161 }
162 return st.st_size;
163 #else
164 struct stat st;
165 if (stat(filename, &st) == -1) {
166 return (cs_off_t) convert_errno_to_fdb_status(errno, FDB_RESULT_READ_FAIL);
167 }
168 return st.st_size;
169 #endif
170 }
171
_filemgr_win_fsync(int fd)172 int _filemgr_win_fsync(int fd)
173 {
174 HANDLE file = handle_to_win(fd);
175
176 if (!FlushFileBuffers(file)) {
177 #ifdef _MSC_VER
178 errno_t err;
179 _get_errno(&err);
180 return (int) convert_errno_to_fdb_status(err, FDB_RESULT_FSYNC_FAIL);
181 #else
182 return (int) convert_errno_to_fdb_status(errno, FDB_RESULT_FSYNC_FAIL);
183 #endif
184 }
185 return FDB_RESULT_SUCCESS;
186 }
187
_filemgr_win_fdatasync(int fd)188 int _filemgr_win_fdatasync(int fd)
189 {
190 return _filemgr_win_fsync(fd);
191 }
192
_filemgr_win_get_errno_str(char *buf, size_t size)193 void _filemgr_win_get_errno_str(char *buf, size_t size)
194 {
195 if (!buf) {
196 return;
197 }
198
199 char* win_msg = NULL;
200 DWORD err = GetLastError();
201 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
202 FORMAT_MESSAGE_FROM_SYSTEM |
203 FORMAT_MESSAGE_IGNORE_INSERTS,
204 NULL, err,
205 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
206 (LPTSTR) &win_msg,
207 0, NULL);
208 _snprintf(buf, size, "errno = %d: '%s'", err, win_msg);
209 LocalFree(win_msg);
210 }
211
_filemgr_aio_init(struct async_io_handle *aio_handle)212 int _filemgr_aio_init(struct async_io_handle *aio_handle)
213 {
214 return FDB_RESULT_AIO_NOT_SUPPORTED;
215 }
216
_filemgr_aio_prep_read(struct async_io_handle *aio_handle, size_t aio_idx, size_t read_size, uint64_t offset)217 int _filemgr_aio_prep_read(struct async_io_handle *aio_handle, size_t aio_idx,
218 size_t read_size, uint64_t offset)
219 {
220 return FDB_RESULT_AIO_NOT_SUPPORTED;
221 }
222
_filemgr_aio_submit(struct async_io_handle *aio_handle, int num_subs)223 int _filemgr_aio_submit(struct async_io_handle *aio_handle, int num_subs)
224 {
225 return FDB_RESULT_AIO_NOT_SUPPORTED;
226 }
227
_filemgr_aio_getevents(struct async_io_handle *aio_handle, int min, int max, unsigned int timeout)228 int _filemgr_aio_getevents(struct async_io_handle *aio_handle, int min,
229 int max, unsigned int timeout)
230 {
231 return FDB_RESULT_AIO_NOT_SUPPORTED;
232 }
233
_filemgr_aio_destroy(struct async_io_handle *aio_handle)234 int _filemgr_aio_destroy(struct async_io_handle *aio_handle)
235 {
236 return FDB_RESULT_AIO_NOT_SUPPORTED;
237 }
238
_filemgr_win_get_fs_type(int src_fd)239 int _filemgr_win_get_fs_type(int src_fd)
240 {
241 return FILEMGR_FS_NO_COW;
242 }
243
_filemgr_win_copy_file_range(int fstype, int src_fd, int dst_fd, uint64_t src_off, uint64_t dst_off, uint64_t len)244 int _filemgr_win_copy_file_range(int fstype, int src_fd, int dst_fd,
245 uint64_t src_off, uint64_t dst_off,
246 uint64_t len)
247 {
248 return FDB_RESULT_INVALID_ARGS;
249 }
250
251 struct filemgr_ops win_ops = {
252 _filemgr_win_open,
253 _filemgr_win_pwrite,
254 _filemgr_win_pread,
255 _filemgr_win_close,
256 _filemgr_win_goto_eof,
257 _filemgr_win_file_size,
258 _filemgr_win_fdatasync,
259 _filemgr_win_fsync,
260 _filemgr_win_get_errno_str,
261 // Async I/O operations
262 _filemgr_aio_init,
263 _filemgr_aio_prep_read,
264 _filemgr_aio_submit,
265 _filemgr_aio_getevents,
266 _filemgr_aio_destroy,
267 _filemgr_win_get_fs_type,
268 _filemgr_win_copy_file_range
269 };
270
get_win_filemgr_ops()271 struct filemgr_ops * get_win_filemgr_ops()
272 {
273 return &win_ops;
274 }
275
276 #endif
277