mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Allow pulling files off disk.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
44
src/fe-getfile.cc
Normal 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;
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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.", },
|
||||
|
||||
Reference in New Issue
Block a user