M .gitignore => .gitignore +6 -0
@@ 43,3 43,9 @@ docker/Dockerfile
docker/assets/actions*
docker/assets/cmake*
docker/assets/gcc-arm*
+
+# vim temporary files
+*.swp
+*.swo
+tags
+.ycm_extra_conf.py
A module-utils/split_sv.hpp => module-utils/split_sv.hpp +33 -0
@@ 0,0 1,33 @@
+// 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 <list>
+#include <string>
+#include <type_traits>
+
+namespace utils
+{
+ template <template <class, class> class Container, class T, class Allocator = std::allocator<T>>
+ auto split(T strv, T delims = " ")
+ {
+ static_assert(std::is_same<T, std::string>::value || std::is_same<T, std::string_view>::value,
+ "std::string or std::string_view expected");
+ Container<T, Allocator> output;
+ size_t first = 0;
+
+ while (first < strv.size()) {
+ const auto second = strv.find_first_of(delims, first);
+
+ if (first != second)
+ output.emplace_back(strv.substr(first, second - first));
+
+ if (second == std::string_view::npos)
+ break;
+
+ first = second + 1;
+ }
+
+ return output;
+ }
+} // namespace utils
M module-vfs/CMakeLists.txt => module-vfs/CMakeLists.txt +4 -0
@@ 49,6 49,10 @@ set(SOURCES ""
src/purefs/blkdev/disk.cpp
src/purefs/blkdev/partition_parser.cpp
src/purefs/blkdev/disk_handle.cpp
+ src/purefs/fs/filesystem.cpp
+ src/purefs/fs/filesystem_operations.cpp
+ src/purefs/fs/filesystem_syscalls.cpp
+ src/purefs/fs/filesystem_cwd.cpp
src/deprecated/vfs-utils.cpp
src/deprecated/vfs.cpp
src/deprecated/vfsNotifier.cpp
A module-vfs/board/linux/purefs/src/fs/thread_local_cwd.cpp => module-vfs/board/linux/purefs/src/fs/thread_local_cwd.cpp +27 -0
@@ 0,0 1,27 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <string>
+#include <purefs/fs/thread_local_cwd.hpp>
+
+namespace purefs::fs::internal
+{
+
+ namespace
+ {
+ thread_local std::string cwd_per_thread{"/"};
+ }
+ auto get_thread_local_cwd_path() noexcept -> std::string_view
+ {
+ return cwd_per_thread;
+ }
+ auto set_thread_cwd_path(std::string_view path) noexcept -> int
+ {
+ cwd_per_thread = path;
+ return 0;
+ }
+ auto cleanup_thread_local_cwd_mem() -> void
+ {
+ cwd_per_thread.erase();
+ }
+} // namespace purefs::fs::internal
A module-vfs/board/rt1051/purefs/src/fs/thread_local_cwd.cpp => module-vfs/board/rt1051/purefs/src/fs/thread_local_cwd.cpp +57 -0
@@ 0,0 1,57 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+#include <thread.hpp>
+#include <limits.h>
+#include <cstring>
+#include <purefs/fs/thread_local_cwd.hpp>
+
+#if configNUM_THREAD_LOCAL_STORAGE_POINTERS < 4
+#error Not enough TLS pointers
+#endif
+
+namespace purefs::fs::internal
+{
+ namespace
+ {
+ constexpr auto CWD_THREAD_LOCAL_INDEX = 3;
+ auto get_tls() noexcept -> char *
+ {
+ auto pcwd = reinterpret_cast<char *>(pvTaskGetThreadLocalStoragePointer(nullptr, CWD_THREAD_LOCAL_INDEX));
+ if (pcwd == nullptr) {
+ pcwd = new (std::nothrow) char[PATH_MAX + 1];
+ if (pcwd) {
+ std::strncpy(pcwd, "/", PATH_MAX);
+ vTaskSetThreadLocalStoragePointer(nullptr, CWD_THREAD_LOCAL_INDEX, pcwd);
+ }
+ }
+ return pcwd;
+ }
+ } // namespace
+ auto get_thread_local_cwd_path() noexcept -> std::string_view
+ {
+ return get_tls();
+ }
+ auto set_thread_cwd_path(std::string_view path) noexcept -> int
+ {
+ if (path.size() > PATH_MAX) {
+ return -ERANGE;
+ }
+ auto tls = get_tls();
+ if (!tls) {
+ return -ENOMEM;
+ }
+ else {
+ std::memcpy(tls, path.data(), path.size());
+ tls[path.size()] = '\0';
+ return 0;
+ }
+ }
+ auto cleanup_thread_local_cwd_mem() -> void
+ {
+ auto pcwd = reinterpret_cast<char *>(pvTaskGetThreadLocalStoragePointer(nullptr, CWD_THREAD_LOCAL_INDEX));
+ if (pcwd) {
+ delete[] pcwd;
+ vTaskSetThreadLocalStoragePointer(nullptr, CWD_THREAD_LOCAL_INDEX, nullptr);
+ }
+ }
+} // namespace purefs::fs::internal
M module-vfs/include/internal/purefs/fs/directory_handle.hpp => module-vfs/include/internal/purefs/fs/directory_handle.hpp +4 -2
@@ 10,8 10,10 @@ namespace purefs::fs::internal
class directory_handle
{
public:
+ directory_handle(int error, std::shared_ptr<mount_point> mount_point = nullptr)
+ : m_error(error), m_mount_point(mount_point)
+ {}
directory_handle(const directory_handle &) = delete;
- virtual ~directory_handle() = delete;
auto operator=(const directory_handle &) = delete;
auto error(int error) noexcept -> void
{
@@ 24,6 26,6 @@ namespace purefs::fs::internal
private:
int m_error{};
- std::weak_ptr<mount_point> m_mount_point;
+ const std::weak_ptr<mount_point> m_mount_point;
};
} // namespace purefs::fs::internal
M module-vfs/include/internal/purefs/fs/file_handle.hpp => module-vfs/include/internal/purefs/fs/file_handle.hpp +7 -1
@@ 14,6 14,8 @@ namespace purefs::fs::internal
public:
file_handle(const file_handle &) = delete;
virtual ~file_handle() = default;
+ explicit file_handle(std::shared_ptr<mount_point> mp) : m_mount_point(mp)
+ {}
[[nodiscard]] auto error() const noexcept
{
return m_error;
@@ 30,9 32,13 @@ namespace purefs::fs::internal
{
return m_flags;
}
- std::weak_ptr<mount_point> m_mount_point;
+ [[nodiscard]] auto mntpoint() const noexcept
+ {
+ return m_mount_point;
+ }
private:
+ const std::weak_ptr<mount_point> m_mount_point;
int m_error{};
int m_flags{};
};
R module-vfs/include/internal/purefs/utils/handle_mapper.hpp => module-vfs/include/internal/purefs/fs/handle_mapper.hpp +2 -2
@@ 4,7 4,7 @@
#pragma once
#include <vector>
-namespace purefs::utils::internal
+namespace purefs::fs::internal
{
template <typename T> class handle_mapper
@@ 44,4 44,4 @@ namespace purefs::utils::internal
data[result] = value;
return result;
}
-} // namespace purefs::utils::internal
+} // namespace purefs::fs::internal
M module-vfs/include/internal/purefs/fs/mount_point.hpp => module-vfs/include/internal/purefs/fs/mount_point.hpp +26 -8
@@ 5,25 5,43 @@
#include <memory>
#include <string>
-namespace purefs::blkdev
+namespace purefs::blkdev::internal
{
- class disk;
+ class disk_handle;
}
namespace purefs::fs
{
- class filesystem_operation;
+ class filesystem_operations;
}
namespace purefs::fs::internal
{
//! Mount point disk private structure
- //! TODO fill the blanks
class mount_point
{
- virtual ~mount_point() = default;
- int device{-1}; //! Owning device
- std::string mount_path; //! Mounted path
- std::weak_ptr<filesystem_operation> filesystem; //! Filesystem operation
+ public:
+ mount_point(std::shared_ptr<blkdev::internal::disk_handle> diskh,
+ std::string_view path,
+ std::shared_ptr<filesystem_operations> fs)
+ : m_diskh(diskh), m_path(path), m_fs(fs)
+ {}
+ auto disk() const noexcept
+ {
+ return m_diskh;
+ }
+ auto mount_path() const noexcept
+ {
+ return m_path;
+ }
+ auto fs_ops() const noexcept
+ {
+ return m_fs;
+ }
+
+ private:
+ const std::weak_ptr<blkdev::internal::disk_handle> m_diskh;
+ const std::string_view m_path; //! Mounted path
+ const std::weak_ptr<filesystem_operations> m_fs; //! Filesystem operation
};
} // namespace purefs::fs::internal
A module-vfs/include/internal/purefs/fs/thread_local_cwd.hpp => module-vfs/include/internal/purefs/fs/thread_local_cwd.hpp +12 -0
@@ 0,0 1,12 @@
+// 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 <string>
+
+namespace purefs::fs::internal
+{
+ auto get_thread_local_cwd_path() noexcept -> std::string_view;
+ auto set_thread_cwd_path(std::string_view path) noexcept -> int;
+ auto cleanup_thread_local_cwd_mem() -> void;
+} // namespace purefs::fs::internal
M module-vfs/include/user/purefs/fs/filesystem.hpp => module-vfs/include/user/purefs/fs/filesystem.hpp +117 -9
@@ 6,18 6,29 @@
#include <memory>
#include <list>
#include <array>
+#include <mutex.hpp>
+#include <unordered_map>
+#include <map>
+#include <functional>
+#include <ctime>
+#include <purefs/fs/handle_mapper.hpp>
+#include <purefs/fs/file_handle.hpp>
+#include <purefs/fs/mount_point.hpp>
-namespace purefs::fs
+namespace purefs::blkdev
{
+ class disk_manager;
+}
+namespace purefs::fs
+{
/** This is the filesystem class layer
* All methods can be called from the user thread
* but generally those functions are for internal use for
* example for newlib or glibc syscalls
*/
- class filesystem_operation;
struct statvfs;
- struct timespec;
+ class filesystem_operations;
namespace internal
{
class directory_handle;
@@ 26,7 37,10 @@ namespace purefs::fs
class filesystem
{
public:
+ static constexpr auto path_separator = '/';
using fsdir = std::shared_ptr<internal::directory_handle>;
+ using fsfile = std::shared_ptr<internal::file_handle>;
+ explicit filesystem(std::shared_ptr<blkdev::disk_manager> diskmm);
filesystem(const filesystem &) = delete;
auto operator=(const filesystem &) = delete;
/** Utility API */
@@ 35,7 49,7 @@ namespace purefs::fs
* @param[in] fops Filesystem operation structure
* @return zero on sucess otherwise error
*/
- auto register_filesystem(std::string_view fsname, std::shared_ptr<filesystem_operation> fops) -> int;
+ auto register_filesystem(std::string_view fsname, std::shared_ptr<filesystem_operations> fops) -> int;
/** Unregister filesystem driver
* @param[in] fsname Unique filesystem name for example fat
* @return zero on success otherwise error
@@ 72,8 86,8 @@ namespace purefs::fs
auto write(int fd, const char *ptr, size_t len) noexcept -> ssize_t;
auto read(int fd, char *ptr, size_t len) noexcept -> ssize_t;
auto seek(int fd, off_t pos, int dir) noexcept -> off_t;
- auto fstat(int fd, struct stat *st) noexcept -> int;
- auto stat(std::string_view file, struct stat *st) noexcept -> int;
+ auto fstat(int fd, struct stat &st) noexcept -> int;
+ auto stat(std::string_view file, struct stat &st) noexcept -> int;
auto link(std::string_view existing, std::string_view newlink) noexcept -> int;
auto symlink(std::string_view existing, std::string_view newlink) noexcept -> int;
auto unlink(std::string_view name) noexcept -> int;
@@ 91,13 105,107 @@ namespace purefs::fs
auto fsync(int fd) noexcept -> int;
auto ioctl(std::string_view path, int cmd, void *arg) noexcept -> int;
auto utimens(std::string_view path, std::array<timespec, 2> &tv) noexcept -> int;
- auto flock(std::string_view path, int cmd) noexcept -> int;
- auto isatty(std::string_view path) noexcept -> int;
+ auto flock(int fd, int cmd) noexcept -> int;
+ auto isatty(int fd) noexcept -> int;
auto chmod(std::string_view path, mode_t mode) noexcept -> int;
auto fchmod(int fd, mode_t mode) noexcept -> int;
- auto getcwd() noexcept -> std::string;
+ auto getcwd() noexcept -> std::string_view;
auto chdir(std::string_view name) noexcept -> int;
+
+ private:
+ /** Find the mount point object matching to the mount point path
+ * @param[in] path Absolute input path
+ * @return mount point object and the matching shortest path
+ */
+ auto find_mount_point(std::string_view path) const noexcept
+ -> std::tuple<std::shared_ptr<internal::mount_point>, size_t>;
+ /** Return absolute path from the relative path
+ * @param[in] path Unormalized path
+ * @return Full Normalized path
+ */
+ static auto absolute_path(std::string_view path) noexcept -> std::string;
+ /** Normalize full path
+ * @param[in] path Unnormalized full path
+ * @param[out] Normalized path
+ */
+ static auto normalize_path(std::string_view path) noexcept -> std::string;
+ /** Add handle to file descriptor
+ */
+ auto add_filehandle(fsfile file) noexcept -> int;
+ auto remove_filehandle(int fds) noexcept -> fsfile;
+ auto find_filehandle(int fds) const noexcept -> fsfile;
+
+ private:
+ template <class Base, class T, typename... Args>
+ inline auto invoke_fops(T Base::*method, int fds, Args &&... args)
+ -> decltype((static_cast<Base *>(nullptr)->*method)(0, std::forward<Args>(args)...))
+ {
+ auto fil = find_filehandle(fds);
+ if (!fil) {
+ return -EBADF;
+ }
+ else {
+ auto mp = fil->mntpoint().lock();
+ if (!mp) {
+ return -ENOENT;
+ }
+ auto fsops = mp->fs_ops().lock();
+ if (!fsops) {
+ return -EIO;
+ }
+ else {
+ return (fsops.get()->*method)(fil, std::forward<Args>(args)...);
+ }
+ }
+ }
+
+ template <class Base, class T, typename... Args>
+ inline auto invoke_fops(T Base::*method, std::string_view path, Args &&... args) const
+ -> decltype((static_cast<Base *>(nullptr)->*method)(nullptr, {}, std::forward<Args>(args)...))
+ {
+ const auto abspath = absolute_path(path);
+ auto [mountp, pathpos] = find_mount_point(abspath);
+ if (!mountp) {
+ return -ENOENT;
+ }
+ auto fsops = mountp->fs_ops().lock();
+ if (fsops)
+ return (fsops.get()->*method)(mountp, abspath, std::forward<Args>(args)...);
+ else
+ return -EIO;
+ }
+
+ template <class Base, class T, typename... Args>
+ inline auto invoke_fops_same_mp(T Base::*method,
+ std::string_view path,
+ std::string_view path2,
+ Args &&... args) const
+ -> decltype((static_cast<Base *>(nullptr)->*method)(nullptr, {}, {}, std::forward<Args>(args)...))
+ {
+ const auto abspath = absolute_path(path);
+ const auto abspath2 = absolute_path(path2);
+ auto [mountp, pathpos] = find_mount_point(abspath);
+ if (!mountp) {
+ return -ENOENT;
+ }
+ if (path.compare(0, pathpos, path2, 0, pathpos) != 0) {
+ // Mount points are not the same
+ return -EXDEV;
+ }
+ auto fsops = mountp->fs_ops().lock();
+ if (fsops)
+ return (fsops.get()->*method)(mountp, abspath, abspath2, std::forward<Args>(args)...);
+ else
+ return -EIO;
+ }
+
+ private:
+ std::weak_ptr<blkdev::disk_manager> m_diskmm;
+ std::unordered_map<std::string, std::shared_ptr<filesystem_operations>> m_fstypes;
+ std::map<std::string, std::shared_ptr<internal::mount_point>> m_mounts;
+ internal::handle_mapper<fsfile> m_fds;
+ mutable cpp_freertos::MutexRecursive m_lock;
};
} // namespace purefs::fs
D module-vfs/include/user/purefs/fs/filesystem_operation.hpp => module-vfs/include/user/purefs/fs/filesystem_operation.hpp +0 -69
@@ 1,69 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 <string>
-#include <list>
-#include <tuple>
-#include <memory>
-
-namespace purefs::fs
-{
- struct statvfs;
- namespace internal
- {
- class file_handle;
- class directory_handle;
- class mount_point;
- }; // namespace internal
-
- /** Filesystem specific driver base class */
- class filesystem_operation
- {
- public:
- using fsfile = std::shared_ptr<internal::file_handle>;
- using fsdir = std::shared_ptr<internal::directory_handle>;
- using fsmount = std::shared_ptr<internal::mount_point>;
- filesystem_operation(const filesystem_operation &) = delete;
- virtual ~filesystem_operation() = default;
- auto operator=(const filesystem_operation &) = delete;
- /** Allocate mount point class specify to the VFS
- * @return Allocated mount point structure
- */
- virtual auto mount_prealloc() -> fsmount = 0;
- virtual auto mount(fsmount mnt) noexcept -> int;
- virtual auto umount(fsmount mnt) noexcept -> int = 0;
- virtual auto stat_vfs(std::string_view path, statvfs &stat) const noexcept -> int = 0;
-
- /** Standard file access API */
- virtual auto open(fsmount mnt, std::string_view path, int flags, int mode) noexcept -> fsfile = 0;
- virtual auto close(fsfile zfile) noexcept -> int = 0;
- virtual auto write(fsfile zfile, const char *ptr, size_t len) noexcept -> ssize_t = 0;
- virtual auto read(fsfile zfile, char *ptr, size_t len) noexcept -> ssize_t = 0;
- virtual auto seek(fsfile zfile, off_t pos, int dir) noexcept -> off_t = 0;
- virtual auto fstat(fsfile zfile, struct stat *st) noexcept -> int = 0;
- virtual auto stat(fsmount mnt, std::string_view file, struct stat *st) noexcept -> int = 0;
- virtual auto link(fsmount mnt, std::string_view existing, std::string_view newlink) noexcept -> int = 0;
- virtual auto symlink(fsmount mnt, std::string_view existing, std::string_view newlink) noexcept -> int = 0;
- virtual auto unlink(fsmount mnt, std::string_view name) noexcept -> int = 0;
- virtual auto rename(fsmount mnt, std::string_view oldname, std::string_view newname) noexcept -> int = 0;
- virtual auto mkdir(fsmount mnt, std::string_view path, int mode) noexcept -> int = 0;
-
- /** Directory support API */
- virtual auto diropen(fsmount mnt, std::string_view path) noexcept -> fsdir = 0;
- virtual auto dirreset(fsdir dirstate) noexcept -> int = 0;
- virtual auto dirnext(fsdir dirstate, std::string &filename, struct stat &filestat) noexcept -> int = 0;
- virtual auto dirclose(fsdir dirstate) noexcept -> int;
-
- /** Other fops API */
- virtual auto ftruncate(fsfile zfile, off_t len) noexcept -> int = 0;
- virtual auto fsync(fsfile zfile) noexcept -> int = 0;
- virtual auto ioctl(fsfile zfile, int cmd, void *arg) noexcept -> int = 0;
- virtual auto utimens(fsmount mnt, std::string_view path, std::array<timespec, 2> &tv) noexcept -> int = 0;
- virtual auto flock(fsfile zfile, int cmd) noexcept -> int = 0;
- virtual auto isatty(fsfile zfile) noexcept -> int = 0;
-
- virtual auto chmod(fsmount mnt, std::string_view path, mode_t mode) noexcept -> int = 0;
- virtual auto fchmod(fsfile zfile, mode_t mode) noexcept -> int = 0;
- };
-} // namespace purefs::fs
A module-vfs/include/user/purefs/fs/filesystem_operations.hpp => module-vfs/include/user/purefs/fs/filesystem_operations.hpp +84 -0
@@ 0,0 1,84 @@
+// 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 <string>
+#include <list>
+#include <tuple>
+#include <memory>
+
+namespace purefs::blkdev::internal
+{
+ class disk_handle;
+}
+
+namespace purefs::fs
+{
+ struct statvfs;
+ namespace internal
+ {
+ class file_handle;
+ class directory_handle;
+ class mount_point;
+ }; // namespace internal
+
+ /** Filesystem specific driver base class */
+ class filesystem_operations
+ {
+ public:
+ using fsfile = std::shared_ptr<internal::file_handle>;
+ using fsdir = std::shared_ptr<internal::directory_handle>;
+ using fsmount = std::shared_ptr<internal::mount_point>;
+ filesystem_operations(const filesystem_operations &) = delete;
+ virtual ~filesystem_operations() = default;
+ auto operator=(const filesystem_operations &) = delete;
+ /** Allocate mount point class specify to the VFS
+ * @return Allocated mount point structure
+ */
+ virtual auto mount_prealloc(std::shared_ptr<blkdev::internal::disk_handle> diskh, std::string_view path)
+ -> fsmount = 0;
+ virtual auto mount(fsmount mnt) noexcept -> int = 0;
+ virtual auto umount(fsmount mnt) noexcept -> int = 0;
+ virtual auto stat_vfs(fsmount mnt, std::string_view path, statvfs &stat) const noexcept -> int;
+
+ /** Standard file access API */
+ virtual auto open(fsmount mnt, std::string_view path, int flags, int mode) noexcept -> fsfile = 0;
+ virtual auto close(fsfile zfile) noexcept -> int = 0;
+ virtual auto write(fsfile zfile, const char *ptr, size_t len) noexcept -> ssize_t = 0;
+ virtual auto read(fsfile zfile, char *ptr, size_t len) noexcept -> ssize_t = 0;
+ virtual auto seek(fsfile zfile, off_t pos, int dir) noexcept -> off_t;
+ virtual auto fstat(fsfile zfile, struct stat &st) noexcept -> int;
+ virtual auto stat(fsmount mnt, std::string_view file, struct stat &st) noexcept -> int;
+ virtual auto link(fsmount mnt, std::string_view existing, std::string_view newlink) noexcept -> int;
+ virtual auto symlink(fsmount mnt, std::string_view existing, std::string_view newlink) noexcept -> int;
+ virtual auto unlink(fsmount mnt, std::string_view name) noexcept -> int;
+ virtual auto rename(fsmount mnt, std::string_view oldname, std::string_view newname) noexcept -> int;
+ virtual auto mkdir(fsmount mnt, std::string_view path, int mode) noexcept -> int;
+
+ /** Directory support API */
+ virtual auto diropen(fsmount mnt, std::string_view path) noexcept -> fsdir;
+ virtual auto dirreset(fsdir dirstate) noexcept -> int;
+ virtual auto dirnext(fsdir dirstate, std::string &filename, struct stat &filestat) -> int;
+ virtual auto dirclose(fsdir dirstate) noexcept -> int;
+
+ /** Other fops API */
+ virtual auto ftruncate(fsfile zfile, off_t len) noexcept -> int;
+ virtual auto fsync(fsfile zfile) noexcept -> int;
+ virtual auto ioctl(fsmount mnt, std::string_view path, int cmd, void *arg) noexcept -> int;
+ virtual auto utimens(fsmount mnt, std::string_view path, std::array<timespec, 2> &tv) noexcept -> int;
+ virtual auto flock(fsfile zfile, int cmd) noexcept -> int;
+ virtual auto isatty(fsfile zfile) noexcept -> int = 0;
+
+ virtual auto chmod(fsmount mnt, std::string_view path, mode_t mode) noexcept -> int;
+ virtual auto fchmod(fsfile zfile, mode_t mode) noexcept -> int;
+
+ /** Internal use */
+ auto mount_count() const noexcept
+ {
+ return m_mount_count;
+ }
+
+ private:
+ std::size_t m_mount_count{};
+ };
+} // namespace purefs::fs
A module-vfs/src/purefs/fs/filesystem.cpp => module-vfs/src/purefs/fs/filesystem.cpp +214 -0
@@ 0,0 1,214 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+#include <purefs/fs/filesystem.hpp>
+#include <purefs/fs/filesystem_operations.hpp>
+#include <purefs/fs/mount_point.hpp>
+#include <purefs/blkdev/disk_manager.hpp>
+#include <purefs/fs/thread_local_cwd.hpp>
+#include <log/log.hpp>
+#include <split_sv.hpp>
+#include <errno.h>
+
+namespace purefs::fs
+{
+ filesystem::filesystem(std::shared_ptr<blkdev::disk_manager> diskmm) : m_diskmm(diskmm)
+ {}
+
+ auto filesystem::register_filesystem(std::string_view fsname, std::shared_ptr<filesystem_operations> fops) -> int
+ {
+ cpp_freertos::LockGuard _lck(m_lock);
+ const auto ret = m_fstypes.find(std::string(fsname));
+ if (ret != std::end(m_fstypes)) {
+ LOG_ERROR("Disc: %.*s already registered.", int(fsname.length()), fsname.data());
+ return -EEXIST;
+ }
+ else {
+ m_fstypes.emplace(std::make_pair(fsname, fops));
+ return {};
+ }
+ }
+
+ auto filesystem::unregister_filesystem(std::string_view fsname) -> int
+ {
+ cpp_freertos::LockGuard _lck(m_lock);
+ const auto it = m_fstypes.find(std::string(fsname));
+ if (it == std::end(m_fstypes)) {
+ LOG_ERROR("VFS: filesystem %.*s doesn't exists in manager.", int(fsname.length()), fsname.data());
+ return -ENOENT;
+ }
+ if (it->second->mount_count() > 0) {
+ LOG_ERROR("VFS: fileystem %.*s is already used", int(fsname.length()), fsname.data());
+ return -EBUSY;
+ }
+ m_fstypes.erase(it);
+ return {};
+ }
+
+ auto filesystem::mount(std::string_view dev_or_part,
+ std::string_view target,
+ std::string_view fs_type,
+ unsigned flags) -> int
+ {
+ // Sanity check input data
+ if (target.size() <= 1 || target[0] != '/') {
+ LOG_ERROR("VFS: Invalid target mountpoint path %.*s", int(target.length()), target.data());
+ return -EINVAL;
+ }
+ {
+ cpp_freertos::LockGuard _lock(m_lock);
+ const auto mpi = m_mounts.find(std::string(target));
+ if (mpi != std::end(m_mounts)) {
+ LOG_ERROR("VFS: mount point already exists %.*s", int(target.length()), target.data());
+ return -EBUSY;
+ }
+ const auto vsi = m_fstypes.find(std::string(fs_type));
+ if (vsi == std::end(m_fstypes)) {
+ LOG_ERROR("VFS: requested filesystem %.*s not registered", int(fs_type.length()), fs_type.data());
+ }
+ // Trying to open disk or part by manager
+ blkdev::disk_fd_t diskh;
+ {
+ auto disk_mgr = m_diskmm.lock();
+ if (disk_mgr) {
+ diskh = disk_mgr->device_handle(dev_or_part);
+ }
+ else {
+ LOG_ERROR("VFS: Unable to lock device manager");
+ return -EIO;
+ }
+ }
+ if (diskh) {
+ const auto mnt_point = vsi->second->mount_prealloc(diskh, target);
+ const auto ret_mnt = vsi->second->mount(mnt_point);
+ if (!ret_mnt)
+ m_mounts.emplace(std::make_pair(target, mnt_point));
+ else
+ return ret_mnt;
+ }
+ }
+ return {};
+ }
+
+ auto filesystem::umount(std::string_view mount_point) -> int
+ {
+ cpp_freertos::LockGuard _lck(m_lock);
+ auto mnti = m_mounts.find(std::string(mount_point));
+ if (mnti == std::end(m_mounts)) {
+ return -ENOENT;
+ }
+ auto fsops = mnti->second->fs_ops().lock();
+ if (!fsops) {
+ LOG_ERROR("Unable to lock filesystem operation");
+ return -EIO;
+ }
+ const auto umnt_ret = fsops->umount(mnti->second);
+ if (umnt_ret) {
+ return umnt_ret;
+ }
+ m_mounts.erase(mnti);
+ return {};
+ }
+
+ auto filesystem::read_mountpoints(std::list<std::string> &mountpoints) const -> int
+ {
+ cpp_freertos::LockGuard _lck(m_lock);
+ for (const auto &mntp : m_mounts) {
+ mountpoints.push_back(mntp.first);
+ }
+ return {};
+ }
+
+ auto filesystem::find_mount_point(std::string_view path) const noexcept
+ -> std::tuple<std::shared_ptr<internal::mount_point>, size_t>
+ {
+ size_t longest_match{};
+ std::shared_ptr<internal::mount_point> mount_pnt;
+ cpp_freertos::LockGuard _lck(m_lock);
+ for (const auto &mntp : m_mounts) {
+ const auto slen = mntp.first.size();
+ if ((slen < longest_match) || (slen > path.size())) {
+ continue;
+ }
+ if ((slen > 1) && (path[slen] != '/') && (path[slen] != '\0')) {
+ continue;
+ }
+ if (path.compare(0, slen, mntp.first) == 0) {
+ mount_pnt = mntp.second;
+ longest_match = slen;
+ }
+ }
+ return std::make_tuple(mount_pnt, longest_match);
+ }
+
+ auto filesystem::absolute_path(std::string_view path) noexcept -> std::string
+ {
+ std::string ret{};
+ if (!path.empty() && path[0] == path_separator) {
+ ret.append(path);
+ }
+ else {
+ ret.append(internal::get_thread_local_cwd_path()).append("/").append(path);
+ }
+ return normalize_path(ret);
+ }
+
+ auto filesystem::normalize_path(std::string_view path) noexcept -> std::string
+ {
+ std::string ret;
+ auto paths = utils::split<std::list, std::string_view>(path, "/");
+ for (auto it = std::begin(paths); it != std::end(paths);) {
+ if (!it->compare(".")) {
+ it = paths.erase(it);
+ }
+ else if (!it->compare("..")) {
+ auto pit = it;
+ --pit;
+ if (pit != std::end(paths)) {
+ it = paths.erase(pit);
+ if (it != std::end(paths))
+ it = paths.erase(it);
+ }
+ else {
+ it = paths.erase(it);
+ }
+ }
+ else {
+ ++it;
+ }
+ }
+ for (auto ep : paths) {
+ if (!ep.empty()) {
+ ret.append("/").append(ep);
+ }
+ }
+ if (ret.empty())
+ ret.append("/");
+ return ret;
+ }
+
+ auto filesystem::add_filehandle(fsfile file) noexcept -> int
+ {
+ cpp_freertos::LockGuard _lck(m_lock);
+ return m_fds.insert(file);
+ }
+
+ auto filesystem::remove_filehandle(int fds) noexcept -> fsfile
+ {
+ cpp_freertos::LockGuard _lck(m_lock);
+ fsfile ret{};
+ if (m_fds.exists(fds)) {
+ ret = m_fds[fds];
+ m_fds.remove(fds);
+ }
+ return ret;
+ }
+ auto filesystem::find_filehandle(int fds) const noexcept -> fsfile
+ {
+ fsfile ret{};
+ cpp_freertos::LockGuard _lck(m_lock);
+ if (m_fds.exists(fds)) {
+ ret = m_fds[fds];
+ }
+ return ret;
+ }
+} // namespace purefs::fs
A module-vfs/src/purefs/fs/filesystem_cwd.cpp => module-vfs/src/purefs/fs/filesystem_cwd.cpp +32 -0
@@ 0,0 1,32 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <sys/types.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <purefs/fs/filesystem.hpp>
+#include <purefs/fs/thread_local_cwd.hpp>
+#include <unistd.h>
+
+namespace purefs::fs
+{
+ auto filesystem::getcwd() noexcept -> std::string_view
+ {
+ return internal::get_thread_local_cwd_path();
+ }
+ auto filesystem::chdir(std::string_view name) noexcept -> int
+ {
+ struct stat sts;
+ int ret;
+ ret = this->stat(name, sts);
+ if (ret) {
+ return ret;
+ }
+ if ((sts.st_mode & S_IFMT) != S_IFDIR) {
+ return -ENOTDIR;
+ }
+ const auto abspath = absolute_path(name);
+ ret = internal::set_thread_cwd_path(abspath);
+ return ret;
+ }
+} // namespace purefs::fs
A module-vfs/src/purefs/fs/filesystem_operations.cpp => module-vfs/src/purefs/fs/filesystem_operations.cpp +104 -0
@@ 0,0 1,104 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+#include <purefs/fs/filesystem_operations.hpp>
+#include <purefs/fs/directory_handle.hpp>
+
+#include <errno.h>
+
+namespace purefs::fs
+{
+
+ auto filesystem_operations::mount(fsmount mnt) noexcept -> int
+ {
+ ++m_mount_count;
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::umount(fsmount mnt) noexcept -> int
+ {
+ if (m_mount_count > 0) {
+ --m_mount_count;
+ }
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::stat_vfs(fsmount mntp, std::string_view path, statvfs &stat) const noexcept -> int
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::seek(fsfile zfile, off_t pos, int dir) noexcept -> off_t
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::fstat(fsfile zfile, struct stat &st) noexcept -> int
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::stat(fsmount mnt, std::string_view file, struct stat &st) noexcept -> int
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::link(fsmount mnt, std::string_view existing, std::string_view newlink) noexcept -> int
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::symlink(fsmount mnt, std::string_view existing, std::string_view newlink) noexcept
+ -> int
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::unlink(fsmount mnt, std::string_view name) noexcept -> int
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::rename(fsmount mnt, std::string_view oldname, std::string_view newname) noexcept -> int
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::mkdir(fsmount mnt, std::string_view path, int mode) noexcept -> int
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::diropen(fsmount mnt, std::string_view path) noexcept -> fsdir
+ {
+ return std::make_shared<internal::directory_handle>(-ENOTSUP);
+ }
+ auto filesystem_operations::dirreset(fsdir dirstate) noexcept -> int
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::dirnext(fsdir dirstate, std::string &filename, struct stat &filestat) -> int
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::dirclose(fsdir dirstate) noexcept -> int
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::ftruncate(fsfile zfile, off_t len) noexcept -> int
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::fsync(fsfile zfile) noexcept -> int
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::ioctl(fsmount mnt, std::string_view path, int cmd, void *arg) noexcept -> int
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::utimens(fsmount mnt, std::string_view path, std::array<timespec, 2> &tv) noexcept -> int
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::flock(fsfile zfile, int cmd) noexcept -> int
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::chmod(fsmount mnt, std::string_view path, mode_t mode) noexcept -> int
+ {
+ return -ENOTSUP;
+ }
+ auto filesystem_operations::fchmod(fsfile zfile, mode_t mode) noexcept -> int
+ {
+ return -ENOTSUP;
+ }
+} // namespace purefs::fs
A module-vfs/src/purefs/fs/filesystem_syscalls.cpp => module-vfs/src/purefs/fs/filesystem_syscalls.cpp +139 -0
@@ 0,0 1,139 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+#include <purefs/fs/filesystem.hpp>
+#include <errno.h>
+#include <log/log.hpp>
+#include <purefs/fs/mount_point.hpp>
+#include <purefs/fs/filesystem_operations.hpp>
+#include <purefs/fs/file_handle.hpp>
+#include <purefs/fs/thread_local_cwd.hpp>
+
+namespace purefs::fs
+{
+ auto filesystem::stat_vfs(std::string_view path, statvfs &stat) const noexcept -> int
+ {
+ return invoke_fops(&filesystem_operations::stat_vfs, path, stat);
+ }
+
+ auto filesystem::stat(std::string_view file, struct stat &st) noexcept -> int
+ {
+ return invoke_fops(&filesystem_operations::stat, file, st);
+ }
+
+ auto filesystem::unlink(std::string_view name) noexcept -> int
+ {
+ return invoke_fops(&filesystem_operations::unlink, name);
+ }
+
+ auto filesystem::mkdir(std::string_view path, int mode) noexcept -> int
+ {
+ return invoke_fops(&filesystem_operations::mkdir, path, mode);
+ }
+
+ auto filesystem::ioctl(std::string_view path, int cmd, void *arg) noexcept -> int
+ {
+ return invoke_fops(&filesystem_operations::ioctl, path, cmd, arg);
+ }
+
+ auto filesystem::utimens(std::string_view path, std::array<timespec, 2> &tv) noexcept -> int
+ {
+ return invoke_fops(&filesystem_operations::utimens, path, tv);
+ }
+
+ auto filesystem::flock(int fd, int cmd) noexcept -> int
+ {
+ return invoke_fops(&filesystem_operations::flock, fd, cmd);
+ }
+
+ auto filesystem::isatty(int fd) noexcept -> int
+ {
+ return invoke_fops(&filesystem_operations::isatty, fd);
+ }
+
+ auto filesystem::chmod(std::string_view path, mode_t mode) noexcept -> int
+ {
+ return invoke_fops(&filesystem_operations::chmod, path, mode);
+ }
+
+ auto filesystem::close(int fd) noexcept -> int
+ {
+ return invoke_fops(&filesystem_operations::close, fd);
+ }
+
+ auto filesystem::write(int fd, const char *ptr, size_t len) noexcept -> ssize_t
+ {
+ return invoke_fops(&filesystem_operations::write, fd, ptr, len);
+ }
+
+ auto filesystem::read(int fd, char *ptr, size_t len) noexcept -> ssize_t
+ {
+ return invoke_fops(&filesystem_operations::read, fd, ptr, len);
+ }
+
+ auto filesystem::seek(int fd, off_t pos, int dir) noexcept -> off_t
+ {
+ return invoke_fops(&filesystem_operations::seek, fd, pos, dir);
+ }
+
+ auto filesystem::fstat(int fd, struct stat &st) noexcept -> int
+ {
+ return invoke_fops(&filesystem_operations::fstat, fd, st);
+ }
+
+ auto filesystem::ftruncate(int fd, off_t len) noexcept -> int
+ {
+ return invoke_fops(&filesystem_operations::ftruncate, fd, len);
+ }
+
+ auto filesystem::fsync(int fd) noexcept -> int
+ {
+ return invoke_fops(&filesystem_operations::fsync, fd);
+ }
+
+ auto filesystem::fchmod(int fd, mode_t mode) noexcept -> int
+ {
+ return invoke_fops(&filesystem_operations::fchmod, fd, mode);
+ }
+
+ auto filesystem::symlink(std::string_view existing, std::string_view newlink) noexcept -> int
+ {
+ return invoke_fops_same_mp(&filesystem_operations::symlink, existing, newlink);
+ }
+
+ auto filesystem::link(std::string_view existing, std::string_view newlink) noexcept -> int
+ {
+ return invoke_fops_same_mp(&filesystem_operations::link, existing, newlink);
+ }
+
+ auto filesystem::rename(std::string_view oldname, std::string_view newname) noexcept -> int
+ {
+ return invoke_fops_same_mp(&filesystem_operations::rename, oldname, newname);
+ }
+
+ auto filesystem::open(std::string_view path, int flags, int mode) noexcept -> int
+ {
+ const auto abspath = absolute_path(path);
+ auto [mountp, pathpos] = find_mount_point(abspath);
+ if (!mountp) {
+ LOG_ERROR("VFS: Unable to find mount point");
+ return -ENOENT;
+ }
+ auto fsops = mountp->fs_ops().lock();
+ if (fsops) {
+ auto fh = fsops->open(mountp, abspath, flags, mode);
+ if (!fh) {
+ LOG_ERROR("VFS: Unable to get fops");
+ return -EBADF;
+ }
+ const auto err = fh->error();
+ if (err) {
+ return err;
+ }
+ return add_filehandle(fh);
+ }
+ else {
+ LOG_ERROR("VFS: Unable to lock fops");
+ return -EIO;
+ }
+ }
+} // namespace purefs::fs
M module-vfs/targets/Target_Linux.cmake => module-vfs/targets/Target_Linux.cmake +1 -0
@@ 3,6 3,7 @@ set(BOARD_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/board/linux/free_rtos_custom/portable/common.cpp
${CMAKE_CURRENT_SOURCE_DIR}/board/linux/free_rtos_custom/portable/vfs.cpp
${CMAKE_CURRENT_SOURCE_DIR}/board/linux/purefs/src/blkdev/disk_image.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/linux/purefs/src/fs/thread_local_cwd.cpp
CACHE INTERNAL ""
)
M module-vfs/targets/Target_RT1051.cmake => module-vfs/targets/Target_RT1051.cmake +4 -3
@@ 2,12 2,13 @@ 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
CACHE INTERNAL ""
)
set(BOARD_DIR_INCLUDES ${BOARD_DIR_INCLUDES}
-
-
- ${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051 CACHE INTERNAL "")
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051
+ CACHE INTERNAL ""
+)