~aleteoryx/muditaos

dde4bef8a57cfafa0463a37a82a7633ea05c2f3a — Lucjan Bryndza 5 years ago 32de9ec
[EGD-5075] Add new vfs core to new lib syscalls

Add new vfs core support to the new lib filesystem syscalls,
so currently new platform is switched to the new fs
10 files changed, 252 insertions(+), 185 deletions(-)

M board/linux/libiosyscalls/include/iosyscalls.hpp
M board/rt1051/newlib/include/sys/dirent.h
M board/rt1051/newlib/io_syscalls.cpp
M module-vfs/include/internal/newlib/vfs_io_syscalls.hpp
D module-vfs/src/newlib/HandleManager.cpp
D module-vfs/src/newlib/HandleManager.hpp
D module-vfs/src/newlib/vfs_internal_dirent.cpp
D module-vfs/src/newlib/vfs_internal_dirent.hpp
M module-vfs/src/newlib/vfs_io_syscalls.cpp
M module-vfs/targets/Target_RT1051.cmake
M board/linux/libiosyscalls/include/iosyscalls.hpp => board/linux/libiosyscalls/include/iosyscalls.hpp +1 -1
@@ 32,7 32,7 @@ namespace vfsn::linux::internal
        auto vfs = purefs::subsystem::vfs_core();
        if(!vfs) {
            errno = EIO;
            return 0;
            return -1;
        }
        auto ret = (vfs.get()->*lfs_fun)(std::forward<Args>(args)...);
        if(ret < 0) {

M board/rt1051/newlib/include/sys/dirent.h => board/rt1051/newlib/include/sys/dirent.h +4 -18
@@ 29,28 29,14 @@ extern "C" {
	struct dirent {
		ino_t	d_ino;
		unsigned char  d_type;
		size_t  d_reclen;
		char	d_name[NAME_MAX+1];
	};

    struct DIR_ITER {
        void *dir_state;
        char name_state[NAME_MAX+1];
    };

	typedef struct {
		long int        position;
		DIR_ITER*       dir_data;
		struct dirent   file_data;
	} DIR;
	
	int closedir(DIR *dirp);
	DIR *opendir(const char *dirname);
	struct dirent *readdir(DIR *dirp);
	int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
	void rewinddir(DIR *dirp);
	void seekdir(DIR *dirp, long int loc);
	long int telldir(DIR *dirp);
	struct __dirstream;
	typedef struct __dirstream DIR;
	

#ifdef __cplusplus
}
#endif

M board/rt1051/newlib/io_syscalls.cpp => board/rt1051/newlib/io_syscalls.cpp +1 -1
@@ 112,7 112,7 @@ extern "C"
    }
    int statvfs(const char *path, struct statvfs *buf)
    {
        return syscalls::statvfs(path,buf);
        return syscalls::statvfs( _REENT->_errno, path,buf);
    }
}


M module-vfs/include/internal/newlib/vfs_io_syscalls.hpp => module-vfs/include/internal/newlib/vfs_io_syscalls.hpp +1 -1
@@ 35,6 35,6 @@ namespace vfsn::internal::syscalls
    int chmod(int &_errno_, const char *path, mode_t mode);
    int fchmod(int &_errno_, int fd, mode_t mode);
    int fsync(int &_errno_, int fd);
    int statvfs(const char *path, struct statvfs *buf);
    int statvfs(int &_errno_, const char *path, struct statvfs *buf);

} // namespace vfsn::internal::syscalls

D module-vfs/src/newlib/HandleManager.cpp => module-vfs/src/newlib/HandleManager.cpp +0 -27
@@ 1,27 0,0 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "HandleManager.hpp"

namespace vfsn::internal::stdlib::impl
{
    auto HandleManager::clearHandle(int hwnd) noexcept -> void *
    {
        if (hwnd < FIRST_HANDLE || hwnd >= MAX_HANDLES + FIRST_HANDLE) {
            return nullptr;
        }
        hwnd -= FIRST_HANDLE;
        return mHandles[hwnd].exchange(nullptr);
    }

    auto HandleManager::setHandle(void *hwnd) noexcept -> int
    {
        for (int h = 0; h < MAX_HANDLES; ++h) {
            void *tst_val = nullptr;
            if (mHandles[h].compare_exchange_strong(tst_val, hwnd)) {
                return h + FIRST_HANDLE;
            }
        }
        return -1;
    }
} // namespace vfsn::internal::stdlib::impl

D module-vfs/src/newlib/HandleManager.hpp => module-vfs/src/newlib/HandleManager.hpp +0 -64
@@ 1,64 0,0 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include <cstdint>
#include <array>
#include <atomic>
namespace vfsn::internal::stdlib
{
    // Generic handle manager standard syscalls
    namespace impl
    {
        class HandleManager
        {
            /* Number of simultaneously open files by the
             * stdio library
             */
            static constexpr auto MAX_HANDLES = 128;
            /*
             * According to the POSIX standard handle no 0 is reserved for standard input
             * stream (STDIN_FILENO),
             * handle no 1 is reserved for standard output stream (STDOUT_FILENO) ,
             * handle no 2 is reserved for standard error output stream (STDERR_FILENO),
             * so the first allowed file descriptor returned by open should be 3 or greater.
             */
            static constexpr auto FIRST_HANDLE = 3;

          protected:
            /*
             * Atomically remove file descriptor from
             * global file descriptor table and return handle
             * which can be released by underlaying library
             */
            auto clearHandle(int hwnd) noexcept -> void *;
            auto setHandle(void *hwnd) noexcept -> int;
            auto get(int handle) const noexcept -> void *
            {
                if (handle < FIRST_HANDLE || handle >= FIRST_HANDLE + MAX_HANDLES)
                    return nullptr;
                else
                    return mHandles[handle - FIRST_HANDLE].load();
            }

          private:
            std::array<std::atomic<void *>, MAX_HANDLES> mHandles;
        };
    } // namespace impl
    template <typename T> class HandleManager : public impl::HandleManager
    {
      public:
        auto setHandle(T *hwnd) noexcept
        {
            return impl::HandleManager::setHandle(hwnd);
        }
        auto operator[](int handle) const noexcept
        {
            return reinterpret_cast<T *>(impl::HandleManager::get(handle));
        }
        auto clearHandle(int hwnd)
        {
            return reinterpret_cast<T *>(impl::HandleManager::clearHandle(hwnd));
        }
    };
} // namespace vfsn::internal::stdlib

D module-vfs/src/newlib/vfs_internal_dirent.cpp => module-vfs/src/newlib/vfs_internal_dirent.cpp +0 -30
@@ 1,30 0,0 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "vfs_internal_dirent.hpp"
#include <cstring>
#include <errno.h>
#include <new>
#include <dirent.h>

namespace vfsn::internal::dirent
{
    DIR_ITER *diropen(int &_errno_, const char *path)
    {
        return nullptr;
    }

    int dirreset(int &_errno_, DIR_ITER *state)
    {
        return -1;
    }
    int dirnext(int &_errno_, DIR_ITER *state)
    {
        return -1;
    }

    int dirclose(int &_errno_, DIR_ITER *state)
    {
        return -1;
    }

} // namespace vfsn::internal::dirent

D module-vfs/src/newlib/vfs_internal_dirent.hpp => module-vfs/src/newlib/vfs_internal_dirent.hpp +0 -13
@@ 1,13 0,0 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once

#include <dirent.h>

namespace vfsn::internal::dirent
{
    DIR_ITER *diropen(int &_errno_, const char *path);
    int dirreset(int &_errno_, DIR_ITER *state);
    int dirnext(int &_errno_, DIR_ITER *state);
    int dirclose(int &_errno_, DIR_ITER *state);
} // namespace vfsn::internal::dirent

M module-vfs/src/newlib/vfs_io_syscalls.cpp => module-vfs/src/newlib/vfs_io_syscalls.cpp +245 -28
@@ 1,129 1,346 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <errno.h>
#include <dirent.h>
#include <log/log.hpp>
#include <fcntl.h>
#include <cstring>
#include <unistd.h>
#include "vfs_internal_dirent.hpp"
#include "HandleManager.hpp"
#include <newlib/vfs_io_syscalls.hpp>
#include <cstring>
#include <sys/statvfs.h>
#include <purefs/vfs_subsystem.hpp>
#include <newlib/vfs_io_syscalls.hpp>

struct __dirstream
{
    purefs::fs::filesystem::fsdir dirh;
    size_t position;
    struct dirent dir_data;
};

namespace
{
    template <class Base, typename T, typename... Args>
    auto invoke_fs(int &error, T Base::*lfs_fun, Args &&... args)
        -> decltype((static_cast<Base *>(nullptr)->*lfs_fun)(std::forward<Args>(args)...))
    {
        auto vfs = purefs::subsystem::vfs_core();
        if (!vfs) {
            error = EIO;
            return -1;
        }
        auto ret = (vfs.get()->*lfs_fun)(std::forward<Args>(args)...);
        if (ret < 0) {
            error = -ret;
            ret   = -1;
        }
        return ret;
    }
} // namespace

namespace vfsn::internal::syscalls
{
    int open(int &_errno_, const char *file, int flags, int mode)
    {
        return -1;
        return invoke_fs(_errno_, &purefs::fs::filesystem::open, file, flags, mode);
    }

    long close(int &_errno_, int fd)
    {
        return -1;
        return invoke_fs(_errno_, &purefs::fs::filesystem::close, fd);
    }

    long write(int &_errno_, int fd, const void *buf, size_t cnt)
    {
        return -1;
        return invoke_fs(_errno_, &purefs::fs::filesystem::write, fd, reinterpret_cast<const char *>(buf), cnt);
    }

    long read(int &_errno_, int fd, void *buf, size_t cnt)
    {
        return -1;
        return invoke_fs(_errno_, &purefs::fs::filesystem::read, fd, reinterpret_cast<char *>(buf), cnt);
    }

    off_t lseek(int &_errno_, int fd, off_t pos, int dir)
    {
        return -1;
        return invoke_fs(_errno_, &purefs::fs::filesystem::seek, fd, pos, dir);
    }

    int fstat(int &_errno_, int fd, struct stat *pstat)
    {
        return -1;
        if (pstat) {
            return invoke_fs(_errno_, &purefs::fs::filesystem::fstat, fd, *pstat);
        }
        else {
            _errno_ = EINVAL;
            return -1;
        }
    }

    int link(int &_errno_, const char *existing, const char *newLink)
    {
        return -1;
        return invoke_fs(_errno_, &purefs::fs::filesystem::link, existing, newLink);
    }

    int unlink(int &_errno_, const char *name)
    {
        return -1;
        return invoke_fs(_errno_, &purefs::fs::filesystem::unlink, name);
    }

    int fcntl(int &_errno_, int fd, int cmd, int arg)
    {
        _errno_ = ENOTSUP;
        return -1;
    }

    int stat(int &_errno_, const char *file, struct stat *pstat)
    {
        return -1;
        if (pstat) {
            return invoke_fs(_errno_, &purefs::fs::filesystem::stat, file, *pstat);
        }
        else {
            _errno_ = EINVAL;
            return -1;
        }
    }

    int chdir(int &_errno_, const char *path)
    {
        return -1;
        return invoke_fs(_errno_, &purefs::fs::filesystem::chdir, path);
    }

    char *getcwd(int &_errno_, char *buf, size_t size)
    {
        return nullptr;
        if (!buf) {
            _errno_ = EINVAL;
            return nullptr;
        }
        auto vfs = purefs::subsystem::vfs_core();
        if (!vfs) {
            _errno_ = EIO;
            return nullptr;
        }
        const auto ret  = vfs->getcwd();
        const auto slen = ret.copy(buf, size);
        if (size < slen) {
            buf[slen] = '\0';
        }
        return buf;
    }

    int rename(int &_errno_, const char *oldName, const char *newName)
    {
        return -1;
        return invoke_fs(_errno_, &purefs::fs::filesystem::rename, oldName, newName);
    }

    int mkdir(int &_errno_, const char *path, uint32_t mode)
    {
        return -1;
        return invoke_fs(_errno_, &purefs::fs::filesystem::mkdir, path, mode);
    }

    DIR *opendir(int &_errno_, const char *dirname)
    {
        return nullptr;
        __dirstream *ret{};
        if (!dirname) {
            _errno_ = EIO;
            return ret;
        }
        auto vfs = purefs::subsystem::vfs_core();
        if (!vfs) {
            _errno_ = EIO;
            return ret;
        }
        ret = new (std::nothrow) __dirstream;
        if (!ret) {
            _errno_ = ENOMEM;
            return ret;
        }
        ret->position = 0;
        ret->dirh     = vfs->diropen(dirname);
        if (!ret->dirh) {
            delete ret;
            _errno_ = EIO;
            ret     = nullptr;
        }
        else if (ret->dirh->error()) {
            _errno_ = -ret->dirh->error();
            delete ret;
            ret = nullptr;
        }
        return ret;
    }

    int closedir(int &_errno_, DIR *dirp)
    {
        return -1;
        if (!dirp) {
            _errno_ = EBADF;
            return -1;
        }
        auto vfs = purefs::subsystem::vfs_core();
        if (!vfs) {
            _errno_ = EIO;
            return -1;
        }
        auto ret = vfs->dirclose(dirp->dirh);
        if (ret < 0) {
            _errno_ = -ret;
            ret     = -1;
        }
        delete dirp;
        return ret;
    }

    struct dirent *readdir(int &_errno_, DIR *dirp)
    {
        return nullptr;
        if (!dirp) {
            _errno_ = EBADF;
            return nullptr;
        }
        auto vfs = purefs::subsystem::vfs_core();
        if (!vfs) {
            _errno_ = EIO;
            return nullptr;
        }
        std::string fname;
        struct stat stdata;
        auto ret = vfs->dirnext(dirp->dirh, fname, stdata);
        if (ret < 0) {
            if (ret != -ENODATA) {
                _errno_ = -ret;
            }
            return nullptr;
        }
        else {
            if (fname.size() >= sizeof(dirp->dir_data.d_name)) {
                _errno_ = EOVERFLOW;
                return nullptr;
            }
            dirp->position += 1;
            dirp->dir_data.d_ino    = stdata.st_ino;
            dirp->dir_data.d_type   = S_ISREG(stdata.st_mode) ? DT_REG : DT_DIR;
            dirp->dir_data.d_reclen = fname.size();
            std::strncpy(dirp->dir_data.d_name, fname.c_str(), sizeof(dirp->dir_data.d_name));
            return &dirp->dir_data;
        }
    }

    int readdir_r(int &_errno_, DIR *dirp, struct dirent *entry, struct dirent **result)
    {
        return -1;
        if (!dirp) {
            _errno_ = EBADF;
            return -1;
        }
        if (!*result) {
            _errno_ = EINVAL;
            return -1;
        }
        auto vfs = purefs::subsystem::vfs_core();
        if (!vfs) {
            _errno_ = EIO;
            return -1;
        }
        std::string fname;
        struct stat stdata;
        auto ret = vfs->dirnext(dirp->dirh, fname, stdata);
        if (ret == -ENODATA) {
            *result = nullptr;
            return 0;
        }
        else if (ret < 0) {
            _errno_ = -ret;
            return -1;
        }
        else {
            if (fname.size() >= sizeof(dirp->dir_data.d_name)) {
                _errno_ = EOVERFLOW;
                return -1;
            }
            dirp->position += 1;
            entry->d_ino    = stdata.st_ino;
            entry->d_type   = S_ISREG(stdata.st_mode) ? DT_REG : DT_DIR;
            entry->d_reclen = fname.size();
            std::strncpy(entry->d_name, fname.c_str(), sizeof(entry->d_name));
            *result = entry;
            return 0;
        }
    }

    void rewinddir(int &_errno_, DIR *dirp)
    {
        if (!dirp) {
            _errno_ = EBADF;
            return;
        }
        auto vfs = purefs::subsystem::vfs_core();
        if (!vfs) {
            _errno_ = EIO;
            return;
        }
        auto res = vfs->dirreset(dirp->dirh);
        if (res < 0) {
            _errno_ = -res;
            return;
        }
        dirp->position = 0;
    }

    void seekdir(int &_errno_, DIR *dirp, long int loc)
    {
        if (!dirp) {
            _errno_ = EBADF;
            return;
        }
        if (loc < 0) {
            _errno_ = EINVAL;
            return;
        }
        auto vfs = purefs::subsystem::vfs_core();
        if (!vfs) {
            _errno_ = EIO;
            return;
        }
        if (long(dirp->position) > loc) {
            vfs->dirreset(dirp->dirh);
            dirp->position = 0;
        }
        std::string name;
        struct stat st;
        while ((long(dirp->position) < loc) && (vfs->dirnext(dirp->dirh, name, st)) >= 0) {
            dirp->position += 1;
        }
    }

    long int telldir(int &_errno_, DIR *dirp)
    {
        return -1;
        if (!dirp) {
            _errno_ = EBADF;
            return -1;
        }
        return dirp->position;
    }

    int chmod(int &_errno_, const char *path, mode_t mode)
    {
        return -1;
        return invoke_fs(_errno_, &purefs::fs::filesystem::chmod, path, mode);
    }

    int fchmod(int &_errno_, int fd, mode_t mode)
    {
        return -1;
        return invoke_fs(_errno_, &purefs::fs::filesystem::fchmod, fd, mode);
    }

    int fsync(int &_errno_, int fd)
    {
        return -1;
        return invoke_fs(_errno_, &purefs::fs::filesystem::fsync, fd);
    }
    int statvfs(const char *path, struct statvfs *buf)

    int statvfs(int &_errno_, const char *path, struct statvfs *buf)
    {
        return -1;
        if (!buf) {
            _errno_ = EINVAL;
            return -1;
        }
        else {
            return invoke_fs(_errno_, &purefs::fs::filesystem::stat_vfs, path, *buf);
        }
    }

} // namespace vfsn::internal::syscalls

M module-vfs/targets/Target_RT1051.cmake => module-vfs/targets/Target_RT1051.cmake +0 -2
@@ 1,7 1,5 @@
set(BOARD_SOURCES ${BOARD_SOURCES}
        src/newlib/vfs_io_syscalls.cpp
        src/newlib/vfs_internal_dirent.cpp
        src/newlib/HandleManager.cpp
        board/rt1051/purefs/src/fs/thread_local_cwd.cpp
        board/rt1051/purefs/src/vfs_subsystem_internal.cpp
        CACHE INTERNAL ""