summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deymo <deymo@google.com>2015-10-14 20:43:15 -0700
committerAlex Deymo <deymo@google.com>2015-10-23 20:09:15 -0700
commitdaf35169e3fa51cc9ff468f12acd435a9b075266 (patch)
tree538b9665188ed7c163e041964d5ce37b0bdcc291
parent03f1debab429e673ba5e9e317c5a04e36e850cef (diff)
downloadbsdiff-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.cc5
-rw-r--r--extents_file.h1
-rw-r--r--extents_file_unittest.cc9
-rw-r--r--file.cc36
-rw-r--r--file.h1
-rw-r--r--file_interface.h4
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}});
diff --git a/file.cc b/file.cc
index 972273a..2eebc4d 100644
--- a/file.cc
+++ b/file.cc
@@ -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, &sectors) == 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) {}
diff --git a/file.h b/file.h
index 00cd638..e9659c7 100644
--- a/file.h
+++ b/file.h
@@ -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;
};