CheckFreeSpace POSIX fix

This commit is contained in:
Jack Andersen 2016-01-25 16:01:55 -10:00
parent 9a6bd14667
commit 02a7b95606
6 changed files with 61 additions and 129 deletions

View File

@ -1,6 +1,6 @@
### NODLib ### NODLib
**NODLib** is a library and utility (`nodtool`) for traversing, dumping, and authoring **NODLib** is a library and utility (`nodtool`) for traversing, dumping, and authoring
*GameCube* and *Wii* optical disc images. *GameCube* and *Wii* optical disc images.
#### Library #### Library
@ -8,23 +8,23 @@
The primary motivation of NODLib is to supply a *uniform C++11 API* for accessing data The primary motivation of NODLib is to supply a *uniform C++11 API* for accessing data
from image files directly. `NOD::DiscBase` provides a common interface for traversing partitions from image files directly. `NOD::DiscBase` provides a common interface for traversing partitions
and individual files. Files may be individually streamed, or the whole partition may be extracted and individual files. Files may be individually streamed, or the whole partition may be extracted
to the user's filesystem. Raw *ISO* and *WBFS* images are supported read sources. to the user's filesystem. Raw *ISO* and *WBFS* images are supported read sources.
```cpp ```cpp
bool isWii; /* Set by reference next line */ bool isWii; /* Set by reference next line */
std::unique_ptr<NOD::DiscBase> disc = NOD::OpenDiscFromImage(path, isWii); std::unique_ptr<NOD::DiscBase> disc = NOD::OpenDiscFromImage(path, isWii);
if (!disc) if (!disc)
return FAILURE; return FAILURE;
/* Access first data-partition on Wii, or full GameCube disc */ /* Access first data-partition on Wii, or full GameCube disc */
NOD::Partition* dataPart = disc->getDataPartition(); NOD::Partition* dataPart = disc->getDataPartition();
if (!dataPart) if (!dataPart)
return FAILURE; return FAILURE;
/* One-shot extraction to filesystem */ /* One-shot extraction to filesystem */
if (!dataPart->extractToDirectory(outDir, ctx)) if (!dataPart->extractToDirectory(outDir, ctx))
return FAILURE; return FAILURE;
return SUCCESS; return SUCCESS;
``` ```
@ -36,18 +36,18 @@ a content pipeline using the `NOD::DiscBuilderBase` interface.
size_t lastIdx = -1; size_t lastIdx = -1;
auto progFunc = [&](size_t idx, const NOD::SystemString& name, size_t bytes) auto progFunc = [&](size_t idx, const NOD::SystemString& name, size_t bytes)
{ {
if (idx != lastIdx) if (idx != lastIdx)
{ {
lastIdx = idx; lastIdx = idx;
/* NOD provides I/O wrappers using wchar_t on Windows; /* NOD provides I/O wrappers using wchar_t on Windows;
* _S() conditionally makes string-literals wide */ * _S() conditionally makes string-literals wide */
NOD::Printf(_S("\n")); NOD::Printf(_S("\n"));
} }
if (bytes != -1) if (bytes != -1)
NOD::Printf(_S("\r%s %" PRISize " B"), name.c_str(), bytes); NOD::Printf(_S("\r%s %" PRISize " B"), name.c_str(), bytes);
else else
NOD::Printf(_S("\r%s"), name.c_str()); NOD::Printf(_S("\r%s"), name.c_str());
fflush(stdout); fflush(stdout);
}; };
/* Making a GCN image */ /* Making a GCN image */

View File

@ -29,6 +29,7 @@ public:
{ {
virtual ~IReadStream() {} virtual ~IReadStream() {}
virtual void seek(int64_t offset, int whence)=0; virtual void seek(int64_t offset, int whence)=0;
virtual int64_t position()=0;
virtual uint64_t read(void* buf, uint64_t length)=0; virtual uint64_t read(void* buf, uint64_t length)=0;
virtual uint64_t copyToDisc(struct IPartWriteStream& discio, uint64_t length)=0; virtual uint64_t copyToDisc(struct IPartWriteStream& discio, uint64_t length)=0;
}; };

View File

@ -290,6 +290,17 @@ static inline int FSeek(FILE* fp, int64_t offset, int whence)
#endif #endif
} }
static inline int64_t FTell(FILE* fp)
{
#if _WIN32
return _ftelli64(fp);
#elif __APPLE__ || __FreeBSD__
return ftello(fp);
#else
return ftello64(fp);
#endif
}
static inline bool CheckFreeSpace(const SystemChar* path, size_t reqSz) static inline bool CheckFreeSpace(const SystemChar* path, size_t reqSz)
{ {
#if _WIN32 #if _WIN32
@ -308,7 +319,7 @@ static inline bool CheckFreeSpace(const SystemChar* path, size_t reqSz)
struct statvfs svfs; struct statvfs svfs;
if (statvfs(path, &svfs)) if (statvfs(path, &svfs))
LogModule.report(LogVisor::FatalError, "statvfs %s: %s", path, strerror(errno)); LogModule.report(LogVisor::FatalError, "statvfs %s: %s", path, strerror(errno));
return reqSz < svfs.f_bsize * svfs.f_bfree; return reqSz < svfs.f_frsize * svfs.f_bavail;
#endif #endif
} }

View File

@ -1,146 +1,55 @@
#include <stdio.h> #include <stdio.h>
#include "NOD/Util.hpp" #include "NOD/Util.hpp"
#include "NOD/IDiscIO.hpp" #include "NOD/IDiscIO.hpp"
#include "NOD/IFileIO.hpp"
namespace NOD namespace NOD
{ {
class DiscIOISO : public IDiscIO class DiscIOISO : public IDiscIO
{ {
SystemString filepath; std::unique_ptr<IFileIO> m_fio;
public: public:
DiscIOISO(const SystemString& fpin) DiscIOISO(const SystemString& fpin)
: filepath(fpin) {} : m_fio(std::move(NewFileIO(fpin))) {}
class ReadStream : public IReadStream class ReadStream : public IReadStream
{ {
friend class DiscIOISO; friend class DiscIOISO;
#if _WIN32 std::unique_ptr<IFileIO::IReadStream> fp;
HANDLE fp; ReadStream(std::unique_ptr<IFileIO::IReadStream>&& fpin)
ReadStream(HANDLE fpin) : fp(std::move(fpin)) {}
: fp(fpin) {}
~ReadStream() {CloseHandle(fp);}
#else
FILE* fp;
ReadStream(FILE* fpin)
: fp(fpin) {}
~ReadStream() {fclose(fp);}
#endif
public: public:
#if _WIN32
uint64_t read(void* buf, uint64_t length) uint64_t read(void* buf, uint64_t length)
{ {return fp->read(buf, length);}
DWORD ret = 0;
ReadFile(fp, buf, length, &ret, nullptr);
return ret;
}
uint64_t position() const uint64_t position() const
{ {return fp->position();}
LARGE_INTEGER liOfs={0};
LARGE_INTEGER liNew={0};
SetFilePointerEx(fp, liOfs, &liNew, FILE_CURRENT);
return liNew.QuadPart;
}
void seek(int64_t offset, int whence) void seek(int64_t offset, int whence)
{ {fp->seek(offset, whence);}
LARGE_INTEGER li;
li.QuadPart = offset;
SetFilePointerEx(fp, li, nullptr, whence);
}
#else
uint64_t read(void* buf, uint64_t length)
{return fread(buf, 1, length, fp);}
uint64_t position() const
{return ftello(fp);}
void seek(int64_t offset, int whence)
{FSeek(fp, offset, whence);}
#endif
}; };
#if _WIN32
std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const
{ {
HANDLE fp = CreateFileW(filepath.c_str(), GENERIC_READ, FILE_SHARE_READ, return std::unique_ptr<IReadStream>(new ReadStream(std::move(m_fio->beginReadStream(offset))));
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (fp == INVALID_HANDLE_VALUE)
{
LogModule.report(LogVisor::Error, _S("Unable to open '%s' for reading"), filepath.c_str());
return std::unique_ptr<IReadStream>();
}
LARGE_INTEGER li;
li.QuadPart = offset;
SetFilePointerEx(fp, li, nullptr, FILE_BEGIN);
return std::unique_ptr<IReadStream>(new ReadStream(fp));
} }
#else
std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const
{
FILE* fp = fopen(filepath.c_str(), "rb");
if (!fp)
{
LogModule.report(LogVisor::Error, _S("Unable to open '%s' for reading"), filepath.c_str());
return std::unique_ptr<IReadStream>();
}
FSeek(fp, offset, SEEK_SET);
return std::unique_ptr<IReadStream>(new ReadStream(fp));
}
#endif
class WriteStream : public IWriteStream class WriteStream : public IWriteStream
{ {
friend class DiscIOISO; friend class DiscIOISO;
#if _WIN32 std::unique_ptr<IFileIO::IWriteStream> fp;
HANDLE fp; WriteStream(std::unique_ptr<IFileIO::IWriteStream>&& fpin)
WriteStream(HANDLE fpin) : fp(std::move(fpin)) {}
: fp(fpin) {}
~WriteStream() {CloseHandle(fp);}
#else
FILE* fp;
WriteStream(FILE* fpin)
: fp(fpin) {}
~WriteStream() {fclose(fp);}
#endif
public: public:
uint64_t write(const void* buf, uint64_t length) uint64_t write(const void* buf, uint64_t length)
{ {
#if _WIN32 return fp->write(buf, length);
DWORD ret = 0;
WriteFile(fp, buf, length, &ret, nullptr);
return ret;
#else
return fwrite(buf, 1, length, fp);
#endif
} }
}; };
#if _WIN32
std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const
{ {
HANDLE fp = CreateFileW(filepath.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, return std::unique_ptr<IWriteStream>(new WriteStream(std::move(m_fio->beginWriteStream(offset))));
nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (fp == INVALID_HANDLE_VALUE)
{
LogModule.report(LogVisor::Error, _S("Unable to open '%s' for writing"), filepath.c_str());
return std::unique_ptr<IWriteStream>();
}
LARGE_INTEGER li;
li.QuadPart = offset;
SetFilePointerEx(fp, li, nullptr, FILE_BEGIN);
return std::unique_ptr<IWriteStream>(new WriteStream(fp));
} }
#else
std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const
{
FILE* fp = fopen(filepath.c_str(), "wb");
if (!fp)
{
LogModule.report(LogVisor::Error, _S("Unable to open '%s' for writing"), filepath.c_str());
return std::unique_ptr<IWriteStream>();
}
FSeek(fp, offset, SEEK_SET);
return std::unique_ptr<IWriteStream>(new WriteStream(fp));
}
#endif
}; };
std::unique_ptr<IDiscIO> NewDiscIOISO(const SystemChar* path) std::unique_ptr<IDiscIO> NewDiscIOISO(const SystemChar* path)

View File

@ -37,7 +37,6 @@ public:
struct WriteStream : public IFileIO::IWriteStream struct WriteStream : public IFileIO::IWriteStream
{ {
uint8_t buf[0x7c00];
FILE* fp; FILE* fp;
WriteStream(const SystemString& path) WriteStream(const SystemString& path)
{ {
@ -70,6 +69,7 @@ public:
uint64_t copyFromDisc(IPartReadStream& discio, uint64_t length) uint64_t copyFromDisc(IPartReadStream& discio, uint64_t length)
{ {
uint64_t read = 0; uint64_t read = 0;
uint8_t buf[0x7c00];
while (length) while (length)
{ {
uint64_t thisSz = NOD::min(uint64_t(0x7c00), length); uint64_t thisSz = NOD::min(uint64_t(0x7c00), length);
@ -102,7 +102,6 @@ public:
struct ReadStream : public IFileIO::IReadStream struct ReadStream : public IFileIO::IReadStream
{ {
FILE* fp; FILE* fp;
uint8_t buf[0x7c00];
ReadStream(const SystemString& path) ReadStream(const SystemString& path)
{ {
fp = fopen(path.c_str(), "rb"); fp = fopen(path.c_str(), "rb");
@ -122,6 +121,10 @@ public:
{ {
FSeek(fp, offset, whence); FSeek(fp, offset, whence);
} }
int64_t position()
{
return FTell(fp);
}
uint64_t read(void* buf, uint64_t length) uint64_t read(void* buf, uint64_t length)
{ {
return fread(buf, 1, length, fp); return fread(buf, 1, length, fp);
@ -129,6 +132,7 @@ public:
uint64_t copyToDisc(IPartWriteStream& discio, uint64_t length) uint64_t copyToDisc(IPartWriteStream& discio, uint64_t length)
{ {
uint64_t written = 0; uint64_t written = 0;
uint8_t buf[0x7c00];
while (length) while (length)
{ {
uint64_t thisSz = NOD::min(uint64_t(0x7c00), length); uint64_t thisSz = NOD::min(uint64_t(0x7c00), length);

View File

@ -43,7 +43,6 @@ public:
struct WriteStream : public IFileIO::IWriteStream struct WriteStream : public IFileIO::IWriteStream
{ {
uint8_t buf[0x7c00];
HANDLE fp; HANDLE fp;
WriteStream(const SystemString& path) WriteStream(const SystemString& path)
{ {
@ -75,6 +74,7 @@ public:
uint64_t copyFromDisc(IPartReadStream& discio, uint64_t length) uint64_t copyFromDisc(IPartReadStream& discio, uint64_t length)
{ {
uint64_t read = 0; uint64_t read = 0;
uint8_t buf[0x7c00];
while (length) while (length)
{ {
uint64_t thisSz = NOD::min(uint64_t(0x7c00), length); uint64_t thisSz = NOD::min(uint64_t(0x7c00), length);
@ -107,7 +107,6 @@ public:
struct ReadStream : public IFileIO::IReadStream struct ReadStream : public IFileIO::IReadStream
{ {
HANDLE fp; HANDLE fp;
uint8_t buf[0x7c00];
ReadStream(const SystemString& path) ReadStream(const SystemString& path)
{ {
fp = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, fp = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ,
@ -132,6 +131,13 @@ public:
li.QuadPart = offset; li.QuadPart = offset;
SetFilePointerEx(fp, li, nullptr, whence); SetFilePointerEx(fp, li, nullptr, whence);
} }
int64_t position()
{
LARGE_INTEGER li = {};
LARGE_INTEGER res;
SetFilePointerEx(fp, li, &res, FILE_CURRENT);
return res.QuadPart;
}
uint64_t read(void* buf, uint64_t length) uint64_t read(void* buf, uint64_t length)
{ {
DWORD ret = 0; DWORD ret = 0;
@ -141,6 +147,7 @@ public:
uint64_t copyToDisc(IPartWriteStream& discio, uint64_t length) uint64_t copyToDisc(IPartWriteStream& discio, uint64_t length)
{ {
uint64_t written = 0; uint64_t written = 0;
uint8_t buf[0x7c00];
while (length) while (length)
{ {
uint64_t thisSz = NOD::min(uint64_t(0x7c00), length); uint64_t thisSz = NOD::min(uint64_t(0x7c00), length);