File-size limiting

This commit is contained in:
Jack Andersen 2016-02-02 11:18:16 -10:00
parent 39e9cea094
commit 48f79b2369
6 changed files with 46 additions and 33 deletions

View File

@ -356,13 +356,15 @@ protected:
const SystemChar* m_outPath; const SystemChar* m_outPath;
std::unique_ptr<IFileIO> m_fileIO; std::unique_ptr<IFileIO> m_fileIO;
std::vector<std::unique_ptr<PartitionBuilderBase>> m_partitions; std::vector<std::unique_ptr<PartitionBuilderBase>> m_partitions;
int64_t m_discCapacity;
public: public:
std::function<void(size_t idx, const SystemString&, size_t)> m_progressCB; std::function<void(size_t idx, const SystemString&, size_t)> m_progressCB;
size_t m_progressIdx = 0; size_t m_progressIdx = 0;
virtual ~DiscBuilderBase() {} virtual ~DiscBuilderBase() {}
DiscBuilderBase(const SystemChar* outPath, DiscBuilderBase(const SystemChar* outPath, int64_t discCapacity,
std::function<void(size_t idx, const SystemString&, size_t)> progressCB) std::function<void(size_t idx, const SystemString&, size_t)> progressCB)
: m_fileIO(std::move(NewFileIO(outPath))), m_outPath(outPath), m_progressCB(progressCB) {} : m_outPath(outPath), m_fileIO(std::move(NewFileIO(outPath, discCapacity))),
m_discCapacity(discCapacity), m_progressCB(progressCB) {}
IFileIO& getFileIO() {return *m_fileIO;} IFileIO& getFileIO() {return *m_fileIO;}
}; };

View File

@ -37,9 +37,8 @@ public:
virtual std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const=0; virtual std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const=0;
}; };
std::unique_ptr<IFileIO> NewFileIO(const SystemString& path); std::unique_ptr<IFileIO> NewFileIO(const SystemString& path, int64_t maxWriteSize=-1);
std::unique_ptr<IFileIO> NewFileIO(const SystemChar* path); std::unique_ptr<IFileIO> NewFileIO(const SystemChar* path, int64_t maxWriteSize=-1);
std::unique_ptr<IFileIO> NewMemIO(void* buf, uint64_t size);
} }

View File

@ -249,7 +249,7 @@ bool DiscBuilderGCN::buildFromDirectory(const SystemChar* dirIn, const SystemCha
DiscBuilderGCN::DiscBuilderGCN(const SystemChar* outPath, const char gameID[6], const char* gameTitle, DiscBuilderGCN::DiscBuilderGCN(const SystemChar* outPath, const char gameID[6], const char* gameTitle,
uint32_t fstMemoryAddr, std::function<void(size_t, const SystemString&, size_t)> progressCB) uint32_t fstMemoryAddr, std::function<void(size_t, const SystemString&, size_t)> progressCB)
: DiscBuilderBase(outPath, progressCB) : DiscBuilderBase(outPath, 0x57058000, progressCB)
{ {
PartitionBuilderGCN* partBuilder = new PartitionBuilderGCN(*this, PartitionBuilderBase::Kind::Data, PartitionBuilderGCN* partBuilder = new PartitionBuilderGCN(*this, PartitionBuilderBase::Kind::Data,
gameID, gameTitle, fstMemoryAddr); gameID, gameTitle, fstMemoryAddr);

View File

@ -850,24 +850,22 @@ public:
bool DiscBuilderWii::buildFromDirectory(const SystemChar* dirIn, const SystemChar* dolIn, bool DiscBuilderWii::buildFromDirectory(const SystemChar* dirIn, const SystemChar* dolIn,
const SystemChar* apploaderIn, const SystemChar* partHeadIn) const SystemChar* apploaderIn, const SystemChar* partHeadIn)
{ {
size_t DISC_CAPACITY = m_dualLayer ? 0x1FB4E0000 : 0x118240000;
PartitionBuilderWii& pb = static_cast<PartitionBuilderWii&>(*m_partitions[0]); PartitionBuilderWii& pb = static_cast<PartitionBuilderWii&>(*m_partitions[0]);
uint64_t filledSz = pb.m_baseOffset; uint64_t filledSz = pb.m_baseOffset;
m_fileIO->beginWriteStream(); m_fileIO->beginWriteStream();
if (!CheckFreeSpace(m_outPath, DISC_CAPACITY)) if (!CheckFreeSpace(m_outPath, m_discCapacity))
{ {
LogModule.report(LogVisor::Error, _S("not enough free disk space for %s"), m_outPath); LogModule.report(LogVisor::Error, _S("not enough free disk space for %s"), m_outPath);
return false; return false;
} }
++m_progressIdx; ++m_progressIdx;
m_progressCB(m_progressIdx, _S("Preallocating image"), -1); m_progressCB(m_progressIdx, _S("Preallocating image"), -1);
m_fileIO->beginWriteStream(DISC_CAPACITY - 1)->write("", 1); m_fileIO->beginWriteStream(m_discCapacity - 1)->write("", 1);
/* Assemble image */ /* Assemble image */
filledSz = pb.buildFromDirectory(dirIn, dolIn, apploaderIn, partHeadIn); filledSz = pb.buildFromDirectory(dirIn, dolIn, apploaderIn, partHeadIn);
if (filledSz >= DISC_CAPACITY) if (filledSz >= m_discCapacity)
{ {
LogModule.report(LogVisor::FatalError, "data partition exceeds disc capacity"); LogModule.report(LogVisor::FatalError, "data partition exceeds disc capacity");
return false; return false;
@ -910,7 +908,7 @@ bool DiscBuilderWii::buildFromDirectory(const SystemChar* dirIn, const SystemCha
ws = m_fileIO->beginWriteStream(filledSz); ws = m_fileIO->beginWriteStream(filledSz);
uint8_t fillBuf[512]; uint8_t fillBuf[512];
memset(fillBuf, 0xff, 512); memset(fillBuf, 0xff, 512);
for (size_t i=DISC_CAPACITY-filledSz ; i>0 ;) for (size_t i=m_discCapacity-filledSz ; i>0 ;)
{ {
if (i >= 512) if (i >= 512)
{ {
@ -927,7 +925,7 @@ bool DiscBuilderWii::buildFromDirectory(const SystemChar* dirIn, const SystemCha
DiscBuilderWii::DiscBuilderWii(const SystemChar* outPath, const char gameID[6], const char* gameTitle, bool dualLayer, DiscBuilderWii::DiscBuilderWii(const SystemChar* outPath, const char gameID[6], const char* gameTitle, bool dualLayer,
std::function<void(size_t, const SystemString&, size_t)> progressCB) std::function<void(size_t, const SystemString&, size_t)> progressCB)
: DiscBuilderBase(outPath, progressCB), m_dualLayer(dualLayer) : DiscBuilderBase(outPath, dualLayer ? 0x1FB4E0000 : 0x118240000, progressCB), m_dualLayer(dualLayer)
{ {
PartitionBuilderWii* partBuilder = new PartitionBuilderWii(*this, PartitionBuilderBase::Kind::Data, PartitionBuilderWii* partBuilder = new PartitionBuilderWii(*this, PartitionBuilderBase::Kind::Data,
gameID, gameTitle, 0x200000); gameID, gameTitle, 0x200000);

View File

@ -1,5 +1,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <inttypes.h>
#include "NOD/Util.hpp" #include "NOD/Util.hpp"
#include "NOD/IFileIO.hpp" #include "NOD/IFileIO.hpp"
@ -9,11 +10,12 @@ namespace NOD
class FileIOFILE : public IFileIO class FileIOFILE : public IFileIO
{ {
SystemString m_path; SystemString m_path;
int64_t m_maxWriteSize;
public: public:
FileIOFILE(const SystemString& path) FileIOFILE(const SystemString& path, int64_t maxWriteSize)
: m_path(path) {} : m_path(path), m_maxWriteSize(maxWriteSize) {}
FileIOFILE(const SystemChar* path) FileIOFILE(const SystemChar* path, int64_t maxWriteSize)
: m_path(path) {} : m_path(path), m_maxWriteSize(maxWriteSize) {}
bool exists() bool exists()
{ {
@ -38,13 +40,16 @@ public:
struct WriteStream : public IFileIO::IWriteStream struct WriteStream : public IFileIO::IWriteStream
{ {
FILE* fp; FILE* fp;
WriteStream(const SystemString& path) int64_t m_maxWriteSize;
WriteStream(const SystemString& path, int64_t maxWriteSize)
: m_maxWriteSize(maxWriteSize)
{ {
fp = fopen(path.c_str(), "wb"); fp = fopen(path.c_str(), "wb");
if (!fp) if (!fp)
LogModule.report(LogVisor::FatalError, _S("unable to open '%s' for writing"), path.c_str()); LogModule.report(LogVisor::FatalError, _S("unable to open '%s' for writing"), path.c_str());
} }
WriteStream(const SystemString& path, uint64_t offset) WriteStream(const SystemString& path, uint64_t offset, int64_t maxWriteSize)
: m_maxWriteSize(maxWriteSize)
{ {
fp = fopen(path.c_str(), "ab"); fp = fopen(path.c_str(), "ab");
if (!fp) if (!fp)
@ -64,6 +69,8 @@ public:
} }
uint64_t write(const void* buf, uint64_t length) uint64_t write(const void* buf, uint64_t length)
{ {
if (FTell(fp) + length > m_maxWriteSize)
LogModule.report(LogVisor::FatalError, _S("write operation exceeds file's %" PRIi64 "-byte limit"), m_maxWriteSize);
return fwrite(buf, 1, length, fp); return fwrite(buf, 1, length, fp);
} }
uint64_t copyFromDisc(IPartReadStream& discio, uint64_t length) uint64_t copyFromDisc(IPartReadStream& discio, uint64_t length)
@ -92,11 +99,11 @@ public:
}; };
std::unique_ptr<IWriteStream> beginWriteStream() const std::unique_ptr<IWriteStream> beginWriteStream() const
{ {
return std::unique_ptr<IWriteStream>(new WriteStream(m_path)); return std::unique_ptr<IWriteStream>(new WriteStream(m_path, m_maxWriteSize));
} }
std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const
{ {
return std::unique_ptr<IWriteStream>(new WriteStream(m_path, offset)); return std::unique_ptr<IWriteStream>(new WriteStream(m_path, offset, m_maxWriteSize));
} }
struct ReadStream : public IFileIO::IReadStream struct ReadStream : public IFileIO::IReadStream
@ -162,14 +169,14 @@ public:
} }
}; };
std::unique_ptr<IFileIO> NewFileIO(const SystemString& path) std::unique_ptr<IFileIO> NewFileIO(const SystemString& path, int64_t maxWriteSize)
{ {
return std::unique_ptr<IFileIO>(new FileIOFILE(path)); return std::unique_ptr<IFileIO>(new FileIOFILE(path, maxWriteSize));
} }
std::unique_ptr<IFileIO> NewFileIO(const SystemChar* path) std::unique_ptr<IFileIO> NewFileIO(const SystemChar* path, int64_t maxWriteSize)
{ {
return std::unique_ptr<IFileIO>(new FileIOFILE(path)); return std::unique_ptr<IFileIO>(new FileIOFILE(path, maxWriteSize));
} }
} }

View File

@ -1,5 +1,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <inttypes.h>
#include "NOD/Util.hpp" #include "NOD/Util.hpp"
#include "NOD/IFileIO.hpp" #include "NOD/IFileIO.hpp"
@ -9,11 +10,12 @@ namespace NOD
class FileIOWin32 : public IFileIO class FileIOWin32 : public IFileIO
{ {
SystemString m_path; SystemString m_path;
int64_t m_maxWriteSize;
public: public:
FileIOWin32(const SystemString& path) FileIOWin32(const SystemString& path, int64_t maxWriteSize)
: m_path(path) {} : m_path(path), m_maxWriteSize(maxWriteSize) {}
FileIOWin32(const SystemChar* path) FileIOWin32(const SystemChar* path, int64_t maxWriteSize)
: m_path(path) {} : m_path(path), m_maxWriteSize(maxWriteSize) {}
bool exists() bool exists()
{ {
@ -44,14 +46,17 @@ public:
struct WriteStream : public IFileIO::IWriteStream struct WriteStream : public IFileIO::IWriteStream
{ {
HANDLE fp; HANDLE fp;
WriteStream(const SystemString& path) int64_t m_maxWriteSize;
WriteStream(const SystemString& path, int64_t maxWriteSize)
: m_maxWriteSize(maxWriteSize)
{ {
fp = CreateFileW(path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, fp = CreateFileW(path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE,
nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (fp == INVALID_HANDLE_VALUE) if (fp == INVALID_HANDLE_VALUE)
LogModule.report(LogVisor::FatalError, _S("unable to open '%s' for writing"), path.c_str()); LogModule.report(LogVisor::FatalError, _S("unable to open '%s' for writing"), path.c_str());
} }
WriteStream(const SystemString& path, uint64_t offset) WriteStream(const SystemString& path, uint64_t offset, int64_t maxWriteSize)
: m_maxWriteSize(maxWriteSize)
{ {
fp = CreateFileW(path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, fp = CreateFileW(path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE,
nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
@ -67,6 +72,8 @@ public:
} }
uint64_t write(const void* buf, uint64_t length) uint64_t write(const void* buf, uint64_t length)
{ {
if (FTell(fp) + length > m_maxWriteSize)
LogModule.report(LogVisor::FatalError, _S("write operation exceeds file's %" PRIi64 "-byte limit"), m_maxWriteSize);
DWORD ret = 0; DWORD ret = 0;
WriteFile(fp, buf, length, &ret, nullptr); WriteFile(fp, buf, length, &ret, nullptr);
return ret; return ret;
@ -97,11 +104,11 @@ public:
}; };
std::unique_ptr<IWriteStream> beginWriteStream() const std::unique_ptr<IWriteStream> beginWriteStream() const
{ {
return std::unique_ptr<IWriteStream>(new WriteStream(m_path)); return std::unique_ptr<IWriteStream>(new WriteStream(m_path, m_maxWriteSize));
} }
std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const
{ {
return std::unique_ptr<IWriteStream>(new WriteStream(m_path, offset)); return std::unique_ptr<IWriteStream>(new WriteStream(m_path, offset, m_maxWriteSize));
} }
struct ReadStream : public IFileIO::IReadStream struct ReadStream : public IFileIO::IReadStream