diff --git a/src/CryFuse.cpp b/src/CryFuse.cpp index 87fc6b29..98cc8669 100644 --- a/src/CryFuse.cpp +++ b/src/CryFuse.cpp @@ -29,7 +29,7 @@ CryFuse::CryFuse(CryDevice *device) int CryFuse::getattr(const path &path, struct stat *stbuf) { try { - _device->LoadFromPath(path)->stat(stbuf); + _device->lstat(path, stbuf); return 0; } catch(cryfs::CryErrnoException &e) { return -e.getErrno(); @@ -47,8 +47,12 @@ int CryFuse::fgetattr(const path &path, struct stat *stbuf, fuse_file_info *file return getattr(path, stbuf); } - int retstat = fstat(fileinfo->fh, stbuf); - return errcode_map(retstat); + try { + _device->fstat(fileinfo->fh, stbuf); + return 0; + } catch(cryfs::CryErrnoException &e) { + return -e.getErrno(); + } } int CryFuse::readlink(const path &path, char *buf, size_t size) { diff --git a/src/cryfs_lib/CMakeLists.txt b/src/cryfs_lib/CMakeLists.txt index 0a0910f7..ff852416 100644 --- a/src/cryfs_lib/CMakeLists.txt +++ b/src/cryfs_lib/CMakeLists.txt @@ -1,3 +1,3 @@ -add_library(cryfs_lib CryDevice.cpp CryDir.cpp CryErrnoException.cpp CryFile.cpp CryNode.cpp) +add_library(cryfs_lib CryDevice.cpp CryDir.cpp CryErrnoException.cpp CryFile.cpp CryNode.cpp CryOpenFile.cpp CryOpenFileList.cpp) target_link_libraries(cryfs_lib boost_filesystem) diff --git a/src/cryfs_lib/CryDevice.cpp b/src/cryfs_lib/CryDevice.cpp index d9fe5395..1efb2851 100644 --- a/src/cryfs_lib/CryDevice.cpp +++ b/src/cryfs_lib/CryDevice.cpp @@ -4,7 +4,9 @@ #include "CryDir.h" #include "CryFile.h" +#include "CryOpenFile.h" #include "CryErrnoException.h" +#include "utils/pointer.h" using namespace cryfs; @@ -12,13 +14,13 @@ using std::unique_ptr; using std::make_unique; CryDevice::CryDevice(const bf::path &rootdir) - :_rootdir(rootdir) { + :_rootdir(rootdir), _open_files() { } CryDevice::~CryDevice() { } -unique_ptr CryDevice::LoadFromPath(const bf::path &path) { +unique_ptr CryDevice::Load(const bf::path &path) { auto real_path = RootDir() / path; if(bf::is_directory(real_path)) { return make_unique(this, path); @@ -28,3 +30,25 @@ unique_ptr CryDevice::LoadFromPath(const bf::path &path) { throw CryErrnoException(ENOENT); } + +std::unique_ptr CryDevice::LoadFile(const bf::path &path) { + auto node = Load(path); + auto file = dynamic_pointer_move(node); + if (!file) { + throw CryErrnoException(EISDIR); + } + return file; +} + +int CryDevice::OpenFile(const bf::path &path, int flags) { + auto file = LoadFile(path); + return _open_files.open(*file, flags); +} + +void CryDevice::lstat(const bf::path &path, struct ::stat *stbuf) { + Load(path)->stat(stbuf); +} + +void CryDevice::fstat(int descriptor, struct ::stat *stbuf) { + _open_files.get(descriptor)->stat(stbuf); +} diff --git a/src/cryfs_lib/CryDevice.h b/src/cryfs_lib/CryDevice.h index e63a3718..b4ffc0d1 100644 --- a/src/cryfs_lib/CryDevice.h +++ b/src/cryfs_lib/CryDevice.h @@ -3,11 +3,15 @@ #define CRYFS_LIB_CRYDEVICE_H_ #include -#include "utils/macros.h" +#include #include +#include + +#include "utils/macros.h" namespace cryfs { class CryNode; +class CryFile; namespace bf = boost::filesystem; @@ -16,12 +20,16 @@ public: CryDevice(const bf::path &rootdir); virtual ~CryDevice(); - std::unique_ptr LoadFromPath(const bf::path &path); - //std::unique_ptr LoadFromPath(const bf::path &path) const; + int OpenFile(const bf::path &path, int flags); + void lstat(const bf::path &path, struct ::stat *stbuf); + void fstat(int descriptor, struct ::stat *stbuf); const bf::path &RootDir() const; private: + std::unique_ptr Load(const bf::path &path); + std::unique_ptr LoadFile(const bf::path &path); const bf::path _rootdir; + CryOpenFileList _open_files; DISALLOW_COPY_AND_ASSIGN(CryDevice); }; diff --git a/src/cryfs_lib/CryDir.h b/src/cryfs_lib/CryDir.h index 16d74865..5f53d7ea 100644 --- a/src/cryfs_lib/CryDir.h +++ b/src/cryfs_lib/CryDir.h @@ -3,6 +3,7 @@ #define CRYFS_LIB_CRYDIR_H_ #include "CryNode.h" +#include "utils/macros.h" namespace cryfs { class CryDevice; @@ -11,6 +12,8 @@ class CryDir: public CryNode { public: CryDir(CryDevice *device, const bf::path &path); virtual ~CryDir(); +private: + DISALLOW_COPY_AND_ASSIGN(CryDir); }; } /* namespace cryfs */ diff --git a/src/cryfs_lib/CryFile.cpp b/src/cryfs_lib/CryFile.cpp index db0ee485..0dd96ca1 100644 --- a/src/cryfs_lib/CryFile.cpp +++ b/src/cryfs_lib/CryFile.cpp @@ -1,5 +1,8 @@ #include "CryFile.h" -#include "CryErrnoException.h" +#include "CryOpenFile.h" + +using std::unique_ptr; +using std::make_unique; namespace cryfs { @@ -10,4 +13,8 @@ CryFile::CryFile(CryDevice *device, const bf::path &path) CryFile::~CryFile() { } +std::unique_ptr CryFile::open(int flags) const { + return make_unique(base_path(), flags); +} + } /* namespace cryfs */ diff --git a/src/cryfs_lib/CryFile.h b/src/cryfs_lib/CryFile.h index 3e1ac14b..20eed94a 100644 --- a/src/cryfs_lib/CryFile.h +++ b/src/cryfs_lib/CryFile.h @@ -6,13 +6,19 @@ #include "CryDevice.h" #include "CryNode.h" +#include "utils/macros.h" namespace cryfs { +class CryOpenFile; class CryFile: public CryNode { public: CryFile(CryDevice *device, const bf::path &path); virtual ~CryFile(); + + std::unique_ptr open(int flags) const; +private: + DISALLOW_COPY_AND_ASSIGN(CryFile); }; } /* namespace cryfs */ diff --git a/src/cryfs_lib/CryNode.cpp b/src/cryfs_lib/CryNode.cpp index c6ea9d61..5fd995e5 100644 --- a/src/cryfs_lib/CryNode.cpp +++ b/src/cryfs_lib/CryNode.cpp @@ -12,7 +12,7 @@ CryNode::CryNode(CryDevice *device, const bf::path &path) CryNode::~CryNode() { } -void CryNode::stat(struct stat *result) const { +void CryNode::stat(struct ::stat *result) const { int retval = ::lstat(base_path().c_str(), result); CHECK_RETVAL(retval); } diff --git a/src/cryfs_lib/CryNode.h b/src/cryfs_lib/CryNode.h index a39747e3..c3081ade 100644 --- a/src/cryfs_lib/CryNode.h +++ b/src/cryfs_lib/CryNode.h @@ -17,11 +17,10 @@ public: CryNode(CryDevice *device, const bf::path &path); virtual ~CryNode(); - void stat(struct stat *result) const; + void stat(struct ::stat *result) const; protected: bf::path base_path() const; - CryDevice *device(); private: CryDevice *const _device; diff --git a/src/cryfs_lib/CryOpenFile.cpp b/src/cryfs_lib/CryOpenFile.cpp new file mode 100644 index 00000000..88990392 --- /dev/null +++ b/src/cryfs_lib/CryOpenFile.cpp @@ -0,0 +1,24 @@ +#include + +#include +#include + +#include "CryErrnoException.h" + +using namespace cryfs; + +CryOpenFile::CryOpenFile(const bf::path &path, int flags) + :_descriptor(::open(path.c_str(), flags)) { + CHECK_RETVAL(_descriptor); +} + +CryOpenFile::~CryOpenFile() { + int retval = close(_descriptor); + CHECK_RETVAL(retval); +} + +void CryOpenFile::stat(struct ::stat *result) const { + int retval = ::fstat(_descriptor, result); + CHECK_RETVAL(retval); +} + diff --git a/src/cryfs_lib/CryOpenFile.h b/src/cryfs_lib/CryOpenFile.h new file mode 100644 index 00000000..b5463f1d --- /dev/null +++ b/src/cryfs_lib/CryOpenFile.h @@ -0,0 +1,27 @@ +#ifndef CRYFS_LIB_CRYOPENFILE_H_ +#define CRYFS_LIB_CRYOPENFILE_H_ + +#include +#include + +#include "utils/macros.h" + +namespace cryfs { + +namespace bf = boost::filesystem; + +class CryOpenFile { +public: + CryOpenFile(const bf::path &path, int flags); + virtual ~CryOpenFile(); + + void stat(struct ::stat *result) const; +private: + int _descriptor; + + DISALLOW_COPY_AND_ASSIGN(CryOpenFile); +}; + +} + +#endif /* CRYFS_LIB_CRYOPENFILE_H_ */ diff --git a/src/cryfs_lib/CryOpenFileList.cpp b/src/cryfs_lib/CryOpenFileList.cpp new file mode 100644 index 00000000..9cf34102 --- /dev/null +++ b/src/cryfs_lib/CryOpenFileList.cpp @@ -0,0 +1,28 @@ +#include +#include "CryFile.h" +#include "CryOpenFile.h" + +using namespace cryfs; + +CryOpenFileList::CryOpenFileList() + :_open_files() { +} + +CryOpenFileList::~CryOpenFileList() { +} + +int CryOpenFileList::open(const CryFile &file, int flags) { + //TODO Reuse descriptors + int desc = _open_files.size(); + _open_files[desc] = file.open(flags); + return desc; +} + +CryOpenFile *CryOpenFileList::get(int descriptor) { + return _open_files.at(descriptor).get(); +} + +void CryOpenFileList::close(int descriptor) { + //The destructor of the stored CryFile::OpenFile closes the file + _open_files.erase(descriptor); +} diff --git a/src/cryfs_lib/CryOpenFileList.h b/src/cryfs_lib/CryOpenFileList.h new file mode 100644 index 00000000..dafc649f --- /dev/null +++ b/src/cryfs_lib/CryOpenFileList.h @@ -0,0 +1,29 @@ +#ifndef CRYFS_LIB_CRYOPENFILELIST_H_ +#define CRYFS_LIB_CRYOPENFILELIST_H_ + +#include +#include +#include "utils/macros.h" + +namespace cryfs { +class CryFile; +class CryOpenFile; + +class CryOpenFileList { +public: + CryOpenFileList(); + virtual ~CryOpenFileList(); + + int open(const CryFile &rhs, int flags); + CryOpenFile *get(int descriptor); + void close(int descriptor); + +private: + std::map> _open_files; + + DISALLOW_COPY_AND_ASSIGN(CryOpenFileList); +}; + +} + +#endif /* CRYFS_LIB_CRYOPENFILELIST_H_ */ diff --git a/src/cryfs_lib/utils/pointer.h b/src/cryfs_lib/utils/pointer.h new file mode 100644 index 00000000..9ad0a5fd --- /dev/null +++ b/src/cryfs_lib/utils/pointer.h @@ -0,0 +1,18 @@ +#pragma once +#ifndef CRYFS_LIB_UTILS_POINTER_H_ +#define CRYFS_LIB_UTILS_POINTER_H_ + +#include + +namespace cryfs { + template + inline std::unique_ptr dynamic_pointer_move(std::unique_ptr &source) { + DST *casted = dynamic_cast(source.get()); + if (casted != nullptr) { + source.release(); + } + return std::unique_ptr(casted); + } +} + +#endif