FileUtil.h 8.7 KB

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