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; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|     int symlink(std::string const & target, std::string const & linkpath) override |         return (result >= 0) ? 0 : -errno; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     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