diff options
author | Alex Deymo <deymo@google.com> | 2015-10-14 20:43:15 -0700 |
---|---|---|
committer | Alex Deymo <deymo@google.com> | 2015-10-23 20:09:15 -0700 |
commit | daf35169e3fa51cc9ff468f12acd435a9b075266 (patch) | |
tree | 538b9665188ed7c163e041964d5ce37b0bdcc291 | |
parent | 03f1debab429e673ba5e9e317c5a04e36e850cef (diff) | |
download | bsdiff-daf35169e3fa51cc9ff468f12acd435a9b075266.tar.gz |
FileInterface: Implement GetSize().
Implemented a method to get the size of the FileInterface object
directly.
Bug: 24478450
Change-Id: I9aab80b33cc554551ce79bfee52e94e8e04775db
Test: make all test && ./unittest
-rw-r--r-- | extents_file.cc | 5 | ||||
-rw-r--r-- | extents_file.h | 1 | ||||
-rw-r--r-- | extents_file_unittest.cc | 9 | ||||
-rw-r--r-- | file.cc | 36 | ||||
-rw-r--r-- | file.h | 1 | ||||
-rw-r--r-- | file_interface.h | 4 |
6 files changed, 56 insertions, 0 deletions
diff --git a/extents_file.cc b/extents_file.cc index fc4a10d..2d2ea83 100644 --- a/extents_file.cc +++ b/extents_file.cc @@ -62,6 +62,11 @@ bool ExtentsFile::Close() { return file_->Close(); } +bool ExtentsFile::GetSize(uint64_t* size) { + *size = total_ex_len_; + return true; +} + void ExtentsFile::AdvancePos(uint64_t size) { curr_pos_ += size; for (; curr_ex_idx_ < extents_.size(); curr_ex_idx_++) { diff --git a/extents_file.h b/extents_file.h index a8007dd..865e2a2 100644 --- a/extents_file.h +++ b/extents_file.h @@ -53,6 +53,7 @@ class ExtentsFile : public FileInterface { bool Write(const void* buf, size_t count, size_t* bytes_written) override; bool Seek(off_t pos) override; bool Close() override; + bool GetSize(uint64_t* size) override; private: void AdvancePos(uint64_t size); diff --git a/extents_file_unittest.cc b/extents_file_unittest.cc index 206328c..fa9ed22 100644 --- a/extents_file_unittest.cc +++ b/extents_file_unittest.cc @@ -28,6 +28,7 @@ class MockFile : public FileInterface { MOCK_METHOD3(Write, bool(const void*, size_t, size_t*)); MOCK_METHOD1(Seek, bool(off_t)); MOCK_METHOD0(Close, bool()); + MOCK_METHOD1(GetSize, bool(uint64_t*)); }; ACTION(SucceedIO) { @@ -67,6 +68,14 @@ TEST_F(ExtentsFileTest, CloseIsForwarded) { EXPECT_CALL(*mock_file_, Close()).WillOnce(Return(false)); } +TEST_F(ExtentsFileTest, GetSizeSumExtents) { + ExtentsFile file(std::move(mock_file_ptr_), + {ex_t{10, 5}, ex_t{20, 5}, {25, 2}}); + uint64_t size; + EXPECT_TRUE(file.GetSize(&size)); + EXPECT_EQ(12U, size); +} + TEST_F(ExtentsFileTest, SeekToRightOffsets) { ExtentsFile file(std::move(mock_file_ptr_), {ex_t{10, 5}, ex_t{20, 5}, {25, 2}}); @@ -6,6 +6,9 @@ #include <errno.h> #include <fcntl.h> +#ifdef __linux__ +#include <linux/fs.h> +#endif // __linux__ #include <string.h> #include <sys/ioctl.h> #include <sys/stat.h> @@ -88,6 +91,39 @@ bool File::Close() { return success; } +bool File::GetSize(uint64_t* size) { + struct stat stbuf; + if (fstat(fd_, &stbuf) == -1) + return false; + if (S_ISREG(stbuf.st_mode)) { + return stbuf.st_size; + } + if (S_ISBLK(stbuf.st_mode)) { +#if defined(BLKGETSIZE64) + return ioctl(fd_, BLKGETSIZE64, size); +#elif defined(DKIOCGETBLOCKCOUNT) + uint64_t sectors = 0; + if (ioctl(fd_, DKIOCGETBLOCKCOUNT, §ors) == 0) { + *size = sectors << 9; + return true; + } + return false; +#else + // Fall back to doing seeks to know the EOF. + off_t pos = lseek(fd_, 0, SEEK_CUR); + if (pos == -1) + return false; + off_t end_pos = lseek(fd_, 0, SEEK_END); + if (end_pos == -1) + return false; + *size = end_pos; + lseek(fd_, 0, SEEK_END); + return true; +#endif + } + return false; +} + File::File(int fd) : fd_(fd) {} @@ -24,6 +24,7 @@ class File : public FileInterface { bool Write(const void* buf, size_t count, size_t* bytes_written) override; bool Seek(off_t pos) override; bool Close() override; + bool GetSize(uint64_t* size) override; private: // Creates the File instance for the |fd|. Takes ownership of the file diff --git a/file_interface.h b/file_interface.h index b32115a..a643f45 100644 --- a/file_interface.h +++ b/file_interface.h @@ -35,6 +35,10 @@ class FileInterface { // succeeded. virtual bool Close() = 0; + // Compute the size of the file and store it in |size|. Returns whether it + // computed the size successfully. + virtual bool GetSize(uint64_t* size) = 0; + protected: FileInterface() = default; }; |