proxygen
File.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/File.h>
18 
19 #include <folly/Exception.h>
20 #include <folly/FileUtil.h>
21 #include <folly/Format.h>
22 #include <folly/ScopeGuard.h>
26 
27 #include <system_error>
28 
29 #include <glog/logging.h>
30 
31 namespace folly {
32 
33 File::File() noexcept : fd_(-1), ownsFd_(false) {}
34 
35 File::File(int fd, bool ownsFd) noexcept : fd_(fd), ownsFd_(ownsFd) {
36  CHECK_GE(fd, -1) << "fd must be -1 or non-negative";
37  CHECK(fd != -1 || !ownsFd) << "cannot own -1";
38 }
39 
40 File::File(const char* name, int flags, mode_t mode)
41  : fd_(::open(name, flags, mode)), ownsFd_(false) {
42  if (fd_ == -1) {
44  folly::format("open(\"{}\", {:#o}, 0{:#o}) failed", name, flags, mode)
45  .fbstr());
46  }
47  ownsFd_ = true;
48 }
49 
50 File::File(const std::string& name, int flags, mode_t mode)
51  : File(name.c_str(), flags, mode) {}
52 
54  : File(name.str(), flags, mode) {}
55 
56 File::File(File&& other) noexcept : fd_(other.fd_), ownsFd_(other.ownsFd_) {
57  other.release();
58 }
59 
61  closeNoThrow();
62  swap(other);
63  return *this;
64 }
65 
67  auto fd = fd_;
68  if (!closeNoThrow()) { // ignore most errors
69  DCHECK_NE(errno, EBADF)
70  << "closing fd " << fd << ", it may already "
71  << "have been closed. Another time, this might close the wrong FD.";
72  }
73 }
74 
75 /* static */ File File::temporary() {
76  // make a temp file with tmpfile(), dup the fd, then return it in a File.
77  FILE* tmpFile = tmpfile();
78  checkFopenError(tmpFile, "tmpfile() failed");
79  SCOPE_EXIT {
80  fclose(tmpFile);
81  };
82 
83  int fd = ::dup(fileno(tmpFile));
84  checkUnixError(fd, "dup() failed");
85 
86  return File(fd, true);
87 }
88 
90  int released = fd_;
91  fd_ = -1;
92  ownsFd_ = false;
93  return released;
94 }
95 
96 void File::swap(File& other) noexcept {
97  using std::swap;
98  swap(fd_, other.fd_);
99  swap(ownsFd_, other.ownsFd_);
100 }
101 
102 void swap(File& a, File& b) noexcept {
103  a.swap(b);
104 }
105 
106 File File::dup() const {
107  if (fd_ != -1) {
108  int fd = ::dup(fd_);
109  checkUnixError(fd, "dup() failed");
110 
111  return File(fd, true);
112  }
113 
114  return File();
115 }
116 
117 void File::close() {
118  if (!closeNoThrow()) {
119  throwSystemError("close() failed");
120  }
121 }
122 
124  int r = ownsFd_ ? ::close(fd_) : 0;
125  release();
126  return r == 0;
127 }
128 
129 void File::lock() {
130  doLock(LOCK_EX);
131 }
133  return doTryLock(LOCK_EX);
134 }
136  doLock(LOCK_SH);
137 }
139  return doTryLock(LOCK_SH);
140 }
141 
142 void File::doLock(int op) {
143  checkUnixError(flockNoInt(fd_, op), "flock() failed (lock)");
144 }
145 
146 bool File::doTryLock(int op) {
147  int r = flockNoInt(fd_, op | LOCK_NB);
148  // flock returns EWOULDBLOCK if already locked
149  if (r == -1 && errno == EWOULDBLOCK) {
150  return false;
151  }
152  checkUnixError(r, "flock() failed (try_lock)");
153  return true;
154 }
155 
156 void File::unlock() {
157  checkUnixError(flockNoInt(fd_, LOCK_UN), "flock() failed (unlock)");
158 }
160  unlock();
161 }
162 
163 } // namespace folly
void lock()
Definition: File.cpp:129
flags
Definition: http_parser.h:127
char b
void doLock(int op)
Definition: File.cpp:142
#define SCOPE_EXIT
Definition: ScopeGuard.h:274
int release() noexcept
Definition: File.cpp:89
File & operator=(File &&)
Definition: File.cpp:60
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
void swap(File &a, File &b) noexcept
Definition: File.cpp:102
folly::Optional< PskKeyExchangeMode > mode
void swap(File &other) noexcept
Definition: File.cpp:96
const char * name
Definition: http_parser.c:437
int fd_
Definition: File.h:152
bool closeNoThrow()
Definition: File.cpp:123
int fd() const
Definition: File.h:85
void checkFopenError(FILE *fp, Args &&...args)
Definition: Exception.h:118
char a
int flockNoInt(int fd, int operation)
Definition: FileUtil.cpp:94
bool ownsFd_
Definition: File.h:153
void close()
Definition: File.cpp:117
void checkUnixError(ssize_t ret, Args &&...args)
Definition: Exception.h:101
const char * string
Definition: Conv.cpp:212
bool try_lock_shared()
Definition: File.cpp:138
bool try_lock()
Definition: File.cpp:132
void unlock()
Definition: File.cpp:156
Formatter< false, Args... > format(StringPiece fmt, Args &&...args)
Definition: Format.h:271
File dup() const
Definition: File.cpp:106
bool doTryLock(int op)
Definition: File.cpp:146
void throwSystemError(Args &&...args)
Definition: Exception.h:76
static File temporary()
Definition: File.cpp:75
GMockOutputTest ExpectedCall FILE
File() noexcept
Definition: File.cpp:33
void unlock_shared()
Definition: File.cpp:159
void lock_shared()
Definition: File.cpp:135