1 #ifndef _BABELTRACE_COMPAT_FCNTL_H
2 #define _BABELTRACE_COMPAT_FCNTL_H
5 * Copyright 2015 (c) - Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * fcntl compatibility layer.
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:
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
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
28 #ifdef BABELTRACE_HAVE_POSIX_FALLOCATE
33 int bt_posix_fallocate(int fd
, off_t offset
, off_t len
)
35 return posix_fallocate(fd
, offset
, len
);
38 #elif defined(__MINGW32__) /* #ifdef BABELTRACE_HAVE_POSIX_FALLOCATE */
45 int bt_posix_fallocate(int fd
, off_t offset
, off_t len
)
48 LARGE_INTEGER pos
, file_pos
, orig_end_offset
, range_end
;
53 if (offset
< 0 || len
<= 0) {
58 range_end
.QuadPart
= (__int64
) offset
+ (__int64
) len
;
60 /* Get a handle from the fd */
61 handle
= (HANDLE
) _get_osfhandle(fd
);
62 if (handle
== INVALID_HANDLE_VALUE
) {
67 /* Get the file original end offset */
68 ret
= GetFileSizeEx(handle
, &orig_end_offset
);
74 /* Make sure we don't truncate the file */
75 if (orig_end_offset
.QuadPart
>= range_end
.QuadPart
) {
80 /* Get the current file pointer position */
82 ret
= SetFilePointerEx(handle
, pos
, &file_pos
, FILE_CURRENT
);
88 /* Move the file pointer to the new end offset */
89 ret
= SetFilePointerEx(handle
, range_end
, NULL
, FILE_BEGIN
);
95 /* Sets the physical file size to the current position */
96 ret
= SetEndOfFile(handle
);
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
108 ret
= SetFilePointerEx(handle
, pos
, NULL
, FILE_END
);
114 ret
= WriteFile(handle
, &zero
, 1, &byteswritten
, NULL
);
115 if (ret
== 0 || byteswritten
!= 1) {
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. */
134 #include <sys/types.h>
138 #define BABELTRACE_FALLOCATE_BUFLEN 256
141 #define min_t(type, a, b) \
142 ((type) (a) < (type) (b) ? (type) (a) : (type) (b))
146 int bt_posix_fallocate(int fd
, off_t offset
, off_t len
)
150 char buf
[BABELTRACE_FALLOCATE_BUFLEN
];
151 off_t i
, file_pos
, orig_end_offset
, range_end
;
153 if (offset
< 0 || len
< 0) {
158 range_end
= offset
+ len
;
164 file_pos
= lseek(fd
, 0, SEEK_CUR
);
170 orig_end_offset
= lseek(fd
, 0, SEEK_END
);
171 if (orig_end_offset
< 0) {
176 /* Seek back to original position. */
177 ret
= lseek(fd
, file_pos
, SEEK_SET
);
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.
188 for (i
= file_pos
; i
< min_t(off_t
, range_end
, orig_end_offset
);
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
) {
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.
207 copy_ret
= pwrite(fd
, &buf
, copy_len
, i
);
208 if (copy_ret
< copy_len
) {
209 /* Same caveat as noted at pread() */
215 /* Grow file, as necessary. */
216 memset(&buf
, 0, BABELTRACE_FALLOCATE_BUFLEN
);
217 for (i
= orig_end_offset
; i
< range_end
; i
+= copy_len
) {
220 copy_len
= min_t(size_t, BABELTRACE_FALLOCATE_BUFLEN
,
222 write_ret
= pwrite(fd
, &buf
, copy_len
, i
);
223 if (write_ret
< copy_len
) {
231 #endif /* #else #ifdef BABELTRACE_HAVE_POSIX_FALLOCATE */
233 #endif /* _BABELTRACE_COMPAT_FCNTL_H */