22 #if defined(__linux__) 26 #include <glog/logging.h> 37 using namespace fileutil_detail;
47 ssize_t operator()(
int fd,
void* buf,
size_t count);
50 ssize_t operator()(
int fd,
void* buf,
size_t count, off_t offset);
53 ssize_t operator()(
int fd,
const iovec* iov,
int count);
56 ssize_t operator()(
int fd,
const iovec* iov,
int count, off_t offset);
58 const std::deque<ssize_t> spec()
const {
70 Reader::Reader(off_t offset,
StringPiece data, std::deque<ssize_t> spec)
73 ssize_t Reader::nextSize() {
75 throw std::runtime_error(
"spec empty");
77 ssize_t n =
spec_.front();
90 ssize_t Reader::operator()(
int ,
void* buf,
size_t count) {
91 ssize_t n = nextSize();
95 if (
size_t(n) > count) {
96 throw std::runtime_error(
"requested count too small");
98 memcpy(buf,
data_.data(), n);
103 ssize_t Reader::operator()(
int fd,
void* buf,
size_t count, off_t offset) {
105 return operator()(fd, buf, count);
108 ssize_t Reader::operator()(
int ,
const iovec* iov,
int count) {
109 ssize_t n = nextSize();
113 ssize_t remaining = n;
114 for (; count != 0 && remaining != 0; ++iov, --
count) {
115 ssize_t len =
std::min(remaining, ssize_t(iov->iov_len));
116 memcpy(iov->iov_base,
data_.data(), len);
120 if (remaining != 0) {
121 throw std::runtime_error(
"requested total size too small");
126 ssize_t Reader::operator()(
int fd,
const iovec* iov,
int count, off_t offset) {
128 return operator()(fd, iov, count);
137 Reader reader(std::deque<ssize_t> spec);
143 FileUtilTest::FileUtilTest()
144 :
in_(
"1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") {
145 CHECK_EQ(62,
in_.size());
167 if (p.first != (decltype(p.first))(-1)) {
168 EXPECT_EQ(
in_.substr(0, p.first), out.substr(0, p.first));
177 if (p.first != (decltype(p.first))(-1)) {
178 EXPECT_EQ(
in_.substr(0, p.first), out.substr(0, p.first));
188 std::vector<iovec>
iov()
const {
202 iov_.reserve(sizes.size());
203 for (
auto&
s : sizes) {
206 for (
auto&
b : buffers_) {
208 iov.iov_base = &
b[0];
209 iov.iov_len =
b.size();
215 iov_.reserve(sizes.size());
216 for (
auto s : sizes) {
219 for (
auto&
b : buffers_) {
221 iov.iov_base = &
b[0];
222 iov.iov_len =
b.size();
229 for (
auto&
b : buffers_) {
240 auto iov = buf.iov();
242 if (p.first != (decltype(p.first))(-1)) {
243 EXPECT_EQ(
in_.substr(0, p.first), buf.join().substr(0, p.first));
250 std::vector<size_t>
sizes;
253 sizes.push_back(
i % 3 + 1);
258 auto iov = buf.
iov();
267 auto iov = buf.iov();
269 p.first,
wrapvFull(p.second, 0, iov.data(), iov.size(), off_t(42)));
270 if (p.first != (decltype(p.first))(-1)) {
271 EXPECT_EQ(
in_.substr(0, p.first), buf.join().substr(0, p.first));
278 auto afile = afileTemp.
path().string();
279 auto emptyFile = emptyFileTemp.
path().string();
296 vector<unsigned char> contents;
298 EXPECT_EQ(vector<unsigned char>(), contents);
300 EXPECT_EQ(vector<unsigned char>(), contents);
302 EXPECT_EQ(vector<unsigned char>({
'b',
'a'}), contents);
304 EXPECT_EQ(vector<unsigned char>({
'b',
'a',
'r'}), contents);
336 File f(aFile.path().string(), O_WRONLY);
343 File f(aFile.path().string());
356 std::set<std::string> entries;
357 for (
auto& entry : fs::directory_iterator(tmpDir_.path())) {
358 entries.insert(entry.path().filename().string());
373 auto rc = stat(path.c_str(), &
s);
379 return (statFile(path).st_mode & 0777);
383 return tmpDir_.path().string() +
"/" + name.
str();
387 auto rc = chmod(tmpDir_.path().string().c_str(),
mode);
396 auto path = tmpPath(
"foo");
401 EXPECT_EQ(set<string>{
"foo"}, listTmpDir());
408 auto path = tmpPath(
"foo");
412 EXPECT_EQ(set<string>{
"foo"}, listTmpDir());
419 EXPECT_EQ(set<string>{
"foo"}, listTmpDir());
425 "asdf" +
string(10240,
'\n') +
"foobar\n" +
string(10240,
'b') +
"\n";
427 EXPECT_EQ(set<string>{
"foo"}, listTmpDir());
439 EXPECT_EQ(set<string>{
"foo"}, listTmpDir());
455 }
catch (
const std::exception&) {
462 auto path1 = tmpPath(
"foo");
471 EXPECT_EQ(set<string>{
"foo"}, listTmpDir());
478 writeFileAtomic(tmpPath(
"another_file.txt"),
"x\n"), std::system_error);
479 EXPECT_EQ(set<string>{
"foo"}, listTmpDir());
489 auto expectedPaths = set<string>{
"foo.txt",
"bar.txt",
"foo_txt",
"foo.txt2"};
491 EXPECT_EQ(
"foo", readData(tmpPath(
"foo.txt")));
492 EXPECT_EQ(
"bar", readData(tmpPath(
"bar.txt")));
493 EXPECT_EQ(
"underscore", readData(tmpPath(
"foo_txt")));
494 EXPECT_EQ(
"foo2", readData(tmpPath(
"foo.txt2")));
495 EXPECT_EQ(0644, getPerms(tmpPath(
"foo.txt")));
496 EXPECT_EQ(0400, getPerms(tmpPath(
"bar.txt")));
497 EXPECT_EQ(0440, getPerms(tmpPath(
"foo_txt")));
498 EXPECT_EQ(0444, getPerms(tmpPath(
"foo.txt2")));
503 #if defined(__linux__) 509 class FChmodFailure {
518 static bool shouldFail() {
519 return forceFailure_.load() > 0;
523 static std::atomic<int> forceFailure_;
526 std::atomic<int> FChmodFailure::forceFailure_{0};
531 int fchmod(
int fd, mode_t
mode) {
532 static const auto realFunction =
533 reinterpret_cast<int (*)(
int, mode_t)
>(dlsym(RTLD_NEXT,
"fchmod"));
536 CHECK_NE(realFunction, fchmod);
538 if (FChmodFailure::shouldFail()) {
542 return realFunction(fd, mode);
548 auto path = tmpPath(
"foo");
565 EXPECT_EQ(set<string>{
"foo"}, listTmpDir());
575 EXPECT_EQ(set<string>{
"foo"}, listTmpDir());
bool readFile(int fd, Container &out, size_t num_bytes=std::numeric_limits< size_t >::max())
std::atomic< int64_t > sum(0)
#define EXPECT_THROW(statement, expected_exception)
#define ASSERT_EQ(val1, val2)
std::set< std::string > listTmpDir() const
std::string readData(const string &path) const
std::vector< iovec > iov_
#define EXPECT_EQ(val1, val2)
constexpr detail::Map< Move > move
—— Concurrent Priority Queue Implementation ——
auto msvcSuppressAbortOnInvalidParams(Func func) -> decltype(func())
folly::Optional< PskKeyExchangeMode > mode
constexpr auto size(C const &c) -> decltype(c.size())
std::vector< std::pair< size_t, Reader > > readers_
std::vector< std::string > buffers_
size_t read(T &out, folly::io::Cursor &cursor)
ssize_t wrapvFull(F f, int fd, iovec *iov, int count, Offset...offset)
constexpr auto data(C &c) -> decltype(c.data())
mode_t getPerms(const string &path)
const fs::path & path() const
ssize_t preadv(int fd, const iovec *iov, int count, off_t offset)
void setDirPerms(mode_t mode)
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)
TEST(ProgramOptionsTest, Errors)
string tmpPath(StringPiece name)
void checkUnixError(ssize_t ret, Args &&...args)
#define EXPECT_TRUE(condition)
IovecBuffers(std::initializer_list< size_t > sizes)
void join(const Delim &delimiter, Iterator begin, Iterator end, String &output)
bool writeFile(const Container &data, const char *filename, int flags=O_WRONLY|O_CREAT|O_TRUNC, mode_t mode=0666)
#define EXPECT_FALSE(condition)
TEST_F(FileUtilTest, read)
void throwSystemError(Args &&...args)
std::vector< iovec > iov() const
Range< const char * > StringPiece
#define ASSERT_TRUE(condition)
std::deque< ssize_t > spec_
Reader reader(std::deque< ssize_t > spec)