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.h221
1 files changed, 63 insertions, 158 deletions
diff --git a/src/lib/formats/fsblk.h b/src/lib/formats/fsblk.h
index 63ed910a507..7f368a7307c 100644
--- a/src/lib/formats/fsblk.h
+++ b/src/lib/formats/fsblk.h
@@ -10,8 +10,10 @@
#include "fsmeta.h"
+#include <memory>
#include <string>
#include <string_view>
+#include <system_error>
#include <utility>
#include <vector>
@@ -22,110 +24,14 @@ using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
-enum err_t {
- ERR_OK = 0,
- ERR_UNSUPPORTED,
- ERR_INVALID,
- ERR_NOT_FOUND,
- ERR_NOT_EMPTY,
- ERR_NO_SPACE,
-};
-
-template<typename T> class refcounted_outer {
-public:
- refcounted_outer(bool weak) : m_object(nullptr), m_is_weak_ref(weak) {}
- refcounted_outer(T *object, bool weak) : m_object(object), m_is_weak_ref(weak) {
- ref();
- }
-
- refcounted_outer(const refcounted_outer &cref) {
- m_object = cref.m_object;
- m_is_weak_ref = cref.m_is_weak_ref;
- ref();
- }
-
- refcounted_outer(refcounted_outer &&cref) {
- m_object = cref.m_object;
- m_is_weak_ref = cref.m_is_weak_ref;
- cref.m_object = nullptr;
- }
-
- ~refcounted_outer() {
- unref();
- }
-
- refcounted_outer<T> &operator =(T *dir) {
- if(m_object != dir) {
- unref();
- m_object = dir;
- ref();
- }
- return *this;
- }
-
- refcounted_outer<T> &operator =(const refcounted_outer<T> &cref) {
- if(m_object != cref.m_object) {
- unref();
- m_object = cref.m_object;
- ref();
- }
- return *this;
- }
-
- refcounted_outer<T> &operator =(refcounted_outer<T> &&cref) {
- if(m_object != cref.m_object) {
- unref();
- m_object = cref.m_object;
- ref();
- } else if(m_is_weak_ref != cref.m_is_weak_ref) {
- ref();
- cref.unref();
- m_object = cref.m_object; // In case the object got deleted (when going from strong ref to weak on the last strong)
- }
- cref.m_object = nullptr;
- return *this;
- }
-
- operator bool() const { return m_object != nullptr; }
-
-protected:
- T *m_object;
- bool m_is_weak_ref;
-
-private:
- void ref() {
- if(m_object) {
- if(m_is_weak_ref)
- m_object->ref_weak();
- else
- m_object->ref();
- }
- }
-
- void unref() {
- if(m_object) {
- bool del = m_is_weak_ref ? m_object->unref_weak() : m_object->unref();
- if(del)
- m_object = nullptr;
- }
- }
-};
-
-
-class refcounted_inner {
-public:
- refcounted_inner() : m_ref(0), m_weak_ref(0) {}
- virtual ~refcounted_inner() = default;
-
- void ref();
- void ref_weak();
- bool unref();
- bool unref_weak();
-
- virtual void drop_weak_references() = 0;
-
-public:
- u32 m_ref, m_weak_ref;
+enum class error : int {
+ unsupported = 1,
+ not_found,
+ no_space,
+ invalid_block,
+ invalid_name,
+ incorrect_size,
+ already_exists,
};
enum class dir_entry_type {
@@ -142,51 +48,32 @@ struct dir_entry {
};
class fsblk_t {
-protected:
- class iblock_t : public refcounted_inner {
- public:
- iblock_t(u32 size) : refcounted_inner(), m_size(size) {}
- virtual ~iblock_t() = default;
-
- u32 size() const { return m_size; }
-
- virtual const u8 *rodata() = 0;
- virtual u8 *data() = 0;
- u8 *offset(const char *function, u32 off, u32 size);
- const u8 *rooffset(const char *function, u32 off, u32 size);
-
- protected:
- u32 m_size;
- };
-
-
public:
- class block_t : public refcounted_outer<iblock_t> {
+ class block_t {
public:
- block_t(bool weak = false) : refcounted_outer<iblock_t>(weak) {}
- block_t(iblock_t *block, bool weak = true) : refcounted_outer(block, weak) {}
- virtual ~block_t() = default;
-
- block_t strong() { return block_t(m_object, false); }
- block_t weak() { return block_t(m_object, true); }
+ using ptr = std::shared_ptr<block_t>;
- u32 size() const { return m_object->size(); }
+ block_t(u32 size) : m_size(size) {}
+ virtual ~block_t() = default;
- const u8 *rodata() const { return m_object->rodata(); }
- u8 *data() { return m_object->data(); }
+ u32 size() const { return m_size; }
- void copy(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);
+ 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;
@@ -195,6 +82,13 @@ public:
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) {}
@@ -202,8 +96,8 @@ public:
virtual void set_block_size(u32 block_size);
virtual u32 block_count() const = 0;
- virtual block_t get(u32 id) = 0;
- virtual void fill(u8 data) = 0;
+ virtual block_t::ptr get(u32 id) = 0;
+ virtual void fill_all(u8 data) = 0;
protected:
u32 m_block_size;
@@ -218,44 +112,44 @@ public:
virtual meta_data volume_metadata();
// Change the metadata for the volume
- virtual err_t volume_metadata_change(const meta_data &meta);
+ 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<err_t, meta_data> metadata(const std::vector<std::string> &path);
+ 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 err_t metadata_change(const std::vector<std::string> &path, const meta_data &meta);
+ 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<err_t, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path);
+ 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 err_t rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath);
+ 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 err_t remove(const std::vector<std::string> &path);
+ 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 err_t dir_create(const std::vector<std::string> &path, const meta_data &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 err_t file_create(const std::vector<std::string> &path, const meta_data &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<err_t, std::vector<u8>> file_read(const std::vector<std::string> &path);
+ 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 err_t file_write(const std::vector<std::string> &path, const std::vector<u8> &data);
+ 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<err_t, std::vector<u8>> file_rsrc_read(const std::vector<std::string> &path);
+ 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 err_t file_rsrc_write(const std::vector<std::string> &path, const std::vector<u8> &data);
+ 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 err_t format(const meta_data &meta);
+ virtual std::error_condition format(const meta_data &meta);
static void wstr(u8 *p, std::string_view str);
@@ -271,6 +165,17 @@ protected:
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