mirror of
				https://github.com/falk-werner/webfuse
				synced 2025-06-13 12:54:15 +00:00 
			
		
		
		
	implemented filesystem provider
This commit is contained in:
		
							parent
							
								
									4610b82d78
								
							
						
					
					
						commit
						023b595b1c
					
				@ -2,6 +2,7 @@
 | 
				
			|||||||
#include "webfuse/version.hpp"
 | 
					#include "webfuse/version.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <sys/stat.h>
 | 
					#include <sys/stat.h>
 | 
				
			||||||
#include <dirent.h>
 | 
					#include <dirent.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -120,9 +121,22 @@ class filesystem: public webfuse::filesystem_i
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    explicit filesystem(std::string const & base_path)
 | 
					    explicit filesystem(std::string const & base_path)
 | 
				
			||||||
    : base_path_(base_path)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        char buffer[PATH_MAX];
 | 
				
			||||||
 | 
					        char * resolved_path = ::realpath(base_path.c_str(), buffer);
 | 
				
			||||||
 | 
					        if (nullptr == resolved_path)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw std::runtime_error("failed to resolve path");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        struct stat info;
 | 
				
			||||||
 | 
					        int const rc = stat(resolved_path, &info);
 | 
				
			||||||
 | 
					        if (!S_ISDIR(info.st_mode))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw std::runtime_error("path is not a directory");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        base_path_ = resolved_path;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ~filesystem() override
 | 
					    ~filesystem() override
 | 
				
			||||||
@ -133,7 +147,6 @@ public:
 | 
				
			|||||||
    int access(std::string const & path, int mode) override
 | 
					    int access(std::string const & path, int mode) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        auto const full_path = get_full_path(path);
 | 
					        auto const full_path = get_full_path(path);
 | 
				
			||||||
        std::cout << "access: " << full_path << std::endl;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto const result = ::access(full_path.c_str(), mode);
 | 
					        auto const result = ::access(full_path.c_str(), mode);
 | 
				
			||||||
        return (result == 0) ? 0 : -errno;
 | 
					        return (result == 0) ? 0 : -errno;
 | 
				
			||||||
@ -142,7 +155,6 @@ public:
 | 
				
			|||||||
    int getattr(std::string const & path, struct stat * attr) override
 | 
					    int getattr(std::string const & path, struct stat * attr) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        auto const full_path = get_full_path(path);
 | 
					        auto const full_path = get_full_path(path);
 | 
				
			||||||
        std::cout << "getattr: " << full_path << std::endl;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto const result = lstat(full_path.c_str(), attr);
 | 
					        auto const result = lstat(full_path.c_str(), attr);
 | 
				
			||||||
        return (result == 0) ? 0 : -errno;
 | 
					        return (result == 0) ? 0 : -errno;
 | 
				
			||||||
@ -150,93 +162,219 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    int readlink(std::string const & path, std::string & out) override
 | 
					    int readlink(std::string const & path, std::string & out) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        auto const full_path = get_full_path(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        char buffer[PATH_MAX];
 | 
				
			||||||
 | 
					        int const result = ::readlink(full_path.c_str(), buffer, PATH_MAX);
 | 
				
			||||||
 | 
					        if ((0 <= result) && (result < PATH_MAX))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            buffer[result] = '\0';
 | 
				
			||||||
 | 
					            out = buffer;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (result >= 0) ? 0 : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    int symlink(std::string const & target, std::string const & linkpath) override
 | 
					    int symlink(std::string const & from, std::string const & to) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        auto const full_from = ('/' == from.at(0)) ? get_full_path(from) : from;
 | 
				
			||||||
 | 
					        auto const full_to = get_full_path(to);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int const result = ::symlink(full_from.c_str(), full_to.c_str());
 | 
				
			||||||
 | 
					        return (result == 0) ? 0 : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int link(std::string const & old_path, std::string const & new_path) override
 | 
					    int link(std::string const & old_path, std::string const & new_path) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        auto const from = get_full_path(old_path);
 | 
				
			||||||
 | 
					        auto const to = get_full_path(new_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int const result = ::link(from.c_str(), to.c_str());
 | 
				
			||||||
 | 
					        return (result == 0) ? 0 : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int rename(std::string const & old_path, std::string const & new_path, int flags) override
 | 
					    int rename(std::string const & old_path, std::string const & new_path, int flags) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        auto const full_old = get_full_path(old_path);
 | 
				
			||||||
 | 
					        auto const full_new = get_full_path(new_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int const result = ::renameat2(-1, full_old.c_str(), -1, full_new.c_str(), flags);
 | 
				
			||||||
 | 
					        return (result == 0) ? 0 : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int chmod(std::string const & path, mode_t mode) override
 | 
					    int chmod(std::string const & path, mode_t mode) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        auto const full_path = get_full_path(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int const result = ::chmod(full_path.c_str(), mode);
 | 
				
			||||||
 | 
					        return (result == 0) ? 0 : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int chown(std::string const & path, uid_t uid, gid_t gid) override
 | 
					    int chown(std::string const & path, uid_t uid, gid_t gid) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        auto const full_path = get_full_path(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int const result = ::chown(full_path.c_str(), uid, gid);
 | 
				
			||||||
 | 
					        return (result == 0) ? 0 : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int truncate(std::string const & path, uint64_t size, uint64_t handle) override
 | 
					    int truncate(std::string const & path, uint64_t size, uint64_t handle) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        auto const full_path = get_full_path(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int result = 0;
 | 
				
			||||||
 | 
					        if (handle == webfuse::invalid_handle)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            result = ::truncate(full_path.c_str(), size);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            result = ::ftruncate(static_cast<int>(handle), size);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (result == 0) ? 0 : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int fsync(std::string const & path, bool is_datasync, uint64_t handle) override
 | 
					    int fsync(std::string const & path, bool is_datasync, uint64_t handle) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        int result = 0;
 | 
				
			||||||
 | 
					        if (handle != webfuse::invalid_handle)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (!is_datasync)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                result = ::fsync(static_cast<int>(handle));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                result = ::fdatasync(static_cast<int>(handle));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // we do not sync files, which are not open
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (result == 0) ? 0 : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int utimens(std::string const &path, struct timespec const tv[2], uint64_t handle) override
 | 
					    int utimens(std::string const &path, struct timespec const tv[2], uint64_t handle) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        int result = 0;
 | 
				
			||||||
 | 
					        if (handle == webfuse::invalid_handle)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto const full_path = get_full_path(path);
 | 
				
			||||||
 | 
					            result = ::utimensat(-1, full_path.c_str(), tv, 0);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            result = ::futimens(static_cast<int>(handle), tv);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (result == 0) ? 0 : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int open(std::string const & path, int flags, uint64_t & handle) override
 | 
					    int open(std::string const & path, int flags, uint64_t & handle) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        auto const full_path = get_full_path(path);
 | 
				
			||||||
 | 
					        int const fd = ::open(full_path.c_str(), flags);
 | 
				
			||||||
 | 
					        if (0 <= fd)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            handle = static_cast<int>(fd);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return (0 <= fd) ? 0 : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int mknod(std::string const & path, mode_t mode, dev_t rdev) override
 | 
					    int mknod(std::string const & path, mode_t mode, dev_t rdev) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        auto const full_path = get_full_path(path);
 | 
				
			||||||
 | 
					        int const result = ::mknod(full_path.c_str(), mode, rdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (result == 0) ? 0 : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int create(std::string const & path, mode_t mode, uint64_t & handle) override
 | 
					    int create(std::string const & path, mode_t mode, uint64_t & handle) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        auto const full_path = get_full_path(path);
 | 
				
			||||||
 | 
					        int const fd = ::creat(full_path.c_str(), mode);
 | 
				
			||||||
 | 
					        if (0 <= fd)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            handle = static_cast<int>(fd);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return (0 <= fd) ? 0 : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int release(std::string const & path, uint64_t handle) override
 | 
					    int release(std::string const & path, uint64_t handle) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        int result = 0;
 | 
				
			||||||
 | 
					        if (handle != webfuse::invalid_handle)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            result = ::close(static_cast<int>(handle));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (result == 0) ? 0 : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int unlink(std::string const & path) override
 | 
					    int unlink(std::string const & path) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        auto const full_path = get_full_path(path);
 | 
				
			||||||
 | 
					        int const result = ::unlink(full_path.c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (result == 0) ? 0 : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int read(std::string const & path, char * buffer, size_t buffer_size, uint64_t offset, uint64_t handle) override
 | 
					    int read(std::string const & path, char * buffer, size_t buffer_size, uint64_t offset, uint64_t handle) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        int result = -1;
 | 
				
			||||||
 | 
					        if (handle != webfuse::invalid_handle)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto const full_path = get_full_path(path);
 | 
				
			||||||
 | 
					            int fd = ::open(full_path.c_str(), O_RDONLY);
 | 
				
			||||||
 | 
					            if (0 <= fd)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                result = ::pread(fd, buffer, buffer_size, offset);
 | 
				
			||||||
 | 
					                ::close(fd);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            result = ::pread(static_cast<int>(handle), buffer, buffer_size, offset);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (result >= 0) ? result : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int write(std::string const & path, char const * buffer, size_t buffer_size, uint64_t offset, uint64_t handle) override
 | 
					    int write(std::string const & path, char const * buffer, size_t buffer_size, uint64_t offset, uint64_t handle) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        int result = -1;
 | 
				
			||||||
 | 
					        if (handle == webfuse::invalid_handle)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto const full_path = get_full_path(path);
 | 
				
			||||||
 | 
					            int fd = ::open(full_path.c_str(), O_WRONLY);
 | 
				
			||||||
 | 
					            if (0 <= fd)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                result = ::pwrite(fd, buffer, buffer_size, offset);
 | 
				
			||||||
 | 
					                ::close(fd);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            result = ::pwrite(static_cast<int>(handle), buffer, buffer_size, offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (result >= 0) ? result : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int mkdir(std::string const & path, mode_t mode) override
 | 
					    int mkdir(std::string const & path, mode_t mode) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        auto const full_path = get_full_path(path);
 | 
				
			||||||
 | 
					        int const result = ::mkdir(full_path.c_str(), mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (result == 0) ? 0 : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int readdir(std::string const & path, std::vector<std::string> & entries) override
 | 
					    int readdir(std::string const & path, std::vector<std::string> & entries) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        auto const full_path = get_full_path(path);
 | 
					        auto const full_path = get_full_path(path);
 | 
				
			||||||
        std::cout << "readdir: " << full_path << std::endl;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        int result = 0;
 | 
					        int result = 0;
 | 
				
			||||||
        DIR * directory = opendir(full_path.c_str());
 | 
					        DIR * directory = opendir(full_path.c_str());
 | 
				
			||||||
@ -260,12 +398,18 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    int rmdir(std::string const & path) override
 | 
					    int rmdir(std::string const & path) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        auto const full_path = get_full_path(path);
 | 
				
			||||||
 | 
					        int const result = ::rmdir(full_path.c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (result == 0) ? 0 : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int statfs(std::string const & path, struct statvfs * statistics) override
 | 
					    int statfs(std::string const & path, struct statvfs * statistics) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return -ENOENT;
 | 
					        auto const full_path = get_full_path(path);
 | 
				
			||||||
 | 
					        int const result = ::statvfs(full_path.c_str(), statistics);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (result == 0) ? 0 : -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -289,6 +433,7 @@ int main(int argc, char* argv[])
 | 
				
			|||||||
    switch (ctx.cmd)
 | 
					    switch (ctx.cmd)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        case command::run:
 | 
					        case command::run:
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                signal(SIGINT, &on_signal);
 | 
					                signal(SIGINT, &on_signal);
 | 
				
			||||||
                signal(SIGTERM, &on_signal);
 | 
					                signal(SIGTERM, &on_signal);
 | 
				
			||||||
@ -307,6 +452,16 @@ int main(int argc, char* argv[])
 | 
				
			|||||||
                    provider.service();
 | 
					                    provider.service();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            catch (std::exception const & ex)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                std::cerr << "error: " << ex.what() << std::endl;
 | 
				
			||||||
 | 
					                ctx.exit_code = EXIT_FAILURE;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch (...)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                std::cerr << "error: unspecified error" << std::endl;
 | 
				
			||||||
 | 
					                ctx.exit_code = EXIT_FAILURE;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case command::show_version:
 | 
					        case command::show_version:
 | 
				
			||||||
            print_version();
 | 
					            print_version();
 | 
				
			||||||
 | 
				
			|||||||
@ -13,6 +13,8 @@
 | 
				
			|||||||
namespace webfuse
 | 
					namespace webfuse
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					constexpr uint64_t const invalid_handle = static_cast<uint64_t>(-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class filesystem_i
 | 
					class filesystem_i
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user