Filesystem code refactoring (#11570)

- Separate fs::block_t and fs::filesystem_t to a new source file and header
- Remove inclusion of flopimg.h from fsmgr.h
This commit is contained in:
ajrhacker 2023-09-27 03:48:50 -04:00 committed by GitHub
parent 7edf0aa2ab
commit d8f1b27939
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 574 additions and 513 deletions

View File

@ -75,6 +75,8 @@ project "formats"
MAME_DIR .. "src/lib/formats/fsmgr.h",
MAME_DIR .. "src/lib/formats/fsmgr.cpp",
MAME_DIR .. "src/lib/formats/fsblk.h",
MAME_DIR .. "src/lib/formats/fsblk.cpp",
MAME_DIR .. "src/lib/formats/fsblk_vec.h",
MAME_DIR .. "src/lib/formats/fsblk_vec.cpp",
MAME_DIR .. "src/lib/formats/fs_unformatted.h",

View File

@ -12,10 +12,13 @@
#include "fs_cbmdos.h"
#include "d64_dsk.h"
#include "fsblk.h"
#include "corestr.h"
#include "strformat.h"
#include <array>
#include <optional>
#include <set>
#include <string_view>
#include <tuple>

View File

@ -13,10 +13,7 @@
#pragma once
#include "fsmgr.h"
#include <optional>
#include <string_view>
namespace fs {

View File

@ -15,10 +15,13 @@
#include "fs_coco_os9.h"
#include "coco_rawdsk.h"
#include "fsblk.h"
#include "multibyte.h"
#include "strformat.h"
#include <optional>
using namespace fs;

View File

@ -14,8 +14,6 @@
#pragma once
#include "fsmgr.h"
#include <optional>
#include <string_view>
namespace fs {

View File

@ -10,6 +10,8 @@
#include "fs_coco_rsdos.h"
#include "coco_rawdsk.h"
#include "fsblk.h"
#include "util/strformat.h"
#include <bitset>

View File

@ -14,8 +14,6 @@
#pragma once
#include "fsmgr.h"
#include <optional>
#include <string_view>
namespace fs {

View File

@ -141,10 +141,13 @@
****************************************************************************/
#include "fs_fat.h"
#include "fsblk.h"
#include "pc_dsk.h"
#include "strformat.h"
#include <optional>
using namespace fs;
const fs::pc_fat_image fs::PC_FAT;

View File

@ -14,11 +14,11 @@
#pragma once
#include "fsmgr.h"
#include <optional>
#include <string_view>
namespace fs {
using u8 = uint8_t;
// ======================> fat_image
class fat_image : public manager_t {

View File

@ -59,8 +59,11 @@
*********************************************************************/
#include "fs_hp98x5.h"
#include "fsblk.h"
#include "hpi_dsk.h"
#include "strformat.h"
#include <bitset>
#include <map>

View File

@ -9,16 +9,20 @@
***************************************************************************/
#include "fs_hplif.h"
#include "fsblk.h"
#include "hp300_dsk.h"
#include "corestr.h"
#include "osdcomm.h"
#include "strformat.h"
#include <array>
#include <optional>
#include <set>
#include <string_view>
#include <tuple>
#include <iostream>
namespace fs {
const hplif_image HPLIF;
};

View File

@ -13,10 +13,7 @@
#pragma once
#include "fsmgr.h"
#include <optional>
#include <string_view>
namespace fs {
@ -39,7 +36,6 @@ namespace fs {
virtual std::vector<meta_description> file_meta_description() const override;
};
extern const hplif_image HPLIF;
} // namespace fs

View File

@ -9,6 +9,7 @@
*********************************************************************/
#include "fs_isis.h"
#include "fsblk.h"
#include "img_dsk.h"
#include "multibyte.h"

View File

@ -4,6 +4,7 @@
// Management of Oric Jasmin floppy images
#include "fs_oric_jasmin.h"
#include "fsblk.h"
#include "oric_dsk.h"
#include "multibyte.h"

View File

@ -5,6 +5,7 @@
#include "fs_prodos.h"
#include "ap_dsk35.h"
#include "fsblk.h"
#include "multibyte.h"
#include "strformat.h"

View File

@ -4,6 +4,8 @@
// Creation of unformatted floppy images
#include "fs_unformatted.h"
#include "flopimg.h"
#include "fsblk.h"
namespace fs {

View File

@ -10,6 +10,8 @@
#include "fsmgr.h"
class floppy_image;
namespace fs {
class unformatted_image : public manager_t {

View File

@ -4,6 +4,7 @@
// Management of VTech images
#include "fs_vtech.h"
#include "fsblk.h"
#include "vt_dsk.h"
#include "multibyte.h"

254
src/lib/formats/fsblk.cpp Normal file
View File

@ -0,0 +1,254 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
// Filesystem operations on mounted image blocks
#include "fsblk.h"
#include "multibyte.h"
#include "strformat.h"
#include <cstring>
#include <stdexcept>
namespace fs {
void refcounted_inner::ref()
{
m_ref ++;
}
void refcounted_inner::ref_weak()
{
m_weak_ref ++;
}
bool refcounted_inner::unref()
{
m_ref --;
if(m_ref == 0) {
if(m_weak_ref)
drop_weak_references();
else
delete this;
return true;
}
return false;
}
bool refcounted_inner::unref_weak()
{
m_weak_ref --;
if(m_weak_ref == 0 && m_ref == 0) {
delete this;
return true;
}
return false;
}
void fsblk_t::set_block_size(u32 block_size)
{
m_block_size = block_size;
}
u8 *fsblk_t::iblock_t::offset(const char *function, u32 off, u32 size)
{
if(off + size > m_size)
throw std::out_of_range(util::string_format("block_t::%s out-of-block access, offset=%d, size=%d, block size=%d", function, off, size, m_size));
return data() + off;
}
const u8 *fsblk_t::iblock_t::rooffset(const char *function, u32 off, u32 size)
{
if(off + size > m_size)
throw std::out_of_range(util::string_format("block_t::%s out-of-block read access, offset=%d, size=%d, block size=%d\n", function, off, size, m_size));
return rodata() + off;
}
void fsblk_t::block_t::copy(u32 offset, const u8 *src, u32 size)
{
memcpy(m_object->offset("copy", offset, size), src, size);
}
void fsblk_t::block_t::fill(u32 offset, u8 data, u32 size)
{
memset(m_object->offset("fill", offset, size), data, size);
}
void fsblk_t::block_t::fill(u8 data)
{
memset(m_object->data(), data, m_object->size());
}
void fsblk_t::block_t::wstr(u32 offset, std::string_view str)
{
memcpy(m_object->offset("wstr", offset, str.size()), str.data(), str.size());
}
void fsblk_t::block_t::w8(u32 offset, u8 data)
{
m_object->offset("w8", offset, 1)[0] = data;
}
void fsblk_t::block_t::w16b(u32 offset, u16 data)
{
put_u16be(m_object->offset("w16b", offset, 2), data);
}
void fsblk_t::block_t::w24b(u32 offset, u32 data)
{
put_u24be(m_object->offset("w24b", offset, 3), data);
}
void fsblk_t::block_t::w32b(u32 offset, u32 data)
{
put_u32be(m_object->offset("w32b", offset, 4), data);
}
void fsblk_t::block_t::w16l(u32 offset, u16 data)
{
put_u16le(m_object->offset("w16l", offset, 2), data);
}
void fsblk_t::block_t::w24l(u32 offset, u32 data)
{
put_u24le(m_object->offset("w24l", offset, 3), data);
}
void fsblk_t::block_t::w32l(u32 offset, u32 data)
{
put_u32le(m_object->offset("w32l", offset, 4), data);
}
std::string_view fsblk_t::block_t::rstr(u32 offset, u32 size) const
{
const u8 *d = m_object->rooffset("rstr", offset, size);
return std::string_view(reinterpret_cast<const char *>(d), size);
}
u8 fsblk_t::block_t::r8(u32 offset) const
{
return m_object->offset("r8", offset, 1)[0];
}
u16 fsblk_t::block_t::r16b(u32 offset) const
{
return get_u16be(m_object->offset("r16b", offset, 2));
}
u32 fsblk_t::block_t::r24b(u32 offset) const
{
return get_u24be(m_object->offset("r24b", offset, 3));
}
u32 fsblk_t::block_t::r32b(u32 offset) const
{
return get_u32be(m_object->offset("r32b", offset, 4));
}
u16 fsblk_t::block_t::r16l(u32 offset) const
{
return get_u16le(m_object->offset("r16l", offset, 2));
}
u32 fsblk_t::block_t::r24l(u32 offset) const
{
return get_u24le(m_object->offset("r24l", offset, 3));
}
u32 fsblk_t::block_t::r32l(u32 offset) const
{
return get_u32le(m_object->offset("r32l", offset, 4));
}
void filesystem_t::wstr(u8 *p, std::string_view str)
{
memcpy(p, str.data(), str.size());
}
std::string_view filesystem_t::rstr(const u8 *p, u32 size)
{
return std::string_view(reinterpret_cast<const char *>(p), size);
}
std::string_view filesystem_t::trim_end_spaces(std::string_view str)
{
const auto i = str.find_last_not_of(' ');
return str.substr(0, (std::string::npos != i) ? (i + 1) : 0);
}
meta_data filesystem_t::volume_metadata()
{
return meta_data();
}
err_t filesystem_t::volume_metadata_change(const meta_data &meta)
{
return ERR_UNSUPPORTED;
}
std::pair<err_t, meta_data> filesystem_t::metadata(const std::vector<std::string> &path)
{
return std::make_pair(ERR_UNSUPPORTED, meta_data());
}
err_t filesystem_t::metadata_change(const std::vector<std::string> &path, const meta_data &meta)
{
return ERR_UNSUPPORTED;
}
std::pair<err_t, std::vector<dir_entry>> filesystem_t::directory_contents(const std::vector<std::string> &path)
{
return std::make_pair(ERR_UNSUPPORTED, std::vector<dir_entry>());
}
err_t filesystem_t::rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath)
{
return ERR_UNSUPPORTED;
}
err_t filesystem_t::remove(const std::vector<std::string> &path)
{
return ERR_UNSUPPORTED;
}
err_t filesystem_t::dir_create(const std::vector<std::string> &path, const meta_data &meta)
{
return ERR_UNSUPPORTED;
}
err_t filesystem_t::file_create(const std::vector<std::string> &path, const meta_data &meta)
{
return ERR_UNSUPPORTED;
}
std::pair<err_t, std::vector<u8>> filesystem_t::file_read(const std::vector<std::string> &path)
{
return std::make_pair(ERR_UNSUPPORTED, std::vector<u8>());
}
err_t filesystem_t::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
{
return ERR_UNSUPPORTED;
}
std::pair<err_t, std::vector<u8>> filesystem_t::file_rsrc_read(const std::vector<std::string> &path)
{
return std::make_pair(ERR_UNSUPPORTED, std::vector<u8>());
}
err_t filesystem_t::file_rsrc_write(const std::vector<std::string> &path, const std::vector<u8> &data)
{
return ERR_UNSUPPORTED;
}
err_t filesystem_t::format(const meta_data &meta)
{
return ERR_UNSUPPORTED;
}
} // namespace fs

276
src/lib/formats/fsblk.h Normal file
View File

@ -0,0 +1,276 @@
// 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 <string>
#include <string_view>
#include <utility>
#include <vector>
namespace fs {
using u8 = uint8_t;
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 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 {
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> {
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); }
u32 size() const { return m_object->size(); }
const u8 *rodata() const { return m_object->rodata(); }
u8 *data() { return m_object->data(); }
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);
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;
};
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 get(u32 id) = 0;
virtual void fill(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 err_t 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);
// 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);
// 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);
// 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);
// 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);
// 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);
// 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);
// Read the contents of a file
virtual std::pair<err_t, 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);
// 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);
// 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);
// Format an image, provide the volume metadata
virtual err_t 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;
};
} // namespace fs
#endif

View File

@ -3,7 +3,7 @@
// Block device on vector<uint8_t>
#include "fsmgr.h"
#include "fsblk.h"
namespace fs {

View File

@ -6,49 +6,10 @@
// Currently limited to floppies and creation of preformatted images
#include "fsmgr.h"
#include "multibyte.h"
#include "strformat.h"
#include <stdexcept>
#include "flopimg.h"
namespace fs {
void refcounted_inner::ref()
{
m_ref ++;
}
void refcounted_inner::ref_weak()
{
m_weak_ref ++;
}
bool refcounted_inner::unref()
{
m_ref --;
if(m_ref == 0) {
if(m_weak_ref)
drop_weak_references();
else
delete this;
return true;
}
return false;
}
bool refcounted_inner::unref_weak()
{
m_weak_ref --;
if(m_weak_ref == 0 && m_ref == 0) {
delete this;
return true;
}
return false;
}
void manager_t::enumerate_f(floppy_enumerator &fe) const
{
}
@ -104,209 +65,6 @@ char manager_t::directory_separator() const
return 0; // Subdirectories not supported by default
}
void fsblk_t::set_block_size(u32 block_size)
{
m_block_size = block_size;
}
u8 *fsblk_t::iblock_t::offset(const char *function, u32 off, u32 size)
{
if(off + size > m_size)
throw std::out_of_range(util::string_format("block_t::%s out-of-block access, offset=%d, size=%d, block size=%d", function, off, size, m_size));
return data() + off;
}
const u8 *fsblk_t::iblock_t::rooffset(const char *function, u32 off, u32 size)
{
if(off + size > m_size)
throw std::out_of_range(util::string_format("block_t::%s out-of-block read access, offset=%d, size=%d, block size=%d\n", function, off, size, m_size));
return rodata() + off;
}
void fsblk_t::block_t::copy(u32 offset, const u8 *src, u32 size)
{
memcpy(m_object->offset("copy", offset, size), src, size);
}
void fsblk_t::block_t::fill(u32 offset, u8 data, u32 size)
{
memset(m_object->offset("fill", offset, size), data, size);
}
void fsblk_t::block_t::fill(u8 data)
{
memset(m_object->data(), data, m_object->size());
}
void fsblk_t::block_t::wstr(u32 offset, std::string_view str)
{
memcpy(m_object->offset("wstr", offset, str.size()), str.data(), str.size());
}
void fsblk_t::block_t::w8(u32 offset, u8 data)
{
m_object->offset("w8", offset, 1)[0] = data;
}
void fsblk_t::block_t::w16b(u32 offset, u16 data)
{
put_u16be(m_object->offset("w16b", offset, 2), data);
}
void fsblk_t::block_t::w24b(u32 offset, u32 data)
{
put_u24be(m_object->offset("w24b", offset, 3), data);
}
void fsblk_t::block_t::w32b(u32 offset, u32 data)
{
put_u32be(m_object->offset("w32b", offset, 4), data);
}
void fsblk_t::block_t::w16l(u32 offset, u16 data)
{
put_u16le(m_object->offset("w16l", offset, 2), data);
}
void fsblk_t::block_t::w24l(u32 offset, u32 data)
{
put_u24le(m_object->offset("w24l", offset, 3), data);
}
void fsblk_t::block_t::w32l(u32 offset, u32 data)
{
put_u32le(m_object->offset("w32l", offset, 4), data);
}
std::string_view fsblk_t::block_t::rstr(u32 offset, u32 size) const
{
const u8 *d = m_object->rooffset("rstr", offset, size);
return std::string_view(reinterpret_cast<const char *>(d), size);
}
u8 fsblk_t::block_t::r8(u32 offset) const
{
return m_object->offset("r8", offset, 1)[0];
}
u16 fsblk_t::block_t::r16b(u32 offset) const
{
return get_u16be(m_object->offset("r16b", offset, 2));
}
u32 fsblk_t::block_t::r24b(u32 offset) const
{
return get_u24be(m_object->offset("r24b", offset, 3));
}
u32 fsblk_t::block_t::r32b(u32 offset) const
{
return get_u32be(m_object->offset("r32b", offset, 4));
}
u16 fsblk_t::block_t::r16l(u32 offset) const
{
return get_u16le(m_object->offset("r16l", offset, 2));
}
u32 fsblk_t::block_t::r24l(u32 offset) const
{
return get_u24le(m_object->offset("r24l", offset, 3));
}
u32 fsblk_t::block_t::r32l(u32 offset) const
{
return get_u32le(m_object->offset("r32l", offset, 4));
}
void filesystem_t::wstr(u8 *p, std::string_view str)
{
memcpy(p, str.data(), str.size());
}
std::string_view filesystem_t::rstr(const u8 *p, u32 size)
{
return std::string_view(reinterpret_cast<const char *>(p), size);
}
std::string_view filesystem_t::trim_end_spaces(std::string_view str)
{
const auto i = str.find_last_not_of(' ');
return str.substr(0, (std::string::npos != i) ? (i + 1) : 0);
}
meta_data filesystem_t::volume_metadata()
{
return meta_data();
}
err_t filesystem_t::volume_metadata_change(const meta_data &meta)
{
return ERR_UNSUPPORTED;
}
std::pair<err_t, meta_data> filesystem_t::metadata(const std::vector<std::string> &path)
{
return std::make_pair(ERR_UNSUPPORTED, meta_data());
}
err_t filesystem_t::metadata_change(const std::vector<std::string> &path, const meta_data &meta)
{
return ERR_UNSUPPORTED;
}
std::pair<err_t, std::vector<dir_entry>> filesystem_t::directory_contents(const std::vector<std::string> &path)
{
return std::make_pair(ERR_UNSUPPORTED, std::vector<dir_entry>());
}
err_t filesystem_t::rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath)
{
return ERR_UNSUPPORTED;
}
err_t filesystem_t::remove(const std::vector<std::string> &path)
{
return ERR_UNSUPPORTED;
}
err_t filesystem_t::dir_create(const std::vector<std::string> &path, const meta_data &meta)
{
return ERR_UNSUPPORTED;
}
err_t filesystem_t::file_create(const std::vector<std::string> &path, const meta_data &meta)
{
return ERR_UNSUPPORTED;
}
std::pair<err_t, std::vector<u8>> filesystem_t::file_read(const std::vector<std::string> &path)
{
return std::make_pair(ERR_UNSUPPORTED, std::vector<u8>());
}
err_t filesystem_t::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
{
return ERR_UNSUPPORTED;
}
std::pair<err_t, std::vector<u8>> filesystem_t::file_rsrc_read(const std::vector<std::string> &path)
{
return std::make_pair(ERR_UNSUPPORTED, std::vector<u8>());
}
err_t filesystem_t::file_rsrc_write(const std::vector<std::string> &path, const std::vector<u8> &data)
{
return ERR_UNSUPPORTED;
}
err_t filesystem_t::format(const meta_data &meta)
{
return ERR_UNSUPPORTED;
}
manager_t::floppy_enumerator::floppy_enumerator(u32 form_factor, const std::vector<u32> &variants)
: m_form_factor(form_factor)
, m_variants(variants)

View File

@ -8,266 +8,20 @@
#pragma once
#include "flopimg.h"
#include "fsmeta.h"
#include <memory>
#include <vector>
class floppy_image_format_t;
namespace fs {
using u8 = uint8_t;
using u16 = uint16_t;
// declared in fsblk.h
class filesystem_t;
class fsblk_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 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 {
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> {
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); }
u32 size() const { return m_object->size(); }
const u8 *rodata() const { return m_object->rodata(); }
u8 *data() { return m_object->data(); }
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);
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;
};
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 get(u32 id) = 0;
virtual void fill(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 err_t 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);
// 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);
// 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);
// 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);
// 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);
// 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);
// 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);
// Read the contents of a file
virtual std::pair<err_t, 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);
// 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);
// 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);
// Format an image, provide the volume metadata
virtual err_t 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;
};
class unformatted_floppy_creator;
class manager_t {
public:
@ -301,7 +55,6 @@ public:
virtual void add(const manager_t *manager, const char *name, const char *description) = 0;
};
virtual ~manager_t() = default;
virtual const char *name() const = 0;

View File

@ -8,6 +8,8 @@
#include "image_handler.h"
#include "formats/fsblk.h"
#include "corestr.h"
#include "ioprocs.h"
#include "path.h"

View File

@ -8,6 +8,7 @@
#pragma once
#include "formats/flopimg.h"
#include "formats/fsmgr.h"
#include "harddisk.h"