Allow pulling files off disk.

This commit is contained in:
David Given
2022-08-27 16:06:33 +02:00
parent c5fd24496f
commit c9a58e9d57
8 changed files with 116 additions and 10 deletions

View File

@@ -59,6 +59,23 @@ public:
return result;
}
Bytes getFile(const Path& path)
{
auto dirent = findFile(path);
int sectors = (dirent->length + 255) / 256;
Bytes data;
ByteWriter bw(data);
for (int i = 0; i < sectors; i++)
{
auto sector = getLogicalSector(dirent->start_sector + i);
bw.append(sector);
}
data.resize(dirent->length);
return data;
}
std::map<std::string, std::string> getMetadata(const Path& path)
{
std::map<std::string, std::string> attributes;

View File

@@ -6,7 +6,10 @@
/* Number of sectors on a 120kB disk. */
static constexpr int SECTOR_COUNT = 468;
/* Start sector for data (after the directory */
/* Start sector for the FAT (after the directory) */
static constexpr int FAT_START_SECTOR = 8;
/* Start sector for data (after the FAT) */
static constexpr int DATA_START_SECTOR = 14;
/* Size of a sector */
@@ -15,6 +18,9 @@ static constexpr int SECTOR_SIZE = 256;
/* Number of dirents in a directory. */
static constexpr int DIRECTORY_SIZE = 128;
/* Number of sectors in the FAT. */
static constexpr int FAT_SECTORS = 4;
/* Number of sectors in a directory. */
static constexpr int DIRECTORY_SECTORS = 8;
@@ -68,6 +74,23 @@ public:
return result;
}
Bytes getFile(const Path& path)
{
auto fat = readFat();
auto dirent = findFile(path);
int sector = dirent->start_sector;
Bytes data;
ByteWriter bw(data);
while ((sector != 0) && (sector != 0xffff))
{
bw += getLogicalSector(sector - 1);
sector = fat.at(sector);
}
return data;
}
std::map<std::string, std::string> getMetadata(const Path& path)
{
std::map<std::string, std::string> attributes;
@@ -85,6 +108,19 @@ public:
}
private:
std::vector<uint32_t> readFat()
{
Bytes bytes = getLogicalSector(FAT_START_SECTOR, FAT_SECTORS);
ByteReader br(bytes);
std::vector<uint32_t> table;
table.push_back(0xffff);
for (int sector = 1; sector != SECTOR_COUNT; sector++)
table.push_back(br.read_be16());
return table;
}
std::vector<std::unique_ptr<Brother120Dirent>> findAllFiles()
{
std::vector<std::unique_ptr<Brother120Dirent>> result;

View File

@@ -68,13 +68,19 @@ std::unique_ptr<Filesystem> Filesystem::createFilesystem(
}
}
Bytes Filesystem::getLogicalSector(uint32_t number)
Bytes Filesystem::getLogicalSector(uint32_t number, uint32_t count)
{
if (number >= _locations.size())
if ((number+count) > _locations.size())
throw BadFilesystemException();
auto& i = _locations[number];
return _sectors->get(std::get<0>(i), std::get<1>(i), std::get<2>(i))->data;
Bytes data;
ByteWriter bw(data);
for (int i = 0; i < count; i++)
{
auto& it = _locations[number + i];
bw += _sectors->get(std::get<0>(it), std::get<1>(it), std::get<2>(it))->data;
}
return data;
}
void Filesystem::putLogicalSector(uint32_t number, const Bytes& data)

View File

@@ -59,22 +59,22 @@ public:
virtual std::vector<std::unique_ptr<Dirent>> list(const Path& path)
{ throw UnimplementedFilesystemException(); }
virtual Bytes read(const Path& path)
virtual Bytes getFile(const Path& path)
{ throw UnimplementedFilesystemException(); }
virtual void write(const Path& path, const Bytes& data)
virtual void putFile(const Path& path, const Bytes& data)
{ throw UnimplementedFilesystemException(); }
virtual std::map<std::string, std::string> getMetadata(const Path& path)
{ throw UnimplementedFilesystemException(); }
virtual void setMetadata(const Path& path, const std::map<std::string, std::string>& metadata)
virtual void putMetadata(const Path& path, const std::map<std::string, std::string>& metadata)
{ throw UnimplementedFilesystemException(); }
protected:
Filesystem(std::shared_ptr<SectorInterface> sectors);
Bytes getLogicalSector(uint32_t number);
Bytes getLogicalSector(uint32_t number, uint32_t count = 1);
void putLogicalSector(uint32_t number, const Bytes& data);
private:

View File

@@ -3,6 +3,7 @@ include src/formats/build.mk
FLUXENGINE_SRCS = \
src/fe-analysedriveresponse.cc \
src/fe-analyselayout.cc \
src/fe-getfile.cc \
src/fe-getfileinfo.cc \
src/fe-inspect.cc \
src/fe-ls.cc \

44
src/fe-getfile.cc Normal file
View File

@@ -0,0 +1,44 @@
#include "globals.h"
#include "flags.h"
#include "fluxmap.h"
#include "sector.h"
#include "proto.h"
#include "readerwriter.h"
#include "imagereader/imagereader.h"
#include "imagewriter/imagewriter.h"
#include "lib/fluxsource/fluxsource.h"
#include "lib/decoders/decoders.h"
#include "fmt/format.h"
#include "fluxengine.h"
#include "lib/vfs/sectorinterface.h"
#include "lib/vfs/vfs.h"
#include "src/fileutils.h"
#include <google/protobuf/text_format.h>
#include <fstream>
static FlagGroup flags({ &fileFlags });
static StringFlag directory({"-p", "--path"}, "path to work on", "");
static StringFlag output({"-o", "--output"}, "local filename to write to", "");
int mainGetFile(int argc, const char* argv[])
{
if (argc == 1)
showProfiles("getfile", formats);
flags.parseFlagsWithConfigFiles(argc, argv, formats);
Path inputFilename(directory);
if (inputFilename.size() == 0)
Error() << "you must supply a filename to read";
std::string outputFilename = output;
if (outputFilename.empty())
outputFilename = inputFilename.back();
fmt::print("{}\n", outputFilename);
auto filesystem = createFilesystemFromConfig();
auto data = filesystem->getFile(inputFilename);
data.writeToFile(outputFilename);
return 0;
}

View File

@@ -23,7 +23,7 @@ static StringFlag directory({"-p", "--path"}, "path to work on", "");
int mainGetFileInfo(int argc, const char* argv[])
{
if (argc == 1)
showProfiles("ls", formats);
showProfiles("getfileinfo", formats);
flags.parseFlagsWithConfigFiles(argc, argv, formats);
auto filesystem = createFilesystemFromConfig();

View File

@@ -6,6 +6,7 @@ typedef int command_cb(int agrc, const char* argv[]);
extern command_cb mainAnalyseDriveResponse;
extern command_cb mainAnalyseLayout;
extern command_cb mainGetFile;
extern command_cb mainGetFileInfo;
extern command_cb mainInspect;
extern command_cb mainLs;
@@ -37,6 +38,7 @@ static std::vector<Command> commands =
{ "rawread", mainRawRead, "Reads raw flux from a disk. Warning: you can't use this to copy disks.", },
{ "rawwrite", mainRawWrite, "Writes a flux file to a disk. Warning: you can't use this to copy disks.", },
{ "ls", mainLs, "Show files on disk (or image).", },
{ "getfile", mainGetFile, "Read a file off a disk (or image).", },
{ "getfileinfo", mainGetFileInfo, "Read file metadata off a disk (or image).", },
{ "rpm", mainRpm, "Measures the disk rotational speed.", },
{ "seek", mainSeek, "Moves the disk head.", },