proxygen
FileUtil.cpp
Go to the documentation of this file.
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 #include <folly/FileUtil.h>
18 
19 #include <cerrno>
20 #include <string>
21 #include <system_error>
22 #include <vector>
23 
25 #include <folly/net/NetOps.h>
31 
32 namespace folly {
33 
34 using namespace fileutil_detail;
35 
36 int openNoInt(const char* name, int flags, mode_t mode) {
37  return int(wrapNoInt(open, name, flags, mode));
38 }
39 
40 static int filterCloseReturn(int r) {
41  // Ignore EINTR. On Linux, close() may only return EINTR after the file
42  // descriptor has been closed, so you must not retry close() on EINTR --
43  // in the best case, you'll get EBADF, and in the worst case, you'll end up
44  // closing a different file (one opened from another thread).
45  //
46  // Interestingly enough, the Single Unix Specification says that the state
47  // of the file descriptor is unspecified if close returns EINTR. In that
48  // case, the safe thing to do is also not to retry close() -- leaking a file
49  // descriptor is definitely better than closing the wrong file.
50  if (r == -1 && errno == EINTR) {
51  return 0;
52  }
53  return r;
54 }
55 
56 int closeNoInt(int fd) {
57  return filterCloseReturn(close(fd));
58 }
59 
61  return filterCloseReturn(netops::close(fd));
62 }
63 
64 int fsyncNoInt(int fd) {
65  return int(wrapNoInt(fsync, fd));
66 }
67 
68 int dupNoInt(int fd) {
69  return int(wrapNoInt(dup, fd));
70 }
71 
72 int dup2NoInt(int oldfd, int newfd) {
73  return int(wrapNoInt(dup2, oldfd, newfd));
74 }
75 
76 int fdatasyncNoInt(int fd) {
77 #if defined(__APPLE__)
78  return int(wrapNoInt(fcntl, fd, F_FULLFSYNC));
79 #elif defined(__FreeBSD__) || defined(_MSC_VER)
80  return int(wrapNoInt(fsync, fd));
81 #else
82  return int(wrapNoInt(fdatasync, fd));
83 #endif
84 }
85 
86 int ftruncateNoInt(int fd, off_t len) {
87  return int(wrapNoInt(ftruncate, fd, len));
88 }
89 
90 int truncateNoInt(const char* path, off_t len) {
91  return int(wrapNoInt(truncate, path, len));
92 }
93 
94 int flockNoInt(int fd, int operation) {
95  return int(wrapNoInt(flock, fd, operation));
96 }
97 
98 int shutdownNoInt(NetworkSocket fd, int how) {
99  return int(wrapNoInt(netops::shutdown, fd, how));
100 }
101 
102 ssize_t readNoInt(int fd, void* buf, size_t count) {
103  return wrapNoInt(read, fd, buf, count);
104 }
105 
106 ssize_t preadNoInt(int fd, void* buf, size_t count, off_t offset) {
107  return wrapNoInt(pread, fd, buf, count, offset);
108 }
109 
110 ssize_t readvNoInt(int fd, const iovec* iov, int count) {
111  return wrapNoInt(readv, fd, iov, count);
112 }
113 
114 ssize_t writeNoInt(int fd, const void* buf, size_t count) {
115  return wrapNoInt(write, fd, buf, count);
116 }
117 
118 ssize_t pwriteNoInt(int fd, const void* buf, size_t count, off_t offset) {
119  return wrapNoInt(pwrite, fd, buf, count, offset);
120 }
121 
122 ssize_t writevNoInt(int fd, const iovec* iov, int count) {
123  return wrapNoInt(writev, fd, iov, count);
124 }
125 
126 ssize_t readFull(int fd, void* buf, size_t count) {
127  return wrapFull(read, fd, buf, count);
128 }
129 
130 ssize_t preadFull(int fd, void* buf, size_t count, off_t offset) {
131  return wrapFull(pread, fd, buf, count, offset);
132 }
133 
134 ssize_t writeFull(int fd, const void* buf, size_t count) {
135  return wrapFull(write, fd, const_cast<void*>(buf), count);
136 }
137 
138 ssize_t pwriteFull(int fd, const void* buf, size_t count, off_t offset) {
139  return wrapFull(pwrite, fd, const_cast<void*>(buf), count, offset);
140 }
141 
142 ssize_t readvFull(int fd, iovec* iov, int count) {
143  return wrapvFull(readv, fd, iov, count);
144 }
145 
146 ssize_t preadvFull(int fd, iovec* iov, int count, off_t offset) {
147  return wrapvFull(preadv, fd, iov, count, offset);
148 }
149 
150 ssize_t writevFull(int fd, iovec* iov, int count) {
151  return wrapvFull(writev, fd, iov, count);
152 }
153 
154 ssize_t pwritevFull(int fd, iovec* iov, int count, off_t offset) {
155  return wrapvFull(pwritev, fd, iov, count, offset);
156 }
157 
159  StringPiece filename,
160  iovec* iov,
161  int count,
162  mode_t permissions) {
163  // We write the data to a temporary file name first, then atomically rename
164  // it into place. This ensures that the file contents will always be valid,
165  // even if we crash or are killed partway through writing out data.
166  //
167  // Create a buffer that will contain two things:
168  // - A nul-terminated version of the filename
169  // - The temporary file name
170  std::vector<char> pathBuffer;
171  // Note that we have to explicitly pass in the size here to make
172  // sure the nul byte gets included in the data.
173  constexpr folly::StringPiece suffix(".XXXXXX\0", 8);
174  pathBuffer.resize((2 * filename.size()) + 1 + suffix.size());
175  // Copy in the filename and then a nul terminator
176  memcpy(pathBuffer.data(), filename.data(), filename.size());
177  pathBuffer[filename.size()] = '\0';
178  const char* const filenameCStr = pathBuffer.data();
179  // Now prepare the temporary path template
180  char* const tempPath = pathBuffer.data() + filename.size() + 1;
181  memcpy(tempPath, filename.data(), filename.size());
182  memcpy(tempPath + filename.size(), suffix.data(), suffix.size());
183 
184  auto tmpFD = mkstemp(tempPath);
185  if (tmpFD == -1) {
186  return errno;
187  }
188  bool success = false;
189  SCOPE_EXIT {
190  if (tmpFD != -1) {
191  close(tmpFD);
192  }
193  if (!success) {
194  unlink(tempPath);
195  }
196  };
197 
198  auto rc = writevFull(tmpFD, iov, count);
199  if (rc == -1) {
200  return errno;
201  }
202 
203  rc = fchmod(tmpFD, permissions);
204  if (rc == -1) {
205  return errno;
206  }
207 
208  // Close the file before renaming to make sure all data has
209  // been successfully written.
210  rc = close(tmpFD);
211  tmpFD = -1;
212  if (rc == -1) {
213  return errno;
214  }
215 
216  rc = rename(tempPath, filenameCStr);
217  if (rc == -1) {
218  return errno;
219  }
220  success = true;
221  return 0;
222 }
223 
225  StringPiece filename,
226  iovec* iov,
227  int count,
228  mode_t permissions) {
229  auto rc = writeFileAtomicNoThrow(filename, iov, count, permissions);
230  if (rc != 0) {
231  auto msg = std::string(__func__) + "() failed to update " + filename.str();
232  throw std::system_error(rc, std::generic_category(), msg);
233  }
234 }
235 
236 void writeFileAtomic(StringPiece filename, ByteRange data, mode_t permissions) {
237  iovec iov;
238  iov.iov_base = const_cast<unsigned char*>(data.data());
239  iov.iov_len = data.size();
240  writeFileAtomic(filename, &iov, 1, permissions);
241 }
242 
244  StringPiece filename,
246  mode_t permissions) {
247  writeFileAtomic(filename, ByteRange(data), permissions);
248 }
249 
250 } // namespace folly
ssize_t wrapNoInt(F f, Args...args)
flags
Definition: http_parser.h:127
ssize_t readvFull(int fd, iovec *iov, int count)
Definition: FileUtil.cpp:142
void write(const T &in, folly::io::Appender &appender)
Definition: Types-inl.h:112
std::string str() const
Definition: Range.h:591
int shutdownNoInt(NetworkSocket fd, int how)
Definition: FileUtil.cpp:98
int writeFileAtomicNoThrow(StringPiece filename, iovec *iov, int count, mode_t permissions)
Definition: FileUtil.cpp:158
ssize_t preadNoInt(int fd, void *buf, size_t count, off_t offset)
Definition: FileUtil.cpp:106
ssize_t pwriteFull(int fd, const void *buf, size_t count, off_t offset)
Definition: FileUtil.cpp:138
int closeNoInt(int fd)
Definition: FileUtil.cpp:56
int fdatasyncNoInt(int fd)
Definition: FileUtil.cpp:76
ssize_t readNoInt(int fd, void *buf, size_t count)
Definition: FileUtil.cpp:102
ssize_t readFull(int fd, void *buf, size_t count)
Definition: FileUtil.cpp:126
static int filterCloseReturn(int r)
Definition: FileUtil.cpp:40
constexpr size_type size() const
Definition: Range.h:431
#define SCOPE_EXIT
Definition: ScopeGuard.h:274
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
ssize_t pwritev(int fd, const iovec *iov, int count, off_t offset)
Definition: SysUio.cpp:58
int truncateNoInt(const char *path, off_t len)
Definition: FileUtil.cpp:90
ssize_t writevFull(int fd, iovec *iov, int count)
Definition: FileUtil.cpp:150
folly::Optional< PskKeyExchangeMode > mode
ssize_t writevNoInt(int fd, const iovec *iov, int count)
Definition: FileUtil.cpp:122
const char * name
Definition: http_parser.c:437
int fsyncNoInt(int fd)
Definition: FileUtil.cpp:64
int shutdown(NetworkSocket s, int how)
Definition: NetOps.cpp:408
ssize_t preadFull(int fd, void *buf, size_t count, off_t offset)
Definition: FileUtil.cpp:130
ssize_t readvNoInt(int fd, const iovec *iov, int count)
Definition: FileUtil.cpp:110
size_t read(T &out, folly::io::Cursor &cursor)
Definition: Types-inl.h:258
ssize_t wrapvFull(F f, int fd, iovec *iov, int count, Offset...offset)
const char * suffix
Definition: String.cpp:272
constexpr Iter data() const
Definition: Range.h:446
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
ssize_t writeNoInt(int fd, const void *buf, size_t count)
Definition: FileUtil.cpp:114
int dupNoInt(int fd)
Definition: FileUtil.cpp:68
ssize_t writeFull(int fd, const void *buf, size_t count)
Definition: FileUtil.cpp:134
int flockNoInt(int fd, int operation)
Definition: FileUtil.cpp:94
ssize_t preadv(int fd, const iovec *iov, int count, off_t offset)
Definition: SysUio.cpp:52
ssize_t wrapFull(F f, int fd, void *buf, size_t count, Offset...offset)
void writeFileAtomic(StringPiece filename, iovec *iov, int count, mode_t permissions)
Definition: FileUtil.cpp:224
int * count
int openNoInt(const char *name, int flags, mode_t mode)
Definition: FileUtil.cpp:36
const char * string
Definition: Conv.cpp:212
ssize_t pwriteNoInt(int fd, const void *buf, size_t count, off_t offset)
Definition: FileUtil.cpp:118
Range< const unsigned char * > ByteRange
Definition: Range.h:1163
int dup2NoInt(int oldfd, int newfd)
Definition: FileUtil.cpp:72
int ftruncateNoInt(int fd, off_t len)
Definition: FileUtil.cpp:86
ssize_t pwritevFull(int fd, iovec *iov, int count, off_t offset)
Definition: FileUtil.cpp:154
int close(NetworkSocket s)
Definition: NetOps.cpp:90
ssize_t preadvFull(int fd, iovec *iov, int count, off_t offset)
Definition: FileUtil.cpp:146