summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats/fsblk.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/formats/fsblk.h')
-rw-r--r--src/lib/formats/fsblk.h181
1 files changed, 181 insertions, 0 deletions
diff --git a/src/lib/formats/fsblk.h b/src/lib/formats/fsblk.h
new file mode 100644
index 00000000000..7f368a7307c
--- /dev/null
+++ b/src/lib/formats/fsblk.h
@@ -0,0 +1,181 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Filesystem operations on mounted image blocks
+
+#ifndef MAME_FORMATS_FSBLK_H
+#define MAME_FORMATS_FSBLK_H
+
+#pragma once
+
+#include "fsmeta.h"
+
+#include <memory>
+#include <string>
+#include <string_view>
+#include <system_error>
+#include <utility>
+#include <vector>
+
+namespace fs {
+
+using u8 = uint8_t;
+using u16 = uint16_t;
+using u32 = uint32_t;
+using u64 = uint64_t;
+
+enum class error : int {
+ unsupported = 1,
+ not_found,
+ no_space,
+ invalid_block,
+ invalid_name,
+ incorrect_size,
+ already_exists,
+};
+
+enum class dir_entry_type {
+ dir,
+ file,
+};
+
+struct dir_entry {
+ std::string m_name;
+ dir_entry_type m_type;
+ meta_data m_meta;
+
+ dir_entry(dir_entry_type type, const meta_data &meta) : m_name(meta.get_string(meta_name::name)), m_type(type), m_meta(std::move(meta)) {}
+};
+
+class fsblk_t {
+public:
+ class block_t {
+ public:
+ using ptr = std::shared_ptr<block_t>;
+
+ block_t(u32 size) : m_size(size) {}
+ virtual ~block_t() = default;
+
+ u32 size() const { return m_size; }
+
+ virtual const u8 *rodata() const = 0;
+ virtual u8 *data() = 0;
+
+ void write(u32 offset, const u8 *src, u32 size);
+ void fill( u8 data);
+ void fill( u32 offset, u8 data, u32 size);
+ void wstr( u32 offset, std::string_view str);
+ void w8( u32 offset, u8 data);
+ void w16b( u32 offset, u16 data);
+ void w24b( u32 offset, u32 data);
+ void w32b( u32 offset, u32 data);
+ void w16l( u32 offset, u16 data);
+ void w24l( u32 offset, u32 data);
+ void w32l( u32 offset, u32 data);
+
+ void read(u32 offset, u8 *dst, u32 size) const;
+ std::string_view rstr(u32 offset, u32 size) const;
+ u8 r8( u32 offset) const;
+ u16 r16b(u32 offset) const;
+ u32 r24b(u32 offset) const;
+ u32 r32b(u32 offset) const;
+ u16 r16l(u32 offset) const;
+ u32 r24l(u32 offset) const;
+ u32 r32l(u32 offset) const;
+
+ protected:
+ u32 m_size;
+
+ private:
+ const u8 *roffs(const char *function, u32 off, u32 size) const;
+ u8 *woffs(const char *function, u32 off, u32 size);
+ };
+
+ fsblk_t() : m_block_size(0) {}
+ virtual ~fsblk_t() = default;
+
+ virtual void set_block_size(u32 block_size);
+ virtual u32 block_count() const = 0;
+ virtual block_t::ptr get(u32 id) = 0;
+ virtual void fill_all(u8 data) = 0;
+
+protected:
+ u32 m_block_size;
+};
+
+
+class filesystem_t {
+public:
+ virtual ~filesystem_t() = default;
+
+ // Get the metadata for the volume
+ virtual meta_data volume_metadata();
+
+ // Change the metadata for the volume
+ virtual std::error_condition volume_metadata_change(const meta_data &meta);
+
+ // Get the metadata for a file or a directory. Empty path targets the root directory
+ virtual std::pair<std::error_condition, meta_data> metadata(const std::vector<std::string> &path);
+
+ // Change the metadata for a file or a directory. Empty path targets the root directory
+ virtual std::error_condition metadata_change(const std::vector<std::string> &path, const meta_data &meta);
+
+ // Get the contents of a directory, empty path targets the root directory
+ virtual std::pair<std::error_condition, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path);
+
+ // Rename a file or a directory. In contrast to metadata_change, this can move the object
+ // between directories
+ virtual std::error_condition rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath);
+
+ // Remove a file or a directory. Directories must be empty (e.g. it's not recursive)
+ virtual std::error_condition remove(const std::vector<std::string> &path);
+
+ // Create a directory, path designates where the directory must be, directory name is in meta
+ virtual std::error_condition dir_create(const std::vector<std::string> &path, const meta_data &meta);
+
+ // Create an empty file, path designates where the file must be, file name is in meta
+ virtual std::error_condition file_create(const std::vector<std::string> &path, const meta_data &meta);
+
+ // Read the contents of a file
+ virtual std::pair<std::error_condition, std::vector<u8>> file_read(const std::vector<std::string> &path);
+
+ // Replace the contents of a file, the file must already exist
+ virtual std::error_condition file_write(const std::vector<std::string> &path, const std::vector<u8> &data);
+
+ // Read the resource fork of a file on systems that handle those
+ virtual std::pair<std::error_condition, std::vector<u8>> file_rsrc_read(const std::vector<std::string> &path);
+
+ // Replace the resource fork of a file, the file must already exist
+ virtual std::error_condition file_rsrc_write(const std::vector<std::string> &path, const std::vector<u8> &data);
+
+ // Format an image, provide the volume metadata
+ virtual std::error_condition format(const meta_data &meta);
+
+ static void wstr(u8 *p, std::string_view str);
+
+ static std::string_view rstr(const u8 *p, u32 size);
+
+ static std::string_view trim_end_spaces(std::string_view str);
+
+protected:
+ filesystem_t(fsblk_t &blockdev, u32 size) : m_blockdev(blockdev) {
+ m_blockdev.set_block_size(size);
+ }
+
+ fsblk_t &m_blockdev;
+};
+
+// error category for filesystem errors
+std::error_category const &fs_category() noexcept;
+inline std::error_condition make_error_condition(error err) noexcept { return std::error_condition(int(err), fs_category()); }
+
+} // namespace fs
+
+
+namespace std {
+
+template <> struct is_error_condition_enum<fs::error> : public std::true_type { };
+
+} // namespace std
+
+#endif