123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- /*
- * Copyright 2013-present Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include <folly/File.h>
- #include <folly/Exception.h>
- #include <folly/FileUtil.h>
- #include <folly/Format.h>
- #include <folly/ScopeGuard.h>
- #include <folly/portability/Fcntl.h>
- #include <folly/portability/SysFile.h>
- #include <folly/portability/Unistd.h>
- #include <system_error>
- #include <glog/logging.h>
- namespace folly {
- File::File() noexcept : fd_(-1), ownsFd_(false) {}
- File::File(int fd, bool ownsFd) noexcept : fd_(fd), ownsFd_(ownsFd) {
- CHECK_GE(fd, -1) << "fd must be -1 or non-negative";
- CHECK(fd != -1 || !ownsFd) << "cannot own -1";
- }
- File::File(const char* name, int flags, mode_t mode)
- : fd_(::open(name, flags, mode)), ownsFd_(false) {
- if (fd_ == -1) {
- throwSystemError(
- folly::format("open(\"{}\", {:#o}, 0{:#o}) failed", name, flags, mode)
- .fbstr());
- }
- ownsFd_ = true;
- }
- File::File(const std::string& name, int flags, mode_t mode)
- : File(name.c_str(), flags, mode) {}
- File::File(StringPiece name, int flags, mode_t mode)
- : File(name.str(), flags, mode) {}
- File::File(File&& other) noexcept : fd_(other.fd_), ownsFd_(other.ownsFd_) {
- other.release();
- }
- File& File::operator=(File&& other) {
- closeNoThrow();
- swap(other);
- return *this;
- }
- File::~File() {
- auto fd = fd_;
- if (!closeNoThrow()) { // ignore most errors
- DCHECK_NE(errno, EBADF)
- << "closing fd " << fd << ", it may already "
- << "have been closed. Another time, this might close the wrong FD.";
- }
- }
- /* static */ File File::temporary() {
- // make a temp file with tmpfile(), dup the fd, then return it in a File.
- FILE* tmpFile = tmpfile();
- checkFopenError(tmpFile, "tmpfile() failed");
- SCOPE_EXIT {
- fclose(tmpFile);
- };
- int fd = ::dup(fileno(tmpFile));
- checkUnixError(fd, "dup() failed");
- return File(fd, true);
- }
- int File::release() noexcept {
- int released = fd_;
- fd_ = -1;
- ownsFd_ = false;
- return released;
- }
- void File::swap(File& other) noexcept {
- using std::swap;
- swap(fd_, other.fd_);
- swap(ownsFd_, other.ownsFd_);
- }
- void swap(File& a, File& b) noexcept {
- a.swap(b);
- }
- File File::dup() const {
- if (fd_ != -1) {
- int fd = ::dup(fd_);
- checkUnixError(fd, "dup() failed");
- return File(fd, true);
- }
- return File();
- }
- void File::close() {
- if (!closeNoThrow()) {
- throwSystemError("close() failed");
- }
- }
- bool File::closeNoThrow() {
- int r = ownsFd_ ? ::close(fd_) : 0;
- release();
- return r == 0;
- }
- void File::lock() {
- doLock(LOCK_EX);
- }
- bool File::try_lock() {
- return doTryLock(LOCK_EX);
- }
- void File::lock_shared() {
- doLock(LOCK_SH);
- }
- bool File::try_lock_shared() {
- return doTryLock(LOCK_SH);
- }
- void File::doLock(int op) {
- checkUnixError(flockNoInt(fd_, op), "flock() failed (lock)");
- }
- bool File::doTryLock(int op) {
- int r = flockNoInt(fd_, op | LOCK_NB);
- // flock returns EWOULDBLOCK if already locked
- if (r == -1 && errno == EWOULDBLOCK) {
- return false;
- }
- checkUnixError(r, "flock() failed (try_lock)");
- return true;
- }
- void File::unlock() {
- checkUnixError(flockNoInt(fd_, LOCK_UN), "flock() failed (unlock)");
- }
- void File::unlock_shared() {
- unlock();
- }
- } // namespace folly
|