~aleteoryx/muditaos

e8d1fd23a378169c85a6b9be7e21221ccf04eea0 — Wiktor S. Ovalle Correa 5 years ago f7fef99
[EGD-5177] Change iosyscalls code style

This commit is part of libiosyscalls refining task.
Its purpose is to make this code more predictable and
easier to maintain (as well as fixing some minor bugs).
M board/linux/libiosyscalls/CMakeLists.txt => board/linux/libiosyscalls/CMakeLists.txt +1 -2
@@ 8,9 8,8 @@ set(SOURCES
        ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_stdio.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_scan_family.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_posix.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_posix_dirent.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/src/iosyscalls.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/src/dirent.cpp

)



M board/linux/libiosyscalls/include/iosyscalls.hpp => board/linux/libiosyscalls/include/iosyscalls.hpp +3 -2
@@ 12,8 12,6 @@ namespace vfsn::linux::internal
{
    bool redirect_to_image();
    bool is_image_handle(const FILE* fil);
    int native_fd_to_image_fd(int fd);
    int image_fd_to_native_fd(int fd);
    bool is_image_fd(int fd);
    bool redirect_to_image(const char* inpath);
    const char* npath_translate(const char* inpath, char *buffer);


@@ 23,6 21,9 @@ namespace vfsn::linux::internal
        int error {0};
        int ungetchar {-1};
    };

    int get_native_fd(FILEX*);

    FILEX* allocate_filex(int fd);
    bool is_filex(const void* fd);
    void remove_filex(FILEX *fil);

M board/linux/libiosyscalls/src/iosyscalls.cpp => board/linux/libiosyscalls/src/iosyscalls.cpp +2 -11
@@ 104,18 104,9 @@ namespace vfsn::linux::internal
        return false;
    }

    int native_fd_to_image_fd(int fd)
    int get_native_fd(FILEX* file)
    {
        return FIRST_FILEDESC + fd;
    }

    int image_fd_from_native_fd(int fd)
    {
        if(fd < FIRST_FILEDESC ) {
            return -1;
        } else {
            return fd - FIRST_FILEDESC;
        }
        return file ? (FIRST_FILEDESC + file->fd) : -1;
    }

    bool is_image_fd(int fd)

M board/linux/libiosyscalls/src/syscalls_posix.cpp => board/linux/libiosyscalls/src/syscalls_posix.cpp +80 -89
@@ 8,29 8,20 @@
#include <sys/stat.h>
#include <sys/mount.h>
#include <fcntl.h>

#include <errno.h>

#include <stdarg.h>     // for va_*
#include <limits.h>     // for PATH_MAX
#include <dlfcn.h>      // for dlsym()

#include <stdio.h>

#include <purefs/fs/filesystem.hpp>
#include "syscalls_real.hpp"

#include "debug.hpp"

#define __REAL_DECL(fun) decltype(::fun) *fun
#define __REAL_DLSYM(fun) real::fun = reinterpret_cast<decltype(real::fun)>(dlsym(RTLD_NEXT, #fun))

#define __VFS(fun) (&purefs::fs::filesystem::fun)

namespace
{
    namespace real {
        __REAL_DECL(link);
        __REAL_DECL(unlink);
        __REAL_DECL(symlink);

        __REAL_DECL(fcntl);
        __REAL_DECL(fcntl64);


@@ 50,7 41,7 @@ namespace
        __REAL_DECL(chmod);
        __REAL_DECL(fchmod);
        __REAL_DECL(fsync);
        __REAL_DECL(symlink);
        __REAL_DECL(fdatasync);

        __REAL_DECL(__xstat);
        __REAL_DECL(__lxstat);


@@ 59,14 50,13 @@ namespace
        __REAL_DECL(__xstat64);
        __REAL_DECL(__lxstat64);
        __REAL_DECL(__fxstat64);

        __REAL_DECL(rename);
    } // namespace real

    void __attribute__((constructor)) _lib_posix_initialize()
    {
        __REAL_DLSYM(link);
        __REAL_DLSYM(unlink);
        __REAL_DLSYM(symlink);

        __REAL_DLSYM(fcntl);
        __REAL_DLSYM(fcntl64);


@@ 82,7 72,7 @@ namespace
        __REAL_DLSYM(chmod);
        __REAL_DLSYM(fchmod);
        __REAL_DLSYM(fsync);
        __REAL_DLSYM(symlink);
        __REAL_DLSYM(fdatasync);

        __REAL_DLSYM(__xstat);
        __REAL_DLSYM(__lxstat);


@@ 92,15 82,13 @@ namespace
        __REAL_DLSYM(__lxstat64);
        __REAL_DLSYM(__fxstat64);

        __REAL_DLSYM(rename);

        if (!(real::link && real::unlink
            && real::fcntl && real::fcntl64 && real::chdir && real::fchdir
            && real::getcwd && real::getwd && real::get_current_dir_name && real::mkdir
            && real::chmod && real::chdir && real::fchdir && real::fsync && real::symlink
        if (!(real::link && real::unlink && real::symlink && real::fcntl && real::fcntl64
            && real::chdir && real::fchdir && real::getcwd && real::getwd
            && real::get_current_dir_name && real::mkdir && real::chmod && real::fchmod
            && real::fsync && real::fdatasync
            && real::__xstat && real::__lxstat && real::__fxstat
            && real::__xstat64 && real::__lxstat64 && real::__fxstat64
            && real::rename))
            && real::__xstat64 && real::__lxstat64 && real::__fxstat64))
        {
            abort();
        }


@@ 109,18 97,20 @@ namespace

extern "C" {
    namespace vfs = vfsn::linux::internal;
    using fs = purefs::fs::filesystem;

    int _iosys_link(const char *oldpath, const char *newpath)
    {
        TRACE_SYSCALL();
        if(vfs::redirect_to_image(oldpath))
        {
            TRACE_SYSCALLN("(%s,%s) -> VFS", oldpath, newpath);
            errno = ENOSYS;
            std::cerr << "Unsupported syscall " <<  __PRETTY_FUNCTION__ << std::endl;
            return -1;
        }
        else
        {
            TRACE_SYSCALLN("(%s,%s) -> linux fs", oldpath, newpath);
            char tmp[PATH_MAX], tmp2[PATH_MAX];
            const auto oldp = vfs::npath_translate(oldpath,tmp);
            const auto newp = vfs::npath_translate(newpath,tmp2);


@@ 131,13 121,14 @@ extern "C" {

     int _iosys_unlink(const char *name)
     {
        TRACE_SYSCALL();
        if(vfs::redirect_to_image(name))
        {
            return vfs::invoke_fs(__VFS(unlink), name);
            TRACE_SYSCALLN("(%s) -> VFS", name);
            return vfs::invoke_fs(&fs::unlink, name);
        }
        else
        {
            TRACE_SYSCALLN("(%s) -> linux fs", name);
            char tmp[PATH_MAX];
            const auto path = vfs::npath_translate(name,tmp);
            return real::unlink(path);


@@ 147,13 138,14 @@ extern "C" {

    int _iosys_stat(const char *file, struct stat *pstat)
    {
        TRACE_SYSCALL();
        if(vfs::redirect_to_image(file))
        {
            return vfs::invoke_fs(__VFS(stat), file, *pstat);
            TRACE_SYSCALLN("(%s) -> VFS", file);
            return vfs::invoke_fs(&fs::stat, file, *pstat);
        }
        else
        {
            TRACE_SYSCALLN("(%s) -> linux fs", file);
            char tmp[PATH_MAX];
            const auto newfile = vfs::npath_translate(file,tmp);
            return real::__xstat(1,newfile,pstat);


@@ 163,13 155,14 @@ extern "C" {

    int _iosys_lstat(const char *pathname, struct stat *statbuf)
    {
        TRACE_SYSCALL();
        if(vfs::redirect_to_image(pathname))
        {
            return vfs::invoke_fs(__VFS(stat), pathname, *statbuf);
            TRACE_SYSCALLN("(%s) -> VFS", pathname);
            return vfs::invoke_fs(&fs::stat, pathname, *statbuf);
        }
        else
        {
            TRACE_SYSCALLN("(%s) -> linux fs", pathname);
            char tmp[PATH_MAX];
            const auto newpath = vfs::npath_translate(pathname,tmp);
            return real::__lxstat(1,newpath,statbuf);


@@ 179,13 172,14 @@ extern "C" {

    int _iosys_fstat(int fd, struct stat *pstat)
    {
        TRACE_SYSCALL();
        if(vfs::is_image_fd(fd))
        {
            return vfs::invoke_fs(__VFS(fstat),fd,*pstat);
            TRACE_SYSCALLN("(%d) -> VFS", fd);
            return vfs::invoke_fs(&fs::fstat,fd,*pstat);
        }
        else
        {
            TRACE_SYSCALLN("(%d) -> linux fs", fd);
            return real::__fxstat(1,fd,pstat);
        }
    }


@@ 193,16 187,16 @@ extern "C" {

    int _iosys_fcntl(int fd, int cmd, ... /* arg */ )
    {
        TRACE_SYSCALL();
        if(vfs::is_image_fd(fd))
        {
            TRACE_SYSCALLN("(%d) -> VFS", fd);
            errno = ENOSYS;
            std::cerr << "Unsupported syscall " << __PRETTY_FUNCTION__ << std::endl;
            return -1;
        }
        else
        {
            TRACE_SYSCALLN("%s", "Redirecting to linux fs");
            TRACE_SYSCALLN("(%d) -> linux fs", fd);
            uintptr_t param;
            va_list args;
            va_start(args,cmd);


@@ 216,14 210,14 @@ extern "C" {

    int _iosys_fcntl64(int fd, int cmd, ... /* arg */ )
    {
        TRACE_SYSCALL();
        if(vfs::is_image_fd(fd))
        {
            TRACE_SYSCALLN("(%d) -> VFS", fd);
            errno = ENOSYS;
            std::cerr << "Unsupported syscall " << __PRETTY_FUNCTION__ << std::endl;
            return -1;
        } else {
            TRACE_SYSCALLN("%s", "Redirecting to linux fs");
            TRACE_SYSCALLN("(%d) -> linux fs", fd);
            uintptr_t param;
            va_list args;
            va_start(args,cmd);


@@ 237,14 231,14 @@ extern "C" {

    int _iosys_chdir(const char *path)
    {
        TRACE_SYSCALL();
        if(vfs::redirect_to_image(path))
        {
            return vfs::invoke_fs(__VFS(chdir), path);
            TRACE_SYSCALLN("(%s) -> VFS", path);
            return vfs::invoke_fs(&fs::chdir, path);
        }
        else
        {
            TRACE_SYSCALLN("%s", "Redirecting to linux fs");
            TRACE_SYSCALLN("(%s) -> linux fs", path);
            char tmp[PATH_MAX];
            const auto newpath = vfs::npath_translate(path,tmp);
            return real::chdir(newpath);


@@ 254,16 248,16 @@ extern "C" {

    int _iosys_fchdir(int fd)
    {
        TRACE_SYSCALL();
        if(vfs::is_image_fd(fd))
        {
            TRACE_SYSCALLN("(%d) -> VFS", fd);
            errno = ENOSYS;
            std::cerr << "Unsupported syscall " << __PRETTY_FUNCTION__ << std::endl;
            return -1;
        }
        else
        {
            TRACE_SYSCALLN("%s", "Redirecting to linux fs");
            TRACE_SYSCALLN("(%d) -> linux fs", fd);
            return real::fchdir(fd);
        }
    }


@@ 271,9 265,9 @@ extern "C" {

    char *_iosys_getcwd(char *buf, size_t size)
    {
        TRACE_SYSCALL();
        if(vfs::redirect_to_image())
        {
            TRACE_SYSCALLN("%s", "() -> VFS");
            auto vfs = purefs::subsystem::vfs_core();
            if(!vfs) {
                errno = EIO;


@@ 285,7 279,7 @@ extern "C" {
        }
        else
        {
            TRACE_SYSCALLN("%s", "Redirecting to linux fs");
            TRACE_SYSCALLN("%s", "() -> linux fs");
            return real::getcwd(buf,size);
        }
    }


@@ 293,9 287,9 @@ extern "C" {

    char *_iosys_getwd(char *buf)
    {
        TRACE_SYSCALL();
        if(vfs::redirect_to_image())
        {
            TRACE_SYSCALLN("%s", "() -> VFS");
            auto vfs = purefs::subsystem::vfs_core();
            if(!vfs) {
                errno = EIO;


@@ 307,7 301,7 @@ extern "C" {
        }
        else
        {
            TRACE_SYSCALLN("%s", "Redirecting to linux fs");
            TRACE_SYSCALLN("%s", "() -> linux fs");
            return real::getwd(buf);
        }
    }


@@ 316,9 310,9 @@ extern "C" {

    char *_iosys_get_current_dir_name(void)
    {
        TRACE_SYSCALL();
        if(vfs::redirect_to_image())
        {
            TRACE_SYSCALLN("%s", "() -> VFS");
            auto vfs = purefs::subsystem::vfs_core();
            if(!vfs) {
                errno = EIO;


@@ 332,39 326,22 @@ extern "C" {
        }
        else
        {
            TRACE_SYSCALLN("%s", "Redirecting to linux fs");
            TRACE_SYSCALLN("%s", "() -> linux fs");
            return real::get_current_dir_name();
        }
    }
    __asm__(".symver _iosys_get_current_dir_name,get_current_dir_name@GLIBC_2.2.5");

    int _iosys_rename(const char *oldpath, const char *newpath)
    {
        TRACE_SYSCALL();
        if(vfs::redirect_to_image(oldpath))
        {
            return vfs::invoke_fs(__VFS(rename), oldpath, newpath);
        }
        else
        {
            TRACE_SYSCALLN("%s", "Redirecting to linux fs");
            char tmp[PATH_MAX], tmp2[PATH_MAX];
            const auto oldp = vfs::npath_translate(oldpath,tmp);
            const auto newp = vfs::npath_translate(newpath,tmp2);
            return real::rename(oldp,newp);
        }
    }
    __asm__(".symver _iosys_rename,rename@GLIBC_2.2.5");

    int _iosys_mkdir(const char *pathname, mode_t mode)
    {
        if(vfs::redirect_to_image(pathname))
        {
            return vfs::invoke_fs(__VFS(mkdir), pathname, mode);
            TRACE_SYSCALLN("(%s) -> VFS", pathname);
            return vfs::invoke_fs(&fs::mkdir, pathname, mode);
        }
        else
        {
            TRACE_SYSCALLN("%s", "Redirecting to linux fs");
            TRACE_SYSCALLN("(%s) -> linux fs", pathname);
            char tmp[PATH_MAX];
            const auto path = vfs::npath_translate(pathname,tmp);
            return real::mkdir(path,mode);


@@ 374,14 351,14 @@ extern "C" {

    int _iosys_chmod(const char *pathname, mode_t mode)
    {
        TRACE_SYSCALL();
        if(vfs::redirect_to_image(pathname))
        {
            return vfs::invoke_fs(__VFS(chmod),pathname,mode);
            TRACE_SYSCALLN("(%s) -> VFS", pathname);
            return vfs::invoke_fs(&fs::chmod,pathname,mode);
        }
        else
        {
            TRACE_SYSCALLN("%s", "Redirecting to linux fs");
            TRACE_SYSCALLN("(%s) -> linux fs", pathname);
            char tmp[PATH_MAX];
            const auto path = vfs::npath_translate(pathname,tmp);
            return real::chmod(path,mode);


@@ 391,14 368,14 @@ extern "C" {

    int _iosys_fchmod(int fd, mode_t mode)
    {
        TRACE_SYSCALL();
        if(vfs::is_image_fd(fd))
        {
            return vfs::invoke_fs(__VFS(fchmod),fd,mode);
            TRACE_SYSCALLN("(%d) -> VFS", fd);
            return vfs::invoke_fs(&fs::fchmod,fd,mode);
        }
        else
        {
            TRACE_SYSCALLN("%s", "Redirecting to linux fs");
            TRACE_SYSCALLN("(%d) -> linux fs", fd);
            return real::fchmod(fd,mode);
        }
    }


@@ 406,14 383,14 @@ extern "C" {

    int _iosys_fsync(int fd)
    {
        TRACE_SYSCALL();
        if(vfs::is_image_fd(fd))
        {
            return vfs::invoke_fs(__VFS(fsync), fd);
            TRACE_SYSCALLN("(%d) -> VFS", fd);
            return vfs::invoke_fs(&fs::fsync, fd);
        }
        else
        {
            TRACE_SYSCALLN("%s", "Redirecting to linux fs");
            TRACE_SYSCALLN("(%d) -> linux fs", fd);
            return real::fsync(fd);
        }
    }


@@ 421,21 398,29 @@ extern "C" {

    int _iosys_fdatasync(int fd)
    {
        TRACE_SYSCALL();
        return fsync(fd);
        if(vfs::is_image_fd(fd))
        {
            TRACE_SYSCALLN("(%d) -> VFS", fd);
            return vfs::invoke_fs(&fs::fsync, fd);
        }
        else
        {
            TRACE_SYSCALLN("(%d) -> linux fs", fd);
            return real::fdatasync(fd);
        }
    }
    __asm__(".symver _iosys_fdatasync,fdatasync@GLIBC_2.2.5");

    int _iosys_symlink(const char *target, const char *linkpath)
    {
        TRACE_SYSCALL();
        if(vfs::redirect_to_image(target))
        {
            return vfs::invoke_fs(__VFS(symlink),target,linkpath);
            TRACE_SYSCALLN("(%s,%s) -> VFS", target, linkpath);
            return vfs::invoke_fs(&fs::symlink,target,linkpath);
        }
        else
        {
            TRACE_SYSCALLN("%s", "Redirecting to linux fs");
            TRACE_SYSCALLN("(%s,%s) -> linux fs", target, linkpath);
            char tmp[PATH_MAX], tmp2[PATH_MAX];
            const auto tgtp = vfs::npath_translate(target,tmp);
            const auto linp = vfs::npath_translate(linkpath,tmp2);


@@ 448,7 433,8 @@ extern "C" {
    {
        if(vfs::redirect_to_image(path))
        {
            return vfs::invoke_fs(__VFS(stat), path, *stat_buf);
            TRACE_SYSCALLN("(%s) -> VFS", path);
            return vfs::invoke_fs(&fs::stat, path, *stat_buf);
        }
        else
        {


@@ 464,7 450,8 @@ extern "C" {
    {
        if(vfs::redirect_to_image(path))
        {
            return vfs::invoke_fs(__VFS(stat), path, *stat_buf);
            TRACE_SYSCALLN("(%s) -> VFS", path);
            return vfs::invoke_fs(&fs::stat, path, *stat_buf);
        }
        else
        {


@@ 480,7 467,8 @@ extern "C" {
    {
        if(vfs::is_image_fd(fildes))
        {
            return vfs::invoke_fs(__VFS(fstat), fildes, *stat_buf);
            TRACE_SYSCALLN("(%d) -> VFS", fildes);
            return vfs::invoke_fs(&fs::fstat, fildes, *stat_buf);
        }
        else
        {


@@ 496,13 484,14 @@ extern "C" {
        std::cerr << "Unsupported syscall " << __PRETTY_FUNCTION__ << std::endl;
        return -1;
    }
    __asm__(".symver _iosys_fxstatat,__fxstatat@GLIBC_2.2.5");
    __asm__(".symver _iosys_fxstatat,__fxstatat@GLIBC_2.4");

    int _iosys_xstat64(int ver, const char * path, struct stat64 * stat_buf)
    {
        if(vfs::redirect_to_image(path))
        {
            return vfs::invoke_fs(__VFS(stat), path, *(struct stat*)stat_buf);
            TRACE_SYSCALLN("(%s) -> VFS", path);
            return vfs::invoke_fs(&fs::stat, path, *(struct stat*)stat_buf);
        }
        else
        {


@@ 518,7 507,8 @@ extern "C" {
    {
        if(vfs::redirect_to_image(path))
        {
            return vfs::invoke_fs(__VFS(stat), path, *(struct stat*)stat_buf);
            TRACE_SYSCALLN("(%s) -> VFS", path);
            return vfs::invoke_fs(&fs::stat, path, *(struct stat*)stat_buf);
        }
        else
        {


@@ 534,7 524,8 @@ extern "C" {
    {
        if(vfs::is_image_fd(fildes))
        {
            return vfs::invoke_fs(__VFS(fstat), fildes, *(struct stat*)stat_buf);
            TRACE_SYSCALLN("(%d) -> VFS", fildes);
            return vfs::invoke_fs(&fs::fstat, fildes, *(struct stat*)stat_buf);
        }
        else
        {


@@ 558,7 549,7 @@ extern "C" {
    {
        if(vfs::redirect_to_image(dir))
        {
            return vfs::invoke_fs(__VFS(mount), special_file, dir, fstype, rwflag );
            return vfs::invoke_fs(&fs::mount, special_file, dir, fstype, rwflag );
        }
        else
        {


@@ 573,7 564,7 @@ extern "C" {
    {
        if(vfs::redirect_to_image(mount_point))
        {
            return vfs::invoke_fs(__VFS(umount), mount_point );
            return vfs::invoke_fs(&fs::umount, mount_point );
        }
        else
        {

R board/linux/libiosyscalls/src/dirent.cpp => board/linux/libiosyscalls/src/syscalls_posix_dirent.cpp +155 -123
@@ 1,16 1,16 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <iosyscalls.hpp>
#include <purefs/vfs_subsystem.hpp>
#include "debug.hpp"

#include <dirent.h>
#include <errno.h>
#include <cstring>
#include <dlfcn.h>
#include <sys/stat.h>

#include "syscalls_real.hpp"

#include "debug.hpp"

struct __dirstream {
    purefs::fs::filesystem::fsdir dirh;


@@ 18,154 18,183 @@ struct __dirstream {
    size_t position;
};

namespace {
    namespace real {
        __REAL_DECL(opendir);
        __REAL_DECL(closedir);
        __REAL_DECL(readdir);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
        __REAL_DECL(readdir_r);
#pragma GCC diagnostic pop
        __REAL_DECL(rewinddir);
        __REAL_DECL(seekdir);
        __REAL_DECL(telldir);
    } // namespace real

    void __attribute__((constructor)) _lib_posix_dirent_initialize()
    {
        __REAL_DLSYM(opendir);
        __REAL_DLSYM(closedir);
        __REAL_DLSYM(readdir);
        __REAL_DLSYM(readdir_r);
        __REAL_DLSYM(rewinddir);
        __REAL_DLSYM(seekdir);
        __REAL_DLSYM(telldir);

        if (!(real::opendir && real::closedir && real::readdir && real::readdir_r
            && real::rewinddir && real::seekdir && real::telldir))
        {
            abort();
        }
    }
} // namespace

extern "C" {
    using namespace vfsn::linux::internal;
    namespace vfs = vfsn::linux::internal;

    DIR *opendir(const char *dirname)
    DIR *_iosys_opendir(const char *dirname)
    {
        __dirstream* ret {};
        if(!dirname)
        {
            TRACE_SYSCALLN("(%p) invalid argument", dirname);
            errno = EINVAL;
            return ret;
        }
        else
        if( vfs::redirect_to_image(dirname) )
        {
            if( redirect_to_image(dirname) )
            TRACE_SYSCALLN("(%s) -> VFS", dirname);
            auto vfs = purefs::subsystem::vfs_core();
            if(!vfs)
            {
                errno = EIO;
            }
            else
            {
                auto vfs = purefs::subsystem::vfs_core();
                if(!vfs)
                ret = new(std::nothrow)__dirstream;
                if(!ret)
                {
                    errno = EIO;
                    errno = ENOMEM;
                }
                else
                {
                    ret = new(std::nothrow)__dirstream;
                    if(!ret)
                    ret->position = 0;
                    ret->dirh = vfs->diropen(dirname);
                    if(!ret->dirh)
                    {
                        errno = ENOMEM;
                        delete ret;
                        errno = EIO;
                        ret = nullptr;
                    }
                    else
                    else if(ret->dirh->error())
                    {
                        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;
                        }
                        errno = -ret->dirh->error();
                        delete ret;
                        ret = nullptr;
                    }
                }
                if(ret) {
                    add_DIR_to_image_list(ret);
                }
            }
            else
            {
                char tmp[PATH_MAX];
                const auto newpath = npath_translate(dirname,tmp);
                auto r_opendir = reinterpret_cast<DIR* (*)(const char *)>(dlsym(RTLD_NEXT,"opendir"));
                ret = r_opendir(newpath);
            if(ret) {
                vfs::add_DIR_to_image_list(ret);
            }
        }
        else
        {
            char tmp[PATH_MAX];
            const auto newpath = vfs::npath_translate(dirname,tmp);
            TRACE_SYSCALLN("(%s) -> (%s) linux fs", dirname, newpath);
            ret = real::opendir(newpath);
        }
        TRACE_SYSCALLN("(%s)=%p errno=%i",dirname,ret,errno);
        return ret;
    }
    __asm__(".symver _iosys_opendir,opendir@GLIBC_2.2.5");

    __asm__(".symver diropen,diropen@GLIBC_2.2.5");

    int closedir(DIR *dirp)
    int _iosys_closedir(DIR *dirp)
    {
        int ret {};
        do {
            if (!dirp) {
                errno = EBADF;
                ret = -1;
                break;
        if (!dirp) {
            TRACE_SYSCALLN("(%p) invalid argument", dirp);
            errno = EBADF;
            return -1;
        }
        if(vfs::is_image_DIR(dirp)) {
            TRACE_SYSCALLN("(%p) -> VFS", dirp);
            auto vfs = purefs::subsystem::vfs_core();
            if(!vfs) {
                errno = EIO;
                return -1;
            }
            if(is_image_DIR(dirp)) {
                auto vfs = purefs::subsystem::vfs_core();
                if(!vfs) {
                    errno = EIO;
                    ret = -1;
                    break;
                }
                ret = vfs->dirclose(dirp->dirh);
                if(ret < 0) {
                    errno = -ret;
                    ret = -1;
                }
                remove_DIR_from_image_list(dirp);
                delete dirp;
            } else {
                auto r_closedir = reinterpret_cast<int (*)(DIR*)>(dlsym(RTLD_NEXT,"closedir"));
                ret = r_closedir(dirp);
            ret = vfs->dirclose(dirp->dirh);
            if(ret < 0) {
                errno = -ret;
                ret = -1;
            }
        } while(0);
            vfs::remove_DIR_from_image_list(dirp);
            delete dirp;
        } else {
            TRACE_SYSCALLN("(%p) -> linux fs", dirp);
            ret = real::closedir(dirp);
        }
        TRACE_SYSCALLN("(%p)=%i errno=%i", dirp, ret, errno);
        return ret;
    }
    __asm__(".symver closedir,closedir@GLIBC_2.2.5");
    __asm__(".symver _iosys_closedir,closedir@GLIBC_2.2.5");

    struct dirent *readdir(DIR *dirp)
    struct dirent *_iosys_readdir(DIR *dirp)
    {
        dirent* ret {};
        do {
            if (!dirp) {
                errno = EBADF;
                break;
        if (!dirp) {
            TRACE_SYSCALLN("(%p) invalid argument", dirp);
            errno = EBADF;
            return ret;
        }
        if(vfs::is_image_DIR(dirp)) {
            TRACE_SYSCALLN("(%p) -> VFS", dirp);
            auto vfs = purefs::subsystem::vfs_core();
            if(!vfs) {
                errno = EIO;
                return ret;
            }
            if(is_image_DIR(dirp)) {
                auto vfs = purefs::subsystem::vfs_core();
                if(!vfs) {
                    errno = EIO;
                    break;
                }
                std::string fname;
                struct stat stdata;
                auto res = vfs->dirnext(dirp->dirh, fname, stdata);
                if(res < 0) {
                    if(res != -ENODATA) {
                        errno = -res;
                    }
                    break;
                } else {
                    if (fname.size() >= sizeof(dirp->dir_data.d_name)) {
                        errno = EOVERFLOW;
                        break;
                    }
                    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));
                    ret = &dirp->dir_data;
            std::string fname;
            struct stat stdata;
            auto res = vfs->dirnext(dirp->dirh, fname, stdata);
            if(res < 0) {
                if(res != -ENODATA) {
                    errno = -res;
                }
                return ret;
            } else {
                auto r_readdir = reinterpret_cast<struct dirent* (*)(DIR*)>(dlsym(RTLD_NEXT,"readdir"));
                ret = r_readdir(dirp);
                if (fname.size() >= sizeof(dirp->dir_data.d_name)) {
                    errno = EOVERFLOW;
                    return ret;
                }
                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));
                ret = &dirp->dir_data;
            }
        } while(0);
        } else {
            TRACE_SYSCALLN("(%p) -> linux fs", dirp);
            ret = real::readdir(dirp);
        }
        TRACE_SYSCALLN("(%p)=%p errno=%i", dirp,ret,errno);
        return ret;
    }
    __asm__(".symver readdir,readdir@GLIBC_2.2.5");
    __asm__(".symver _iosys_readdir,readdir@GLIBC_2.2.5");

    int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
    int _iosys_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
    {
        TRACE_SYSCALL();
        if (!dirp) {
            TRACE_SYSCALLN("(%p) invalid argument", dirp);
            errno = EBADF;
            return -1;
        }
        if(is_image_DIR(dirp)) {
        if(vfs::is_image_DIR(dirp)) {
            TRACE_SYSCALLN("(%p) -> VFS", dirp);
            auto vfs = purefs::subsystem::vfs_core();
            if(!vfs) {
                errno = EIO;


@@ 192,21 221,22 @@ extern "C" {
                return 0;
            }
        } else {
            auto r_readdir_r = reinterpret_cast<int (*)(DIR*, struct dirent*, struct dirent**)>(dlsym(RTLD_NEXT,"readdir_r"));
            return r_readdir_r(dirp,entry,result);
            TRACE_SYSCALLN("(%p) -> linux fs", dirp);
            return real::readdir_r(dirp,entry,result);
        }
    }
    __asm__(".symver readdir_r,readdir_r@GLIBC_2.2.5");
    __asm__(".symver _iosys_readdir_r,readdir_r@GLIBC_2.2.5");

    void rewinddir(DIR *dirp)
    void _iosys_rewinddir(DIR *dirp)
    {
        TRACE_SYSCALL();
        if (!dirp) {
            TRACE_SYSCALLN("(%p) invalid argument", dirp);
            errno = EBADF;
            return;
        }
        if(is_image_DIR(dirp))
        if(vfs::is_image_DIR(dirp))
        {
            TRACE_SYSCALLN("(%p) -> VFS", dirp);
            auto vfs = purefs::subsystem::vfs_core();
            if(!vfs) {
                return;


@@ 219,21 249,22 @@ extern "C" {
        }
        else
        {
            auto r_rewinddir = reinterpret_cast<void (*)(DIR*)>(dlsym(RTLD_NEXT,"rewinddir"));
            r_rewinddir(dirp);
            TRACE_SYSCALLN("(%p) -> linux fs", dirp);
            real::rewinddir(dirp);
        }
    }
    __asm__(".symver rewinddir,rewinddir@GLIBC_2.2.5");
    __asm__(".symver _iosys_rewinddir,rewinddir@GLIBC_2.2.5");

    void seekdir( DIR *dirp, long int loc)
    void _iosys_seekdir( DIR *dirp, long int loc)
    {
        TRACE_SYSCALL();
        if (!dirp) {
            TRACE_SYSCALLN("(%p,%ld) invalid argument", dirp, loc);
            errno = EBADF;
            return;
        }
        if( is_image_DIR(dirp) )
        if( vfs::is_image_DIR(dirp) )
        {
            TRACE_SYSCALLN("(%p,%ld) -> VFS", dirp, loc);
            if (loc < 0) {
                return;
            }


@@ 253,30 284,31 @@ extern "C" {
        }
        else
        {
            auto r_seekdir = reinterpret_cast<void (*)(DIR*,long int)>(dlsym(RTLD_NEXT,"seekdir"));
            r_seekdir(dirp,loc);
            TRACE_SYSCALLN("(%p,%ld) -> linux fs", dirp, loc);
            real::seekdir(dirp,loc);
        }
    }
    __asm__(".symver seekdir,seekdir@GLIBC_2.2.5");
    __asm__(".symver _iosys_seekdir,seekdir@GLIBC_2.2.5");

    long int telldir(DIR *dirp)
    long int _iosys_telldir(DIR *dirp)
    {
        TRACE_SYSCALL();
        if (!dirp) {
            TRACE_SYSCALLN("(%p) invalid argument", dirp);
            errno = EBADF;
            return -1;
        }
        if( is_image_DIR(dirp) )
        if( vfs::is_image_DIR(dirp) )
        {
            TRACE_SYSCALLN("(%p) -> VFS", dirp);
            return dirp->position;
        }
        else
        {
            auto r_telldir = reinterpret_cast<long int(*)(DIR*)>(dlsym(RTLD_NEXT,"telldir"));
            return r_telldir(dirp);
            TRACE_SYSCALLN("(%p) -> linux fs", dirp);
            return real::telldir(dirp);
        }
    }
    __asm__(".symver telldir,telldir@GLIBC_2.2.5");
    __asm__(".symver _iosys_telldir,telldir@GLIBC_2.2.5");

}


A board/linux/libiosyscalls/src/syscalls_real.hpp => board/linux/libiosyscalls/src/syscalls_real.hpp +10 -0
@@ 0,0 1,10 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

/* Helpers for intercepting library calls */
#define __REAL_DECL(fun) decltype(::fun) *fun
#define __REAL_DLSYM(fun) real::fun = reinterpret_cast<decltype(real::fun)>(dlsym(RTLD_NEXT, #fun))

#include <dlfcn.h>      // for dlsym()

M board/linux/libiosyscalls/src/syscalls_scan_family.cpp => board/linux/libiosyscalls/src/syscalls_scan_family.cpp +40 -27
@@ 1,25 1,29 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <stdarg.h>
#include "debug.hpp"
#include <iosyscalls.hpp>
#include <dlfcn.h>

#include "syscalls_real.hpp"

#include "debug.hpp"

namespace
{
    int (*real_fprintf)(FILE *__restrict __stream, const char *__restrict __format, ...);
    int (*real_vfscanf) (FILE *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __wur;
    int (*real_ungetc) (int __c, FILE *__stream);
    namespace real {
        __REAL_DECL(ungetc);
        __REAL_DECL(vfscanf);
    }

    void __attribute__((constructor)) _syscalls_scan_family()
    {
        real_fprintf = reinterpret_cast<decltype(real_fprintf)>(dlsym(RTLD_NEXT, "fprintf"));
        real_ungetc = reinterpret_cast<decltype(real_ungetc)>(dlsym(RTLD_NEXT, "ungetc"));
        real_vfscanf = reinterpret_cast<decltype(real_vfscanf)>(dlsym(RTLD_NEXT, "vfscanf"));
        if(!real_fprintf || !real_ungetc || !real_vfscanf) {
        __REAL_DLSYM(ungetc);
        __REAL_DLSYM(vfscanf);

        if(!(real::ungetc && real::vfscanf)) {
            abort();
        }
    }


@@ 27,8 31,10 @@ namespace

namespace
{
    namespace vfs = vfsn::linux::internal;
    using FILEX = vfs::FILEX;
    using fs = purefs::fs::filesystem;

    using namespace vfsn::linux::internal;
    int ic(FILEX *fp)
    {
        char ch;


@@ 40,7 46,7 @@ namespace
        }
        else
        {
            auto ret = invoke_fs(&purefs::fs::filesystem::read,fp->fd,&ch,1);
            auto ret = vfs::invoke_fs(&fs::read,fp->fd,&ch,1);
            fp->error = errno;
            return ret==1?0:ret;
        }


@@ 95,32 101,39 @@ namespace
}
extern "C"
{
    namespace vfs = vfsn::linux::internal;
    using FILEX = vfs::FILEX;

    using namespace vfsn::linux::internal;
    int ungetc (int __c, FILE *__stream)
    {
        TRACE_SYSCALL();
        if(!is_filex(__stream))
        {
            return real_ungetc(__c,__stream);
        }
        else
        if(vfs::is_filex(__stream))
        {
            TRACE_SYSCALLN("(%p) -> VFS", __stream);
            auto fx = reinterpret_cast<FILEX*>(__stream);
            fx->ungetchar = __c;
            return 0;
        }
        else
        {
            TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            return real::ungetc(__c,__stream);
        }
    }
    __asm__(".symver ungetc,vfscanf@GLIBC_2.2.5");
    /* WARNING:
     *   this implementation of ungetc() is work-in-progress
     *   and should remain local until FILEX buffering is implemented!
     */
//    __asm__(".symver _iosys_ungetc,ungetc@GLIBC_2.2.5");

    int vfscanf (FILE *__restrict fp, const char *__restrict fmt,
    int _iosys_vfscanf (FILE *__restrict fp, const char *__restrict fmt,
                    __gnuc_va_list ap)
    {
        if(!is_filex(fp))
        if(!vfs::is_filex(fp))
        {
            return real_vfscanf(fp,fmt,ap);
            TRACE_SYSCALLN("(%p) -> linux fs", fp);
            return real::vfscanf(fp,fmt,ap);
        }
        TRACE_SYSCALL();
        TRACE_SYSCALLN("(%p) -> VFS", fp);
        int ret = 0;
        int t, c;
        int wid = 1 << 20;


@@ 168,12 181,12 @@ extern "C"
        }
        return ret;
    }
    __asm__(".symver vfscanf,vfscanf@GLIBC_2.2.5");
    __asm__(".symver _iosys_vfscanf,vfscanf@GLIBC_2.2.5");

    int fscanf (FILE *__restrict fp,
    int _iosys_fscanf (FILE *__restrict fp,
                   const char *__restrict fmt, ...)
    {
        TRACE_SYSCALL();
        TRACE_SYSCALLN("(%p) -> vfscanf()", fp);
        va_list ap;
        int ret;
        va_start(ap, fmt);


@@ 181,5 194,5 @@ extern "C"
        va_end(ap);
        return ret;
    }
    __asm__(".symver fscanf,fscanf@GLIBC_2.2.5");
    __asm__(".symver _iosys_fscanf,fscanf@GLIBC_2.2.5");
}

M board/linux/libiosyscalls/src/syscalls_stdio.cpp => board/linux/libiosyscalls/src/syscalls_stdio.cpp +264 -175
@@ 1,83 1,91 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <dlfcn.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <mutex>
#include <unordered_map>
#include <iosyscalls.hpp>

#include <stdio.h>
#include <fcntl.h>
#include <stdarg.h>
#include <limits.h>
#include <stdarg.h>     // for va_*
#include <limits.h>     // for PATH_MAX
#include <string.h>     // for strlen

#include "syscalls_real.hpp"

#include "debug.hpp"

namespace
{
    int (*real_fprintf)(FILE *__restrict __stream, const char *__restrict __format, ...);
    size_t (*real_fwrite)(const void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __s);
    int (*real_fputs)(const char *__restrict __s, FILE *__restrict __stream);
    int (*real_fputc)(int __c, FILE *__stream);
    int (*real_putc) (int __c, FILE *__stream);
    int (*real_fileno)(FILE *__stream) __THROW __wur;
    int (*real_vfprintf)(FILE *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg);
    FILE *(*real_fopen) (const char *__restrict __filename, const char *__restrict __modes) __wur;
    int (*real_fclose) (FILE *__stream);
    int (*real_getc) (FILE *__stream);
    int (*real_feof) (FILE *__stream) __THROW __wur;
    char *(*real_fgets) (char *__restrict __s, int __n, FILE *__restrict __stream) __wur;
    int (*real_ferror) (FILE *__stream) __THROW __wur;
    int (*real_fflush) (FILE *__stream);
    int (*real_fgetc) (FILE *__stream);
    int (*real_fgetpos) (FILE *__restrict __stream, fpos_t *__restrict __pos);
    int (*real_fgetpos64) (FILE *__restrict __stream, fpos64_t *__restrict __pos);
    size_t (*real_fread) (void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __stream) __wur;
    FILE *(*real_freopen) (const char *__restrict __filename, const char *__restrict __modes, FILE *__restrict __stream) __wur;
    int (*real_fseek) (FILE *__stream, long int __off, int __whence);
    int (*real_fsetpos) (FILE *__stream, const fpos_t *__pos);
    int (*real_fsetpos64) (FILE *__stream, const fpos64_t *__pos);
    long int (*real_ftell) (FILE *__stream) __wur;
    void (*real_rewind) (FILE *__stream);

    namespace real {
        __REAL_DECL(fprintf);
        __REAL_DECL(fwrite);
        __REAL_DECL(fread);
        __REAL_DECL(fopen);
        __REAL_DECL(fopen64);
        __REAL_DECL(fclose);
        __REAL_DECL(fputc);
        __REAL_DECL(fputs);
        __REAL_DECL(putc);
        __REAL_DECL(fgetc);
        __REAL_DECL(fgets);
        __REAL_DECL(getc);
        __REAL_DECL(freopen);
        __REAL_DECL(fdopen);
        __REAL_DECL(fseek);
        __REAL_DECL(ftell);
        __REAL_DECL(fgetpos);
        __REAL_DECL(fgetpos64);
        __REAL_DECL(fsetpos);
        __REAL_DECL(fsetpos64);
        __REAL_DECL(feof);
        __REAL_DECL(rewind);
        __REAL_DECL(fileno);
        __REAL_DECL(ferror);
        __REAL_DECL(fflush);
        __REAL_DECL(remove);
        __REAL_DECL(rename);
    } // namespace real

    void __attribute__((constructor)) _lib_stdio_initialize()
    {
        real_fprintf = reinterpret_cast<decltype(real_fprintf)>(dlsym(RTLD_NEXT, "fprintf"));
        real_fwrite = reinterpret_cast<decltype(real_fwrite)>(dlsym(RTLD_NEXT, "fwrite"));
        real_fputs = reinterpret_cast<decltype(real_fputs)>(dlsym(RTLD_NEXT, "fputs"));
        real_fputc = reinterpret_cast<decltype(real_fputc)>(dlsym(RTLD_NEXT, "fputc"));
        real_putc = reinterpret_cast<decltype(real_putc)>(dlsym(RTLD_NEXT, "putc"));
        real_fileno = reinterpret_cast<decltype(real_fileno)>(dlsym(RTLD_NEXT, "fileno"));
        real_vfprintf = reinterpret_cast<decltype(real_vfprintf)>(dlsym(RTLD_NEXT, "vfprintf"));
        real_fopen = reinterpret_cast<decltype(real_fopen)>(dlsym(RTLD_NEXT, "fopen"));
        real_fclose = reinterpret_cast<decltype(real_fclose)>(dlsym(RTLD_NEXT, "fclose"));
        real_getc = reinterpret_cast<decltype(real_getc)>(dlsym(RTLD_NEXT, "getc"));
        real_feof = reinterpret_cast<decltype(real_feof)>(dlsym(RTLD_NEXT, "feof"));
        real_fgets = reinterpret_cast<decltype(real_fgets)>(dlsym(RTLD_NEXT, "fgets"));
        real_ferror = reinterpret_cast<decltype(real_ferror)>(dlsym(RTLD_NEXT, "ferror"));
        real_fgetc = reinterpret_cast<decltype(real_fgetc)>(dlsym(RTLD_NEXT, "fgetc"));
        real_fgetpos = reinterpret_cast<decltype(real_fgetpos)>(dlsym(RTLD_NEXT, "fgetpos"));
        real_fgetpos64 = reinterpret_cast<decltype(real_fgetpos64)>(dlsym(RTLD_NEXT, "fgetpos64"));
        real_fread = reinterpret_cast<decltype(real_fread)>(dlsym(RTLD_NEXT, "fread"));
        real_freopen = reinterpret_cast<decltype(real_freopen)>(dlsym(RTLD_NEXT, "freopen"));
        real_fseek = reinterpret_cast<decltype(real_fseek)>(dlsym(RTLD_NEXT, "fseek"));
        real_fsetpos = reinterpret_cast<decltype(real_fsetpos)>(dlsym(RTLD_NEXT, "fsetpos"));
        real_fsetpos64 = reinterpret_cast<decltype(real_fsetpos64)>(dlsym(RTLD_NEXT, "fsetpos64"));
        real_ftell = reinterpret_cast<decltype(real_ftell)>(dlsym(RTLD_NEXT, "ftell"));
        real_rewind = reinterpret_cast<decltype(real_rewind)>(dlsym(RTLD_NEXT, "rewind"));
        real_fflush = reinterpret_cast<decltype(real_fflush)>(dlsym(RTLD_NEXT, "fflush"));
        if(!real_fprintf || !real_fwrite || !real_fputs || !real_fputc
            || !real_fileno || !real_vfprintf || !real_putc || !real_fopen
            || !real_fclose || !real_getc || !real_feof || !real_fgets
            || !real_ferror || !real_fflush || ! real_fgetc || !real_fgetpos
            || !real_fgetpos64 || !real_fread || !real_freopen || !real_fseek
            || !real_fsetpos || !real_fsetpos64 || !real_ftell || !real_rewind )
        __REAL_DLSYM(fprintf);
        __REAL_DLSYM(fwrite);
        __REAL_DLSYM(fread);
        __REAL_DLSYM(fopen);
        __REAL_DLSYM(fopen64);
        __REAL_DLSYM(fclose);
        __REAL_DLSYM(fputc);
        __REAL_DLSYM(fputs);
        __REAL_DLSYM(putc);
        __REAL_DLSYM(fgetc);
        __REAL_DLSYM(fgets);
        __REAL_DLSYM(getc);
        __REAL_DLSYM(freopen);
        __REAL_DLSYM(fdopen);
        __REAL_DLSYM(fseek);
        __REAL_DLSYM(ftell);
        __REAL_DLSYM(fgetpos);
        __REAL_DLSYM(fgetpos64);
        __REAL_DLSYM(fsetpos);
        __REAL_DLSYM(fsetpos64);
        __REAL_DLSYM(feof);
        __REAL_DLSYM(rewind);
        __REAL_DLSYM(fileno);
        __REAL_DLSYM(ferror);
        __REAL_DLSYM(fflush);
        __REAL_DLSYM(remove);
        __REAL_DLSYM(rename);

        if (!(real::fprintf && real::fwrite && real::fread && real::fopen && real::fopen64
            && real::fclose && real::fputc && real::fputs && real::putc && real::fgetc
            && real::fgets && real::getc && real::freopen && real::fdopen
            && real::fseek && real::ftell && real::fgetpos && real::fgetpos64
            && real::fsetpos && real::fsetpos64 && real::feof && real::rewind
            && real::fileno && real::ferror && real::fflush && real::remove && real::rename))
        {
            abort();
        }
    }

    auto fopen_to_open_flags(std::string_view flags)
    {
        int ret = 0;


@@ 110,25 118,27 @@ namespace

extern "C"
{
    using namespace vfsn::linux::internal;
    namespace vfs = vfsn::linux::internal;
    using FILEX = vfs::FILEX;
    using fs = purefs::fs::filesystem;

    FILE *_iosys_fopen(const char *pathname, const char *mode)
    {
        FILE* ret {};
        if(redirect_to_image(pathname))
        if(vfs::redirect_to_image(pathname))
        {
            TRACE_SYSCALLN("(%s,%s) -> VFS", pathname, mode);
            const auto fd = invoke_fs(&purefs::fs::filesystem::open, pathname, fopen_to_open_flags(mode),0644);
            const auto fd = vfs::invoke_fs(&fs::open, pathname, fopen_to_open_flags(mode),0644);
            if(fd >= 0) {
                ret = reinterpret_cast<FILE*>(allocate_filex(fd));
                ret = reinterpret_cast<FILE*>(vfs::allocate_filex(fd));
            }
        }
        else
        {
            TRACE_SYSCALLN("(%s,%s) -> linux fs", pathname, mode);
            char tmp[PATH_MAX];
            const auto path = npath_translate(pathname,tmp);
            ret = real_fopen(path,mode);
            const auto path = vfs::npath_translate(pathname,tmp);
            TRACE_SYSCALLN("(%s,%s) -> (%s) linux fs", pathname, mode, path);
            ret = real::fopen(path,mode);
        }
        TRACE_SYSCALLN("(%s,%s)=%p", pathname, mode, ret);
        return ret;


@@ 137,21 147,34 @@ extern "C"

    FILE *_iosys_fopen64(const char *pathname, const char *mode)
    {
        TRACE_SYSCALLN("(%s,%s)", pathname, mode);
        return fopen(pathname,mode);
        FILE* ret {};
        if(vfs::redirect_to_image(pathname))
        {
            TRACE_SYSCALLN("(%s,%s) -> fopen()", pathname, mode);
            return fopen(pathname, mode);
        }
        else
        {
            char tmp[PATH_MAX];
            const auto path = vfs::npath_translate(pathname,tmp);
            TRACE_SYSCALLN("(%s,%s) -> (%s) linux fs", pathname, mode, path);
            ret = real::fopen64(path,mode);
        }
        TRACE_SYSCALLN("(%s,%s)=%p", pathname, mode, ret);
        return ret;
    }
    __asm__(".symver _iosys_fopen64,fopen64@GLIBC_2.2.5");

    int _iosys_fclose(FILE *__stream)
    {
        if(is_filex(__stream))
        if(vfs::is_filex(__stream))
        {
            TRACE_SYSCALLN("(%p) -> VFS", __stream);
            auto fx = reinterpret_cast<FILEX*>(__stream);
            auto ret = invoke_fs(&purefs::fs::filesystem::close, fx->fd);
            auto ret = vfs::invoke_fs(&fs::close, fx->fd);
            if(!ret)
            {
                remove_filex(fx);
                vfs::remove_filex(fx);
            }
            else
            {


@@ 162,38 185,44 @@ extern "C"
        else
        {
            TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            return real_fclose(__stream);
            return real::fclose(__stream);
        }
    }
    __asm__(".symver _iosys_fclose,fclose@GLIBC_2.2.5");

    FILE *_iosys_fdopen(int __fd, const char *__modes) __THROW
    {
        TRACE_SYSCALL();
        std::cerr << "Unimplemented syscall " <<  __PRETTY_FUNCTION__ << std::endl;
        errno = ENOTSUP;
        return nullptr;
        if (vfs::is_image_fd(__fd)) {
            TRACE_SYSCALLN("(%d) -> VFS", __fd);
            std::cerr << "Unimplemented syscall " <<  __PRETTY_FUNCTION__ << std::endl;
            errno = ENOTSUP;
            return nullptr;
        } else {
            TRACE_SYSCALLN("(%d) -> linux fs", __fd);
            return real::fdopen(__fd, __modes);
        }
    }
    __asm__(".symver _iosys_fdopen,fdopen@GLIBC_2.2.5");

    int _iosys_feof(FILE *__stream) __THROW
    {
        int ret {};
        if(is_filex(__stream))
        if(vfs::is_filex(__stream))
        {
            TRACE_SYSCALLN("(%p) -> VFS", __stream);
            auto fx = reinterpret_cast<FILEX*>(__stream);
            do {
                const auto curr = invoke_fs(&purefs::fs::filesystem::seek,fx->fd,0,SEEK_CUR);
                const auto curr = vfs::invoke_fs(&fs::seek,fx->fd,0,SEEK_CUR);
                if(curr<0) {
                    ret = curr;
                    break;
                }
                const auto ends = invoke_fs(&purefs::fs::filesystem::seek,fx->fd,0,SEEK_END);
                const auto ends = vfs::invoke_fs(&fs::seek,fx->fd,0,SEEK_END);
                if(ends<0) {
                    ret = ends;
                    break;
                }
                const auto restored = invoke_fs(&purefs::fs::filesystem::seek,fx->fd,curr,SEEK_SET);
                const auto restored = vfs::invoke_fs(&fs::seek,fx->fd,curr,SEEK_SET);
                if(restored<0) {
                    ret = restored;
                    break;


@@ 203,7 232,8 @@ extern "C"
        }
        else
        {
            ret = real_feof(__stream);
            TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            ret = real::feof(__stream);
        }
        TRACE_SYSCALLN("(%p)=%i",__stream,ret);
        return ret;


@@ 212,15 242,16 @@ extern "C"

    int _iosys_ferror(FILE * stream) __THROW
    {
        TRACE_SYSCALL();
        if(is_filex(stream))
        if(vfs::is_filex(stream))
        {
            TRACE_SYSCALLN("(%p) -> VFS", stream);
            auto fx = reinterpret_cast<FILEX*>(stream);
            return fx->error;
        }
        else
        {
            return real_ferror(stream);
            TRACE_SYSCALLN("(%p) -> linux fs", stream);
            return real::ferror(stream);
        }
    }
    __asm__(".symver _iosys_ferror,ferror@GLIBC_2.2.5");


@@ 228,46 259,51 @@ extern "C"
    int _iosys_fflush(FILE *__stream)
    {
        int ret {};
        if(is_filex(__stream))
        if(vfs::is_filex(__stream))
        {
            TRACE_SYSCALLN("(%p) -> VFS", __stream);
            auto fx = reinterpret_cast<FILEX*>(__stream);
            ret = invoke_fs(&purefs::fs::filesystem::fsync, fx->fd);
            ret = vfs::invoke_fs(&fs::fsync, fx->fd);
            fx->error = errno;
        }
        else
        {
            ret = real_fflush(__stream);
            if (__stream != stdout && __stream != stderr)
                TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            ret = real::fflush(__stream);
        }
        TRACE_SYSCALLN("(%p)=%i",__stream,ret);
        if (__stream != stdout && __stream != stderr)
            TRACE_SYSCALLN("(%p)=%i",__stream,ret);
        return ret;
    }
    __asm__(".symver _iosys_fflush,fflush@GLIBC_2.2.5");

    int _iosys_fgetc(FILE *__stream)
    {
        TRACE_SYSCALL();
        if(is_filex(__stream))
        if(vfs::is_filex(__stream))
        {
            TRACE_SYSCALLN("(%p) -> VFS", __stream);
            auto fx = reinterpret_cast<FILEX*>(__stream);
            char ch;
            auto ret = invoke_fs(&purefs::fs::filesystem::read,fx->fd,&ch,1);
            auto ret = vfs::invoke_fs(&fs::read,fx->fd,&ch,1);
            fx->error = errno;
            return ret;
        }
        else
        {
            return real_fgetc(__stream);
            TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            return real::fgetc(__stream);
        }
    }
    __asm__(".symver _iosys_fgetc,fgetc@GLIBC_2.2.5");

    int _iosys_fgetpos(FILE *__restrict __stream, fpos_t *__restrict __pos)
    {
        TRACE_SYSCALL();
        if(is_filex(__stream))
        if(vfs::is_filex(__stream))
        {
            TRACE_SYSCALLN("(%p) -> VFS", __stream);
            auto fx = reinterpret_cast<FILEX*>(__stream);
            auto ret = invoke_fs(&purefs::fs::filesystem::seek,fx->fd,0,SEEK_CUR);
            auto ret = vfs::invoke_fs(&fs::seek,fx->fd,0,SEEK_CUR);
            fx->error = errno;
            if(__pos) {
                __pos->__pos =  ret;


@@ 276,18 312,19 @@ extern "C"
        }
        else
        {
            return real_fgetpos(__stream, __pos);
            TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            return real::fgetpos(__stream, __pos);
        }
    }
    __asm__(".symver _iosys_fgetpos,fgetpos@GLIBC_2.2.5");

    int _iosys_fgetpos64(FILE *__restrict __stream, fpos64_t *__restrict __pos)
    {
        TRACE_SYSCALL();
        if(is_filex(__stream))
        if(vfs::is_filex(__stream))
        {
            TRACE_SYSCALLN("(%p) -> VFS", __stream);
            auto fx = reinterpret_cast<FILEX*>(__stream);
            auto ret = invoke_fs(&purefs::fs::filesystem::seek,fx->fd,0,SEEK_CUR);
            auto ret = vfs::invoke_fs(&fs::seek,fx->fd,0,SEEK_CUR);
            fx->error = errno;
            if(__pos) {
                __pos->__pos =  ret;


@@ 296,21 333,22 @@ extern "C"
        }
        else
        {
            return real_fgetpos64(__stream, __pos);
            TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            return real::fgetpos64(__stream, __pos);
        }
    }
    __asm__(".symver _iosys_fgetpos64,fgetpos64@GLIBC_2.2.5");

    char *_iosys_fgets(char *__restrict __s, int __n, FILE *__restrict __stream)
    {
        TRACE_SYSCALL();
        if(is_filex(__s))
        if(vfs::is_filex(__stream))
        {
            TRACE_SYSCALLN("(%p) -> VFS", __stream);
            auto fx = reinterpret_cast<FILEX*>(__stream);
            char ch;
            size_t pos = 0;
            do {
                auto ret = invoke_fs(&purefs::fs::filesystem::read,fx->fd,&ch,1);
                auto ret = vfs::invoke_fs(&fs::read,fx->fd,&ch,1);
                if(ret == 0)
                {
                    fx->error = 0;


@@ 328,7 366,8 @@ extern "C"
        }
        else
        {
            return real_fgets(__s,__n,__stream);
            TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            return real::fgets(__s,__n,__stream);
        }
    }
    __asm__(".symver _iosys_fgets,fgets@GLIBC_2.2.5");


@@ 336,14 375,15 @@ extern "C"
    int _iosys_fileno(FILE *__stream) __THROW
    {
        int ret {};
        if(is_filex(__stream))
        if(vfs::is_filex(__stream))
        {
            auto fx = reinterpret_cast<FILEX*>(__stream);
            ret =  native_fd_to_image_fd(fx->fd);
            TRACE_SYSCALLN("(%p) -> VFS", __stream);
            ret =  vfs::get_native_fd(reinterpret_cast<FILEX*>(__stream));
        }
        else
        {
            ret = real_fileno(__stream);
            TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            ret = real::fileno(__stream);
        }
        TRACE_SYSCALLN("(%p)=%i",__stream,ret);
        return ret;


@@ 358,15 398,17 @@ extern "C"
        char *pcBuffer;
        va_list xArgs;

        if(!is_filex(__stream))
        if(!vfs::is_filex(__stream))
        {
            TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            va_list arglist;
            va_start( arglist, __format );
            auto ret = real_vfprintf( __stream, __format, arglist );
            auto ret = vfprintf( __stream, __format, arglist );
            va_end( arglist );
            return ret;
        }
        TRACE_SYSCALL();

        TRACE_SYSCALLN("(%p) -> VFS", __stream);
        pcBuffer = new char[buf_len];
        auto fx = reinterpret_cast<FILEX*>(__stream);
        if (pcBuffer == NULL) {


@@ 381,7 423,7 @@ extern "C"

            /* ff_fwrite() will set ff_errno. */
            if (iCount > 0) {
                xResult = invoke_fs(&purefs::fs::filesystem::write, fx->fd, pcBuffer, iCount);
                xResult = vfs::invoke_fs(&fs::write, fx->fd, pcBuffer, iCount);
                if (xResult < (size_t)iCount) {
                    iCount = -1;
                }


@@ 395,38 437,44 @@ extern "C"

    int _iosys_fputc(int __c, FILE *__stream)
    {
        if(!is_filex(__stream))
        if(vfs::is_filex(__stream))
        {
            return real_fputc( __c, __stream );
        }
        else
        {
            TRACE_SYSCALL();
            TRACE_SYSCALLN("(%p,%d) -> VFS", __stream, __c);
            auto fx = reinterpret_cast<FILEX*>(__stream);
            char ch = __c;
            int ret = invoke_fs(&purefs::fs::filesystem::write,fx->fd, &ch, sizeof ch);
            int ret = vfs::invoke_fs(&fs::write,fx->fd, &ch, sizeof ch);
            fx->error = errno;
            return ret==1?0:ret;
        }
        else
        {
            if (__stream != stdout && __stream != stderr)
                TRACE_SYSCALLN("(%p,%d) -> linux fs", __stream, __c);
            return real::fputc( __c, __stream );
        }
    }
    __asm__(".symver _iosys_fputc,fputc@GLIBC_2.2.5");

    int _iosys_fputs(const char *__restrict __s, FILE *__restrict __stream)
    {
        int ret {};
        if(is_filex(__stream))
        if(vfs::is_filex(__stream))
        {
            TRACE_SYSCALLN("(%p,%p) -> VFS", __s, __stream);
            auto fx = reinterpret_cast<FILEX*>(__stream);
            const auto len = strlen(__s);
            ret = invoke_fs(&purefs::fs::filesystem::write,fx->fd, __s, len);
            ret = vfs::invoke_fs(&fs::write,fx->fd, __s, len);
            fx->error = errno;
            ret = ret==int(len)?0:-1;
        }
        else
        {
            ret = real_fputs( __s, __stream );
            if (__stream != stdout && __stream != stderr)
                TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            ret = real::fputs( __s, __stream );
        }
        TRACE_SYSCALLN("(%s, %p)=%i",__s, __stream, ret);
        if (__stream != stdout && __stream != stderr)
            TRACE_SYSCALLN("(%s, %p)=%i",__s, __stream, ret);
        return ret;
    }
    __asm__(".symver _iosys_fputs,fputs@GLIBC_2.2.5");


@@ 436,12 484,13 @@ extern "C"
        size_t ret {};
        if(__size!=0 && __n!=0)
        {
            if(is_filex(__stream))
            if(vfs::is_filex(__stream))
            {
                TRACE_SYSCALLN("(%p) -> VFS", __stream);
                auto fx = reinterpret_cast<FILEX*>(__stream);
                char* p = reinterpret_cast<char*>(__ptr);
                do {
                    auto res = invoke_fs(&purefs::fs::filesystem::read, fx->fd, p, __size);
                    auto res = vfs::invoke_fs(&fs::read, fx->fd, p, __size);
                    const auto eof = res>0 && size_t(res)<__size;
                    fx->error = errno;
                    if(res<0 || eof) break;


@@ 452,7 501,8 @@ extern "C"
            }
            else
            {
                ret = real_fread(__ptr,__size,__n,__stream);
                TRACE_SYSCALLN("(%p) -> linux fs", __stream);
                ret = real::fread(__ptr,__size,__n,__stream);
            }
        }
        TRACE_SYSCALLN("(%p, %lu, %lu, %p)=%i",__ptr,__size,__n,__stream, ret);


@@ 465,32 515,36 @@ extern "C"
                      const char *__restrict __modes,
                      FILE *__restrict __stream)
    {
        TRACE_SYSCALL();
        if(!is_filex(__filename))
        if(vfs::is_filex(__filename))
        {
            return real_freopen(__filename,__modes,__stream);
        }
        else {
            TRACE_SYSCALLN("(%s,%s) -> VFS", __filename, __modes);
            if( fclose(__stream) < 0) {
                return nullptr;
            }
            return fopen(__filename, __modes );
        }
        else
        {
            TRACE_SYSCALLN("(%s,%s) -> linux fs", __filename, __modes);
            return real::freopen(__filename,__modes,__stream);
        }
    }
    __asm__(".symver _iosys_freopen,freopen@GLIBC_2.2.5");

    int _iosys_fseek (FILE *__stream, long int __off, int __whence)
    {
        int ret {};
        if(is_filex(__stream))
        if(vfs::is_filex(__stream))
        {
            TRACE_SYSCALLN("(%p) -> VFS", __stream);
            auto fx = reinterpret_cast<FILEX*>(__stream);
            ret = invoke_fs(&purefs::fs::filesystem::seek, fx->fd, __off, __whence);
            ret = ret>0?0:ret;
            ret = vfs::invoke_fs(&fs::seek, fx->fd, __off, __whence);
            ret = (ret>0) ? 0 : ret;
        }
        else
        {
            ret = real_fseek(__stream,__off,__whence);
            TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            ret = real::fseek(__stream,__off,__whence);
        }
        TRACE_SYSCALLN("(%p, %li, %i)=%i",__stream,__off,__whence,ret);
        return ret;


@@ 500,30 554,33 @@ extern "C"
    int _iosys_fsetpos (FILE *__stream, const fpos_t *__pos)
    {
        TRACE_SYSCALL();
        if(!is_filex(__stream))
        if(vfs::is_filex(__stream))
        {
            return real_fsetpos(__stream,__pos);
            TRACE_SYSCALLN("(%p) -> VFS", __stream);
            auto fx = reinterpret_cast<FILEX*>(__stream);
            auto ret = vfs::invoke_fs(&fs::seek, fx->fd, __pos->__pos, SEEK_SET);
            return (ret>0) ? 0 : ret;
        }
        else
        {
            auto fx = reinterpret_cast<FILEX*>(__stream);
            auto ret = invoke_fs(&purefs::fs::filesystem::seek, fx->fd, __pos->__pos, SEEK_SET);
            return ret>0?0:ret;
            TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            return real::fsetpos(__stream,__pos);
        }
    }
    __asm__(".symver _iosys_fsetpos,fsetpos@GLIBC_2.2.5");

    int _iosys_fsetpos64 (FILE *__stream, const fpos64_t *__pos)
    {
        TRACE_SYSCALL();
        if(!is_filex(__stream)) {
            return real_fsetpos64(__stream,__pos);
        if(vfs::is_filex(__stream)) {
            TRACE_SYSCALLN("(%p) -> VFS", __stream);
            auto fx = reinterpret_cast<FILEX*>(__stream);
            auto ret = vfs::invoke_fs(&fs::seek, fx->fd, __pos->__pos, SEEK_SET);
            return (ret>0) ? 0 : ret;
        }
        else
        {
            auto fx = reinterpret_cast<FILEX*>(__stream);
            auto ret = invoke_fs(&purefs::fs::filesystem::seek, fx->fd, __pos->__pos, SEEK_SET);
            return ret>0?0:ret;
            TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            return real::fsetpos64(__stream,__pos);
        }
    }
    __asm__(".symver _iosys_fsetpos64,fsetpos64@GLIBC_2.2.5");


@@ 532,14 589,16 @@ extern "C"
    long int _iosys_ftell (FILE *__stream)
    {
        long int ret {};
        if(is_filex(__stream))
        if(vfs::is_filex(__stream))
        {
            TRACE_SYSCALLN("(%p) -> VFS", __stream);
            auto fx = reinterpret_cast<FILEX*>(__stream);
            ret = invoke_fs(&purefs::fs::filesystem::seek,fx->fd,0,SEEK_CUR);
            ret = vfs::invoke_fs(&fs::seek,fx->fd,0,SEEK_CUR);
        }
        else
        {
            ret = real_ftell(__stream);
            TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            ret = real::ftell(__stream);
        }
        TRACE_SYSCALLN("(%p)=%i",__stream, ret);
        return ret;


@@ 552,13 611,14 @@ extern "C"
        int ret {};
        if(__size != 0 && __n != 0)
        {
            if(is_filex(__s))
            if(vfs::is_filex(__s))
            {
                TRACE_SYSCALLN("(%p) -> VFS", __s);
                auto fx = reinterpret_cast<FILEX*>(__s);
                const char* p = reinterpret_cast<const char*>(__ptr);
                size_t items {};
                do {
                    auto ret = invoke_fs(&purefs::fs::filesystem::write, fx->fd, p, __size);
                    auto ret = vfs::invoke_fs(&fs::write, fx->fd, p, __size);
                    const auto eof = ret>=0 && size_t(ret)!=__size;
                    fx->error = errno;
                    if(ret<0 || eof) return ret;


@@ 566,11 626,13 @@ extern "C"
                    --__n;
                    ++items;
                } while(__n > 0 );
                ret = ret<0?(-1):(items);
                ret = (ret<0) ? (-1) : (items);
            }
            else
            {
                ret = real_fwrite( __ptr, __size, __n, __s );
                if (__s != stdout && __s != stderr)
                    TRACE_SYSCALLN("(%p) -> linux fs", __s);
                ret = real::fwrite( __ptr, __size, __n, __s );
            }
        }
        if (__s != stdout && __s != stderr)


@@ 582,17 644,19 @@ extern "C"
    int _iosys_getc(FILE *__stream)
    {
        int ret {};
        if(is_filex(__stream))
        if(vfs::is_filex(__stream))
        {
            TRACE_SYSCALLN("(%p) -> VFS", __stream);
            auto fx = reinterpret_cast<FILEX*>(__stream);
            char ch;
            ret = invoke_fs(&purefs::fs::filesystem::read,fx->fd,&ch,1);
            ret = vfs::invoke_fs(&fs::read,fx->fd,&ch,1);
            fx->error = errno;
            ret = (ret==1)?(ch):(ret);
        }
        else
        {
            ret = real_getc(__stream);
            TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            ret = real::getc(__stream);
        }
        TRACE_SYSCALLN("(%p)=%i",__stream, ret);
        return ret;


@@ 602,19 666,23 @@ extern "C"
    int _iosys_putc(int __c, FILE *__stream)
    {
        int ret {};
        if(is_filex(__stream))
        if(vfs::is_filex(__stream))
        {
            TRACE_SYSCALLN("(%p) -> VFS", __stream);
            auto fx = reinterpret_cast<FILEX*>(__stream);
            char ch = __c;
            ret = invoke_fs(&purefs::fs::filesystem::write,fx->fd, &ch, sizeof ch);
            ret = vfs::invoke_fs(&fs::write,fx->fd, &ch, sizeof ch);
            fx->error = errno;
            ret =  (ret==1)?(__c):(EOF);
        }
        else
        {
            ret = real_fputc( __c, __stream );
            if (__stream != stdout && __stream != stderr)
                TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            ret = real::putc( __c, __stream );
        }
        TRACE_SYSCALLN("(%i %p)=%i",__c,__stream, ret);
        if (__stream != stdout && __stream != stderr)
            TRACE_SYSCALLN("(%i %p)=%i",__c,__stream, ret);
        return ret;
    }
    __asm__(".symver _iosys_putc,putc@GLIBC_2.2.5");


@@ 622,34 690,55 @@ extern "C"
    int _iosys_remove (const char *__filename) __THROW
    {
        int ret {};
        if(redirect_to_image(__filename))
        if(vfs::redirect_to_image(__filename))
        {
            ret = invoke_fs(&purefs::fs::filesystem::unlink, __filename);
            TRACE_SYSCALLN("(%s) -> VFS", __filename);
            ret = vfs::invoke_fs(&fs::unlink, __filename);
        }
        else
        {
            char tmp[PATH_MAX];
            const auto npath = npath_translate(__filename,tmp);
            auto r_remove = reinterpret_cast<int (*)(const char*)>(dlsym(RTLD_NEXT,"remove"));
            ret = r_remove(npath);
            const auto npath = vfs::npath_translate(__filename,tmp);
            TRACE_SYSCALLN("(%s) -> (%s) linux fs", __filename, npath);
            ret = real::remove(npath);
        }
        TRACE_SYSCALLN("(%s)=%i",__filename, ret);
        return ret;
    }
    __asm__(".symver _iosys_remove,remove@GLIBC_2.2.5");

    int _iosys_rename(const char *oldpath, const char *newpath)
    {
        TRACE_SYSCALL();
        if(vfs::redirect_to_image(oldpath))
        {
            TRACE_SYSCALLN("(%s,%s) -> VFS", oldpath, newpath);
            return vfs::invoke_fs(&fs::rename, oldpath, newpath);
        }
        else
        {
            char tmp[PATH_MAX], tmp2[PATH_MAX];
            const auto oldp = vfs::npath_translate(oldpath,tmp);
            const auto newp = vfs::npath_translate(newpath,tmp2);
            TRACE_SYSCALLN("(%s,%s) -> (%s,%s) linux fs", oldpath, newpath, oldp, newp);
            return real::rename(oldp,newp);
        }
    }
    __asm__(".symver _iosys_rename,rename@GLIBC_2.2.5");

    void _iosys_rewind (FILE *__stream)
    {
        TRACE_SYSCALLN("(%p)",__stream);
        if(is_filex(__stream))
        if(vfs::is_filex(__stream))
        {
            TRACE_SYSCALLN("(%p) -> VFS", __stream);
            auto fx = reinterpret_cast<FILEX*>(__stream);
            invoke_fs(&purefs::fs::filesystem::seek,fx->fd,0,SEEK_SET);
            vfs::invoke_fs(&fs::seek,fx->fd,0,SEEK_SET);
            fx->error = errno;
        }
        else
        {
            real_rewind(__stream);
            TRACE_SYSCALLN("(%p) -> linux fs", __stream);
            real::rewind(__stream);
        }
    }
    __asm__(".symver _iosys_rewind,rewind@GLIBC_2.2.5");


@@ 671,7 760,7 @@ extern "C"
        errno = ENOTSUP;
        return 0;
    }
    __asm__(".symver _iosys_setvbuf,setbuf@GLIBC_2.2.5");
    __asm__(".symver _iosys_setvbuf,setvbuf@GLIBC_2.2.5");


    void _iosys_setbuffer (FILE *__restrict __stream, char *__restrict __buf,

M board/linux/libiosyscalls/version.txt => board/linux/libiosyscalls/version.txt +39 -30
@@ 1,48 1,42 @@
GLIBC_2.2.5 {
        global:
                fclose;
                fdopen;
                feof;
                ferror;
                fflush;
                fgetc;
                fgetpos;
                fgetpos64;
                fgets;
                fileno;
# stdio
                fprintf;
                fwrite;
                fread;
                fopen;
                fopen64;
                fprintf;
                fclose;
                fputc;
                fputs;
                fread;
                putc;
                fgetc;
                fgets;
                getc;
                freopen;
                fdopen;
                fseek;
                fscanf;
                ftell;
                fsetpos;
                fsetpos64;
                ftell;
                fwrite;
                getc;
                putc;
                remove;
                fgetpos;
                fgetpos64;
                feof;
                rewind;
                fileno;
                ferror;
                fflush;
                remove;
                rename;
# stdio - scan family
                fscanf;
                vfscanf;
#                ungetc;
# stdio - disabled
                setbuf;
                setvbuf;
                setbuffer;
                setlinebuf;
                fscanf;
                vfscanf;
                ungetc;
                opendir;
                closedir;
                readdir;
                readdir_r;
                rewinddir;
                seekdir;
                telldir;
                rename;

# posix
                link;
                unlink;


@@ 70,6 64,21 @@ GLIBC_2.2.5 {
                __fxstat64;
                mount;
                umount;
# posix - dirent
                opendir;
                closedir;
                readdir;
                readdir_r;
                rewinddir;
                seekdir;
                telldir;
# posix - not implemented
#                read;
#                write;
#                lseek;
#                lseek64;
#                ioctl;
#                poll;

        local:
                *;