Include the fcntl.h portability header where it's needed
[folly.git] / folly / FileUtil.h
1 /*
2  * Copyright 2016 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 <folly/Conv.h>
20 #include <folly/Portability.h>
21 #include <folly/ScopeGuard.h>
22 #include <folly/portability/Fcntl.h>
23 #include <folly/portability/SysUio.h>
24 #include <folly/portability/Unistd.h>
25
26 #include <cassert>
27 #include <limits>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30
31 namespace folly {
32
33 /**
34  * Convenience wrappers around some commonly used system calls.  The *NoInt
35  * wrappers retry on EINTR.  The *Full wrappers retry on EINTR and also loop
36  * until all data is written.  Note that *Full wrappers weaken the thread
37  * semantics of underlying system calls.
38  */
39 int openNoInt(const char* name, int flags, mode_t mode = 0666);
40 int closeNoInt(int fd);
41 int dupNoInt(int fd);
42 int dup2NoInt(int oldfd, int newfd);
43 int fsyncNoInt(int fd);
44 int fdatasyncNoInt(int fd);
45 int ftruncateNoInt(int fd, off_t len);
46 int truncateNoInt(const char* path, off_t len);
47 int flockNoInt(int fd, int operation);
48 int shutdownNoInt(int fd, int how);
49
50 ssize_t readNoInt(int fd, void* buf, size_t n);
51 ssize_t preadNoInt(int fd, void* buf, size_t n, off_t offset);
52 ssize_t readvNoInt(int fd, const iovec* iov, int count);
53
54 ssize_t writeNoInt(int fd, const void* buf, size_t n);
55 ssize_t pwriteNoInt(int fd, const void* buf, size_t n, off_t offset);
56 ssize_t writevNoInt(int fd, const iovec* iov, int count);
57
58 /**
59  * Wrapper around read() (and pread()) that, in addition to retrying on
60  * EINTR, will loop until all data is read.
61  *
62  * This wrapper is only useful for blocking file descriptors (for non-blocking
63  * file descriptors, you have to be prepared to deal with incomplete reads
64  * anyway), and only exists because POSIX allows read() to return an incomplete
65  * read if interrupted by a signal (instead of returning -1 and setting errno
66  * to EINTR).
67  *
68  * Note that this wrapper weakens the thread safety of read(): the file pointer
69  * is shared between threads, but the system call is atomic.  If multiple
70  * threads are reading from a file at the same time, you don't know where your
71  * data came from in the file, but you do know that the returned bytes were
72  * contiguous.  You can no longer make this assumption if using readFull().
73  * You should probably use pread() when reading from the same file descriptor
74  * from multiple threads simultaneously, anyway.
75  *
76  * Note that readvFull and preadvFull require iov to be non-const, unlike
77  * readv and preadv.  The contents of iov after these functions return
78  * is unspecified.
79  */
80 ssize_t readFull(int fd, void* buf, size_t n);
81 ssize_t preadFull(int fd, void* buf, size_t n, off_t offset);
82 ssize_t readvFull(int fd, iovec* iov, int count);
83 ssize_t preadvFull(int fd, iovec* iov, int count, off_t offset);
84
85 /**
86  * Similar to readFull and preadFull above, wrappers around write() and
87  * pwrite() that loop until all data is written.
88  *
89  * Generally, the write() / pwrite() system call may always write fewer bytes
90  * than requested, just like read().  In certain cases (such as when writing to
91  * a pipe), POSIX provides stronger guarantees, but not in the general case.
92  * For example, Linux (even on a 64-bit platform) won't write more than 2GB in
93  * one write() system call.
94  *
95  * Note that writevFull and pwritevFull require iov to be non-const, unlike
96  * writev and pwritev.  The contents of iov after these functions return
97  * is unspecified.
98  */
99 ssize_t writeFull(int fd, const void* buf, size_t n);
100 ssize_t pwriteFull(int fd, const void* buf, size_t n, off_t offset);
101 ssize_t writevFull(int fd, iovec* iov, int count);
102 ssize_t pwritevFull(int fd, iovec* iov, int count, off_t offset);
103
104 /**
105  * Read entire file (if num_bytes is defaulted) or no more than
106  * num_bytes (otherwise) into container *out. The container is assumed
107  * to be contiguous, with element size equal to 1, and offer size(),
108  * reserve(), and random access (e.g. std::vector<char>, std::string,
109  * fbstring).
110  *
111  * Returns: true on success or false on failure. In the latter case
112  * errno will be set appropriately by the failing system primitive.
113  */
114 template <class Container>
115 bool readFile(
116     int fd,
117     Container& out,
118     size_t num_bytes = std::numeric_limits<size_t>::max()) {
119   static_assert(sizeof(out[0]) == 1,
120                 "readFile: only containers with byte-sized elements accepted");
121
122   size_t soFar = 0; // amount of bytes successfully read
123   SCOPE_EXIT {
124     DCHECK(out.size() >= soFar); // resize better doesn't throw
125     out.resize(soFar);
126   };
127
128   // Obtain file size:
129   struct stat buf;
130   if (fstat(fd, &buf) == -1) return false;
131   // Some files (notably under /proc and /sys on Linux) lie about
132   // their size, so treat the size advertised by fstat under advise
133   // but don't rely on it. In particular, if the size is zero, we
134   // should attempt to read stuff. If not zero, we'll attempt to read
135   // one extra byte.
136   constexpr size_t initialAlloc = 1024 * 4;
137   out.resize(
138     std::min(
139       buf.st_size > 0 ? folly::to<size_t>(buf.st_size + 1) : initialAlloc,
140       num_bytes));
141
142   while (soFar < out.size()) {
143     const auto actual = readFull(fd, &out[soFar], out.size() - soFar);
144     if (actual == -1) {
145       return false;
146     }
147     soFar += actual;
148     if (soFar < out.size()) {
149       // File exhausted
150       break;
151     }
152     // Ew, allocate more memory. Use exponential growth to avoid
153     // quadratic behavior. Cap size to num_bytes.
154     out.resize(std::min(out.size() * 3 / 2, num_bytes));
155   }
156
157   return true;
158 }
159
160 /**
161  * Same as above, but takes in a file name instead of fd
162  */
163 template <class Container>
164 bool readFile(
165     const char* file_name,
166     Container& out,
167     size_t num_bytes = std::numeric_limits<size_t>::max()) {
168   DCHECK(file_name);
169
170   const auto fd = openNoInt(file_name, O_RDONLY);
171   if (fd == -1) {
172     return false;
173   }
174
175   SCOPE_EXIT {
176     // Ignore errors when closing the file
177     closeNoInt(fd);
178   };
179
180   return readFile(fd, out, num_bytes);
181 }
182
183 /**
184  * Writes container to file. The container is assumed to be
185  * contiguous, with element size equal to 1, and offering STL-like
186  * methods empty(), size(), and indexed access
187  * (e.g. std::vector<char>, std::string, fbstring, StringPiece).
188  *
189  * "flags" dictates the open flags to use. Default is to create file
190  * if it doesn't exist and truncate it.
191  *
192  * Returns: true on success or false on failure. In the latter case
193  * errno will be set appropriately by the failing system primitive.
194  */
195 template <class Container>
196 bool writeFile(const Container& data, const char* filename,
197               int flags = O_WRONLY | O_CREAT | O_TRUNC) {
198   static_assert(sizeof(data[0]) == 1,
199                 "writeFile works with element size equal to 1");
200   int fd = open(filename, flags, 0666);
201   if (fd == -1) {
202     return false;
203   }
204   bool ok = data.empty() ||
205     writeFull(fd, &data[0], data.size()) == static_cast<ssize_t>(data.size());
206   return closeNoInt(fd) == 0 && ok;
207 }
208
209 }  // namespaces