2 * SPDX-License-Identifier: MIT
4 * Copyright 2015 (c) Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 * fcntl compatibility layer.
9 #ifndef _BABELTRACE_COMPAT_FCNTL_H
10 #define _BABELTRACE_COMPAT_FCNTL_H
12 #include "common/common.h"
14 #ifdef BABELTRACE_HAVE_POSIX_FALLOCATE
19 int bt_posix_fallocate(int fd
, off_t offset
, off_t len
)
21 return posix_fallocate(fd
, offset
, len
);
24 #elif defined(__MINGW32__) /* #ifdef BABELTRACE_HAVE_POSIX_FALLOCATE */
31 int bt_posix_fallocate(int fd
, off_t offset
, off_t len
)
34 LARGE_INTEGER pos
, file_pos
, orig_end_offset
, range_end
;
39 if (offset
< 0 || len
<= 0) {
44 range_end
.QuadPart
= (__int64
) offset
+ (__int64
) len
;
46 /* Get a handle from the fd */
47 handle
= (HANDLE
) _get_osfhandle(fd
);
48 if (handle
== INVALID_HANDLE_VALUE
) {
53 /* Get the file original end offset */
54 ret
= GetFileSizeEx(handle
, &orig_end_offset
);
60 /* Make sure we don't truncate the file */
61 if (orig_end_offset
.QuadPart
>= range_end
.QuadPart
) {
66 /* Get the current file pointer position */
68 ret
= SetFilePointerEx(handle
, pos
, &file_pos
, FILE_CURRENT
);
74 /* Move the file pointer to the new end offset */
75 ret
= SetFilePointerEx(handle
, range_end
, NULL
, FILE_BEGIN
);
81 /* Sets the physical file size to the current position */
82 ret
= SetEndOfFile(handle
);
89 * Move the file pointer back 1 byte, and write a single 0 at the
90 * last byte of the new end offset, the operating system will zero
94 ret
= SetFilePointerEx(handle
, pos
, NULL
, FILE_END
);
100 ret
= WriteFile(handle
, &zero
, 1, &byteswritten
, NULL
);
101 if (ret
== 0 || byteswritten
!= 1) {
108 /* Restore the original file pointer position */
109 if (!SetFilePointerEx(handle
, file_pos
, NULL
, FILE_BEGIN
)) {
110 /* We moved the file pointer but failed to restore it. */
120 #include <sys/types.h>
124 #define BABELTRACE_FALLOCATE_BUFLEN 256
127 #define min_t(type, a, b) \
128 ((type) (a) < (type) (b) ? (type) (a) : (type) (b))
132 int bt_posix_fallocate(int fd
, off_t offset
, off_t len
)
136 char buf
[BABELTRACE_FALLOCATE_BUFLEN
];
137 off_t i
, file_pos
, orig_end_offset
, range_end
;
139 if (offset
< 0 || len
< 0) {
144 range_end
= offset
+ len
;
150 file_pos
= lseek(fd
, 0, SEEK_CUR
);
156 orig_end_offset
= lseek(fd
, 0, SEEK_END
);
157 if (orig_end_offset
< 0) {
162 /* Seek back to original position. */
163 ret
= lseek(fd
, file_pos
, SEEK_SET
);
170 * The file may not need to grow, but we want to ensure the
171 * space has actually been reserved by the file system. First, copy
172 * the "existing" region of the file, then grow the file if needed.
174 for (i
= file_pos
; i
< min_t(off_t
, range_end
, orig_end_offset
);
178 copy_len
= min_t(size_t, BABELTRACE_FALLOCATE_BUFLEN
,
179 min_t(off_t
, range_end
- i
,
180 orig_end_offset
- i
));
181 copy_ret
= pread(fd
, &buf
, copy_len
, i
);
182 if (copy_ret
< copy_len
) {
184 * The caller must handle any EINTR.
185 * POSIX_FALLOCATE(3) does not mention EINTR.
186 * However, glibc does forward to fallocate()
187 * directly on Linux, which may be interrupted.
193 copy_ret
= pwrite(fd
, &buf
, copy_len
, i
);
194 if (copy_ret
< copy_len
) {
195 /* Same caveat as noted at pread() */
201 /* Grow file, as necessary. */
202 memset(&buf
, 0, BABELTRACE_FALLOCATE_BUFLEN
);
203 for (i
= orig_end_offset
; i
< range_end
; i
+= copy_len
) {
206 copy_len
= min_t(size_t, BABELTRACE_FALLOCATE_BUFLEN
,
208 write_ret
= pwrite(fd
, &buf
, copy_len
, i
);
209 if (write_ret
< copy_len
) {
217 #endif /* #else #ifdef BABELTRACE_HAVE_POSIX_FALLOCATE */
219 #endif /* _BABELTRACE_COMPAT_FCNTL_H */