diff options
-rw-r--r-- | src/encoding.cc | 34 | ||||
-rw-r--r-- | src/encoding.h | 6 | ||||
-rw-r--r-- | src/operations.cc | 70 |
3 files changed, 63 insertions, 47 deletions
diff --git a/src/encoding.cc b/src/encoding.cc index 620a821..3cd29a8 100644 --- a/src/encoding.cc +++ b/src/encoding.cc @@ -16,10 +16,13 @@ #include <array> #include <cstdlib> +#include <functional> #include <ios> #include <sstream> #include <string> +#include <glog/logging.h> + namespace scoville { namespace { @@ -47,12 +50,10 @@ char ReadHexAsAscii(std::istringstream* const in) { bool IsVfatBadCharacter(const char c) noexcept { return (0 <= c && c < 0x20) || c == '*' || c == '?' || c == '<' || c == '>' || - c == '|' || c == '"' || c == ':' || c == '/' || c == '\\'; + c == '|' || c == '"' || c == ':' || c == '\\'; } -} // namespace - -void Encode(std::istringstream* const in, std::ostringstream* const out) { +void EncodeStream(std::istringstream* const in, std::ostringstream* const out) { char c; while (!in->get(c).eof()) { if (IsVfatBadCharacter(c)) { @@ -66,7 +67,7 @@ void Encode(std::istringstream* const in, std::ostringstream* const out) { } } -void Decode(std::istringstream* const in, std::ostringstream* const out) { +void DecodeStream(std::istringstream* const in, std::ostringstream* const out) { char c; while (!in->get(c).eof()) { if (c == '%') { @@ -82,4 +83,27 @@ void Decode(std::istringstream* const in, std::ostringstream* const out) { } } +std::string TransformString( + std::function<void(std::istringstream*, std::ostringstream*)> f, + const std::string& in) { + std::istringstream in_stream(in); + std::ostringstream out_stream; + f(&in_stream, &out_stream); + return out_stream.str(); +} + +} // namespace + +std::string Encode(const std::string& in) { + const std::string result = TransformString(EncodeStream, in); + VLOG(1) << "Encode: \"" << in << "\" -> \"" << result << "\""; + return result; +} + +std::string Decode(const std::string& in) { + const std::string result = TransformString(DecodeStream, in); + VLOG(1) << "Decode: \"" << in << "\" -> \"" << result << "\""; + return result; +} + } // scoville diff --git a/src/encoding.h b/src/encoding.h index 717d421..d6e72ea 100644 --- a/src/encoding.h +++ b/src/encoding.h @@ -15,7 +15,7 @@ #ifndef ENCODING_H_ #define ENCODING_H_ -#include <sstream> +#include <string> #include <stdexcept> namespace scoville { @@ -30,9 +30,9 @@ class DecodingFailure : public std::logic_error { using std::logic_error::logic_error; }; -void Encode(std::istringstream*, std::ostringstream*); +std::string Encode(const std::string&); -void Decode(std::istringstream*, std::ostringstream*); +std::string Decode(const std::string&); } // scoville diff --git a/src/operations.cc b/src/operations.cc index cf53b05..8e2b008 100644 --- a/src/operations.cc +++ b/src/operations.cc @@ -37,6 +37,7 @@ #include <sys/types.h> #include <time.h> +#include "encoding.h" #include "fuse.h" #include "posix_extras.h" @@ -51,7 +52,7 @@ mode_t DirectoryTypeToFileType(const unsigned char type) { return static_cast<mode_t>(DTTOIF(type)); } -std::string EncodePath(const std::string& path) { +std::string MakeRelative(const std::string& path) { if (path.at(0) != '/') { throw std::system_error(ENOENT, std::system_category()); } @@ -63,22 +64,22 @@ void* Initialize(fuse_conn_info*) noexcept { return nullptr; } void Destroy(void*) noexcept {} int Statfs(const char* const c_path, struct statvfs* const output) { - const std::string path(c_path); + const std::string path(Encode(c_path)); if (path == "/") { *output = root_->StatVFs(); } else { *output = - root_->OpenAt(EncodePath(path).c_str(), O_RDONLY | O_PATH).StatVFs(); + root_->OpenAt(MakeRelative(path).c_str(), O_RDONLY | O_PATH).StatVFs(); } return 0; } int Getattr(const char* const c_path, struct stat* output) { - const std::string path(c_path); + const std::string path(Encode(c_path)); if (path == "/") { *output = root_->Stat(); } else { - *output = root_->LinkStatAt(EncodePath(path).c_str()); + *output = root_->LinkStatAt(MakeRelative(path).c_str()); } return 0; } @@ -90,12 +91,11 @@ int Fgetattr(const char*, struct stat* const output, } template <typename T> -int OpenResource(const char* const c_path, const int flags, +int OpenResource(const std::string& path, const int flags, uint64_t* const handle, const mode_t mode = 0) { try { - const std::string path(c_path); std::unique_ptr<T> t( - new T(path == "/" ? *root_ : root_->OpenAt(EncodePath(path).c_str(), + new T(path == "/" ? *root_ : root_->OpenAt(MakeRelative(path).c_str(), flags, mode))); static_assert(sizeof(*handle) == sizeof(std::uintptr_t), "FUSE file handles are a different size than pointers"); @@ -113,40 +113,41 @@ int ReleaseResource(const uint64_t handle) noexcept { } int Mknod(const char* const c_path, const mode_t mode, const dev_t dev) { - const std::string path(c_path); + const std::string path(Encode(c_path)); if (path == "/") { return -EISDIR; } else { - root_->MkNod(EncodePath(path).c_str(), mode, dev); + root_->MkNod(MakeRelative(path).c_str(), mode, dev); return 0; } } int Chmod(const char* const c_path, const mode_t mode) { - const std::string path(c_path); - root_->ChModAt(path == "/" ? "." : EncodePath(path).c_str(), mode); + const std::string path(Encode(c_path)); + root_->ChModAt(path == "/" ? "." : MakeRelative(path).c_str(), mode); return 0; } int Rename(const char* const c_old_path, const char* const c_new_path) { - const std::string old_path(c_old_path); - const std::string new_path(c_new_path); + const std::string old_path(Encode(c_old_path)); + const std::string new_path(Encode(c_new_path)); if (old_path == "/" || new_path == "/") { return -EINVAL; } else { - root_->RenameAt(EncodePath(old_path).c_str(), EncodePath(new_path).c_str()); + root_->RenameAt(MakeRelative(old_path).c_str(), + MakeRelative(new_path).c_str()); return 0; } } int Create(const char* const path, const mode_t mode, fuse_file_info* const file_info) { - return OpenResource<File>(path, file_info->flags | O_CREAT, &file_info->fh, - mode); + return OpenResource<File>(Encode(path), file_info->flags | O_CREAT, + &file_info->fh, mode); } int Open(const char* const path, fuse_file_info* const file_info) { - return OpenResource<File>(path, file_info->flags, &file_info->fh); + return OpenResource<File>(Encode(path), file_info->flags, &file_info->fh); } int Read(const char*, char* const buffer, const size_t bytes, @@ -166,8 +167,8 @@ int Write(const char*, const char* const buffer, const size_t bytes, } int Utimens(const char* const c_path, const timespec times[2]) { - const std::string path(c_path); - root_->UTimeNs(path == "/" ? "." : EncodePath(path).c_str(), times[0], + const std::string path(Encode(c_path)); + root_->UTimeNs(path == "/" ? "." : MakeRelative(path).c_str(), times[0], times[1]); return 0; } @@ -177,42 +178,33 @@ int Release(const char*, fuse_file_info* const file_info) { } int Unlink(const char* c_path) { - const std::string path(c_path); + const std::string path(Encode(c_path)); if (path == "/") { // Removing the root is probably a bad idea. return -EPERM; } else { - root_->UnlinkAt(EncodePath(path).c_str()); + root_->UnlinkAt(MakeRelative(path).c_str()); return 0; } } -int Symlink(const char* const target, const char* const source) { - root_->SymLinkAt(target, EncodePath(source).c_str()); - return 0; -} +int Symlink(const char*, const char*) { return -EPERM; } -int Readlink(const char* const path, char* const output, - const size_t output_size) { - const std::string target = root_->ReadLinkAt(EncodePath(path).c_str()); - std::strncpy(output, target.c_str(), output_size); - output[output_size - 1] = '\0'; - return 0; -} +int Readlink(const char*, char*, size_t) { return -EINVAL; } int Mkdir(const char* const c_path, const mode_t mode) { - const std::string path(c_path); + const std::string path(Encode(c_path)); if (path == "/") { // They're asking to create the mount point. Huh? return -EEXIST; } else { - root_->MkDir(EncodePath(path).c_str(), mode); + root_->MkDir(MakeRelative(path).c_str(), mode); return 0; } } int Opendir(const char* const path, fuse_file_info* const file_info) { - return OpenResource<Directory>(path, O_DIRECTORY, &file_info->fh); + return OpenResource<Directory>(Encode(path), O_DIRECTORY, &file_info->fh); } int Readdir(const char*, void* const buffer, fuse_fill_dir_t filler, @@ -232,7 +224,7 @@ int Readdir(const char*, void* const buffer, fuse_fill_dir_t filler, stats.st_ino = entry->d_ino; stats.st_mode = DirectoryTypeToFileType(entry->d_type); const off_t next_offset = directory->offset(); - if (filler(buffer, entry->d_name, &stats, next_offset)) { + if (filler(buffer, Decode(entry->d_name).c_str(), &stats, next_offset)) { break; } } @@ -249,12 +241,12 @@ int Ftruncate(const char*, const off_t size, fuse_file_info* const file_info) { } int Rmdir(const char* c_path) { - const std::string path(c_path); + const std::string path(Encode(c_path)); if (path == "/") { // Removing the root is probably a bad idea. return -EPERM; } else { - root_->RmDirAt(EncodePath(path).c_str()); + root_->RmDirAt(MakeRelative(path).c_str()); return 0; } } |