mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Allow reading files from cbmfs disks (not .REL, though).
This commit is contained in:
51
lib/utils.cc
51
lib/utils.cc
@@ -102,3 +102,54 @@ std::string toIso8601(time_t t)
|
||||
ss << std::put_time(tm, "%FT%T%z");
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string quote(const std::string& s)
|
||||
{
|
||||
bool spaces = s.find(' ') != std::string::npos;
|
||||
if (!spaces
|
||||
&& (s.find('\\') == std::string::npos)
|
||||
&& (s.find('\'') == std::string::npos)
|
||||
&& (s.find('"') == std::string::npos))
|
||||
return s;
|
||||
|
||||
std::stringstream ss;
|
||||
if (spaces)
|
||||
ss << '"';
|
||||
|
||||
for (char c : s)
|
||||
{
|
||||
if ((c == '\\') || (c == '\"') || (c == '!'))
|
||||
ss << '\\';
|
||||
ss << (char)c;
|
||||
}
|
||||
|
||||
if (spaces)
|
||||
ss << '"';
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string unhex(const std::string& s)
|
||||
{
|
||||
std::stringstream sin(s);
|
||||
std::stringstream sout;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int c = sin.get();
|
||||
if (c == -1)
|
||||
break;
|
||||
if (c == '%')
|
||||
{
|
||||
char buf[3];
|
||||
buf[0] = sin.get();
|
||||
buf[1] = sin.get();
|
||||
buf[2] = 0;
|
||||
|
||||
c = std::stoul(buf, nullptr, 16);
|
||||
}
|
||||
sout << (char)c;
|
||||
}
|
||||
|
||||
return sout.str();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ extern std::string rightTrimWhitespace(std::string value);
|
||||
extern std::string trimWhitespace(const std::string& value);
|
||||
extern std::string getLeafname(const std::string& value);
|
||||
extern std::string toIso8601(time_t t);
|
||||
extern std::string quote(const std::string& s);
|
||||
extern std::string unhex(const std::string& s);
|
||||
|
||||
/* If set, any running job will terminate as soon as possible (with an error).
|
||||
*/
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
#include "lib/globals.h"
|
||||
#include "lib/vfs/vfs.h"
|
||||
#include "lib/config.pb.h"
|
||||
#include "lib/utils.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
enum
|
||||
{
|
||||
DEL,
|
||||
SEQ,
|
||||
PRG,
|
||||
USR,
|
||||
REL
|
||||
};
|
||||
|
||||
static std::string fromPetscii(const Bytes& bytes)
|
||||
{
|
||||
std::stringstream ss;
|
||||
@@ -32,11 +42,11 @@ static std::string toFileType(uint8_t cbm_type)
|
||||
{
|
||||
switch (cbm_type & 0x0f)
|
||||
{
|
||||
case 0: return "del";
|
||||
case 1: return "seq";
|
||||
case 2: return "prg";
|
||||
case 3: return "usr";
|
||||
case 4: return "rel";
|
||||
case DEL: return "DEL";
|
||||
case SEQ: return "SEQ";
|
||||
case PRG: return "PRG";
|
||||
case USR: return "USR";
|
||||
case REL: return "REL";
|
||||
default: return fmt::format("[bad type {:x}]", cbm_type & 0x0f);
|
||||
}
|
||||
}
|
||||
@@ -123,13 +133,13 @@ public:
|
||||
{
|
||||
if (path.size() != 1)
|
||||
throw BadPathException();
|
||||
auto de = findFile(path[0]);
|
||||
auto de = findFile(unhex(path[0]));
|
||||
if (!de)
|
||||
throw FileNotFoundException();
|
||||
|
||||
std::map<std::string, std::string> attributes;
|
||||
attributes["filename"] = de->filename;
|
||||
attributes["length"] = de->length;
|
||||
attributes["length"] = fmt::format("{}", de->length);
|
||||
attributes["mode"] = de->mode;
|
||||
attributes["type"] = "file";
|
||||
attributes["cbmfs.type"] = toFileType(de->cbm_type);
|
||||
@@ -142,6 +152,40 @@ public:
|
||||
return attributes;
|
||||
}
|
||||
|
||||
Bytes getFile(const Path& path)
|
||||
{
|
||||
if (path.size() != 1)
|
||||
throw BadPathException();
|
||||
auto de = findFile(unhex(path[0]));
|
||||
if (!de)
|
||||
throw FileNotFoundException();
|
||||
if (de->cbm_type == REL)
|
||||
throw UnimplementedFilesystemException("cannot read .REL files");
|
||||
|
||||
Bytes bytes;
|
||||
ByteWriter bw(bytes);
|
||||
|
||||
uint8_t t = de->start_track - 1;
|
||||
uint8_t s = de->start_sector;
|
||||
for (;;)
|
||||
{
|
||||
auto b = getSector(t, 0, s);
|
||||
|
||||
if (b[0])
|
||||
bw += b.slice(2);
|
||||
else
|
||||
{
|
||||
bw += b.slice(2, b[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
t = b[0] - 1;
|
||||
s = b[1];
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<CbmfsDirent> findFile(const std::string& filename)
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "fluxengine.h"
|
||||
#include "lib/vfs/sectorinterface.h"
|
||||
#include "lib/vfs/vfs.h"
|
||||
#include "lib/utils.h"
|
||||
#include "src/fileutils.h"
|
||||
#include <google/protobuf/text_format.h>
|
||||
#include <fstream>
|
||||
@@ -32,7 +33,7 @@ int mainGetFileInfo(int argc, const char* argv[])
|
||||
auto attributes = filesystem->getMetadata(Path(directory));
|
||||
|
||||
for (const auto& e : attributes)
|
||||
fmt::print("{}={}\n", e.first, e.second);
|
||||
fmt::print("{}={}\n", e.first, quote(e.second));
|
||||
}
|
||||
catch (const FilesystemException& e)
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "fluxengine.h"
|
||||
#include "lib/vfs/sectorinterface.h"
|
||||
#include "lib/vfs/vfs.h"
|
||||
#include "lib/utils.h"
|
||||
#include "src/fileutils.h"
|
||||
#include <google/protobuf/text_format.h>
|
||||
#include <fstream>
|
||||
@@ -47,15 +48,15 @@ int mainLs(int argc, const char* argv[])
|
||||
|
||||
int maxlen = 0;
|
||||
for (const auto& dirent : files)
|
||||
maxlen = std::max(maxlen, (int)dirent->filename.size());
|
||||
maxlen = std::max(maxlen, (int)quote(dirent->filename).size());
|
||||
|
||||
uint32_t total = 0;
|
||||
for (const auto& dirent : files)
|
||||
{
|
||||
fmt::print("{} {:{}} {:6} {}\n",
|
||||
fileTypeChar(dirent->file_type),
|
||||
"'" + dirent->filename + "'",
|
||||
maxlen,
|
||||
quote(dirent->filename),
|
||||
maxlen + 2,
|
||||
dirent->length,
|
||||
dirent->mode);
|
||||
total += dirent->length;
|
||||
|
||||
@@ -43,6 +43,13 @@ static void testLeafname()
|
||||
AssertThat(getLeafname("/path/path/filename"), Equals("filename"));
|
||||
}
|
||||
|
||||
static void testUnhex()
|
||||
{
|
||||
AssertThat(unhex(""), Equals(""));
|
||||
AssertThat(unhex("foo"), Equals("foo"));
|
||||
AssertThat(unhex("f%20o"), Equals("f o"));
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
testJoin();
|
||||
@@ -50,5 +57,6 @@ int main(void)
|
||||
testRightTrim();
|
||||
testTrim();
|
||||
testLeafname();
|
||||
testUnhex();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user