~aleteoryx/muditaos

1b7e8828d603c47adaaaf110a95f97c9d3687c83 — Lucjan Bryndza 4 years ago 8513eaa
[EGD-7881] Fix stat syscalls in the VFS

Fix and unifying the stat() syscall in the VFS.
Fix the ftruncate() syscalls in the FAT and VFS.

Signed-off-by: Lucjan Bryndza <lucjan.bryndza@mudita.com>
M module-platform/linux/tests/unittest_filesystem_core.cpp => module-platform/linux/tests/unittest_filesystem_core.cpp +71 -0
@@ 366,3 366,74 @@ TEST_CASE("Corefs: Autodetect filesystems")
    REQUIRE(fscore->mount("emmc0part0", "/sys", "auto") == 0);
    REQUIRE(fscore->umount("/sys") == 0);
}

TEST_CASE("Corefs: stat extended")
{
    using namespace purefs;
    auto dm   = std::make_shared<blkdev::disk_manager>();
    auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
    REQUIRE(disk);
    REQUIRE(dm->register_device(disk, "emmc0") == 0);
    purefs::fs::filesystem fs_core(dm);
    const auto vfs_vfat = std::make_shared<fs::drivers::filesystem_vfat>();
    REQUIRE(vfs_vfat->mount_count() == 0);
    auto ret = fs_core.register_filesystem("vfat", vfs_vfat);
    REQUIRE(ret == 0);
    REQUIRE(fs_core.mount("emmc0part0", "/sys", "vfat") == 0);

    // Check if it is a directory
    struct stat st;
    REQUIRE(fs_core.stat("/sys", st) == 0);
    REQUIRE(S_ISDIR(st.st_mode));
    REQUIRE(fs_core.stat("/sys/", st) == 0);
    REQUIRE(S_ISDIR(st.st_mode));
    // Check for dir and subdir
    const auto dir = "/sys/advdirx";
    const auto fil = "/sys/advdirx/advfile";
    // Create directory and truncated file
    REQUIRE(fs_core.mkdir(dir, 0755) == 0);
    auto fd = fs_core.open(fil, O_CREAT | O_RDWR, 0);
    REQUIRE(fd >= 3);
    REQUIRE(fs_core.ftruncate(fd, 124567) == 0);
    REQUIRE(fs_core.close(fd) == 0);
    fd = -1;

    // Now check for stat for directories and sub dirs
    // Root dir
    REQUIRE(fs_core.stat("/sys", st) == 0);
    REQUIRE(S_ISFIFO(st.st_mode) == 0);
    REQUIRE(S_ISCHR(st.st_mode) == 0);
    REQUIRE(S_ISDIR(st.st_mode));
    REQUIRE(S_ISBLK(st.st_mode) == 0);
    REQUIRE(S_ISLNK(st.st_mode) == 0);
    REQUIRE(S_ISSOCK(st.st_mode) == 0);
    REQUIRE(S_ISREG(st.st_mode) == 0);

    // Sub dir
    REQUIRE(fs_core.stat(dir, st) == 0);
    REQUIRE(S_ISFIFO(st.st_mode) == 0);
    REQUIRE(S_ISCHR(st.st_mode) == 0);
    REQUIRE(S_ISDIR(st.st_mode));
    REQUIRE(S_ISBLK(st.st_mode) == 0);
    REQUIRE(S_ISLNK(st.st_mode) == 0);
    REQUIRE(S_ISSOCK(st.st_mode) == 0);
    REQUIRE(S_ISREG(st.st_mode) == 0);

    // Check for file
    REQUIRE(0 == fs_core.stat(fil, st));
    REQUIRE(124567 == st.st_size);
    REQUIRE(S_ISFIFO(st.st_mode) == 0);
    REQUIRE(S_ISCHR(st.st_mode) == 0);
    REQUIRE(S_ISDIR(st.st_mode) == 0);
    REQUIRE(S_ISBLK(st.st_mode) == 0);
    REQUIRE(S_ISLNK(st.st_mode) == 0);
    REQUIRE(S_ISSOCK(st.st_mode) == 0);
    REQUIRE(S_ISREG(st.st_mode));

    // Final cleanup
    REQUIRE(0 == fs_core.unlink(fil));
    REQUIRE(0 == fs_core.rmdir(dir));

    // Final umount
    REQUIRE(fs_core.umount("/sys") == 0);
}

M module-platform/linux/tests/unittest_filesystem_ext4.cpp => module-platform/linux/tests/unittest_filesystem_ext4.cpp +64 -1
@@ 239,7 239,7 @@ TEST_CASE("ext4: Directory tests")
    REQUIRE(fs_core->umount("/sys") == 0);
}

TEST_CASE("littlefs: Remount RO->RW->RW")
TEST_CASE("ext4: Remount RO->RW->RW")
{
    using namespace purefs;
    static constexpr auto filename = "/sys/remount_test.txt";


@@ 276,3 276,66 @@ TEST_CASE("littlefs: Remount RO->RW->RW")

    REQUIRE(fs_core->umount("/sys") == 0);
}

TEST_CASE("ext4: stat extended")
{
    using namespace purefs;
    auto [fs_core, dm] = prepare_filesystem("emmc0");
    REQUIRE(fs_core);
    REQUIRE(fs_core->mount("emmc0part0", "/sys", "ext4") == 0);
    // Check if it is a directory
    struct stat st;
    REQUIRE(fs_core->stat("/sys", st) == 0);
    REQUIRE(S_ISDIR(st.st_mode));
    REQUIRE(fs_core->stat("/sys/", st) == 0);
    REQUIRE(S_ISDIR(st.st_mode));
    // Check for dir and subdir
    const auto dir = "/sys/advdirx";
    const auto fil = "/sys/advdirx/advfile";
    // Create directory and truncated file
    REQUIRE(fs_core->mkdir(dir, 0755) == 0);
    auto fd = fs_core->open(fil, O_CREAT | O_RDWR, 0);
    REQUIRE(fd >= 3);
    REQUIRE(fs_core->ftruncate(fd, 124567) == 0);
    REQUIRE(fs_core->close(fd) == 0);
    fd = -1;

    // Now check for stat for directories and sub dirs
    // Root dir
    REQUIRE(fs_core->stat("/sys", st) == 0);
    REQUIRE(S_ISFIFO(st.st_mode) == 0);
    REQUIRE(S_ISCHR(st.st_mode) == 0);
    REQUIRE(S_ISDIR(st.st_mode));
    REQUIRE(S_ISBLK(st.st_mode) == 0);
    REQUIRE(S_ISLNK(st.st_mode) == 0);
    REQUIRE(S_ISSOCK(st.st_mode) == 0);
    REQUIRE(S_ISREG(st.st_mode) == 0);

    // Sub dir
    REQUIRE(fs_core->stat(dir, st) == 0);
    REQUIRE(S_ISFIFO(st.st_mode) == 0);
    REQUIRE(S_ISCHR(st.st_mode) == 0);
    REQUIRE(S_ISDIR(st.st_mode));
    REQUIRE(S_ISBLK(st.st_mode) == 0);
    REQUIRE(S_ISLNK(st.st_mode) == 0);
    REQUIRE(S_ISSOCK(st.st_mode) == 0);
    REQUIRE(S_ISREG(st.st_mode) == 0);

    // Check for file
    REQUIRE(0 == fs_core->stat(fil, st));
    REQUIRE(124567 == st.st_size);
    REQUIRE(S_ISFIFO(st.st_mode) == 0);
    REQUIRE(S_ISCHR(st.st_mode) == 0);
    REQUIRE(S_ISDIR(st.st_mode) == 0);
    REQUIRE(S_ISBLK(st.st_mode) == 0);
    REQUIRE(S_ISLNK(st.st_mode) == 0);
    REQUIRE(S_ISSOCK(st.st_mode) == 0);
    REQUIRE(S_ISREG(st.st_mode));

    // Final cleanup
    REQUIRE(0 == fs_core->unlink(fil));
    REQUIRE(0 == fs_core->rmdir(dir));

    // Final umount
    REQUIRE(fs_core->umount("/sys") == 0);
}

M module-vfs/drivers/src/purefs/fs/filesystem_vfat.cpp => module-vfs/drivers/src/purefs/fs/filesystem_vfat.cpp +49 -7
@@ 127,18 127,48 @@ namespace purefs::fs::drivers
            st.st_rdev  = 0;
            st.st_size  = fs.fsize;

            // TODO: Block FF_MIN_SS != FF_MAX_SS
#if FF_MAX_SS != FF_MIN_SS
            st.st_blksize = fatfs->ssize;
#else
            st.st_blksize = FF_MIN_SS;
#endif
            // TODO: Time is currently not supported
            st.st_blocks = fs.fsize / st.st_blksize;
            st.st_atime  = 0;
            st.st_mtime  = 0;
            st.st_ctime  = 0;
        }

        int internal_stat_rootdir(const char *translated_path, bool ro, struct stat *entry)
        {
            FATFS *fs;
            DWORD bfree;
            FRESULT res = f_getfree(translated_path, &bfree, &fs);
            if (res != FR_OK) {
                return -EIO;
            }
            entry->st_dev  = 0;
            entry->st_ino  = 0;
            entry->st_mode = (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IRUSR | S_IRGRP | S_IROTH);
            if (!ro) {
                entry->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
            }
            entry->st_nlink = 1;
            entry->st_uid   = 0;
            entry->st_gid   = 0;
            entry->st_rdev  = 0;
            entry->st_size  = 0;
#if FF_MAX_SS != FF_MIN_SS
            entry->st_blksize = fatfs->ssize;
#else
            entry->st_blksize = FF_MIN_SS;
#endif
            entry->st_blocks = fs->fsize / entry->st_blksize;
            entry->st_atime  = 0;
            entry->st_mtime  = 0;
            entry->st_ctime  = 0;
            return 0;
        }

    } // namespace

    auto filesystem_vfat::mount_prealloc(std::shared_ptr<blkdev::internal::disk_handle> diskh,


@@ 360,11 390,19 @@ namespace purefs::fs::drivers
        }
        FILINFO finfo;
        const auto fspath = vmnt->native_path(file);
        const int fres    = f_stat(fspath.c_str(), &finfo);
        if (fres == FR_OK) {
            translate_filinfo_to_stat(finfo, nullptr, vmnt->is_ro(), st);
        static constexpr auto slash_pos       = 2U;
        static constexpr auto root_size       = 3U;
        static constexpr auto empty_root_size = 2U;
        if ((fspath[slash_pos] == '/' && fspath.size() == root_size) || fspath.size() == empty_root_size) {
            return internal_stat_rootdir(fspath.c_str(), vmnt->is_ro(), &st);
        }
        else {
            const int fres = f_stat(fspath.c_str(), &finfo);
            if (fres == FR_OK) {
                translate_filinfo_to_stat(finfo, nullptr, vmnt->is_ro(), st);
            }
            return translate_error(fres);
        }
        return translate_error(fres);
    }

    auto filesystem_vfat::unlink(fsmount mnt, std::string_view name) noexcept -> int


@@ 486,7 524,11 @@ namespace purefs::fs::drivers
            LOG_ERROR("Non fat filesystem pointer");
            return -EBADF;
        }
        const int fres = f_truncate(vfile->ff_filp());
        int fres = f_lseek(vfile->ff_filp(), len);
        if (fres != FR_OK) {
            return translate_error(fres);
        }
        fres = f_truncate(vfile->ff_filp());
        return translate_error(fres);
    }