diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/operations.cc | 131 | ||||
-rw-r--r-- | src/scoville.cc | 4 |
2 files changed, 124 insertions, 11 deletions
diff --git a/src/operations.cc b/src/operations.cc index 17ce2a3..abd2f0c 100644 --- a/src/operations.cc +++ b/src/operations.cc @@ -15,12 +15,20 @@ // You should have received a copy of the GNU General Public License along with // this program. If not, see <http://www.gnu.org/licenses/>. +#define BSD_SOURCE +#define _POSIX_C_SOURCE 201602L + #include "operations.h" #include <cerrno> +#include <cstring> +#include <memory> +#include <new> #define FUSE_USE_VERSION 26 +#include <dirent.h> #include <fuse.h> +#include <glog/logging.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -29,19 +37,117 @@ namespace scoville { namespace { -int GetAttr(const char* const path, struct stat* output) { +struct Directory { + DIR* fd; + dirent* entry; + off_t offset; +}; + +Directory* FileInfoDirectory(fuse_file_info* const file_info) { + return reinterpret_cast<Directory*>(file_info->fh); +} + +mode_t DirectoryTypeToFileType(const unsigned char type) { + switch (type) { + case DT_BLK: + return S_IFBLK; + case DT_CHR: + return S_IFCHR; + case DT_DIR: + return S_IFDIR; + case DT_FIFO: + return S_IFIFO; + case DT_LNK: + return S_IFLNK; + case DT_REG: + return S_IFREG; + case DT_SOCK: + return S_IFSOCK; + default: + return 0; + } +} + +void* Initialize(fuse_conn_info*) { + LOG(INFO) << "initialize"; + return nullptr; +} + +void Destroy(void*) { + LOG(INFO) << "destroy"; +} + +int Getattr(const char* const path, struct stat* output) { + LOG(INFO) << "getattr(" << path << ")"; if (lstat(path, output) == -1) { return -errno; } return 0; } -int ReadLink(const char* const path, char *const output, const size_t output_size) { - const ssize_t bytes_written = readlink(path, output, output_size); - if (bytes_written == -1) { +int Opendir(const char* const path, fuse_file_info* const file_info) { + LOG(INFO) << "opendir(" << path << ")"; + + std::unique_ptr<Directory> directory; + try { + directory.reset(new Directory); + } catch (std::bad_alloc) { + return -ENOMEM; + } + + if ((directory->fd = opendir(path)) == nullptr) { return -errno; } - output[bytes_written] = '\0'; + directory->entry = nullptr; + directory->offset = 0; + + static_assert(sizeof(file_info->fh) == sizeof(uintptr_t), + "FUSE file handles are a different size than pointers"); + file_info->fh = reinterpret_cast<uintptr_t>(directory.release()); + return 0; +} + +int Readdir(const char*, void* const buffer, fuse_fill_dir_t filler, + const off_t offset, fuse_file_info* const file_info) { + LOG(INFO) << "readdir"; + + Directory* const directory = FileInfoDirectory(file_info); + + if (offset != directory->offset) { + seekdir(directory->fd, offset); + directory->entry = nullptr; + directory->offset = offset; + } + + while (true) { + if (!directory->entry) { + directory->entry = readdir(directory->fd); + if (!directory->entry) { + break; + } + } + + struct stat stats; + std::memset(&stats, 0, sizeof(stats)); + stats.st_ino = directory->entry->d_ino; + stats.st_mode = DirectoryTypeToFileType(directory->entry->d_type); + const off_t next_offset = telldir(directory->fd); + if (filler(buffer, directory->entry->d_name, &stats, next_offset)) { + break; + } + + directory->entry = nullptr; + directory->offset = next_offset; + } + + return 0; +} + +int Releasedir(const char*, fuse_file_info* const file_info) { + LOG(INFO) << "releasedir"; + Directory* const directory = FileInfoDirectory(file_info); + closedir(directory->fd); + delete directory; return 0; } @@ -49,8 +155,19 @@ int ReadLink(const char* const path, char *const output, const size_t output_siz fuse_operations FuseOperations() { fuse_operations result; - result.getattr = &GetAttr; - result.readlink = &ReadLink; + + result.flag_nullpath_ok = true; + result.flag_nopath = true; + result.flag_utime_omit_ok = true; + + result.init = &Initialize; + result.destroy = &Destroy; + + result.getattr = &Getattr; + result.opendir = &Opendir; + result.readdir = &Readdir; + result.releasedir = &Releasedir; + return result; } diff --git a/src/scoville.cc b/src/scoville.cc index db39ee8..054a6cd 100644 --- a/src/scoville.cc +++ b/src/scoville.cc @@ -19,10 +19,6 @@ #include "operations.h" -namespace { - -} // namespace - int main(const int argc, char* argv[]) { FLAGS_logtostderr = true; google::InstallFailureSignalHandler(); |