1 #ifndef _BABELTRACE_COMPAT_FCNTL_H
2 #define _BABELTRACE_COMPAT_FCNTL_H
5 * babeltrace/compat/fcntl.h
7 * Copyright 2015 (c) - Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 * fcntl compatibility layer.
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 #ifdef BABELTRACE_HAVE_POSIX_FALLOCATE
35 int bt_posix_fallocate(int fd
, off_t offset
, off_t len
)
37 return posix_fallocate(fd
, offset
, len
);
40 #elif defined(__MINGW32__) /* #ifdef BABELTRACE_HAVE_POSIX_FALLOCATE */
47 int bt_posix_fallocate(int fd
, off_t offset
, off_t len
)
50 LARGE_INTEGER pos
, file_pos
, orig_end_offset
, range_end
;
55 if (offset
< 0 || len
<= 0) {
60 range_end
.QuadPart
= (__int64
) offset
+ (__int64
) len
;
62 /* Get a handle from the fd */
63 handle
= (HANDLE
) _get_osfhandle(fd
);
64 if (handle
== INVALID_HANDLE_VALUE
) {
69 /* Get the file original end offset */
70 ret
= GetFileSizeEx(handle
, &orig_end_offset
);
76 /* Make sure we don't truncate the file */
77 if (orig_end_offset
.QuadPart
>= range_end
.QuadPart
) {
82 /* Get the current file pointer position */
84 ret
= SetFilePointerEx(handle
, pos
, &file_pos
, FILE_CURRENT
);
90 /* Move the file pointer to the new end offset */
91 ret
= SetFilePointerEx(handle
, range_end
, NULL
, FILE_BEGIN
);
97 /* Sets the physical file size to the current position */
98 ret
= SetEndOfFile(handle
);
105 * Move the file pointer back 1 byte, and write a single 0 at the
106 * last byte of the new end offset, the operating system will zero
110 ret
= SetFilePointerEx(handle
, pos
, NULL
, FILE_END
);
116 ret
= WriteFile(handle
, &zero
, 1, &byteswritten
, NULL
);
117 if (ret
== 0 || byteswritten
!= 1) {
124 /* Restore the original file pointer position */
125 if (!SetFilePointerEx(handle
, file_pos
, NULL
, FILE_BEGIN
)) {
126 /* We moved the file pointer but failed to restore it. */
136 #include <sys/types.h>
140 #define BABELTRACE_FALLOCATE_BUFLEN 256
143 #define min_t(type, a, b) \
144 ((type) (a) < (type) (b) ? (type) (a) : (type) (b))
148 int bt_posix_fallocate(int fd
, off_t offset
, off_t len
)
152 char buf
[BABELTRACE_FALLOCATE_BUFLEN
];
153 off_t i
, file_pos
, orig_end_offset
, range_end
;
155 if (offset
< 0 || len
< 0) {
160 range_end
= offset
+ len
;
166 file_pos
= lseek(fd
, 0, SEEK_CUR
);
172 orig_end_offset
= lseek(fd
, 0, SEEK_END
);
173 if (orig_end_offset
< 0) {
178 /* Seek back to original position. */
179 ret
= lseek(fd
, file_pos
, SEEK_SET
);
186 * The file may not need to grow, but we want to ensure the
187 * space has actually been reserved by the file system. First, copy
188 * the "existing" region of the file, then grow the file if needed.
190 for (i
= file_pos
; i
< min_t(off_t
, range_end
, orig_end_offset
);
194 copy_len
= min_t(size_t, BABELTRACE_FALLOCATE_BUFLEN
,
195 min_t(off_t
, range_end
- i
,
196 orig_end_offset
- i
));
197 copy_ret
= pread(fd
, &buf
, copy_len
, i
);
198 if (copy_ret
< copy_len
) {
200 * The caller must handle any EINTR.
201 * POSIX_FALLOCATE(3) does not mention EINTR.
202 * However, glibc does forward to fallocate()
203 * directly on Linux, which may be interrupted.
209 copy_ret
= pwrite(fd
, &buf
, copy_len
, i
);
210 if (copy_ret
< copy_len
) {
211 /* Same caveat as noted at pread() */
217 /* Grow file, as necessary. */
218 memset(&buf
, 0, BABELTRACE_FALLOCATE_BUFLEN
);
219 for (i
= orig_end_offset
; i
< range_end
; i
+= copy_len
) {
222 copy_len
= min_t(size_t, BABELTRACE_FALLOCATE_BUFLEN
,
224 write_ret
= pwrite(fd
, &buf
, copy_len
, i
);
225 if (write_ret
< copy_len
) {
233 #endif /* #else #ifdef BABELTRACE_HAVE_POSIX_FALLOCATE */
235 #endif /* _BABELTRACE_COMPAT_FCNTL_H */