From c93232896fd255f40f571e1a88c66bd34ebbef16 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Thu, 19 Mar 2009 01:36:40 +0000 Subject: [PATCH] Added FileSystem and Volume subclasses for the FUSE interface. ATM they are mostly skeletons, doing a bit of initialization. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29604 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../userlandfs/server/fuse/FUSEFileSystem.cpp | 193 ++++++++++ .../userlandfs/server/fuse/FUSEFileSystem.h | 37 ++ .../userlandfs/server/fuse/FUSEVolume.cpp | 350 ++++++++++++++++++ .../userlandfs/server/fuse/FUSEVolume.h | 122 ++++++ .../userlandfs/server/fuse/Jamfile | 2 + .../userlandfs/server/fuse/fuse_main.cpp | 5 + 6 files changed, 709 insertions(+) create mode 100644 src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.cpp create mode 100644 src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.h create mode 100644 src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp create mode 100644 src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.h diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.cpp new file mode 100644 index 0000000000..54051654bc --- /dev/null +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.cpp @@ -0,0 +1,193 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "FUSEFileSystem.h" + +#include +#include + +#include + +#include "FUSEVolume.h" + + +class FUSEFileSystem::ArgumentVector { +private: + enum { MAX_ARGUMENTS = 128 }; + +public: + ArgumentVector() + : + fBuffer(NULL), + fCount(0) + { + } + + ~ArgumentVector() + { + free(fBuffer); + } + + const char* const* Arguments() const + { + return fArguments; + } + + int ArgumentCount() const + { + return fCount; + } + + status_t Init(const char* firstElement, const char* arguments) + { + size_t firstElementSize = firstElement != NULL + ? strlen(firstElement) + 1 : 0; + + // allocate the buffer + fBuffer = (char*)malloc(firstElementSize + strlen(arguments) + 1); + if (fBuffer == NULL) + return B_NO_MEMORY; + + fCount = 0; + + bool inArgument = false; + int bufferIndex = 0; + + // push the first element, if given + if (firstElement != NULL) { + memcpy(fBuffer, firstElement, firstElementSize); + fArguments[fCount++] = fBuffer; + bufferIndex = firstElementSize; + } + + // parse the given string + for (; *arguments != '\0'; arguments++) { + char c = *arguments; + switch (c) { + case ' ': + case '\t': + case '\r': + case '\n': + // white-space marks argument boundaries + if (inArgument) { + // terminate the current argument + fBuffer[bufferIndex++] = '\0'; + inArgument = false; + } + break; + case '\\': + c = *++arguments; + if (c == '\0') + break; + // fall through + default: + if (!inArgument) { + // push a new argument + if (fCount == MAX_ARGUMENTS) + break; + + fArguments[fCount++] = fBuffer + bufferIndex; + inArgument = true; + } + + fBuffer[bufferIndex++] = c; + break; + } + } + + // terminate the last argument + if (inArgument) + fBuffer[bufferIndex++] = '\0'; + + // NULL terminate the argument array + fArguments[fCount] = NULL; + + return B_OK; + } + +private: + char* fBuffer; + const char* fArguments[MAX_ARGUMENTS + 1]; + int fCount; +}; + + +FUSEFileSystem::FUSEFileSystem(int (*mainFunction)(int, const char* const*)) + : + FileSystem(), + fMainFunction(mainFunction) +{ +} + + +FUSEFileSystem::~FUSEFileSystem() +{ +} + + +status_t +FUSEFileSystem::CreateVolume(Volume** _volume, dev_t id) +{ +printf("FUSEFileSystem::CreateVolume()\n"); + // create the volume + FUSEVolume* volume = new(std::nothrow) FUSEVolume(this, id); + if (volume == NULL) + return B_NO_MEMORY; + + *_volume = volume; + return B_OK; +} + + +status_t +FUSEFileSystem::DeleteVolume(Volume* volume) +{ + delete volume; + return B_OK; +} + + +status_t +FUSEFileSystem::InitClientFS(const char* parameters) +{ + // parse the parameters + ArgumentVector args; + status_t error = args.Init("FUSE", parameters); + if (error != B_OK) + RETURN_ERROR(error); + + // call main + fMainFunction(args.ArgumentCount(), args.Arguments()); + +// TODO: Check whether everything went fine! + + return B_OK; +} + + +// #pragma mark - bootstrapping + + +status_t +userlandfs_create_file_system(const char* fsName, image_id image, + FileSystem** _fileSystem) +{ +printf("userlandfs_create_file_system()\n"); + // look up the main() function of the add-on + int (*mainFunction)(int argc, const char* const* argv); + status_t error = get_image_symbol(image, "main", B_SYMBOL_TYPE_TEXT, + (void**)&mainFunction); + if (error != B_OK) + return error; +printf("userlandfs_create_file_system(): found main: %p\n", mainFunction); + + // create the file system + FUSEFileSystem* fileSystem = new(std::nothrow) FUSEFileSystem(mainFunction); + if (fileSystem == NULL) + return B_NO_MEMORY; + + *_fileSystem = fileSystem; + return B_OK; +} diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.h b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.h new file mode 100644 index 0000000000..6493bfa844 --- /dev/null +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.h @@ -0,0 +1,37 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef USERLAND_FS_FUSE_FILE_SYSTEM_H +#define USERLAND_FS_FUSE_FILE_SYSTEM_H + +#include "../FileSystem.h" + + +namespace UserlandFS { + +class FUSEFileSystem : public FileSystem { +public: + FUSEFileSystem( + int (*mainFunction)(int, + const char* const*)); + virtual ~FUSEFileSystem(); + + virtual status_t CreateVolume(Volume** _volume, dev_t id); + virtual status_t DeleteVolume(Volume* volume); + + status_t InitClientFS(const char* parameters); + +private: + class ArgumentVector; + +private: + int (*fMainFunction)(int, const char* const*); +}; + +} // namespace UserlandFS + +using UserlandFS::FUSEFileSystem; + + +#endif // USERLAND_FS_FUSE_FILE_SYSTEM_H diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp new file mode 100644 index 0000000000..7974e9db58 --- /dev/null +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp @@ -0,0 +1,350 @@ +/* + * Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "FUSEVolume.h" + +#include "FUSEFileSystem.h" + + +inline FUSEFileSystem* +FUSEVolume::_FileSystem() const +{ + return static_cast(fFileSystem); +} + + +FUSEVolume::FUSEVolume(FUSEFileSystem* fileSystem, dev_t id) + : + Volume(fileSystem, id) +{ +} + + +FUSEVolume::~FUSEVolume() +{ +} + + +// #pragma mark - FS + + +status_t +FUSEVolume::Mount(const char* device, uint32 flags, const char* parameters, + ino_t* rootID) +{ +printf("FUSEVolume::Mount()\n"); + status_t error = _FileSystem()->InitClientFS(parameters); + if (error != B_OK) + RETURN_ERROR(error); + + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::Unmount() +{ +printf("FUSEVolume::Unmount()\n"); + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::Sync() +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::ReadFSInfo(fs_info* info) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::WriteFSInfo(const struct fs_info* info, uint32 mask) +{ + return B_UNSUPPORTED; +} + + +// #pragma mark - vnodes + + +status_t +FUSEVolume::Lookup(void* dir, const char* entryName, ino_t* vnid) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::GetVNodeType(void* node, int* type) +{ + return B_NOT_SUPPORTED; +} + + +status_t +FUSEVolume::GetVNodeName(void* node, char* buffer, size_t bufferSize) +{ + return B_NOT_SUPPORTED; +} + + +status_t +FUSEVolume::ReadVNode(ino_t vnid, bool reenter, void** node, int* type, + uint32* flags, FSVNodeCapabilities* _capabilities) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::WriteVNode(void* node, bool reenter) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::RemoveVNode(void* node, bool reenter) +{ + return B_UNSUPPORTED; +} + + +// #pragma mark - asynchronous I/O + + +status_t +FUSEVolume::DoIO(void* node, void* cookie, const IORequestInfo& requestInfo) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::CancelIO(void* node, void* cookie, int32 ioRequestID) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::IterativeIOGetVecs(void* cookie, int32 requestID, off_t offset, + size_t size, struct file_io_vec* vecs, size_t* _count) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::IterativeIOFinished(void* cookie, int32 requestID, status_t status, + bool partialTransfer, size_t bytesTransferred) +{ + return B_UNSUPPORTED; +} + + +// #pragma mark - nodes + + +status_t +FUSEVolume::IOCtl(void* node, void* cookie, uint32 command, void *buffer, + size_t size) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::SetFlags(void* node, void* cookie, int flags) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::Select(void* node, void* cookie, uint8 event, selectsync* sync) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::Deselect(void* node, void* cookie, uint8 event, selectsync* sync) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::FSync(void* node) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::ReadSymlink(void* node, char* buffer, size_t bufferSize, + size_t* bytesRead) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::CreateSymlink(void* dir, const char* name, const char* target, + int mode) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::Link(void* dir, const char* name, void* node) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::Unlink(void* dir, const char* name) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::Rename(void* oldDir, const char* oldName, void* newDir, + const char* newName) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::Access(void* node, int mode) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::ReadStat(void* node, struct stat* st) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::WriteStat(void* node, const struct stat *st, uint32 mask) +{ + return B_UNSUPPORTED; +} + + +// #pragma mark - files + + +status_t +FUSEVolume::Create(void* dir, const char* name, int openMode, int mode, + void** cookie, ino_t* vnid) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::Open(void* node, int openMode, void** cookie) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::Close(void* node, void* cookie) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::FreeCookie(void* node, void* cookie) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::Read(void* node, void* cookie, off_t pos, void* buffer, + size_t bufferSize, size_t* bytesRead) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::Write(void* node, void* cookie, off_t pos, const void* buffer, + size_t bufferSize, size_t* bytesWritten) +{ + return B_UNSUPPORTED; +} + + +// #pragma mark - directories + + +status_t +FUSEVolume::CreateDir(void* dir, const char* name, int mode, ino_t *newDir) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::RemoveDir(void* dir, const char* name) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::OpenDir(void* node, void** cookie) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::CloseDir(void* node, void* cookie) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::FreeDirCookie(void* node, void* cookie) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::ReadDir(void* node, void* cookie, void* buffer, size_t bufferSize, + uint32 count, uint32* countRead) +{ + return B_UNSUPPORTED; +} + + +status_t +FUSEVolume::RewindDir(void* node, void* cookie) +{ + return B_UNSUPPORTED; +} diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.h b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.h new file mode 100644 index 0000000000..18984fc6ab --- /dev/null +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.h @@ -0,0 +1,122 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef USERLAND_FS_FUSE_VOLUME_H +#define USERLAND_FS_FUSE_VOLUME_H + +#include "../Volume.h" + + +namespace UserlandFS { + +class FUSEFileSystem; + + +class FUSEVolume : public Volume { +public: + FUSEVolume(FUSEFileSystem* fileSystem, + dev_t id); + virtual ~FUSEVolume(); + + // FS + virtual status_t Mount(const char* device, uint32 flags, + const char* parameters, ino_t* rootID); + virtual status_t Unmount(); + virtual status_t Sync(); + virtual status_t ReadFSInfo(fs_info* info); + virtual status_t WriteFSInfo(const struct fs_info* info, + uint32 mask); + + // vnodes + virtual status_t Lookup(void* dir, const char* entryName, + ino_t* vnid); + virtual status_t GetVNodeType(void* node, int* type); + // Only needs to be implemented when + // the three parameters publish_vnode() is + // used. + virtual status_t GetVNodeName(void* node, char* buffer, + size_t bufferSize); + virtual status_t ReadVNode(ino_t vnid, bool reenter, + void** node, int* type, uint32* flags, + FSVNodeCapabilities* _capabilities); + virtual status_t WriteVNode(void* node, bool reenter); + virtual status_t RemoveVNode(void* node, bool reenter); + + // asynchronous I/O + virtual status_t DoIO(void* node, void* cookie, + const IORequestInfo& requestInfo); + virtual status_t CancelIO(void* node, void* cookie, + int32 ioRequestID); + virtual status_t IterativeIOGetVecs(void* cookie, + int32 requestID, off_t offset, size_t size, + struct file_io_vec* vecs, size_t* _count); + virtual status_t IterativeIOFinished(void* cookie, + int32 requestID, status_t status, + bool partialTransfer, + size_t bytesTransferred); + + // nodes + virtual status_t IOCtl(void* node, void* cookie, + uint32 command, void* buffer, size_t size); + virtual status_t SetFlags(void* node, void* cookie, + int flags); + virtual status_t Select(void* node, void* cookie, + uint8 event, selectsync* sync); + virtual status_t Deselect(void* node, void* cookie, + uint8 event, selectsync* sync); + + virtual status_t FSync(void* node); + + virtual status_t ReadSymlink(void* node, char* buffer, + size_t bufferSize, size_t* bytesRead); + virtual status_t CreateSymlink(void* dir, const char* name, + const char* target, int mode); + + virtual status_t Link(void* dir, const char* name, + void* node); + virtual status_t Unlink(void* dir, const char* name); + virtual status_t Rename(void* oldDir, const char* oldName, + void* newDir, const char* newName); + + virtual status_t Access(void* node, int mode); + virtual status_t ReadStat(void* node, struct stat* st); + virtual status_t WriteStat(void* node, const struct stat *st, + uint32 mask); + + // files + virtual status_t Create(void* dir, const char* name, + int openMode, int mode, void** cookie, + ino_t* vnid); + virtual status_t Open(void* node, int openMode, + void** cookie); + virtual status_t Close(void* node, void* cookie); + virtual status_t FreeCookie(void* node, void* cookie); + virtual status_t Read(void* node, void* cookie, off_t pos, + void* buffer, size_t bufferSize, + size_t* bytesRead); + virtual status_t Write(void* node, void* cookie, + off_t pos, const void* buffer, + size_t bufferSize, size_t* bytesWritten); + + // directories + virtual status_t CreateDir(void* dir, const char* name, + int mode, ino_t *newDir); + virtual status_t RemoveDir(void* dir, const char* name); + virtual status_t OpenDir(void* node, void** cookie); + virtual status_t CloseDir(void* node, void* cookie); + virtual status_t FreeDirCookie(void* node, void* cookie); + virtual status_t ReadDir(void* node, void* cookie, + void* buffer, size_t bufferSize, + uint32 count, uint32* countRead); + virtual status_t RewindDir(void* node, void* cookie); + +private: + inline FUSEFileSystem* _FileSystem() const; +}; + +} // namespace UserlandFS + +using UserlandFS::FUSEVolume; + +#endif // USERLAND_FS_FUSE_VOLUME_H diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/Jamfile b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/Jamfile index fead70a41a..68e15f4d26 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/Jamfile +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/Jamfile @@ -21,6 +21,8 @@ DEFINES += _FILE_OFFSET_BITS=64 ; SharedLibrary libuserlandfs_fuse.so : fuse_main.cpp + FUSEFileSystem.cpp + FUSEVolume.cpp : userlandfs_server diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_main.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_main.cpp index 0f7814d954..9515485950 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_main.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_main.cpp @@ -5,6 +5,8 @@ #define FUSE_USE_VERSION FUSE_VERSION +#include + #include @@ -12,6 +14,8 @@ int fuse_main_real(int argc, char* argv[], const struct fuse_operations* op, size_t op_size, void *user_data) { +printf("fuse_main_real(%d, %p, %p, %ld, %p)\n", argc, argv, op, op_size, +user_data); // TODO: Implement! return 0; } @@ -20,6 +24,7 @@ fuse_main_real(int argc, char* argv[], const struct fuse_operations* op, int fuse_is_lib_option(const char *opt) { +printf("fuse_is_lib_option(\"%s\")\n", opt); // TODO: Implement! return 0; }