lib: rename include dir to babeltrace2
[babeltrace.git] / include / babeltrace2 / compat / fcntl-internal.h
1 #ifndef _BABELTRACE_COMPAT_FCNTL_H
2 #define _BABELTRACE_COMPAT_FCNTL_H
3
4 /*
5 * Copyright 2015 (c) - Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 *
7 * fcntl compatibility layer.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 */
27
28 #ifdef BABELTRACE_HAVE_POSIX_FALLOCATE
29
30 #include <fcntl.h>
31
32 static inline
33 int bt_posix_fallocate(int fd, off_t offset, off_t len)
34 {
35 return posix_fallocate(fd, offset, len);
36 }
37
38 #elif defined(__MINGW32__) /* #ifdef BABELTRACE_HAVE_POSIX_FALLOCATE */
39
40 #include <stdlib.h>
41 #include <windows.h>
42 #include <fcntl.h>
43
44 static inline
45 int bt_posix_fallocate(int fd, off_t offset, off_t len)
46 {
47 HANDLE handle;
48 LARGE_INTEGER pos, file_pos, orig_end_offset, range_end;
49 int ret = 0;
50 char zero = 0;
51 DWORD byteswritten;
52
53 if (offset < 0 || len <= 0) {
54 ret = EINVAL;
55 goto end;
56 }
57
58 range_end.QuadPart = (__int64) offset + (__int64) len;
59
60 /* Get a handle from the fd */
61 handle = (HANDLE) _get_osfhandle(fd);
62 if (handle == INVALID_HANDLE_VALUE) {
63 ret = EBADF;
64 goto end;
65 }
66
67 /* Get the file original end offset */
68 ret = GetFileSizeEx(handle, &orig_end_offset);
69 if (ret == 0) {
70 ret = EBADF;
71 goto end;
72 }
73
74 /* Make sure we don't truncate the file */
75 if (orig_end_offset.QuadPart >= range_end.QuadPart) {
76 ret = 0;
77 goto end;
78 }
79
80 /* Get the current file pointer position */
81 pos.QuadPart = 0;
82 ret = SetFilePointerEx(handle, pos, &file_pos, FILE_CURRENT);
83 if (ret == 0) {
84 ret = EBADF;
85 goto end;
86 }
87
88 /* Move the file pointer to the new end offset */
89 ret = SetFilePointerEx(handle, range_end, NULL, FILE_BEGIN);
90 if (ret == 0) {
91 ret = EBADF;
92 goto end;
93 }
94
95 /* Sets the physical file size to the current position */
96 ret = SetEndOfFile(handle);
97 if (ret == 0) {
98 ret = EINVAL;
99 goto restore;
100 }
101
102 /*
103 * Move the file pointer back 1 byte, and write a single 0 at the
104 * last byte of the new end offset, the operating system will zero
105 * fill the file.
106 */
107 pos.QuadPart = -1;
108 ret = SetFilePointerEx(handle, pos, NULL, FILE_END);
109 if (ret == 0) {
110 ret = EBADF;
111 goto end;
112 }
113
114 ret = WriteFile(handle, &zero, 1, &byteswritten, NULL);
115 if (ret == 0 || byteswritten != 1) {
116 ret = ENOSPC;
117 } else {
118 ret = 0;
119 }
120
121 restore:
122 /* Restore the original file pointer position */
123 if (!SetFilePointerEx(handle, file_pos, NULL, FILE_BEGIN)) {
124 /* We moved the file pointer but failed to restore it. */
125 abort();
126 }
127
128 end:
129 return ret;
130 }
131
132 #else
133
134 #include <sys/types.h>
135 #include <unistd.h>
136 #include <string.h>
137
138 #define BABELTRACE_FALLOCATE_BUFLEN 256
139
140 #ifndef min_t
141 #define min_t(type, a, b) \
142 ((type) (a) < (type) (b) ? (type) (a) : (type) (b))
143 #endif
144
145 static inline
146 int bt_posix_fallocate(int fd, off_t offset, off_t len)
147 {
148 int ret = 0;
149 ssize_t copy_len;
150 char buf[BABELTRACE_FALLOCATE_BUFLEN];
151 off_t i, file_pos, orig_end_offset, range_end;
152
153 if (offset < 0 || len < 0) {
154 ret = EINVAL;
155 goto end;
156 }
157
158 range_end = offset + len;
159 if (range_end < 0) {
160 ret = EFBIG;
161 goto end;
162 }
163
164 file_pos = lseek(fd, 0, SEEK_CUR);
165 if (file_pos < 0) {
166 ret = errno;
167 goto end;
168 }
169
170 orig_end_offset = lseek(fd, 0, SEEK_END);
171 if (orig_end_offset < 0) {
172 ret = errno;
173 goto end;
174 }
175
176 /* Seek back to original position. */
177 ret = lseek(fd, file_pos, SEEK_SET);
178 if (ret) {
179 ret = errno;
180 goto end;
181 }
182
183 /*
184 * The file may not need to grow, but we want to ensure the
185 * space has actually been reserved by the file system. First, copy
186 * the "existing" region of the file, then grow the file if needed.
187 */
188 for (i = file_pos; i < min_t(off_t, range_end, orig_end_offset);
189 i += copy_len) {
190 ssize_t copy_ret;
191
192 copy_len = min_t(size_t, BABELTRACE_FALLOCATE_BUFLEN,
193 min_t(off_t, range_end - i,
194 orig_end_offset - i));
195 copy_ret = pread(fd, &buf, copy_len, i);
196 if (copy_ret < copy_len) {
197 /*
198 * The caller must handle any EINTR.
199 * POSIX_FALLOCATE(3) does not mention EINTR.
200 * However, glibc does forward to fallocate()
201 * directly on Linux, which may be interrupted.
202 */
203 ret = errno;
204 goto end;
205 }
206
207 copy_ret = pwrite(fd, &buf, copy_len, i);
208 if (copy_ret < copy_len) {
209 /* Same caveat as noted at pread() */
210 ret = errno;
211 goto end;
212 }
213 }
214
215 /* Grow file, as necessary. */
216 memset(&buf, 0, BABELTRACE_FALLOCATE_BUFLEN);
217 for (i = orig_end_offset; i < range_end; i += copy_len) {
218 ssize_t write_ret;
219
220 copy_len = min_t(size_t, BABELTRACE_FALLOCATE_BUFLEN,
221 range_end - i);
222 write_ret = pwrite(fd, &buf, copy_len, i);
223 if (write_ret < copy_len) {
224 ret = errno;
225 goto end;
226 }
227 }
228 end:
229 return ret;
230 }
231 #endif /* #else #ifdef BABELTRACE_HAVE_POSIX_FALLOCATE */
232
233 #endif /* _BABELTRACE_COMPAT_FCNTL_H */
This page took 0.037756 seconds and 4 git commands to generate.