Port: implement posix_fallocate wrapper
[babeltrace.git] / include / babeltrace / compat / fcntl.h
1 #ifndef _BABELTRACE_COMPAT_FCNTL_H
2 #define _BABELTRACE_COMPAT_FCNTL_H
3
4 /*
5 * babeltrace/compat/fcntl.h
6 *
7 * Copyright 2015 (c) - Jérémie Galarneau <jeremie.galarneau@efficios.com>
8 *
9 * fcntl compatibility layer.
10 *
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:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
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
27 * SOFTWARE.
28 */
29
30 #include <config.h>
31
32 #ifdef BABELTRACE_HAVE_POSIX_FALLOCATE
33
34 #include <fcntl.h>
35
36 static inline
37 int bt_posix_fallocate(int fd, off_t offset, off_t len)
38 {
39 return posix_fallocate(fd, offset, len);
40 }
41
42 #else /* #ifdef BABELTRACE_HAVE_POSIX_FALLOCATE */
43
44 #include <sys/types.h>
45 #include <unistd.h>
46 #include <string.h>
47
48 #define BABELTRACE_FALLOCATE_BUFLEN 256
49
50 #ifndef min_t
51 #define min_t(type, a, b) \
52 ((type) (a) < (type) (b) ? (type) (a) : (type) (b))
53 #endif
54
55 static inline
56 int bt_posix_fallocate(int fd, off_t offset, off_t len)
57 {
58 int ret = 0;
59 ssize_t copy_len;
60 char buf[BABELTRACE_FALLOCATE_BUFLEN];
61 off_t i, file_pos, orig_end_offset, range_end;
62
63 if (offset < 0 || len < 0) {
64 ret = EINVAL;
65 goto end;
66 }
67
68 range_end = offset + len;
69 if (range_end < 0) {
70 ret = EFBIG;
71 goto end;
72 }
73
74 file_pos = lseek(fd, 0, SEEK_CUR);
75 if (file_pos < 0) {
76 ret = errno;
77 goto end;
78 }
79
80 orig_end_offset = lseek(fd, 0, SEEK_END);
81 if (orig_end_offset < 0) {
82 ret = errno;
83 goto end;
84 }
85
86 /* Seek back to original position. */
87 ret = lseek(fd, file_pos, SEEK_SET);
88 if (ret) {
89 ret = errno;
90 goto end;
91 }
92
93 /*
94 * The file may not need to grow, but we want to ensure the
95 * space has actually been reserved by the file system. First, copy
96 * the "existing" region of the file, then grow the file if needed.
97 */
98 for (i = file_pos; i < min_t(off_t, range_end, orig_end_offset);
99 i += copy_len) {
100 ssize_t copy_ret;
101
102 copy_len = min_t(size_t, BABELTRACE_FALLOCATE_BUFLEN,
103 min_t(off_t, range_end - i,
104 orig_end_offset - i));
105 copy_ret = pread(fd, &buf, copy_len, i);
106 if (copy_ret < copy_len) {
107 /*
108 * The caller must handle any EINTR.
109 * POSIX_FALLOCATE(3) does not mention EINTR.
110 * However, glibc does forward to fallocate()
111 * directly on Linux, which may be interrupted.
112 */
113 ret = errno;
114 goto end;
115 }
116
117 copy_ret = pwrite(fd, &buf, copy_len, i);
118 if (copy_ret < copy_len) {
119 /* Same caveat as noted at pread() */
120 ret = errno;
121 goto end;
122 }
123 }
124
125 /* Grow file, as necessary. */
126 memset(&buf, 0, BABELTRACE_FALLOCATE_BUFLEN);
127 for (i = orig_end_offset; i < range_end; i += copy_len) {
128 ssize_t write_ret;
129
130 copy_len = min_t(size_t, BABELTRACE_FALLOCATE_BUFLEN,
131 range_end - i);
132 write_ret = pwrite(fd, &buf, copy_len, i);
133 if (write_ret < copy_len) {
134 ret = errno;
135 goto end;
136 }
137 }
138 end:
139 return ret;
140 }
141 #endif /* #else #ifdef BABELTRACE_HAVE_POSIX_FALLOCATE */
142
143 #endif /* _BABELTRACE_COMPAT_FCNTL_H */
This page took 0.03119 seconds and 4 git commands to generate.