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
This commit is contained in:
Ingo Weinhold 2009-03-19 01:36:40 +00:00
parent 7305309909
commit c93232896f
6 changed files with 709 additions and 0 deletions

View File

@ -0,0 +1,193 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "FUSEFileSystem.h"
#include <stdlib.h>
#include <string.h>
#include <new>
#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;
}

View File

@ -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

View File

@ -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<FUSEFileSystem*>(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;
}

View File

@ -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

View File

@ -21,6 +21,8 @@ DEFINES += _FILE_OFFSET_BITS=64 ;
SharedLibrary libuserlandfs_fuse.so
:
fuse_main.cpp
FUSEFileSystem.cpp
FUSEVolume.cpp
:
<nogrist>userlandfs_server

View File

@ -5,6 +5,8 @@
#define FUSE_USE_VERSION FUSE_VERSION
#include <stdio.h>
#include <fuse.h>
@ -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;
}