root/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.h
/*
 * 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"

#include "fuse_api.h"
#include "fuse_config.h"


namespace UserlandFS {

class FUSEFileSystem : public FileSystem {
public:
                                                                FUSEFileSystem(const char* fsName,
                                                                        int (*mainFunction)(int,
                                                                                const char* const*));
        virtual                                         ~FUSEFileSystem();

        static  FUSEFileSystem*         GetInstance();

                        void                            GetVolumeCapabilities(
                                                                        FSVolumeCapabilities& capabilities) const
                                                                        { capabilities = fVolumeCapabilities; }
                        void                            GetNodeCapabilities(
                                                                        FSVNodeCapabilities& capabilities) const
                                                                        { capabilities = fNodeCapabilities; }
                        const FSVNodeCapabilities& GetNodeCapabilities() const
                                                                        { return fNodeCapabilities; }

                        const fuse_lowlevel_ops*        GetLowlevelOps() const
                                                                        {
                                                                                if (fFS == NULL)
                                                                                        return &fLowLevelOps;
                                                                                return  NULL;
                                                                        }
                        fuse_fs*                        GetFS() const   { return fFS; }

                        const fuse_config&      GetFUSEConfig() const   { return fFUSEConfig; }

                        bool                            HasHaikuFuseExtensions() const
                                                                        {
                                                                                return (fConnectionInfo.want
                                                                                        & FUSE_CAP_HAIKU_FUSE_EXTENSIONS) != 0;
                                                                        }

        virtual status_t                        CreateVolume(Volume** _volume, dev_t id);
        virtual status_t                        DeleteVolume(Volume* volume);

        virtual void                            InitRequestThreadContext(
                                                                        RequestThreadContext* context);

                        status_t                        InitClientFS(const char* parameters);
                        void                            ExitClientFS(status_t status);

                        status_t                        FinishInitClientFS(fuse_config* config,
                                                                        const fuse_operations* ops, size_t opSize,
                                                                        void* userData);
                        status_t                        FinishInitClientFS(fuse_config* config,
                                                                        const fuse_lowlevel_ops* ops, size_t opSize,
                                                                        void* userData);
                        status_t                        MainLoop(bool multithreaded);

private:
                        class ArgumentVector;

private:
        static  status_t                        _InitializationThreadEntry(void* data);
                        status_t                        _InitializationThread();

                        status_t                        _InitClientFS(const fuse_operations* ops,
                                                                        size_t opSize, void* userData);
                        status_t                        _InitClientFS(const fuse_lowlevel_ops* ops,
                                                                        size_t opSize, void* userData);

                        void                            _InitCapabilities();

private:
                        int                                     (*fMainFunction)(int, const char* const*);
                        thread_id                       fInitThread;
                        status_t                        fInitStatus;
                        status_t                        fExitStatus;
                        sem_id                          fInitSemaphore;
                        sem_id                          fExitSemaphore;
                        const char*                     fInitParameters;
                        fuse_lowlevel_ops       fLowLevelOps;
                        void*                           fUserData;
                        fuse_fs*                        fFS;
                        fuse_conn_info          fConnectionInfo;
                        fuse_config                     fFUSEConfig;

                        FSVolumeCapabilities fVolumeCapabilities;
                        FSVNodeCapabilities     fNodeCapabilities;
};

}       // namespace UserlandFS

using UserlandFS::FUSEFileSystem;


/*static*/ inline FUSEFileSystem*
FUSEFileSystem::GetInstance()
{
        return static_cast<FUSEFileSystem*>(sInstance);
}


#endif  // USERLAND_FS_FUSE_FILE_SYSTEM_H