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);
}