X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FFile.cpp;h=253d005472a0a80f52c5bb67452071d0b9538c69;hb=668192ca7476ebc5a858056ca9598a3fc2eb2240;hp=4998ec1fa1113067d94f3566121b2ec32d1c8ce7;hpb=9d6c66ddc8f6f38eef4c6f1c09abb3b30f888057;p=folly.git diff --git a/folly/File.cpp b/folly/File.cpp index 4998ec1f..253d0054 100644 --- a/folly/File.cpp +++ b/folly/File.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013 Facebook, Inc. + * Copyright 2015 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,16 @@ * limitations under the License. */ -#include "folly/File.h" -#include "folly/Format.h" -#include "folly/ScopeGuard.h" +#include + +#include +#include +#include + +#include +#include +#include +#include #include @@ -31,25 +38,24 @@ File::File() File::File(int fd, bool ownsFd) : fd_(fd) - , ownsFd_(ownsFd) -{} + , 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_ < 0) { - throw std::system_error(errno, std::system_category(), - folly::format("open(\"{}\", {:#o}, 0{:#o}) failed", - name, flags, mode).str()); + if (fd_ == -1) { + throwSystemError(folly::format("open(\"{}\", {:#o}, 0{:#o}) failed", + name, flags, mode).fbstr()); } ownsFd_ = true; } -File::File(File&& other) +File::File(File&& other) noexcept : fd_(other.fd_) , ownsFd_(other.ownsFd_) { - other.release(); } @@ -60,38 +66,30 @@ File& File::operator=(File&& other) { } File::~File() { - closeNoThrow(); // ignore error + 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(); - if (!tmpFile) { - throw std::system_error(errno, std::system_category(), "tmpfile() failed"); - } + checkFopenError(tmpFile, "tmpfile() failed"); SCOPE_EXIT { fclose(tmpFile); }; - int fd = dup(fileno(tmpFile)); - if (fd < 0) { - throw std::system_error(errno, std::system_category(), "dup() failed"); - } + int fd = ::dup(fileno(tmpFile)); + checkUnixError(fd, "dup() failed"); return File(fd, true); } -/* static */ File File::tryOpen(const char* name, - int flags, - mode_t mode) { - try { - return File(name, flags, mode); - } catch (const std::system_error&) { - return File(); - } -} - -void File::release() { +int File::release() noexcept { + int released = fd_; fd_ = -1; ownsFd_ = false; + return released; } void File::swap(File& other) { @@ -104,9 +102,20 @@ void swap(File& a, File& b) { 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()) { - throw std::system_error(errno, std::system_category(), "close() failed"); + throwSystemError("close() failed"); } } @@ -116,4 +125,26 @@ bool File::closeNoThrow() { 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