aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Benjamin Barenblat <bbaren@mit.edu>2016-02-21 19:23:11 -0500
committerGravatar Benjamin Barenblat <bbaren@mit.edu>2016-02-21 20:38:03 -0500
commit6aa9095865017c06a61f0cb10c1f1231a89b761c (patch)
tree0303312d8f9b2e1671a8e74d6ff11147c153bea0
parent384f7c422acca2f3658393abfc16ea57cd74caa6 (diff)
Implement fgetattr and read
-rw-r--r--src/operations.cc33
-rw-r--r--src/posix_extras.cc18
-rw-r--r--src/posix_extras.h7
3 files changed, 58 insertions, 0 deletions
diff --git a/src/operations.cc b/src/operations.cc
index 355ffc3..897b193 100644
--- a/src/operations.cc
+++ b/src/operations.cc
@@ -25,8 +25,10 @@
#include <new>
#include <system_error>
#include <type_traits>
+#include <vector>
#include <dirent.h>
+#include <fcntl.h>
#include <glog/logging.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -75,6 +77,19 @@ int Getattr(const char* const path, struct stat* output) noexcept {
}
}
+int Fgetattr(const char*, struct stat* const output,
+ struct fuse_file_info* const file_info) noexcept {
+ try {
+ *output = reinterpret_cast<File*>(file_info->fh)->Stat();
+ return 0;
+ } catch (const std::system_error& e) {
+ return -e.code().value();
+ } catch (...) {
+ LOG(ERROR) << "getattr: caught unexpected value";
+ return -ENOTRECOVERABLE;
+ }
+}
+
template <typename T>
int OpenResource(const char* const path, const int flags,
uint64_t* const handle) noexcept {
@@ -131,6 +146,22 @@ int Open(const char* const path, fuse_file_info* const file_info) noexcept {
return OpenResource<File>(path, file_info->flags, &file_info->fh);
}
+int Read(const char*, char* const buffer, const size_t bytes,
+ const off_t offset, fuse_file_info* const file_info) noexcept {
+ LOG(INFO) << "read with offset " << offset;
+ try {
+ auto* const file = reinterpret_cast<File*>(file_info->fh);
+ const std::vector<std::uint8_t> read = file->Read(offset, bytes);
+ std::memcpy(buffer, read.data(), read.size());
+ return static_cast<int>(read.size());
+ } catch (const std::system_error& e) {
+ return -e.code().value();
+ } catch (...) {
+ LOG(ERROR) << "read: caught unexpected value";
+ return -ENOTRECOVERABLE;
+ }
+}
+
int Utimens(const char* const path, const timespec times[2]) noexcept {
try {
root_->UTimeNs(
@@ -230,9 +261,11 @@ fuse_operations FuseOperations(File* const root) {
result.destroy = &Destroy;
result.getattr = &Getattr;
+ result.fgetattr = &Fgetattr;
result.mknod = &Mknod;
result.open = &Open;
+ result.read = &Read;
result.utimens = &Utimens;
result.release = &Release;
result.unlink = &Unlink;
diff --git a/src/posix_extras.cc b/src/posix_extras.cc
index 7529251..ac6e3b2 100644
--- a/src/posix_extras.cc
+++ b/src/posix_extras.cc
@@ -16,9 +16,11 @@
#include <array>
#include <cerrno>
+#include <cstdint>
#include <experimental/optional>
#include <stdexcept>
#include <system_error>
+#include <vector>
#include <dirent.h>
#include <fcntl.h>
@@ -101,6 +103,22 @@ File File::OpenAt(const char* const path, const int flags,
return result;
}
+std::vector<std::uint8_t> File::Read(off_t offset, size_t bytes) const {
+ std::vector<std::uint8_t> result(bytes, 0);
+ size_t cursor = 0;
+ ssize_t bytes_read;
+ while (0 < (bytes_read = pread(fd_, result.data() + cursor, bytes, offset))) {
+ cursor += static_cast<size_t>(bytes_read);
+ offset += bytes_read;
+ bytes -= static_cast<size_t>(bytes_read);
+ }
+ if (bytes_read == -1) {
+ throw SystemError();
+ }
+ result.resize(cursor);
+ return result;
+}
+
void File::UnlinkAt(const char* const path) const {
if (path[0] == '/') {
throw std::invalid_argument("absolute path");
diff --git a/src/posix_extras.h b/src/posix_extras.h
index a73f9fe..5571da6 100644
--- a/src/posix_extras.h
+++ b/src/posix_extras.h
@@ -15,8 +15,10 @@
#ifndef POSIX_EXTRAS_H_
#define POSIX_EXTRAS_H_
+#include <cstdint>
#include <experimental/optional>
#include <string>
+#include <vector>
#include <dirent.h>
#include <sys/stat.h>
@@ -78,6 +80,11 @@ class File {
}
File OpenAt(const char* path, int flags, mode_t mode) const;
+ // Reads exactly the specified number of bytes from the file at the given
+ // offset, unless doing so would run past the end of the file, in which case
+ // fewer bytes are returned.
+ std::vector<std::uint8_t> Read(off_t, size_t) const;
+
// Removes the file at the path relative to the file descriptor. The path
// must indeed be relative (i.e., it must not start with '/').
void UnlinkAt(const char* path) const;