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
33namespace 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 */
41int openNoInt(const char* name, int flags, mode_t mode = 0666);
42// Two overloads, as we may be closing either a file or a socket.
43int closeNoInt(int fd);
44int closeNoInt(NetworkSocket fd);
45int dupNoInt(int fd);
46int dup2NoInt(int oldfd, int newfd);
47int fsyncNoInt(int fd);
48int fdatasyncNoInt(int fd);
49int ftruncateNoInt(int fd, off_t len);
50int truncateNoInt(const char* path, off_t len);
51int flockNoInt(int fd, int operation);
52int shutdownNoInt(NetworkSocket fd, int how);
53
54ssize_t readNoInt(int fd, void* buf, size_t count);
55ssize_t preadNoInt(int fd, void* buf, size_t count, off_t offset);
56ssize_t readvNoInt(int fd, const iovec* iov, int count);
57ssize_t preadvNoInt(int fd, const iovec* iov, int count, off_t offset);
58
59ssize_t writeNoInt(int fd, const void* buf, size_t count);
60ssize_t pwriteNoInt(int fd, const void* buf, size_t count, off_t offset);
61ssize_t writevNoInt(int fd, const iovec* iov, int count);
62ssize_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 */
86FOLLY_NODISCARD ssize_t readFull(int fd, void* buf, size_t count);
87FOLLY_NODISCARD ssize_t preadFull(int fd, void* buf, size_t count, off_t offset);
88FOLLY_NODISCARD ssize_t readvFull(int fd, iovec* iov, int count);
89FOLLY_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 */
108ssize_t writeFull(int fd, const void* buf, size_t count);
109ssize_t pwriteFull(int fd, const void* buf, size_t count, off_t offset);
110ssize_t writevFull(int fd, iovec* iov, int count);
111ssize_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 */
123template <class Container>
124bool 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 */
173template <class Container>
174bool 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 */
209template <class Container>
210bool 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 */
237void writeFileAtomic(
238 StringPiece filename,
239 iovec* iov,
240 int count,
241 mode_t permissions = 0644);
242void writeFileAtomic(
243 StringPiece filename,
244 ByteRange data,
245 mode_t permissions = 0644);
246void 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 */
257int writeFileAtomicNoThrow(
258 StringPiece filename,
259 iovec* iov,
260 int count,
261 mode_t permissions = 0644);
262
263} // namespace folly
264