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;
|
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> getMetadata(const Path& path)
|
||||||
{
|
{
|
||||||
std::map<std::string, std::string> attributes;
|
std::map<std::string, std::string> attributes;
|
||||||
|
|||||||
@@ -6,7 +6,10 @@
|
|||||||
/* Number of sectors on a 120kB disk. */
|
/* Number of sectors on a 120kB disk. */
|
||||||
static constexpr int SECTOR_COUNT = 468;
|
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;
|
static constexpr int DATA_START_SECTOR = 14;
|
||||||
|
|
||||||
/* Size of a sector */
|
/* Size of a sector */
|
||||||
@@ -15,6 +18,9 @@ static constexpr int SECTOR_SIZE = 256;
|
|||||||
/* Number of dirents in a directory. */
|
/* Number of dirents in a directory. */
|
||||||
static constexpr int DIRECTORY_SIZE = 128;
|
static constexpr int DIRECTORY_SIZE = 128;
|
||||||
|
|
||||||
|
/* Number of sectors in the FAT. */
|
||||||
|
static constexpr int FAT_SECTORS = 4;
|
||||||
|
|
||||||
/* Number of sectors in a directory. */
|
/* Number of sectors in a directory. */
|
||||||
static constexpr int DIRECTORY_SECTORS = 8;
|
static constexpr int DIRECTORY_SECTORS = 8;
|
||||||
|
|
||||||
@@ -68,6 +74,23 @@ public:
|
|||||||
return result;
|
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> getMetadata(const Path& path)
|
||||||
{
|
{
|
||||||
std::map<std::string, std::string> attributes;
|
std::map<std::string, std::string> attributes;
|
||||||
@@ -85,6 +108,19 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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>> findAllFiles()
|
||||||
{
|
{
|
||||||
std::vector<std::unique_ptr<Brother120Dirent>> result;
|
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();
|
throw BadFilesystemException();
|
||||||
|
|
||||||
auto& i = _locations[number];
|
Bytes data;
|
||||||
return _sectors->get(std::get<0>(i), std::get<1>(i), std::get<2>(i))->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)
|
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)
|
virtual std::vector<std::unique_ptr<Dirent>> list(const Path& path)
|
||||||
{ throw UnimplementedFilesystemException(); }
|
{ throw UnimplementedFilesystemException(); }
|
||||||
|
|
||||||
virtual Bytes read(const Path& path)
|
virtual Bytes getFile(const Path& path)
|
||||||
{ throw UnimplementedFilesystemException(); }
|
{ throw UnimplementedFilesystemException(); }
|
||||||
|
|
||||||
virtual void write(const Path& path, const Bytes& data)
|
virtual void putFile(const Path& path, const Bytes& data)
|
||||||
{ throw UnimplementedFilesystemException(); }
|
{ throw UnimplementedFilesystemException(); }
|
||||||
|
|
||||||
virtual std::map<std::string, std::string> getMetadata(const Path& path)
|
virtual std::map<std::string, std::string> getMetadata(const Path& path)
|
||||||
{ throw UnimplementedFilesystemException(); }
|
{ 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(); }
|
{ throw UnimplementedFilesystemException(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Filesystem(std::shared_ptr<SectorInterface> sectors);
|
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);
|
void putLogicalSector(uint32_t number, const Bytes& data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ include src/formats/build.mk
|
|||||||
FLUXENGINE_SRCS = \
|
FLUXENGINE_SRCS = \
|
||||||
src/fe-analysedriveresponse.cc \
|
src/fe-analysedriveresponse.cc \
|
||||||
src/fe-analyselayout.cc \
|
src/fe-analyselayout.cc \
|
||||||
|
src/fe-getfile.cc \
|
||||||
src/fe-getfileinfo.cc \
|
src/fe-getfileinfo.cc \
|
||||||
src/fe-inspect.cc \
|
src/fe-inspect.cc \
|
||||||
src/fe-ls.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[])
|
int mainGetFileInfo(int argc, const char* argv[])
|
||||||
{
|
{
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
showProfiles("ls", formats);
|
showProfiles("getfileinfo", formats);
|
||||||
flags.parseFlagsWithConfigFiles(argc, argv, formats);
|
flags.parseFlagsWithConfigFiles(argc, argv, formats);
|
||||||
|
|
||||||
auto filesystem = createFilesystemFromConfig();
|
auto filesystem = createFilesystemFromConfig();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ typedef int command_cb(int agrc, const char* argv[]);
|
|||||||
|
|
||||||
extern command_cb mainAnalyseDriveResponse;
|
extern command_cb mainAnalyseDriveResponse;
|
||||||
extern command_cb mainAnalyseLayout;
|
extern command_cb mainAnalyseLayout;
|
||||||
|
extern command_cb mainGetFile;
|
||||||
extern command_cb mainGetFileInfo;
|
extern command_cb mainGetFileInfo;
|
||||||
extern command_cb mainInspect;
|
extern command_cb mainInspect;
|
||||||
extern command_cb mainLs;
|
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.", },
|
{ "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.", },
|
{ "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).", },
|
{ "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).", },
|
{ "getfileinfo", mainGetFileInfo, "Read file metadata off a disk (or image).", },
|
||||||
{ "rpm", mainRpm, "Measures the disk rotational speed.", },
|
{ "rpm", mainRpm, "Measures the disk rotational speed.", },
|
||||||
{ "seek", mainSeek, "Moves the disk head.", },
|
{ "seek", mainSeek, "Moves the disk head.", },
|
||||||
|
|||||||
Reference in New Issue
Block a user