root/headers/private/kernel/boot/vfs.h
/*
 * Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de.
 * Distributed under the terms of the MIT License.
 */
#ifndef KERNEL_BOOT_VFS_H
#define KERNEL_BOOT_VFS_H


#include <dirent.h>

#include <SupportDefs.h>

#include <util/DoublyLinkedList.h>
#include <boot/stage2_args.h>


#ifdef __cplusplus

struct file_map_run;
struct stat;
class PackageVolumeInfo;
class PackageVolumeState;

/** This is the base class for all VFS nodes */

class Node : public DoublyLinkedListLinkImpl<Node> {
        public:
                Node();
                virtual ~Node();

                virtual status_t Open(void **_cookie, int mode);
                virtual status_t Close(void *cookie);

                virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer,
                        size_t bufferSize) = 0;
                virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer,
                        size_t bufferSize) = 0;

                virtual status_t ReadLink(char* buffer, size_t bufferSize);

                virtual status_t GetName(char *nameBuffer, size_t bufferSize) const;
                virtual status_t GetFileMap(struct file_map_run *runs, int32 *count);
                virtual int32 Type() const;
                virtual off_t Size() const;
                virtual ino_t Inode() const;

                void Stat(struct stat& stat);

                status_t Acquire();
                status_t Release();

        protected:
                int32           fRefCount;
};

typedef DoublyLinkedList<Node> NodeList;
typedef NodeList::Iterator NodeIterator;


class Directory : public Node {
        public:
                Directory();

                virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize);
                virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize);

                virtual int32 Type() const;

                virtual Node* Lookup(const char* name, bool traverseLinks);
                virtual Node* LookupDontTraverse(const char* name) = 0;

                virtual status_t GetNextEntry(void *cookie, char *nameBuffer, size_t bufferSize) = 0;
                virtual status_t GetNextNode(void *cookie, Node **_node) = 0;
                virtual status_t Rewind(void *cookie) = 0;
                virtual bool IsEmpty() = 0;

                virtual status_t CreateFile(const char *name, mode_t permissions,
                        Node **_node);
};

/** The console based nodes don't need cookies for I/O, they
 *      also don't support to change the stream position.
 *      Live is simple in the boot loader :-)
 */

class ConsoleNode : public Node {
        public:
                ConsoleNode();

                virtual ssize_t Read(void *buffer, size_t bufferSize);
                virtual ssize_t Write(const void *buffer, size_t bufferSize);

                virtual void    ClearScreen() = 0;
                virtual int32   Width() = 0;
                virtual int32   Height() = 0;
                virtual void    SetCursor(int32 x, int32 y) = 0;
                virtual void    SetCursorVisible(bool visible) = 0;
                virtual void    SetColors(int32 foreground, int32 background) = 0;
};


class MemoryDisk : public Node {
        public:
                MemoryDisk(const uint8* data, size_t size, const char* name);

                virtual ssize_t ReadAt(void* cookie, off_t pos, void* buffer,
                        size_t bufferSize);
                virtual ssize_t WriteAt(void* cookie, off_t pos, const void* buffer,
                        size_t bufferSize);

                virtual off_t Size() const;
                virtual status_t GetName(char *nameBuffer, size_t bufferSize) const;

        private:
                const uint8*    fData;
                size_t                  fSize;
                char                    fName[64];
};


class BootVolume {
public:
                                                                BootVolume();
                                                                ~BootVolume();

                        status_t                        SetTo(Directory* rootDirectory,
                                                                        PackageVolumeInfo* packageVolumeInfo
                                                                                = NULL,
                                                                        PackageVolumeState* packageVolumeState
                                                                                = NULL);
                        void                            Unset();

                        bool                            IsValid() const
                                                                        { return fRootDirectory != NULL; }

                        Directory*                      RootDirectory() const
                                                                        { return fRootDirectory; }
                        Directory*                      SystemDirectory() const
                                                                        { return fSystemDirectory; }
                        bool                            IsPackaged() const
                                                                        { return fPackageVolumeInfo != NULL; }
                        PackageVolumeInfo*      GetPackageVolumeInfo() const
                                                                        { return fPackageVolumeInfo; }
                        PackageVolumeState*     GetPackageVolumeState() const
                                                                        { return fPackageVolumeState; }

private:
                        status_t                        _SetTo(Directory* rootDirectory,
                                                                        PackageVolumeInfo* packageVolumeInfo,
                                                                        PackageVolumeState* packageVolumeState);
                        int                                     _OpenSystemPackage();

private:
                        Directory*                      fRootDirectory;
                                // root directory of the volume
                        Directory*                      fSystemDirectory;
                                // "system" directory of the volume; if packaged the root
                                // directory of the mounted packagefs
                        PackageVolumeInfo*      fPackageVolumeInfo;
                        PackageVolumeState*     fPackageVolumeState;
};


/* function prototypes */

extern status_t vfs_init(stage2_args *args);
extern status_t register_boot_file_system(BootVolume& bootVolume);
extern status_t get_boot_file_system(stage2_args* args,
                        BootVolume& _bootVolume);
extern status_t mount_file_systems(stage2_args *args);
extern int open_node(Node *node, int mode);
extern int open_from(Directory *directory, const char *path, int mode,
                        mode_t permissions = 0);
extern DIR* open_directory(Directory* baseDirectory, const char* path);
extern status_t get_stat(Directory* directory, const char* path,
                        struct stat& st);

extern Node* get_node_from(int fd);
        // returns a reference
extern Directory* directory_from(DIR* dir);
        // does not return a reference

extern status_t add_partitions_for(int fd, bool mountFileSystems, bool isBootDevice = false);
extern status_t add_partitions_for(Node *device, bool mountFileSystems, bool isBootDevice = false);

#endif  /* __cplusplus */

#endif  /* KERNEL_BOOT_VFS_H */