OXYGENHUB
◆ main openmsx / src / fdc / MSXtar.hh
5.3 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
// This code implements the functionality of my older msxtar program
2
// that could manipulate files and directories on dsk and ide-hd images
3
// Integrating it is seen as temporary bypassing of the need for a
4
// DirAsDisk2 that supports subdirs, partitions etc. since this class will
5
// of those functionalities although not on a dynamic base
6
7
#ifndef MSXTAR_HH
8
#define MSXTAR_HH
9
10
#include "DiskImageUtils.hh"
11
#include "TclObject.hh"
12
13
#include "MemBuffer.hh"
14
#include "zstring_view.hh"
15
16
#include <cstdint>
17
#include <string_view>
18
#include <variant>
19
20
namespace openmsx {
21
22
class SectorAccessibleDisk;
23
class MsxChar2Unicode;
24
25
namespace FAT {
26
	struct Free {
27
		[[nodiscard]] auto operator<=>(const Free&) const = default;
28
	};
29
30
	struct EndOfChain {
31
		[[nodiscard]] auto operator<=>(const EndOfChain&) const = default;
32
	};
33
34
	struct Cluster {
35
		unsigned index;
36
		[[nodiscard]] auto operator<=>(const Cluster&) const = default;
37
	};
38
39
	using DirCluster = std::variant<Free, Cluster>;
40
	using FatCluster = std::variant<Free, EndOfChain, Cluster>;
41
42
	using FileName = decltype(MSXDirEntry::filename);
43
}
44
45
class MSXtar
46
{
47
public:
48
	enum class Add : uint8_t {
49
		PRESERVE,
50
		OVERWRITE,
51
	};
52
public:
53
	explicit MSXtar(SectorAccessibleDisk& disk, const MsxChar2Unicode& msxChars_);
54
	MSXtar(MSXtar&& other) noexcept;
55
	~MSXtar();
56
57
	void chdir(std::string_view newRootDir);
58
	void mkdir(std::string_view newRootDir);
59
	std::string dir(); // formatted output
60
	TclObject dirRaw(); // unformatted output
61
	std::string addItem(const std::string& hostItemName, Add add); // add file or directory
62
	std::string addFile(const std::string& filename, Add add);
63
	std::string addDir(std::string_view rootDirName, Add add); // add files from host-dir, but does not create a top-level dir on the msx side
64
	std::string getItemFromDir(std::string_view rootDirName, std::string_view itemName);
65
	void getDir(std::string_view rootDirName);
66
	std::string deleteItem(std::string_view itemName); // delete file or directory (recursive)
67
	std::string renameItem(std::string_view currentName, std::string_view newName); // rename file or directory
68
	[[nodiscard]] std::string convertToMsxName(std::string_view name) const; // truncate to 8.3 filename
69
70
	struct FreeSpaceResult {
71
		unsigned numFreeClusters;
72
		unsigned clusterSize; // in bytes
73
	};
74
	[[nodiscard]] FreeSpaceResult getFreeSpace() const;
75
76
private:
77
	struct DirEntry {
78
		unsigned sector;
79
		unsigned index;
80
	};
81
82
	void writeLogicalSector(unsigned sector, const SectorBuffer& buf);
83
	void readLogicalSector (unsigned sector,       SectorBuffer& buf);
84
85
	[[nodiscard]] unsigned clusterToSector(FAT::Cluster cluster) const;
86
	[[nodiscard]] FAT::Cluster sectorToCluster(unsigned sector) const;
87
	void parseBootSector(const MSXBootSector& boot);
88
	[[nodiscard]] FAT::FatCluster readFAT(FAT::Cluster cluster) const;
89
	void writeFAT(FAT::Cluster cluster, FAT::FatCluster value);
90
	[[nodiscard]] FAT::Cluster findFirstFreeCluster();
91
	[[nodiscard]] unsigned countFreeClusters() const;
92
	[[nodiscard]] unsigned findUsableIndexInSector(unsigned sector);
93
	[[nodiscard]] unsigned getNextSector(unsigned sector) const;
94
	[[nodiscard]] unsigned appendClusterToSubdir(unsigned sector);
95
	[[nodiscard]] DirEntry addEntryToDir(unsigned sector);
96
	[[nodiscard]] unsigned addSubdir(const FAT::FileName& msxName,
97
	                                 uint16_t t, uint16_t d, unsigned sector);
98
	void alterFileInDSK(MSXDirEntry& msxDirEntry, const std::string& hostName);
99
	void deleteItem(std::string_view itemName, unsigned sector);
100
	std::string deleteEntry(const FAT::FileName& msxName, unsigned rootSector);
101
	void deleteEntry(MSXDirEntry& msxDirEntry);
102
	void deleteDirectory(unsigned sector);
103
	void freeFatChain(FAT::FatCluster cluster);
104
	[[nodiscard]] unsigned addSubdirToDSK(zstring_view hostName,
105
	                                      const FAT::FileName& msxName, unsigned sector);
106
	[[nodiscard]] DirEntry findEntryInDir(const FAT::FileName& msxName, unsigned sector,
107
	                                      SectorBuffer& sectorBuf);
108
	std::string addFileToDSK(const std::string& fullHostName, unsigned sector, Add add);
109
	std::string addOrCreateSubdir(zstring_view hostDirName, unsigned sector, Add add);
110
	std::string recurseDirFill(std::string_view dirName, unsigned sector, Add add);
111
	void fileExtract(const std::string& resultFile, const MSXDirEntry& dirEntry);
112
	void recurseDirExtract(std::string_view dirName, unsigned sector);
113
	std::string singleItemExtract(std::string_view dirName, std::string_view itemName,
114
	                              unsigned sector);
115
	void chroot(std::string_view newRootDir, bool createDir);
116
117
private:
118
	[[nodiscard]] FAT::DirCluster getStartCluster(const MSXDirEntry& entry) const;
119
	void setStartCluster(MSXDirEntry& entry, FAT::DirCluster cluster) const;
120
121
	[[nodiscard]] FAT::FileName hostToMSXFileName(std::string_view hostName) const;
122
	[[nodiscard]] std::string msxToHostFileName(const FAT::FileName& msxName) const;
123
124
	SectorAccessibleDisk& disk;
125
	MemBuffer<SectorBuffer> fatBuffer;
126
	const MsxChar2Unicode& msxChars;
127
	FAT::Cluster findFirstFreeClusterStart{0}; // all clusters before this one are in use
128
129
	unsigned clusterCount;
130
	unsigned fatCount;
131
	unsigned sectorsPerCluster;
132
	unsigned sectorsPerFat;
133
	unsigned fatStart;     // first sector of the first FAT
134
	unsigned rootDirStart; // first sector of the root directory
135
	unsigned dataStart;    // first sector of the cluster data
136
	unsigned chrootSector;
137
	bool fat16;
138
139
	bool fatCacheDirty;
140
};
141
142
} // namespace openmsx
143
144
#endif