1 | /* |
2 | * Copyright 2013-present Facebook, Inc. |
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 n); |
55 | ssize_t preadNoInt(int fd, void* buf, size_t n, off_t offset); |
56 | ssize_t readvNoInt(int fd, const iovec* iov, int count); |
57 | |
58 | ssize_t writeNoInt(int fd, const void* buf, size_t n); |
59 | ssize_t pwriteNoInt(int fd, const void* buf, size_t n, off_t offset); |
60 | ssize_t writevNoInt(int fd, const iovec* iov, int count); |
61 | |
62 | /** |
63 | * Wrapper around read() (and pread()) that, in addition to retrying on |
64 | * EINTR, will loop until all data is read. |
65 | * |
66 | * This wrapper is only useful for blocking file descriptors (for non-blocking |
67 | * file descriptors, you have to be prepared to deal with incomplete reads |
68 | * anyway), and only exists because POSIX allows read() to return an incomplete |
69 | * read if interrupted by a signal (instead of returning -1 and setting errno |
70 | * to EINTR). |
71 | * |
72 | * Note that this wrapper weakens the thread safety of read(): the file pointer |
73 | * is shared between threads, but the system call is atomic. If multiple |
74 | * threads are reading from a file at the same time, you don't know where your |
75 | * data came from in the file, but you do know that the returned bytes were |
76 | * contiguous. You can no longer make this assumption if using readFull(). |
77 | * You should probably use pread() when reading from the same file descriptor |
78 | * from multiple threads simultaneously, anyway. |
79 | * |
80 | * Note that readvFull and preadvFull require iov to be non-const, unlike |
81 | * readv and preadv. The contents of iov after these functions return |
82 | * is unspecified. |
83 | */ |
84 | FOLLY_NODISCARD ssize_t readFull(int fd, void* buf, size_t n); |
85 | FOLLY_NODISCARD ssize_t preadFull(int fd, void* buf, size_t n, off_t offset); |
86 | FOLLY_NODISCARD ssize_t readvFull(int fd, iovec* iov, int count); |
87 | FOLLY_NODISCARD ssize_t preadvFull(int fd, iovec* iov, int count, off_t offset); |
88 | |
89 | /** |
90 | * Similar to readFull and preadFull above, wrappers around write() and |
91 | * pwrite() that loop until all data is written. |
92 | * |
93 | * Generally, the write() / pwrite() system call may always write fewer bytes |
94 | * than requested, just like read(). In certain cases (such as when writing to |
95 | * a pipe), POSIX provides stronger guarantees, but not in the general case. |
96 | * For example, Linux (even on a 64-bit platform) won't write more than 2GB in |
97 | * one write() system call. |
98 | * |
99 | * Note that writevFull and pwritevFull require iov to be non-const, unlike |
100 | * writev and pwritev. The contents of iov after these functions return |
101 | * is unspecified. |
102 | * |
103 | * These functions return -1 on error, or the total number of bytes written |
104 | * (which is always the same as the number of requested bytes) on success. |
105 | */ |
106 | ssize_t writeFull(int fd, const void* buf, size_t n); |
107 | ssize_t pwriteFull(int fd, const void* buf, size_t n, off_t offset); |
108 | ssize_t writevFull(int fd, iovec* iov, int count); |
109 | ssize_t pwritevFull(int fd, iovec* iov, int count, off_t offset); |
110 | |
111 | /** |
112 | * Read entire file (if num_bytes is defaulted) or no more than |
113 | * num_bytes (otherwise) into container *out. The container is assumed |
114 | * to be contiguous, with element size equal to 1, and offer size(), |
115 | * reserve(), and random access (e.g. std::vector<char>, std::string, |
116 | * fbstring). |
117 | * |
118 | * Returns: true on success or false on failure. In the latter case |
119 | * errno will be set appropriately by the failing system primitive. |
120 | */ |
121 | template <class Container> |
122 | bool readFile( |
123 | int fd, |
124 | Container& out, |
125 | size_t num_bytes = std::numeric_limits<size_t>::max()) { |
126 | static_assert( |
127 | sizeof(out[0]) == 1, |
128 | "readFile: only containers with byte-sized elements accepted" ); |
129 | |
130 | size_t soFar = 0; // amount of bytes successfully read |
131 | SCOPE_EXIT { |
132 | DCHECK(out.size() >= soFar); // resize better doesn't throw |
133 | out.resize(soFar); |
134 | }; |
135 | |
136 | // Obtain file size: |
137 | struct stat buf; |
138 | if (fstat(fd, &buf) == -1) { |
139 | return false; |
140 | } |
141 | // Some files (notably under /proc and /sys on Linux) lie about |
142 | // their size, so treat the size advertised by fstat under advise |
143 | // but don't rely on it. In particular, if the size is zero, we |
144 | // should attempt to read stuff. If not zero, we'll attempt to read |
145 | // one extra byte. |
146 | constexpr size_t initialAlloc = 1024 * 4; |
147 | out.resize(std::min( |
148 | buf.st_size > 0 ? (size_t(buf.st_size) + 1) : initialAlloc, num_bytes)); |
149 | |
150 | while (soFar < out.size()) { |
151 | const auto actual = readFull(fd, &out[soFar], out.size() - soFar); |
152 | if (actual == -1) { |
153 | return false; |
154 | } |
155 | soFar += actual; |
156 | if (soFar < out.size()) { |
157 | // File exhausted |
158 | break; |
159 | } |
160 | // Ew, allocate more memory. Use exponential growth to avoid |
161 | // quadratic behavior. Cap size to num_bytes. |
162 | out.resize(std::min(out.size() * 3 / 2, num_bytes)); |
163 | } |
164 | |
165 | return true; |
166 | } |
167 | |
168 | /** |
169 | * Same as above, but takes in a file name instead of fd |
170 | */ |
171 | template <class Container> |
172 | bool readFile( |
173 | const char* file_name, |
174 | Container& out, |
175 | size_t num_bytes = std::numeric_limits<size_t>::max()) { |
176 | DCHECK(file_name); |
177 | |
178 | const auto fd = openNoInt(file_name, O_RDONLY | O_CLOEXEC); |
179 | if (fd == -1) { |
180 | return false; |
181 | } |
182 | |
183 | SCOPE_EXIT { |
184 | // Ignore errors when closing the file |
185 | closeNoInt(fd); |
186 | }; |
187 | |
188 | return readFile(fd, out, num_bytes); |
189 | } |
190 | |
191 | /** |
192 | * Writes container to file. The container is assumed to be |
193 | * contiguous, with element size equal to 1, and offering STL-like |
194 | * methods empty(), size(), and indexed access |
195 | * (e.g. std::vector<char>, std::string, fbstring, StringPiece). |
196 | * |
197 | * "flags" dictates the open flags to use. Default is to create file |
198 | * if it doesn't exist and truncate it. |
199 | * |
200 | * Returns: true on success or false on failure. In the latter case |
201 | * errno will be set appropriately by the failing system primitive. |
202 | * |
203 | * Note that this function may leave the file in a partially written state on |
204 | * failure. Use writeFileAtomic() if you want to ensure that the existing file |
205 | * state will be unchanged on error. |
206 | */ |
207 | template <class Container> |
208 | bool writeFile( |
209 | const Container& data, |
210 | const char* filename, |
211 | int flags = O_WRONLY | O_CREAT | O_TRUNC, |
212 | mode_t mode = 0666) { |
213 | static_assert( |
214 | sizeof(data[0]) == 1, "writeFile works with element size equal to 1" ); |
215 | int fd = open(filename, flags, mode); |
216 | if (fd == -1) { |
217 | return false; |
218 | } |
219 | bool ok = data.empty() || |
220 | writeFull(fd, &data[0], data.size()) == static_cast<ssize_t>(data.size()); |
221 | return closeNoInt(fd) == 0 && ok; |
222 | } |
223 | |
224 | /** |
225 | * Write file contents "atomically". |
226 | * |
227 | * This writes the data to a temporary file in the destination directory, and |
228 | * then renames it to the specified path. This guarantees that the specified |
229 | * file will be replaced the the specified contents on success, or will not be |
230 | * modified on failure. |
231 | * |
232 | * Note that on platforms that do not provide atomic filesystem rename |
233 | * functionality (e.g., Windows) this behavior may not be truly atomic. |
234 | */ |
235 | void writeFileAtomic( |
236 | StringPiece filename, |
237 | iovec* iov, |
238 | int count, |
239 | mode_t permissions = 0644); |
240 | void writeFileAtomic( |
241 | StringPiece filename, |
242 | ByteRange data, |
243 | mode_t permissions = 0644); |
244 | void writeFileAtomic( |
245 | StringPiece filename, |
246 | StringPiece data, |
247 | mode_t permissions = 0644); |
248 | |
249 | /** |
250 | * A version of writeFileAtomic() that returns an errno value instead of |
251 | * throwing on error. |
252 | * |
253 | * Returns 0 on success or an errno value on error. |
254 | */ |
255 | int writeFileAtomicNoThrow( |
256 | StringPiece filename, |
257 | iovec* iov, |
258 | int count, |
259 | mode_t permissions = 0644); |
260 | |
261 | } // namespace folly |
262 | |