summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats/fs_coco_os9.cpp
diff options
context:
space:
mode:
author Olivier Galibert <galibert@pobox.com>2022-06-27 10:26:36 +0200
committer Olivier Galibert <galibert@pobox.com>2022-06-28 23:08:45 +0200
commit43d01755e61da415cc12b3215688d23d912fe185 (patch)
tree1b2dc49bc4fbab36cc5fe73724e47c9fc85069e9 /src/lib/formats/fs_coco_os9.cpp
parent735bd1f62632c853f5401051e1c47b54aa746174 (diff)
fs: new API, blk_t is probably going to change too
Diffstat (limited to 'src/lib/formats/fs_coco_os9.cpp')
-rw-r--r--src/lib/formats/fs_coco_os9.cpp689
1 files changed, 33 insertions, 656 deletions
diff --git a/src/lib/formats/fs_coco_os9.cpp b/src/lib/formats/fs_coco_os9.cpp
index 3813255482c..c4fcd14ea16 100644
--- a/src/lib/formats/fs_coco_os9.cpp
+++ b/src/lib/formats/fs_coco_os9.cpp
@@ -18,147 +18,22 @@
#include "strformat.h"
-//**************************************************************************
-// TYPE DECLARATIONS
-//**************************************************************************
-
-namespace {
-
using namespace fs;
-// methods
-std::string pick_os9_string(std::string_view raw_string);
-std::string to_os9_string(std::string_view s, size_t length);
-util::arbitrary_datetime from_os9_date(u32 os9_date, u16 os9_time = 0);
-std::tuple<u32, u16> to_os9_date(const util::arbitrary_datetime &datetime);
-u32 pick_integer_be(const u8 *data, int length);
-bool validate_filename(std::string_view name);
-bool is_ignored_filename(std::string_view name);
-std::vector<meta_description> entity_meta_description();
+namespace fs { const coco_os9_image COCO_OS9; }
+namespace {
-// ======================> volume_header
-
-class volume_header
-{
+class coco_os9_impl : public filesystem_t {
public:
- volume_header(fsblk_t::block_t &&block);
-
- u32 total_sectors() const { return m_block.r24b(0); }
- u8 track_size_in_sectors() const { return m_block.r8(3); }
- u16 allocation_bitmap_bytes() const { return m_block.r16b(4); }
- u16 cluster_size() const { return m_block.r16b(6); }
- u32 root_dir_lsn() const { return m_block.r24b(8); }
- u16 owner_id() const { return m_block.r16b(11); }
- u16 disk_id() const { return m_block.r16b(14); }
- u8 format_flags() const { return m_block.r8(16); }
- u16 sectors_per_track() const { return m_block.r16b(17); }
- u32 bootstrap_lsn() const { return m_block.r24b(21); }
- u16 bootstrap_size() const { return m_block.r16b(24); }
- util::arbitrary_datetime creation_date() const { return from_os9_date(m_block.r24b(26), m_block.r16b(29)); }
- u16 sector_size() const { u16 result = m_block.r16b(104); return result != 0 ? result : 256; }
- u8 sides() const { return (format_flags() & 0x01) ? 2 : 1; }
- bool double_density() const { return (format_flags() & 0x02) != 0; }
- bool double_track() const { return (format_flags() & 0x04) != 0; }
- bool quad_track_density() const { return (format_flags() & 0x08) != 0; }
- bool octal_track_density() const { return (format_flags() & 0x10) != 0; }
-
- std::string name() const;
-
-private:
- fsblk_t::block_t m_block;
-};
+ coco_os9_impl(fsblk_t &blockdev);
+ virtual ~coco_os9_impl() = default;
-
-// ======================> file_header
-
-class file_header
-{
-public:
- file_header(fsblk_t::block_t &&block);
-
- u8 attributes() const { return m_block.r8(0); }
- u16 owner_id() const { return m_block.r16b(1); }
- u8 link_count() const { return m_block.r8(8); }
- u32 file_size() const { return m_block.r32b(9); }
- util::arbitrary_datetime creation_date() const;
- bool is_directory() const { return (attributes() & 0x80) != 0; }
- bool is_non_sharable() const { return (attributes() & 0x40) != 0; }
- bool is_public_execute() const { return (attributes() & 0x20) != 0; }
- bool is_public_write() const { return (attributes() & 0x10) != 0; }
- bool is_public_read() const { return (attributes() & 0x08) != 0; }
- bool is_user_execute() const { return (attributes() & 0x04) != 0; }
- bool is_user_write() const { return (attributes() & 0x02) != 0; }
- bool is_user_read() const { return (attributes() & 0x01) != 0; }
-
- meta_data metadata() const;
- int get_sector_map_entry_count() const;
- void get_sector_map_entry(int entry_number, u32 &start_lsn, u16 &count) const;
-
-private:
- fsblk_t::block_t m_block;
+ static bool is_ignored_filename(std::string_view name);
+ static bool validate_filename(std::string_view name);
};
-
-
-// ======================> impl
-
-class impl : public filesystem_t {
-public:
- class file : public ifile_t {
- public:
- file(impl &fs, file_header &&file_header);
- virtual ~file() = default;
-
- virtual void drop_weak_references() override;
-
- virtual meta_data metadata() override;
- virtual std::vector<u8> read_all() override;
-
- private:
- impl &m_fs;
- file_header m_file_header;
- };
-
- class directory : public idir_t {
- public:
- directory(impl &i, file_header &&file_header);
- virtual ~directory() = default;
-
- virtual void drop_weak_references() override;
- virtual meta_data metadata() override;
- virtual std::vector<dir_entry> contents() override;
- virtual file_t file_get(u64 key) override;
- virtual dir_t dir_get(u64 key) override;
-
- private:
- impl &m_fs;
- file_header m_file_header;
- };
-
- impl(fsblk_t &blockdev, volume_header &&header);
- virtual ~impl() = default;
-
- virtual meta_data metadata() override;
- virtual dir_t root() override;
- virtual void format(const meta_data &meta) override;
-
-private:
- volume_header m_volume_header;
- dir_t m_root;
-
- directory *open_directory(u32 lsn);
- std::vector<u8> read_file_data(const file_header &header) const;
-};
-
}
-namespace fs {
-
-const coco_os9_image COCO_OS9;
-
-};
-
-
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
@@ -167,7 +42,7 @@ const coco_os9_image COCO_OS9;
// name
//-------------------------------------------------
-const char *fs::coco_os9_image::name() const
+const char *coco_os9_image::name() const
{
return "coco_os9";
}
@@ -177,7 +52,7 @@ const char *fs::coco_os9_image::name() const
// description
//-------------------------------------------------
-const char *fs::coco_os9_image::description() const
+const char *coco_os9_image::description() const
{
return "CoCo OS-9";
}
@@ -187,7 +62,7 @@ const char *fs::coco_os9_image::description() const
// enumerate_f
//-------------------------------------------------
-void fs::coco_os9_image::enumerate_f(floppy_enumerator &fe, u32 form_factor, const std::vector<u32> &variants) const
+void coco_os9_image::enumerate_f(floppy_enumerator &fe, u32 form_factor, const std::vector<u32> &variants) const
{
if (has(form_factor, variants, floppy_image::FF_525, floppy_image::SSDD))
{
@@ -201,7 +76,7 @@ void fs::coco_os9_image::enumerate_f(floppy_enumerator &fe, u32 form_factor, con
// can_format
//-------------------------------------------------
-bool fs::coco_os9_image::can_format() const
+bool coco_os9_image::can_format() const
{
return true;
}
@@ -211,7 +86,7 @@ bool fs::coco_os9_image::can_format() const
// can_read
//-------------------------------------------------
-bool fs::coco_os9_image::can_read() const
+bool coco_os9_image::can_read() const
{
return true;
}
@@ -221,7 +96,7 @@ bool fs::coco_os9_image::can_read() const
// can_write
//-------------------------------------------------
-bool fs::coco_os9_image::can_write() const
+bool coco_os9_image::can_write() const
{
return false;
}
@@ -231,7 +106,7 @@ bool fs::coco_os9_image::can_write() const
// has_rsrc
//-------------------------------------------------
-bool fs::coco_os9_image::has_rsrc() const
+bool coco_os9_image::has_rsrc() const
{
return false;
}
@@ -241,7 +116,7 @@ bool fs::coco_os9_image::has_rsrc() const
// directory_separator
//-------------------------------------------------
-char fs::coco_os9_image::directory_separator() const
+char coco_os9_image::directory_separator() const
{
return '/';
}
@@ -251,7 +126,7 @@ char fs::coco_os9_image::directory_separator() const
// volume_meta_description
//-------------------------------------------------
-std::vector<meta_description> fs::coco_os9_image::volume_meta_description() const
+std::vector<meta_description> coco_os9_image::volume_meta_description() const
{
std::vector<meta_description> results;
results.emplace_back(meta_description(meta_name::name, "UNTITLED", false, [](const meta_value &m) { return m.as_string().size() <= 32; }, "Volume name, up to 32 characters"));
@@ -264,51 +139,10 @@ std::vector<meta_description> fs::coco_os9_image::volume_meta_description() cons
// file_meta_description
//-------------------------------------------------
-std::vector<meta_description> fs::coco_os9_image::file_meta_description() const
-{
- return entity_meta_description();
-}
-
-
-//-------------------------------------------------
-// directory_meta_description
-//-------------------------------------------------
-
-std::vector<meta_description> fs::coco_os9_image::directory_meta_description() const
-{
- return entity_meta_description();
-}
-
-
-//-------------------------------------------------
-// mount
-//-------------------------------------------------
-
-std::unique_ptr<filesystem_t> fs::coco_os9_image::mount(fsblk_t &blockdev) const
-{
- // read the header block
- blockdev.set_block_size(256);
- volume_header header(blockdev.get(0));
-
- // sanity checks
- if (header.sectors_per_track() != header.track_size_in_sectors())
- return { };
-
- // create the implementation
- return std::make_unique<impl>(blockdev, std::move(header));
-}
-
-
-//-------------------------------------------------
-// entity_meta_description
-//-------------------------------------------------
-
-namespace {
-
-std::vector<meta_description> entity_meta_description()
+std::vector<meta_description> coco_os9_image::file_meta_description() const
{
std::vector<meta_description> results;
- results.emplace_back(meta_description(meta_name::name, "", false, [](const meta_value &m) { return validate_filename(m.as_string()); }, "File name"));
+ results.emplace_back(meta_description(meta_name::name, "", false, [](const meta_value &m) { return coco_os9_impl::validate_filename(m.as_string()); }, "File name"));
results.emplace_back(meta_description(meta_name::creation_date, util::arbitrary_datetime::now(), false, nullptr, "Creation time"));
results.emplace_back(meta_description(meta_name::owner_id, 0, true, nullptr, "Owner ID"));
results.emplace_back(meta_description(meta_name::attributes, "", true, nullptr, "File attributes"));
@@ -318,107 +152,38 @@ std::vector<meta_description> entity_meta_description()
//-------------------------------------------------
-// pick_os9_string
-//-------------------------------------------------
-
-std::string pick_os9_string(std::string_view raw_string)
-{
- // find the last NUL or high bit character
- auto iter = std::find_if(raw_string.begin(), raw_string.end(), [](char ch)
- {
- return ch == '\0' || ch & 0x80;
- });
-
- // get the preliminary result
- std::string result(raw_string.begin(), iter);
-
- // and add the final character if we have to
- if (iter < raw_string.end() && *iter & 0x80)
- result.append(1, *iter & 0x7F);
- return result;
-
-}
-
-
-//-------------------------------------------------
-// to_os9_string
-//-------------------------------------------------
-
-std::string to_os9_string(std::string_view s, size_t length)
-{
- std::string result(length, '\0');
- for (auto i = 0; i < std::min(length, s.size()); i++)
- {
- result[i] = (s[i] & 0x7F)
- | (i == s.size() ? 0x80 : 0x00);
- }
- return result;
-}
-
-
-//-------------------------------------------------
-// pick_integer_be
-//-------------------------------------------------
-
-u32 pick_integer_be(const u8 *data, int length)
-{
- u32 result = 0;
- for (int i = 0; i < length; i++)
- result |= u32(data[length - i - 1]) << i * 8;
- return result;
-}
-
-
-//-------------------------------------------------
-// from_os9_date
+// directory_meta_description
//-------------------------------------------------
-util::arbitrary_datetime from_os9_date(u32 os9_date, u16 os9_time)
+std::vector<meta_description> coco_os9_image::directory_meta_description() const
{
- util::arbitrary_datetime dt;
- memset(&dt, 0, sizeof(dt));
- dt.year = ((os9_date >> 16) & 0xFF) + 1900;
- dt.month = (os9_date >> 8) & 0xFF;
- dt.day_of_month = (os9_date >> 0) & 0xFF;
- dt.hour = (os9_time >> 8) & 0xFF;
- dt.minute = (os9_time >> 0) & 0xFF;
- return dt;
+ return file_meta_description();
}
-
//-------------------------------------------------
-// to_os9_date
+// mount
//-------------------------------------------------
-std::tuple<u32, u16> to_os9_date(const util::arbitrary_datetime &datetime)
+std::unique_ptr<filesystem_t> coco_os9_image::mount(fsblk_t &blockdev) const
{
- u32 os9_date = ((datetime.year - 1900) & 0xFF) << 16
- | (datetime.month & 0xFF) << 8
- | (datetime.day_of_month & 0xFF) << 0;
- u16 os9_time = (datetime.hour & 0xFF) << 8
- | (datetime.minute & 0xFF) << 0;
- return std::make_tuple(os9_date, os9_time);
+ return std::make_unique<coco_os9_impl>(blockdev);
}
-
//-------------------------------------------------
-// validate_filename
+// impl ctor
//-------------------------------------------------
-bool validate_filename(std::string_view name)
+coco_os9_impl::coco_os9_impl(fsblk_t &blockdev)
+ : filesystem_t(blockdev, 256)
{
- return !is_ignored_filename(name)
- && name.size() <= 29
- && std::find_if(name.begin(), name.end(), [](const char ch) { return ch == '\0' || ch == '/' || ch >= 0x80; }) == name.end();
}
-
//-------------------------------------------------
// is_ignored_filename - should this file name be
// ignored if it is in the file system?
//-------------------------------------------------
-bool is_ignored_filename(std::string_view name)
+bool coco_os9_impl::is_ignored_filename(std::string_view name)
{
return name.empty()
|| name[0] == '\0'
@@ -426,401 +191,13 @@ bool is_ignored_filename(std::string_view name)
|| name == "..";
}
-
-//-------------------------------------------------
-// volume_header ctor
-//-------------------------------------------------
-
-volume_header::volume_header(fsblk_t::block_t &&block)
- : m_block(std::move(block))
-{
-}
-
-
-//-------------------------------------------------
-// volume_header::name
-//-------------------------------------------------
-
-std::string volume_header::name() const
-{
- std::string_view raw_name((const char *)&m_block.rodata()[31], 32);
- return pick_os9_string(raw_name);
-}
-
-
-//-------------------------------------------------
-// file_header ctor
-//-------------------------------------------------
-
-file_header::file_header(fsblk_t::block_t &&block)
- : m_block(std::move(block))
-{
-}
-
-
-//-------------------------------------------------
-// file_header::creation_date
-//-------------------------------------------------
-
-util::arbitrary_datetime file_header::creation_date() const
-{
- return from_os9_date(m_block.r24b(13));
-}
-
-
-//-------------------------------------------------
-// file_header::metadata
-//-------------------------------------------------
-
-meta_data file_header::metadata() const
-{
- // format the attributes
- std::string attributes = util::string_format("%c%c%c%c%c%c%c%c",
- is_directory() ? 'd' : '-',
- is_non_sharable() ? 's' : '-',
- is_public_execute() ? 'x' : '-',
- is_public_write() ? 'w' : '-',
- is_public_read() ? 'r' : '-',
- is_user_execute() ? 'x' : '-',
- is_user_write() ? 'w' : '-',
- is_user_read() ? 'r' : '-');
-
- meta_data result;
- result.set(meta_name::creation_date, creation_date());
- result.set(meta_name::owner_id, owner_id());
- result.set(meta_name::attributes, std::move(attributes));
- result.set(meta_name::length, file_size());
- return result;
-}
-
-
-//-------------------------------------------------
-// file_header::get_sector_map_entry_count
-//-------------------------------------------------
-
-int file_header::get_sector_map_entry_count() const
-{
- return (m_block.size() - 16) / 5;
-}
-
-
-//-------------------------------------------------
-// file_header::get_sector_map_entry
-//-------------------------------------------------
-
-void file_header::get_sector_map_entry(int entry_number, u32 &start_lsn, u16 &count) const
-{
- start_lsn = m_block.r24b(16 + (entry_number * 5) + 0);
- count = m_block.r16b(16 + (entry_number * 5) + 3);
-}
-
-
-//-------------------------------------------------
-// impl ctor
-//-------------------------------------------------
-
-impl::impl(fsblk_t &blockdev, volume_header &&header)
- : filesystem_t(blockdev, 256)
- , m_volume_header(std::move(header))
-{
-}
-
-
-//-------------------------------------------------
-// impl::metadata
-//-------------------------------------------------
-
-meta_data impl::metadata()
-{
- meta_data results;
- results.set(meta_name::name, m_volume_header.name());
- results.set(meta_name::creation_date, m_volume_header.creation_date());
- return results;
-}
-
-
-//-------------------------------------------------
-// impl::root
-//-------------------------------------------------
-
-filesystem_t::dir_t impl::root()
-{
- if (!m_root)
- m_root = open_directory(m_volume_header.root_dir_lsn());
- return m_root.strong();
-}
-
-
-//-------------------------------------------------
-// impl::format
-//-------------------------------------------------
-
-void impl::format(const meta_data &meta)
-{
- // for some reason, the OS-9 world favored filling with 0xE5
- m_blockdev.fill(0xE5);
-
- // identify geometry info
- u8 sectors = 18; // TODO - we need a definitive technique to get the floppy geometry
- u8 heads = 1; // TODO - we need a definitive technique to get the floppy geometry
- u16 sector_bytes = 256; // TODO - we need a definitive technique to get the floppy geometry
- bool is_double_density = true; // TODO - we need a definitive technique to get the floppy geometry
- u32 tracks = m_blockdev.block_count() / sectors / heads;
-
- // get attributes from metadata
- std::string volume_title = meta.get_string(meta_name::name, "UNTITLED");
- util::arbitrary_datetime creation_datetime = meta.get_date(meta_name::creation_date);
- auto [creation_os9date, creation_os9time] = to_os9_date(creation_datetime);
-
- u32 lsn_count = m_blockdev.block_count();
- u16 cluster_size = 1;
- u16 owner_id = 1;
- u16 disk_id = 1;
- u8 attributes = 0;
- u32 allocation_bitmap_bits = lsn_count / cluster_size;
- u32 allocation_bitmap_lsns = (allocation_bitmap_bits / 8 + sector_bytes - 1) / sector_bytes;
- u8 format_flags = ((heads > 1) ? 0x01 : 0x00)
- | (is_double_density ? 0x02 : 0x00);
-
- // volume header
- auto volume_header = m_blockdev.get(0);
- volume_header.fill(0x00);
- volume_header.w24b(0, lsn_count); // DD.TOT - total secctors
- volume_header.w8(3, sectors); // DD.TKS - track size in sectors
- volume_header.w16b(4, (allocation_bitmap_bits + 7) / 8); // DD.MAP - allocation bitmap in bytes
- volume_header.w16b(6, cluster_size); // DD.BIT - cluster size
- volume_header.w24b(8, 1 + allocation_bitmap_lsns); // DD.DIR - root directory LSN
- volume_header.w16b(11, owner_id); // DD.OWN - owner ID
- volume_header.w8(13, attributes); // DD.ATT - Dattributes
- volume_header.w16b(14, disk_id); // DD.DSK - disk ID
- volume_header.w8(16, format_flags); // DD.FMT - format flags
- volume_header.w16b(17, sectors); // DD.SPT - sectors per track
- volume_header.w24b(26, creation_os9date); // DD.DAT - date of creation
- volume_header.w16b(29, creation_os9time); // DD.DAT - time of creation
- volume_header.wstr(31, to_os9_string(volume_title, 32)); // DD.NAM - title
- volume_header.w16b(103, sector_bytes / 256); // sector bytes
-
- // path descriptor options
- volume_header.w8(0x3f + 0x00, 1); // device class
- volume_header.w8(0x3f + 0x01, 1); // drive number
- volume_header.w8(0x3f + 0x03, 0x20); // device type
- volume_header.w8(0x3f + 0x04, 1); // density capability
- volume_header.w16b(0x3f + 0x05, tracks); // number of tracks
- volume_header.w8(0x3f + 0x07, heads); // number of sides
- volume_header.w16b(0x3f + 0x09, sectors); // sectors per track
- volume_header.w16b(0x3f + 0x0b, sectors); // sectors on track zero
- volume_header.w8(0x3f + 0x0d, 3); // sector interleave factor
- volume_header.w8(0x3f + 0x0e, 8); // default sectors per allocation
-
- // allocation bitmap
- u32 total_allocated_sectors = 1 + allocation_bitmap_lsns + 1 + 8;
- std::vector<u8> abblk_bytes;
- abblk_bytes.resize(sector_bytes);
- for (u32 i = 0; i < allocation_bitmap_lsns; i++)
- {
- for (u32 j = 0; j < sector_bytes; j++)
- {
- u32 pos = (i * sector_bytes + j) * 8;
- if (pos + 8 < total_allocated_sectors)
- abblk_bytes[j] = 0xFF;
- else if (pos >= total_allocated_sectors)
- abblk_bytes[j] = 0x00;
- else
- abblk_bytes[j] = ~((1 << (8 - total_allocated_sectors + pos)) - 1);
- }
-
- auto abblk = m_blockdev.get(1 + i);
- abblk.copy(0, abblk_bytes.data(), sector_bytes);
- }
-
- // root directory header
- auto roothdr_blk = m_blockdev.get(1 + allocation_bitmap_lsns);
- roothdr_blk.fill(0x00);
- roothdr_blk.w8(0x00, 0xBF);
- roothdr_blk.w8(0x01, 0x00);
- roothdr_blk.w8(0x02, 0x00);
- roothdr_blk.w24b(0x03, creation_os9date);
- roothdr_blk.w16b(0x06, creation_os9time);
- roothdr_blk.w8(0x08, 0x01);
- roothdr_blk.w8(0x09, 0x00);
- roothdr_blk.w8(0x0A, 0x00);
- roothdr_blk.w8(0x0B, 0x00);
- roothdr_blk.w8(0x0C, 0x40);
- roothdr_blk.w24b(0x0D, creation_os9date);
- roothdr_blk.w24b(0x10, 1 + allocation_bitmap_lsns + 1);
- roothdr_blk.w16b(0x13, 8);
-
- // root directory data
- auto rootdata_blk = m_blockdev.get(1 + allocation_bitmap_lsns + 1);
- rootdata_blk.fill(0x00);
- rootdata_blk.w8(0x00, 0x2E);
- rootdata_blk.w8(0x01, 0xAE);
- rootdata_blk.w8(0x1F, 1 + allocation_bitmap_lsns);
- rootdata_blk.w8(0x20, 0xAE);
- rootdata_blk.w8(0x3F, 1 + allocation_bitmap_lsns);
-}
-
-
-//-------------------------------------------------
-// impl::open_directory
-//-------------------------------------------------
-
-impl::directory *impl::open_directory(u32 lsn)
-{
- file_header header(m_blockdev.get(lsn));
- return new directory(*this, std::move(header));
-}
-
-
-//-------------------------------------------------
-// impl::read_file_data
-//-------------------------------------------------
-
-std::vector<u8> impl::read_file_data(const file_header &header) const
-{
- std::vector<u8> data;
- data.reserve(header.file_size());
- int entry_count = header.get_sector_map_entry_count();
- for (int i = 0; i < entry_count; i++)
- {
- u32 start_lsn;
- u16 count;
- header.get_sector_map_entry(i, start_lsn, count);
-
- for (u32 lsn = start_lsn; lsn < start_lsn + count; lsn++)
- {
- auto block = m_blockdev.get(lsn);
- size_t block_size = std::min(std::min(u32(m_volume_header.sector_size()), block.size()), header.file_size() - u32(data.size()));
- for (auto i = 0; i < block_size; i++)
- data.push_back(block.rodata()[i]);
- }
- }
- return data;
-}
-
-
-//-------------------------------------------------
-// file ctor
-//-------------------------------------------------
-
-impl::file::file(impl &i, file_header &&file_header)
- : m_fs(i)
- , m_file_header(std::move(file_header))
-{
-}
-
-
-//-------------------------------------------------
-// file::drop_weak_references
//-------------------------------------------------
-
-void impl::file::drop_weak_references()
-{
-}
-
-
-//-------------------------------------------------
-// file::metadata
-//-------------------------------------------------
-
-meta_data impl::file::metadata()
-{
- return m_file_header.metadata();
-}
-
-
-//-------------------------------------------------
-// file::read_all
-//-------------------------------------------------
-
-std::vector<u8> impl::file::read_all()
-{
- return m_fs.read_file_data(m_file_header);
-}
-
-
-//-------------------------------------------------
-// directory ctor
-//-------------------------------------------------
-
-impl::directory::directory(impl &i, file_header &&file_header)
- : m_fs(i)
- , m_file_header(std::move(file_header))
-{
-}
-
-
-//-------------------------------------------------
-// directory::drop_weak_references
-//-------------------------------------------------
-
-void impl::directory::drop_weak_references()
-{
-}
-
-
-//-------------------------------------------------
-// directory::metadata
-//-------------------------------------------------
-
-meta_data impl::directory::metadata()
-{
- return m_file_header.metadata();
-}
-
-
-//-------------------------------------------------
-// directory::contents
-//-------------------------------------------------
-
-std::vector<dir_entry> impl::directory::contents()
-{
- // read the directory data
- std::vector<u8> directory_data = m_fs.read_file_data(m_file_header);
-
- // and assemble results
- std::vector<dir_entry> results;
- int directory_count = directory_data.size() / 32;
- for (int i = 0; i < directory_count; i++)
- {
- // determine the filename
- std::string_view raw_filename((const char *) &directory_data[i * 32], 29);
- std::string filename = pick_os9_string(raw_filename);
- if (is_ignored_filename(filename))
- continue;
-
- // determine the entry type
- u32 lsn = pick_integer_be(&directory_data[i * 32] + 29, 3);
- file_header file_header(m_fs.m_blockdev.get(lsn));
- dir_entry_type entry_type = file_header.is_directory()
- ? dir_entry_type::dir
- : dir_entry_type::file;
-
- // and return the results
- results.emplace_back(std::move(filename), entry_type, lsn);
- }
- return results;
-}
-
-
-//-------------------------------------------------
-// directory::file_get
-//-------------------------------------------------
-
-filesystem_t::file_t impl::directory::file_get(u64 key)
-{
- file_header header(m_fs.m_blockdev.get(u32(key)));
- return file_t(new file(m_fs, std::move(header)));
-}
-
-
-//-------------------------------------------------
-// directory::dir_get
+// validate_filename
//-------------------------------------------------
-filesystem_t::dir_t impl::directory::dir_get(u64 key)
+bool coco_os9_impl::validate_filename(std::string_view name)
{
- return dir_t(m_fs.open_directory(u32(key)));
+ return !is_ignored_filename(name)
+ && name.size() <= 29
+ && std::find_if(name.begin(), name.end(), [](const char ch) { return ch == '\0' || ch == '/' || ch >= 0x80; }) == name.end();
}
-
-};