From 32edc6508c91e51316d67b92eb86b4e72d0a41a4 Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Fri, 4 Jul 2025 15:43:44 +0200 Subject: feat: libmkfs: a new library to format filesystem and utilities for them. Signed-off-by: Amlal El Mahrouss --- tooling/fsck.hefs.cc | 30 +++++++++++-- tooling/hefs.h | 115 ------------------------------------------------- tooling/libmkfs/hefs.h | 115 +++++++++++++++++++++++++++++++++++++++++++++++++ tooling/libmkfs/mkfs.h | 72 +++++++++++++++++++++++++++++++ tooling/mkfs.h | 36 ---------------- tooling/mkfs.hefs.cc | 60 ++++++-------------------- 6 files changed, 226 insertions(+), 202 deletions(-) delete mode 100644 tooling/hefs.h create mode 100644 tooling/libmkfs/hefs.h create mode 100644 tooling/libmkfs/mkfs.h delete mode 100644 tooling/mkfs.h diff --git a/tooling/fsck.hefs.cc b/tooling/fsck.hefs.cc index 37dfbdd7..ce386152 100644 --- a/tooling/fsck.hefs.cc +++ b/tooling/fsck.hefs.cc @@ -4,18 +4,40 @@ ------------------------------------------- */ -#include -#include +#include +#include #include +#include int main(int argc, char** argv) { if (argc < 2) { - mkfs::console_out() << "fsck: hefs: usage: fsck.hefs i " + mkfs::console_out() << "fsck: hefs: usage: fsck.hefs -i=" << "\n"; return EXIT_FAILURE; } - (void) (argv); + auto args = mkfs::detail::build_args(argc, argv); + + auto opt_disk = mkfs::get_option(args, "-i"); + + if (opt_disk.empty()) { + mkfs::console_out() << "fsck: hefs: error: HeFS is empty! Exiting..." + << "\n"; + return EXIT_FAILURE; + } + + + std::ifstream output_device(opt_disk, std::ios::binary); + + if (!output_device.good()) { + mkfs::console_out() << "hefs: error: Unable to open output device: " << opt_disk << "\n"; + return EXIT_FAILURE; + } + + mkfs::hefs::BootNode boot_node; + std::memset(&boot_node, 0, sizeof(boot_node)); + + mkfs::console_out() << "hefs: HeFS partition is is healthy, exiting...\r"; return EXIT_SUCCESS; } \ No newline at end of file diff --git a/tooling/hefs.h b/tooling/hefs.h deleted file mode 100644 index d0da516b..00000000 --- a/tooling/hefs.h +++ /dev/null @@ -1,115 +0,0 @@ -/* ------------------------------------------- - - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. - -------------------------------------------- */ - -#pragma once - -#include -#include - -#define kHeFSVersion (0x0101) -#define kHeFSMagic " HeFS" -#define kHeFSMagicLen (8) - -#define kHeFSFileNameLen (256U) -#define kHeFSPartNameLen (128U) - -#define kHeFSDefaultVolumeName u8"HeFS Volume" - -namespace mkfs::hefs { - -// Drive kinds -enum { - kHeFSHardDrive = 0xC0, // Hard Drive - kHeFSSolidStateDrive = 0xC1, // Solid State Drive - kHeFSOpticalDrive = 0x0C, // Blu-Ray/DVD - kHeFSMassStorageDevice = 0xCC, // USB - kHeFSScsiDrive = 0xC4, // SCSI Hard Drive - kHeFSFlashDrive = 0xC6, - kHeFSUnknown = 0xFF, // Unknown device. - kHeFSDriveCount = 8, -}; - -// Disk status -enum { - kHeFSStatusUnlocked = 0x18, - kHeFSStatusLocked, - kHeFSStatusError, - kHeFSStatusInvalid, - kHeFSStatusCount, -}; - -// Encodings -enum { - kHeFSEncodingFlagsUTF8 = 0x50, - kHeFSEncodingFlagsUTF16, - kHeFSEncodingFlagsUTF32, - kHeFSEncodingFlagsUTF16BE, - kHeFSEncodingFlagsUTF16LE, - kHeFSEncodingFlagsUTF32BE, - kHeFSEncodingFlagsUTF32LE, - kHeFSEncodingFlagsUTF8BE, - kHeFSEncodingFlagsUTF8LE, - kHeFSEncodingFlagsBinary, - kHeFSEncodingFlagsCount = 11, - kHeFSFlagsNone = 0, - kHeFSFlagsReadOnly = 0x100, - kHeFSFlagsHidden, - kHeFSFlagsSystem, - kHeFSFlagsArchive, - kHeFSFlagsDevice, - kHeFSFlagsCount = 7 -}; -// Time type -using ATime = std::uint64_t; - -// File kinds -inline constexpr uint16_t kHeFSFileKindRegular = 0x00; -inline constexpr uint16_t kHeFSFileKindDirectory = 0x01; -inline constexpr uint16_t kHeFSFileKindBlock = 0x02; -inline constexpr uint16_t kHeFSFileKindCharacter = 0x03; -inline constexpr uint16_t kHeFSFileKindFIFO = 0x04; -inline constexpr uint16_t kHeFSFileKindSocket = 0x05; -inline constexpr uint16_t kHeFSFileKindSymbolicLink = 0x06; -inline constexpr uint16_t kHeFSFileKindUnknown = 0x07; -inline constexpr uint16_t kHeFSFileKindCount = 0x08; - -// Red-black tree colors -enum { - kHeFSInvalidColor = 0, - kHeFSRed = 100, - kHeFSBlack, - kHeFSColorCount, -}; - -// Time constants -inline constexpr ATime kHeFSTimeInvalid = 0x0000000000000000; -inline constexpr ATime kHeFSTimeMax = 0xFFFFFFFFFFFFFFFF - 1; - -// Boot Node -struct __attribute__((packed)) BootNode { - char magic[kHeFSMagicLen]{}; - char8_t volumeName[kHeFSPartNameLen]{}; - std::uint32_t version{}; - std::uint64_t badSectors{}; - std::uint64_t sectorCount{}; - std::uint64_t sectorSize{}; - std::uint32_t checksum{}; - std::uint8_t diskKind{}; - std::uint8_t encoding{}; - std::uint64_t startIND{}; - std::uint64_t endIND{}; - std::uint64_t indCount{}; - std::uint64_t diskSize{}; - std::uint16_t diskStatus{}; - std::uint16_t diskFlags{}; - std::uint16_t vid{}; - std::uint64_t startIN{}; - std::uint64_t endIN{}; - std::uint64_t startBlock{}; - std::uint64_t endBlock{}; - char pad[272]{}; -}; -} // namespace mkfs::hefs diff --git a/tooling/libmkfs/hefs.h b/tooling/libmkfs/hefs.h new file mode 100644 index 00000000..d0da516b --- /dev/null +++ b/tooling/libmkfs/hefs.h @@ -0,0 +1,115 @@ +/* ------------------------------------------- + + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + +------------------------------------------- */ + +#pragma once + +#include +#include + +#define kHeFSVersion (0x0101) +#define kHeFSMagic " HeFS" +#define kHeFSMagicLen (8) + +#define kHeFSFileNameLen (256U) +#define kHeFSPartNameLen (128U) + +#define kHeFSDefaultVolumeName u8"HeFS Volume" + +namespace mkfs::hefs { + +// Drive kinds +enum { + kHeFSHardDrive = 0xC0, // Hard Drive + kHeFSSolidStateDrive = 0xC1, // Solid State Drive + kHeFSOpticalDrive = 0x0C, // Blu-Ray/DVD + kHeFSMassStorageDevice = 0xCC, // USB + kHeFSScsiDrive = 0xC4, // SCSI Hard Drive + kHeFSFlashDrive = 0xC6, + kHeFSUnknown = 0xFF, // Unknown device. + kHeFSDriveCount = 8, +}; + +// Disk status +enum { + kHeFSStatusUnlocked = 0x18, + kHeFSStatusLocked, + kHeFSStatusError, + kHeFSStatusInvalid, + kHeFSStatusCount, +}; + +// Encodings +enum { + kHeFSEncodingFlagsUTF8 = 0x50, + kHeFSEncodingFlagsUTF16, + kHeFSEncodingFlagsUTF32, + kHeFSEncodingFlagsUTF16BE, + kHeFSEncodingFlagsUTF16LE, + kHeFSEncodingFlagsUTF32BE, + kHeFSEncodingFlagsUTF32LE, + kHeFSEncodingFlagsUTF8BE, + kHeFSEncodingFlagsUTF8LE, + kHeFSEncodingFlagsBinary, + kHeFSEncodingFlagsCount = 11, + kHeFSFlagsNone = 0, + kHeFSFlagsReadOnly = 0x100, + kHeFSFlagsHidden, + kHeFSFlagsSystem, + kHeFSFlagsArchive, + kHeFSFlagsDevice, + kHeFSFlagsCount = 7 +}; +// Time type +using ATime = std::uint64_t; + +// File kinds +inline constexpr uint16_t kHeFSFileKindRegular = 0x00; +inline constexpr uint16_t kHeFSFileKindDirectory = 0x01; +inline constexpr uint16_t kHeFSFileKindBlock = 0x02; +inline constexpr uint16_t kHeFSFileKindCharacter = 0x03; +inline constexpr uint16_t kHeFSFileKindFIFO = 0x04; +inline constexpr uint16_t kHeFSFileKindSocket = 0x05; +inline constexpr uint16_t kHeFSFileKindSymbolicLink = 0x06; +inline constexpr uint16_t kHeFSFileKindUnknown = 0x07; +inline constexpr uint16_t kHeFSFileKindCount = 0x08; + +// Red-black tree colors +enum { + kHeFSInvalidColor = 0, + kHeFSRed = 100, + kHeFSBlack, + kHeFSColorCount, +}; + +// Time constants +inline constexpr ATime kHeFSTimeInvalid = 0x0000000000000000; +inline constexpr ATime kHeFSTimeMax = 0xFFFFFFFFFFFFFFFF - 1; + +// Boot Node +struct __attribute__((packed)) BootNode { + char magic[kHeFSMagicLen]{}; + char8_t volumeName[kHeFSPartNameLen]{}; + std::uint32_t version{}; + std::uint64_t badSectors{}; + std::uint64_t sectorCount{}; + std::uint64_t sectorSize{}; + std::uint32_t checksum{}; + std::uint8_t diskKind{}; + std::uint8_t encoding{}; + std::uint64_t startIND{}; + std::uint64_t endIND{}; + std::uint64_t indCount{}; + std::uint64_t diskSize{}; + std::uint16_t diskStatus{}; + std::uint16_t diskFlags{}; + std::uint16_t vid{}; + std::uint64_t startIN{}; + std::uint64_t endIN{}; + std::uint64_t startBlock{}; + std::uint64_t endBlock{}; + char pad[272]{}; +}; +} // namespace mkfs::hefs diff --git a/tooling/libmkfs/mkfs.h b/tooling/libmkfs/mkfs.h new file mode 100644 index 00000000..d954624c --- /dev/null +++ b/tooling/libmkfs/mkfs.h @@ -0,0 +1,72 @@ +/* ------------------------------------------- + + Copyright (C) 2025, Amlal El Mahrouss, all rights reserved. + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +/// @internal +namespace mkfs { + +namespace detail { + /// @internal + /// @brief GB‐to‐byte conversion (use multiplication, not XOR). + static constexpr size_t gib_cast(uint32_t gb) { + return static_cast(gb) * 1024ULL * 1024ULL * 1024ULL; + } + + static bool parse_decimal(const std::string& opt, unsigned long long& out) { + if (opt.empty()) return false; + char* endptr = nullptr; + unsigned long long val = std::strtoull(opt.c_str(), &endptr, 10); + if (endptr == opt.c_str() || *endptr != '\0') return false; + out = val; + return true; + } + + static bool parse_signed(const std::string& opt, long& out, int base = 10) { + if (opt.empty()) return false; + char* endptr = nullptr; + long val = std::strtol(opt.c_str(), &endptr, base); + if (endptr == opt.c_str() || *endptr != '\0' || val < 0) return false; + out = val; + return true; + } + + static std::string build_args(int argc, char** argv) { + std::string combined; + for (int i = 1; i < argc; ++i) { + combined += argv[i]; + combined += ' '; + } + return combined; + } +} // namespace detail + +/// @brief Helper function to get the option value from command line arguments. +template +inline std::basic_string get_option(const std::basic_string& args, + const std::basic_string& option) { + size_t pos = args.find(option + CharType('=')); + + if (pos != std::string::npos) { + size_t start = pos + option.length() + 1; + size_t end = args.find(' ', start); + return args.substr(start, end - start); + } + + return std::basic_string{}; +} + +inline auto console_out() -> std::ostream& { + std::ostream& conout = std::cout; + conout << rang::fg::red << "mkfs: " << rang::style::reset; + + return conout; +} +} // namespace mkfs \ No newline at end of file diff --git a/tooling/mkfs.h b/tooling/mkfs.h deleted file mode 100644 index 7180b179..00000000 --- a/tooling/mkfs.h +++ /dev/null @@ -1,36 +0,0 @@ -/* ------------------------------------------- - - Copyright (C) 2025, Amlal El Mahrouss, all rights reserved. - -------------------------------------------- */ - -#pragma once - -#include -#include -#include - -/// @internal -namespace mkfs { -/// @brief Helper function to get the option value from command line arguments. -template -inline std::basic_string get_option(const std::basic_string& args, - const std::basic_string& option) { - size_t pos = args.find(option + CharType('=')); - - if (pos != std::string::npos) { - size_t start = pos + option.length() + 1; - size_t end = args.find(' ', start); - return args.substr(start, end - start); - } - - return std::basic_string{}; -} - -inline auto console_out() -> std::ostream& { - std::ostream& conout = std::cout; - conout << rang::fg::red << "mkfs: " << rang::style::reset; - - return conout; -} -} // namespace mkfs \ No newline at end of file diff --git a/tooling/mkfs.hefs.cc b/tooling/mkfs.hefs.cc index 3960fa5e..c1cf9bca 100644 --- a/tooling/mkfs.hefs.cc +++ b/tooling/mkfs.hefs.cc @@ -4,54 +4,19 @@ ------------------------------------------- */ -#include -#include +#include +#include #include #include #include #include #include -namespace detail { -/// @internal -/// @brief GB‐to‐byte conversion (use multiplication, not XOR). -static constexpr size_t gib_cast(uint32_t gb) { - return static_cast(gb) * 1024ULL * 1024ULL * 1024ULL; -} -} // namespace detail - -static size_t kDiskSize = detail::gib_cast(4UL); +static size_t kDiskSize = mkfs::detail::gib_cast(4UL); static uint16_t kVersion = kHeFSVersion; static std::u8string kLabel; static size_t kSectorSize = 512; -static bool parse_decimal(const std::string& opt, unsigned long long& out) { - if (opt.empty()) return false; - char* endptr = nullptr; - unsigned long long val = std::strtoull(opt.c_str(), &endptr, 10); - if (endptr == opt.c_str() || *endptr != '\0') return false; - out = val; - return true; -} - -static bool parse_signed(const std::string& opt, long& out, int base = 10) { - if (opt.empty()) return false; - char* endptr = nullptr; - long val = std::strtol(opt.c_str(), &endptr, base); - if (endptr == opt.c_str() || *endptr != '\0' || val < 0) return false; - out = val; - return true; -} - -static std::string build_args(int argc, char** argv) { - std::string combined; - for (int i = 1; i < argc; ++i) { - combined += argv[i]; - combined += ' '; - } - return combined; -} - int main(int argc, char** argv) { if (argc < 2) { mkfs::console_out() @@ -62,7 +27,7 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } - std::string args = build_args(argc, argv); + std::string args = mkfs::detail::build_args(argc, argv); auto output_path = mkfs::get_option(args, "-o"); if (output_path.empty()) { @@ -72,7 +37,7 @@ int main(int argc, char** argv) { auto opt_s = mkfs::get_option(args, "-s"); long parsed_s = 0; - if (!parse_signed(opt_s, parsed_s, 10) || parsed_s == 0) { + if (!mkfs::detail::parse_signed(opt_s, parsed_s, 10) || parsed_s == 0) { mkfs::console_out() << "hefs: error: Invalid sector size \"" << opt_s << "\". Must be a positive integer.\n"; return EXIT_FAILURE; @@ -98,7 +63,7 @@ int main(int argc, char** argv) { auto opt_S = mkfs::get_option(args, "-S"); unsigned long long gb = 0; - if (!parse_decimal(opt_S, gb) || gb == 0ULL) { + if (!mkfs::detail::parse_decimal(opt_S, gb) || gb == 0ULL) { mkfs::console_out() << "hefs: error: Invalid disk size \"" << opt_S << "\". Must be a positive integer.\n"; return EXIT_FAILURE; @@ -121,27 +86,27 @@ int main(int argc, char** argv) { long start_block = 0, end_block = 0; long start_in = 0, end_in = 0; - if (!parse_signed(opt_b, start_ind, 16)) { + if (!mkfs::detail::parse_signed(opt_b, start_ind, 16)) { mkfs::console_out() << "hefs: error: Invalid -b argument.\n"; return EXIT_FAILURE; } - if (!parse_signed(opt_e, end_ind, 16) || end_ind <= start_ind) { + if (!mkfs::detail::parse_signed(opt_e, end_ind, 16) || end_ind <= start_ind) { mkfs::console_out() << "hefs: error: Invalid or out-of-range -e argument.\n"; return EXIT_FAILURE; } - if (!parse_signed(opt_bs, start_block, 16)) { + if (!mkfs::detail::parse_signed(opt_bs, start_block, 16)) { mkfs::console_out() << "hefs: error: Invalid -bs argument.\n"; return EXIT_FAILURE; } - if (!parse_signed(opt_be, end_block, 16) || end_block <= start_block) { + if (!mkfs::detail::parse_signed(opt_be, end_block, 16) || end_block <= start_block) { mkfs::console_out() << "hefs: error: Invalid or out-of-range -be argument.\n"; return EXIT_FAILURE; } - if (!parse_signed(opt_is, start_in, 16)) { + if (!mkfs::detail::parse_signed(opt_is, start_in, 16)) { mkfs::console_out() << "hefs: error: Invalid -is argument.\n"; return EXIT_FAILURE; } - if (!parse_signed(opt_ie, end_in, 16) || end_in <= start_in) { + if (!mkfs::detail::parse_signed(opt_ie, end_in, 16) || end_in <= start_in) { mkfs::console_out() << "hefs: error: Invalid or out-of-range -ie argument.\n"; return EXIT_FAILURE; } @@ -153,6 +118,7 @@ int main(int argc, char** argv) { } std::ofstream output_device(output_path, std::ios::binary); + if (!output_device.good()) { mkfs::console_out() << "hefs: error: Unable to open output device: " << output_path << "\n"; return EXIT_FAILURE; -- cgit v1.2.3