summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats/fsmgr.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/formats/fsmgr.h')
-rw-r--r--src/lib/formats/fsmgr.h504
1 files changed, 276 insertions, 228 deletions
diff --git a/src/lib/formats/fsmgr.h b/src/lib/formats/fsmgr.h
index dee33808388..d407a597c6e 100644
--- a/src/lib/formats/fsmgr.h
+++ b/src/lib/formats/fsmgr.h
@@ -9,34 +9,168 @@
#pragma once
#include "flopimg.h"
+#include "timeconv.h"
#include <variant>
#include <unordered_map>
+#include <functional>
enum class fs_meta_name {
+ basic,
creation_date,
length,
loading_address,
locked,
- sequential,
modification_date,
name,
+ os_minimum_version,
+ os_version,
+ rsrc_length,
+ sequential,
size_in_blocks,
};
enum class fs_meta_type {
- string,
- number,
date,
flag,
+ number,
+ string,
+};
+
+enum class fs_dir_entry_type {
+ dir,
+ file,
+ system_file,
};
-using fs_meta = std::variant<std::string, uint64_t, bool>;
-using fs_meta_data = std::unordered_map<fs_meta_name, fs_meta>;
+class fs_meta {
+public:
+ static std::string to_string(fs_meta_type type, const fs_meta &m);
+ static fs_meta from_string(fs_meta_type type, std::string value);
+
+ fs_meta() { value = false; }
+ fs_meta(std::string str) { value = str; }
+ fs_meta(bool b) { value = b; }
+ fs_meta(int32_t num) { value = uint64_t(num); }
+ fs_meta(uint32_t num) { value = uint64_t(num); }
+ fs_meta(int64_t num) { value = uint64_t(num); }
+ fs_meta(uint64_t num) { value = num; }
+ fs_meta(util::arbitrary_datetime dt) { value = dt; }
+
+ util::arbitrary_datetime as_date() const { return *std::get_if<util::arbitrary_datetime>(&value); }
+ bool as_flag() const { return *std::get_if<bool>(&value); }
+ uint64_t as_number() const { return *std::get_if<uint64_t>(&value); }
+ std::string as_string() const { return *std::get_if<std::string>(&value); }
+
+private:
+ std::variant<std::string, uint64_t, bool, util::arbitrary_datetime> value;
+};
+
+class fs_meta_data {
+public:
+ std::unordered_map<fs_meta_name, fs_meta> meta;
+
+ static const char *entry_name(fs_meta_name name);
+
+ bool has(fs_meta_name name) const { return meta.find(name) != meta.end(); }
+ bool empty() const { return meta.empty(); }
+
+ void set(fs_meta_name name, const fs_meta &val) { meta[name] = val; }
+ void set(fs_meta_name name, std::string str) { set(name, fs_meta(str)); }
+ void set(fs_meta_name name, bool b) { set(name, fs_meta(b)); }
+ void set(fs_meta_name name, int32_t num) { set(name, fs_meta(num)); }
+ void set(fs_meta_name name, uint32_t num) { set(name, fs_meta(num)); }
+ void set(fs_meta_name name, int64_t num) { set(name, fs_meta(num)); }
+ void set(fs_meta_name name, uint64_t num) { set(name, fs_meta(num)); }
+ void set(fs_meta_name name, util::arbitrary_datetime dt) { set(name, fs_meta(dt)); }
+ void set_now(fs_meta_name name) { set(name, fs_meta(util::arbitrary_datetime::now())); }
+
+ fs_meta get(fs_meta_name name) const { auto i = meta.find(name); if(i == meta.end()) fatalerror("Entry %s not found\n", entry_name(name)); else return i->second; }
+ util::arbitrary_datetime get_date(fs_meta_name name, util::arbitrary_datetime def = util::arbitrary_datetime::now()) const { auto i = meta.find(name); if(i == meta.end()) return def; else return i->second.as_date(); }
+ bool get_flag(fs_meta_name name, bool def = false) const { auto i = meta.find(name); if(i == meta.end()) return def; else return i->second.as_flag(); }
+ uint64_t get_number(fs_meta_name name, uint64_t def = 0) const { auto i = meta.find(name); if(i == meta.end()) return def; else return i->second.as_number(); }
+ std::string get_string(fs_meta_name name, std::string def = "") const { auto i = meta.find(name); if(i == meta.end()) return def; else return i->second.as_string(); }
+};
+
+template<typename T> class fs_refcounted_outer {
+public:
+ fs_refcounted_outer(bool weak) : m_object(nullptr), m_is_weak_ref(weak) {}
+ fs_refcounted_outer(T *object, bool weak) : m_object(object), m_is_weak_ref(weak) {
+ ref();
+ }
+
+ fs_refcounted_outer(const fs_refcounted_outer &cref) {
+ m_object = cref.m_object;
+ m_is_weak_ref = cref.m_is_weak_ref;
+ ref();
+ }
+
+ fs_refcounted_outer(fs_refcounted_outer &&cref) {
+ m_object = cref.m_object;
+ m_is_weak_ref = cref.m_is_weak_ref;
+ cref.m_object = nullptr;
+ }
+
+ ~fs_refcounted_outer() {
+ unref();
+ }
+
+ fs_refcounted_outer<T> &operator =(T *dir) {
+ if(m_object != dir) {
+ unref();
+ m_object = dir;
+ ref();
+ }
+ return *this;
+ }
+
+ fs_refcounted_outer<T> &operator =(const fs_refcounted_outer<T> &cref) {
+ if(m_object != cref.m_object) {
+ unref();
+ m_object = cref.m_object;
+ ref();
+ }
+ return *this;
+ }
+
+ fs_refcounted_outer<T> &operator =(fs_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;
+ }
-const char *fs_meta_get_name(fs_meta_name name);
-std::string fs_meta_to_string(fs_meta_type type, const fs_meta &m);
-fs_meta fs_meta_from_string(fs_meta_type type, std::string value);
+ 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;
+ }
+ }
+};
struct fs_meta_description {
@@ -56,116 +190,87 @@ struct fs_meta_description {
{}
};
+class fs_refcounted_inner {
+public:
+ fs_refcounted_inner() : m_ref(0), m_weak_ref(0) {}
+ virtual ~fs_refcounted_inner() = default;
+
+ void ref();
+ void ref_weak();
+ bool unref();
+ bool unref_weak();
+
+ virtual void drop_weak_references() = 0;
+
+public:
+ uint32_t m_ref, m_weak_ref;
+};
+
+struct fs_dir_entry {
+ std::string m_name;
+ fs_dir_entry_type m_type;
+ uint64_t m_key;
+
+ fs_dir_entry(const std::string &name, fs_dir_entry_type type, uint64_t key) : m_name(name), m_type(type), m_key(key) {}
+};
+
class fsblk_t {
protected:
- class iblock_t {
+ class iblock_t : public fs_refcounted_inner {
public:
- iblock_t(uint32_t size) : m_ref(0), m_weak_ref(0), m_size(size) {}
+ iblock_t(uint32_t size) : fs_refcounted_inner(), m_size(size) {}
virtual ~iblock_t() = default;
- void ref();
- void ref_weak();
- void unref();
- void unref_weak();
-
uint32_t size() const { return m_size; }
- virtual void drop_weak_references() = 0;
-
virtual const uint8_t *rodata() = 0;
virtual uint8_t *data() = 0;
uint8_t *offset(const char *function, uint32_t off, uint32_t size);
const uint8_t *rooffset(const char *function, uint32_t off, uint32_t size);
protected:
- uint32_t m_ref, m_weak_ref;
uint32_t m_size;
};
public:
- class block_t {
+ class block_t : public fs_refcounted_outer<iblock_t> {
public:
- block_t(iblock_t *block, bool weak = false) : m_block(block), m_is_weak_ref(weak) {
- ref();
- }
-
- block_t(const block_t &cref) {
- m_block = cref.m_block;
- m_is_weak_ref = cref.m_is_weak_ref;
- ref();
- }
-
- block_t(block_t &&cref) {
- m_block = cref.m_block;
- m_is_weak_ref = cref.m_is_weak_ref;
- cref.m_block = nullptr;
- }
-
- ~block_t() {
- unref();
- }
+ block_t(bool weak = false) : fs_refcounted_outer<iblock_t>(weak) {}
+ block_t(iblock_t *block, bool weak = true) : fs_refcounted_outer(block, weak) {}
+ virtual ~block_t() = default;
- block_t &operator =(const block_t &cref) {
- m_block = cref.m_block;
- m_is_weak_ref = cref.m_is_weak_ref;
- ref();
- return *this;
- }
+ block_t strong() { return block_t(m_object, false); }
+ block_t weak() { return block_t(m_object, true); }
- block_t &operator =(block_t &&cref) {
- m_block = cref.m_block;
- m_is_weak_ref = cref.m_is_weak_ref;
- cref.m_block = nullptr;
- return *this;
- }
-
- const uint8_t *rodata() {
- return m_block ? m_block->rodata() : nullptr;
- }
-
- uint8_t *data() {
- return m_block ? m_block->data() : nullptr;
- }
+ const uint8_t *rodata() { return m_object->rodata(); }
+ uint8_t *data() { return m_object->data(); }
void copy(uint32_t offset, const uint8_t *src, uint32_t size);
- void fill( uint8_t data);
+ void fill( uint8_t data);
void fill(uint32_t offset, uint8_t data, uint32_t size);
void wstr(uint32_t offset, const std::string &str);
void w8( uint32_t offset, uint8_t data);
- void w16b(uint32_t offset, u16 data);
+ void w16b(uint32_t offset, uint16_t data);
+ void w24b(uint32_t offset, uint32_t data);
void w32b(uint32_t offset, uint32_t data);
- void w16l(uint32_t offset, u16 data);
+ void w16l(uint32_t offset, uint16_t data);
+ void w24l(uint32_t offset, uint32_t data);
void w32l(uint32_t offset, uint32_t data);
std::string rstr(uint32_t offset, uint32_t size);
-
- private:
- iblock_t *m_block;
- bool m_is_weak_ref;
-
- void ref() {
- if(m_block) {
- if(m_is_weak_ref)
- m_block->ref_weak();
- else
- m_block->ref();
- }
- }
-
- void unref() {
- if(m_block) {
- if(m_is_weak_ref)
- m_block->unref_weak();
- else
- m_block->unref();
- }
- }
+ uint8_t r8( uint32_t offset);
+ uint16_t r16b(uint32_t offset);
+ uint32_t r24b(uint32_t offset);
+ uint32_t r32b(uint32_t offset);
+ uint16_t r16l(uint32_t offset);
+ uint32_t r24l(uint32_t offset);
+ uint32_t r32l(uint32_t offset);
};
fsblk_t() : m_block_size(0) {}
virtual ~fsblk_t() = default;
-
+
virtual void set_block_size(uint32_t block_size);
virtual uint32_t block_count() const = 0;
virtual block_t get(uint32_t id) = 0;
@@ -177,148 +282,72 @@ protected:
class filesystem_t {
+public:
+ class dir_t;
+ class file_t;
+
protected:
- class idir_t {
+ class idir_t : public fs_refcounted_inner {
public:
- virtual ~idir_t();
-
- void ref();
- void ref_weak();
- void unref();
- void unref_weak();
-
- virtual void drop_weak_references();
+ idir_t() : fs_refcounted_inner() {}
+ virtual ~idir_t() = default;
+
+ virtual fs_meta_data metadata() = 0;
+ virtual void metadata_change(const fs_meta_data &info);
+ virtual std::vector<fs_dir_entry> contents() = 0;
+ virtual file_t file_get(uint64_t key) = 0;
+ virtual dir_t dir_get(uint64_t key) = 0;
+ virtual file_t file_create(const fs_meta_data &info);
+ virtual void file_delete(uint64_t key);
};
- class ifile_t {
+ class ifile_t : public fs_refcounted_inner {
public:
- virtual ~ifile_t();
-
- void ref();
- void ref_weak();
- void unref();
- void unref_weak();
-
- virtual void drop_weak_references();
+ ifile_t() : fs_refcounted_inner() {}
+ virtual ~ifile_t() = default;
+
+ virtual fs_meta_data metadata() = 0;
+ virtual void metadata_change(const fs_meta_data &info);
+ virtual std::vector<u8> read_all() = 0;
+ virtual void replace(const std::vector<u8> &data);
+ virtual std::vector<u8> rsrc_read_all();
+ virtual void rsrc_replace(const std::vector<u8> &data);
};
public:
- class dir_t {
+ class dir_t : public fs_refcounted_outer<idir_t> {
public:
- dir_t(idir_t *dir, bool weak = false) : m_dir(dir), m_is_weak_ref(weak) {
- ref();
- }
-
- dir_t(const dir_t &cref) {
- m_dir = cref.m_dir;
- m_is_weak_ref = cref.m_is_weak_ref;
- ref();
- }
-
- dir_t(dir_t &&cref) {
- m_dir = cref.m_dir;
- m_is_weak_ref = cref.m_is_weak_ref;
- cref.m_dir = nullptr;
- }
-
- ~dir_t() {
- unref();
- }
-
- dir_t &operator =(const dir_t &cref) {
- m_dir = cref.m_dir;
- m_is_weak_ref = cref.m_is_weak_ref;
- ref();
- return *this;
- }
-
- dir_t &operator =(dir_t &&cref) {
- m_dir = cref.m_dir;
- m_is_weak_ref = cref.m_is_weak_ref;
- cref.m_dir = nullptr;
- return *this;
- }
-
- private:
- idir_t *m_dir;
- bool m_is_weak_ref;
-
- void ref() {
- if(m_dir) {
- if(m_is_weak_ref)
- m_dir->ref_weak();
- else
- m_dir->ref();
- }
- }
-
- void unref() {
- if(m_dir) {
- if(m_is_weak_ref)
- m_dir->unref_weak();
- else
- m_dir->unref();
- }
- }
+ dir_t(bool weak = false) : fs_refcounted_outer<idir_t>(weak) {}
+ dir_t(idir_t *dir, bool weak = true) : fs_refcounted_outer(dir, weak) {}
+ virtual ~dir_t() = default;
+
+ dir_t strong() { return dir_t(m_object, false); }
+ dir_t weak() { return dir_t(m_object, true); }
+
+ fs_meta_data metadata() { return m_object->metadata(); }
+ void metadata_change(const fs_meta_data &info) { m_object->metadata_change(info); }
+ std::vector<fs_dir_entry> contents() { return m_object->contents(); }
+ file_t file_get(uint64_t key) { return m_object->file_get(key); }
+ dir_t dir_get(uint64_t key) { return m_object->dir_get(key); }
+ file_t file_create(const fs_meta_data &info) { return m_object->file_create(info); }
+ void file_delete(uint64_t key) { m_object->file_delete(key); }
};
- class file_t {
+ class file_t : public fs_refcounted_outer<ifile_t> {
public:
- file_t(ifile_t *file, bool weak = false) : m_file(file), m_is_weak_ref(weak) {
- ref();
- }
-
- file_t(const file_t &cref) {
- m_file = cref.m_file;
- m_is_weak_ref = cref.m_is_weak_ref;
- ref();
- }
-
- file_t(file_t &&cref) {
- m_file = cref.m_file;
- m_is_weak_ref = cref.m_is_weak_ref;
- cref.m_file = nullptr;
- }
-
- ~file_t() {
- unref();
- }
-
- file_t &operator =(const file_t &cref) {
- m_file = cref.m_file;
- m_is_weak_ref = cref.m_is_weak_ref;
- ref();
- return *this;
- }
-
- file_t &operator =(file_t &&cref) {
- m_file = cref.m_file;
- m_is_weak_ref = cref.m_is_weak_ref;
- cref.m_file = nullptr;
- return *this;
- }
-
- private:
- ifile_t *m_file;
- bool m_is_weak_ref;
-
- void ref() {
- if(m_file) {
- if(m_is_weak_ref)
- m_file->ref_weak();
- else
- m_file->ref();
- }
- }
-
- void unref() {
- if(m_file) {
- if(m_is_weak_ref)
- m_file->unref_weak();
- else
- m_file->unref();
- }
- }
+ file_t(bool weak = false) : fs_refcounted_outer<ifile_t>(weak) {}
+ file_t(ifile_t *file, bool weak = true) : fs_refcounted_outer(file, weak) {}
+ virtual ~file_t() = default;
+
+ file_t strong() { return file_t(m_object, false); }
+ file_t weak() { return file_t(m_object, true); }
+
+ fs_meta_data metadata() { return m_object->metadata(); }
+ void metadata_change(const fs_meta_data &info) { m_object->metadata_change(info); }
+ std::vector<u8> read_all() { return m_object->read_all(); }
+ void replace(const std::vector<u8> &data) { m_object->replace(data); }
+ std::vector<u8> rsrc_read_all() { return m_object->rsrc_read_all(); }
+ void rsrc_replace(const std::vector<u8> &data) { m_object->rsrc_replace(data); }
};
filesystem_t(fsblk_t &blockdev, u32 size) : m_blockdev(blockdev) {
@@ -327,22 +356,45 @@ public:
virtual ~filesystem_t() = default;
+ virtual dir_t root();
virtual void format(const fs_meta_data &meta);
virtual fs_meta_data metadata();
- virtual dir_t root();
+ virtual void metadata_change(const fs_meta_data &info);
+
+ static void copy(uint8_t *p, const uint8_t *src, uint32_t size);
+ static void fill(uint8_t *p, uint8_t data, uint32_t size);
+ static void wstr(uint8_t *p, const std::string &str);
+ static void w8( uint8_t *p, uint8_t data);
+ static void w16b(uint8_t *p, uint16_t data);
+ static void w24b(uint8_t *p, uint32_t data);
+ static void w32b(uint8_t *p, uint32_t data);
+ static void w16l(uint8_t *p, uint16_t data);
+ static void w24l(uint8_t *p, uint32_t data);
+ static void w32l(uint8_t *p, uint32_t data);
+
+ static std::string rstr(const uint8_t *p, uint32_t size);
+ static uint8_t r8( const uint8_t *p);
+ static uint16_t r16b(const uint8_t *p);
+ static uint32_t r24b(const uint8_t *p);
+ static uint32_t r32b(const uint8_t *p);
+ static uint16_t r16l(const uint8_t *p);
+ static uint32_t r24l(const uint8_t *p);
+ static uint32_t r32l(const uint8_t *p);
+
+ static std::string trim_end_spaces(const std::string &str);
protected:
fsblk_t &m_blockdev;
};
class unformatted_floppy_creator;
-
+
class filesystem_manager_t {
public:
struct floppy_enumerator {
virtual ~floppy_enumerator() = default;
- virtual void add(const filesystem_manager_t *manager, floppy_format_type type, uint32_t image_size, const char *name, const char *description) = 0;
+ virtual void add(floppy_format_type type, uint32_t image_size, const char *name, const char *description) = 0;
virtual void add_raw(const char *name, uint32_t key, const char *description) = 0;
};
@@ -361,6 +413,9 @@ public:
virtual ~filesystem_manager_t() = default;
+ virtual const char *name() const = 0;
+ virtual const char *description() const = 0;
+
virtual void enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const;
virtual void enumerate_h(hd_enumerator &he) const;
virtual void enumerate_c(cdrom_enumerator &ce) const;
@@ -368,7 +423,10 @@ public:
virtual bool can_format() const = 0;
virtual bool can_read() const = 0;
virtual bool can_write() const = 0;
- virtual bool has_subdirectories() const = 0;
+ virtual bool has_rsrc() const = 0;
+ virtual char directory_separator() const;
+
+ bool has_subdirectories() const { return directory_separator() != 0; }
virtual std::vector<fs_meta_description> volume_meta_description() const;
virtual std::vector<fs_meta_description> file_meta_description() const;
@@ -384,14 +442,4 @@ protected:
static bool has_variant(const std::vector<uint32_t> &variants, uint32_t variant);
};
-
-typedef filesystem_manager_t *(*filesystem_manager_type)();
-
-// this template function creates a stub which constructs a filesystem manager
-template<class _FormatClass>
-filesystem_manager_t *filesystem_manager_creator()
-{
- return new _FormatClass();
-}
-
#endif