1 | /* |
2 | * Copyright (c) Facebook, Inc. and its affiliates. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | #pragma once |
18 | |
19 | #include <sys/stat.h> |
20 | #include <sys/types.h> |
21 | |
22 | #include <cassert> |
23 | #include <limits> |
24 | |
25 | #include <folly/Portability.h> |
26 | #include <folly/Range.h> |
27 | #include <folly/ScopeGuard.h> |
28 | #include <folly/net/NetworkSocket.h> |
29 | #include <folly/portability/Fcntl.h> |
30 | #include <folly/portability/SysUio.h> |
31 | #include <folly/portability/Unistd.h> |
32 | |
33 | namespace folly { |
34 | |
35 | /** |
36 | * Convenience wrappers around some commonly used system calls. The *NoInt |
37 | * wrappers retry on EINTR. The *Full wrappers retry on EINTR and also loop |
38 | * until all data is written. Note that *Full wrappers weaken the thread |
39 | * semantics of underlying system calls. |
40 | */ |
41 | int openNoInt(const char* name, int flags, mode_t mode = 0666); |
42 | // Two overloads, as we may be closing either a file or a socket. |
43 | int closeNoInt(int fd); |
44 | int closeNoInt(NetworkSocket fd); |
45 | int dupNoInt(int fd); |
46 | int dup2NoInt(int oldfd, int newfd); |
47 | int fsyncNoInt(int fd); |
48 | int fdatasyncNoInt(int fd); |
49 | int ftruncateNoInt(int fd, off_t len); |
50 | int truncateNoInt(const char* path, off_t len); |
51 | int flockNoInt(int fd, int operation); |
52 | int shutdownNoInt(NetworkSocket fd, int how); |
53 | |
54 | ssize_t readNoInt(int fd, void* buf, size_t count); |
55 | ssize_t preadNoInt(int fd, void* buf, size_t count, off_t offset); |
56 | ssize_t readvNoInt(int fd, const iovec* iov, int count); |
57 | ssize_t preadvNoInt(int fd, const iovec* iov, int count, off_t offset); |
58 | |
59 | ssize_t writeNoInt(int fd, const void* buf, size_t count); |
60 | ssize_t pwriteNoInt(int fd, const void* buf, size_t count, off_t offset); |
61 | ssize_t writevNoInt(int fd, const iovec* iov, int count); |
62 | ssize_t pwritevNoInt(int fd, const iovec* iov, int count, off_t offset); |
63 | |
64 | /** |
65 | * Wrapper around read() (and pread()) that, in addition to retrying on |
66 | * EINTR, will loop until all data is read. |
67 | * |
68 | * This wrapper is only useful for blocking file descriptors (for non-blocking |
69 | * file descriptors, you have to be prepared to deal with incomplete reads |
70 | * anyway), and only exists because POSIX allows read() to return an incomplete |
71 | * read if interrupted by a signal (instead of returning -1 and setting errno |
72 | * to EINTR). |
73 | * |
74 | * Note that this wrapper weakens the thread safety of read(): the file pointer |
75 | * is shared between threads, but the system call is atomic. If multiple |
76 | * threads are reading from a file at the same time, you don't know where your |
77 | * data came from in the file, but you do know that the returned bytes were |
78 | * contiguous. You can no longer make this assumption if using readFull(). |
79 | * You should probably use pread() when reading from the same file descriptor |
80 | * from multiple threads simultaneously, anyway. |
81 | * |
82 | * Note that readvFull and preadvFull require iov to be non-const, unlike |
83 | * readv and preadv. The contents of iov after these functions return |
84 | * is unspecified. |
85 | */ |
86 | FOLLY_NODISCARD ssize_t readFull(int fd, void* buf, size_t count); |
87 | FOLLY_NODISCARD ssize_t preadFull(int fd, void* buf, size_t count, off_t offset); |
88 | FOLLY_NODISCARD ssize_t readvFull(int fd, iovec* iov, int count); |
89 | FOLLY_NODISCARD ssize_t preadvFull(int fd, iovec* iov, int count, off_t offset); |
90 | |
91 | /** |
92 | * Similar to readFull and preadFull above, wrappers around write() and |
93 | * pwrite() that loop until all data is written. |
94 | * |
95 | * Generally, the write() / pwrite() system call may always write fewer bytes |
96 | * than requested, just like read(). In certain cases (such as when writing to |
97 | * a pipe), POSIX provides stronger guarantees, but not in the general case. |
98 | * For example, Linux (even on a 64-bit platform) won't write more than 2GB in |
99 | * one write() system call. |
100 | * |
101 | * Note that writevFull and pwritevFull require iov to be non-const, unlike |
102 | * writev and pwritev. The contents of iov after these functions return |
103 | * is unspecified. |
104 | * |
105 | * These functions return -1 on error, or the total number of bytes written |
106 | * (which is always the same as the number of requested bytes) on success. |
107 | */ |
108 | ssize_t writeFull(int fd, const void* buf, size_t count); |
109 | ssize_t pwriteFull(int fd, const void* buf, size_t count, off_t offset); |
110 | ssize_t writevFull(int fd, iovec* iov, int count); |
111 | ssize_t pwritevFull(int fd, iovec* iov, int count, off_t offset); |
112 | |
113 | /** |
114 | * Read entire file (if num_bytes is defaulted) or no more than |
115 | * num_bytes (otherwise) into container *out. The container is assumed |
116 | * to be contiguous, with element size equal to 1, and offer size(), |
117 | * reserve(), and random access (e.g. std::vector<char>, std::string, |
118 | * fbstring). |
119 | * |
120 | * Returns: true on success or false on failure. In the latter case |
121 | * errno will be set appropriately by the failing system primitive. |
122 | */ |
123 | template <class Container> |
124 | bool readFile( |
125 | int fd, |
126 | Container& out, |
127 | size_t num_bytes = std::numeric_limits<size_t>::max()) { |
128 | static_assert( |
129 | sizeof(out[0]) == 1, |
130 | "readFile: only containers with byte-sized elements accepted" ); |
131 | |
132 | size_t soFar = 0; // amount of bytes successfully read |
133 | SCOPE_EXIT { |
134 | assert(out.size() >= soFar); // resize better doesn't throw |
135 | out.resize(soFar); |
136 | }; |
137 | |
138 | // Obtain file size: |
139 | struct stat buf; |
140 | if (fstat(fd, &buf) == -1) { |
141 | return false; |
142 | } |
143 | // Some files (notably under /proc and /sys on Linux) lie about |
144 | // their size, so treat the size advertised by fstat under advise |
145 | // but don't rely on it. In particular, if the size is zero, we |
146 | // should attempt to read stuff. If not zero, we'll attempt to read |
147 | // one extra byte. |
148 | constexpr size_t initialAlloc = 1024 * 4; |
149 | out.resize(std::min( |
150 | buf.st_size > 0 ? (size_t(buf.st_size) + 1) : initialAlloc, num_bytes)); |
151 | |
152 | while (soFar < out.size()) { |
153 | const auto actual = readFull(fd, &out[soFar], out.size() - soFar); |
154 | if (actual == -1) { |
155 | return false; |
156 | } |
157 | soFar += actual; |
158 | if (soFar < out.size()) { |
159 | // File exhausted |
160 | break; |
161 | } |
162 | // Ew, allocate more memory. Use exponential growth to avoid |
163 | // quadratic behavior. Cap size to num_bytes. |
164 | out.resize(std::min(out.size() * 3 / 2, num_bytes)); |
165 | } |
166 | |
167 | return true; |
168 | } |
169 | |
170 | /** |
171 | * Same as above, but takes in a file name instead of fd |
172 | */ |
173 | template <class Container> |
174 | bool readFile( |
175 | const char* file_name, |
176 | Container& out, |
177 | size_t num_bytes = std::numeric_limits<size_t>::max()) { |
178 | assert(file_name); |
179 | |
180 | const auto fd = openNoInt(file_name, O_RDONLY | O_CLOEXEC); |
181 | if (fd == -1) { |
182 | return false; |
183 | } |
184 | |
185 | SCOPE_EXIT { |
186 | // Ignore errors when closing the file |
187 | closeNoInt(fd); |
188 | }; |
189 | |
190 | return readFile(fd, out, num_bytes); |
191 | } |
192 | |
193 | /** |
194 | * Writes container to file. The container is assumed to be |
195 | * contiguous, with element size equal to 1, and offering STL-like |
196 | * methods empty(), size(), and indexed access |
197 | * (e.g. std::vector<char>, std::string, fbstring, StringPiece). |
198 | * |
199 | * "flags" dictates the open flags to use. Default is to create file |
200 | * if it doesn't exist and truncate it. |
201 | * |
202 | * Returns: true on success or false on failure. In the latter case |
203 | * errno will be set appropriately by the failing system primitive. |
204 | * |
205 | * Note that this function may leave the file in a partially written state on |
206 | * failure. Use writeFileAtomic() if you want to ensure that the existing file |
207 | * state will be unchanged on error. |
208 | */ |
209 | template <class Container> |
210 | bool writeFile( |
211 | const Container& data, |
212 | const char* filename, |
213 | int flags = O_WRONLY | O_CREAT | O_TRUNC, |
214 | mode_t mode = 0666) { |
215 | static_assert( |
216 | sizeof(data[0]) == 1, "writeFile works with element size equal to 1" ); |
217 | int fd = open(filename, flags, mode); |
218 | if (fd == -1) { |
219 | return false; |
220 | } |
221 | bool ok = data.empty() || |
222 | writeFull(fd, &data[0], data.size()) == static_cast<ssize_t>(data.size()); |
223 | return closeNoInt(fd) == 0 && ok; |
224 | } |
225 | |
226 | /** |
227 | * Write file contents "atomically". |
228 | * |
229 | * This writes the data to a temporary file in the destination directory, and |
230 | * then renames it to the specified path. This guarantees that the specified |
231 | * file will be replaced the the specified contents on success, or will not be |
232 | * modified on failure. |
233 | * |
234 | * Note that on platforms that do not provide atomic filesystem rename |
235 | * functionality (e.g., Windows) this behavior may not be truly atomic. |
236 | */ |
237 | void writeFileAtomic( |
238 | StringPiece filename, |
239 | iovec* iov, |
240 | int count, |
241 | mode_t permissions = 0644); |
242 | void writeFileAtomic( |
243 | StringPiece filename, |
244 | ByteRange data, |
245 | mode_t permissions = 0644); |
246 | void writeFileAtomic( |
247 | StringPiece filename, |
248 | StringPiece data, |
249 | mode_t permissions = 0644); |
250 | |
251 | /** |
252 | * A version of writeFileAtomic() that returns an errno value instead of |
253 | * throwing on error. |
254 | * |
255 | * Returns 0 on success or an errno value on error. |
256 | */ |
257 | int writeFileAtomicNoThrow( |
258 | StringPiece filename, |
259 | iovec* iov, |
260 | int count, |
261 | mode_t permissions = 0644); |
262 | |
263 | } // namespace folly |
264 | |