Merge branch 'main' into 12.0-development

This commit is contained in:
Sasha Szpakowski
2024-02-04 23:07:50 -04:00
2 changed files with 71 additions and 83 deletions
+28 -54
View File
@@ -18,7 +18,6 @@
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
**/ **/
#include <cassert>
#include <algorithm> #include <algorithm>
#include "PhysfsIo.h" #include "PhysfsIo.h"
@@ -32,14 +31,15 @@ namespace physfs
bool StripSuffixIo::determineStrippedLength() bool StripSuffixIo::determineStrippedLength()
{ {
if (!file) { if (!file)
return false; return false;
}
const int64_t fullSize = fullLength(); const int64 fullSize = file->getSize();
int64_t chunkSize = std::min(fullSize, (int64_t)8192);
int64 chunkSize = std::min(fullSize, (int64) 8192);
std::string buffer; std::string buffer;
buffer.reserve(chunkSize); buffer.reserve(chunkSize);
int64_t i = fullSize - chunkSize; int64 i = fullSize - chunkSize;
// I don't think we really need to go through the whole file. The main known use // I don't think we really need to go through the whole file. The main known use
// case for this functionality is to skip windows codesign signatures, which are // case for this functionality is to skip windows codesign signatures, which are
// from what I have seen ~12KB or so, but trying is better than just failing. // from what I have seen ~12KB or so, but trying is better than just failing.
@@ -64,7 +64,7 @@ bool StripSuffixIo::determineStrippedLength()
} }
if (i == 0) if (i == 0)
break; break;
i = std::max((int64_t)0, i - chunkSize); i = std::max((int64)0, i - chunkSize);
} }
if (i > 0) if (i > 0)
@@ -75,7 +75,7 @@ bool StripSuffixIo::determineStrippedLength()
// The comment length (u16) is located 20 bytes from the start of the EOCD record // The comment length (u16) is located 20 bytes from the start of the EOCD record
if (seek(i + 20) == 0) if (seek(i + 20) == 0)
return false; return false;
uint8_t buffer[2]; uint8 buffer[2];
const auto n = read(buffer, 2); const auto n = read(buffer, 2);
if (n <= 0) if (n <= 0)
return false; return false;
@@ -96,17 +96,17 @@ bool StripSuffixIo::determineStrippedLength()
return true; return true;
} }
int64_t StripSuffixIo::read(void* buf, uint64_t len) int64 StripSuffixIo::read(void *buf, uint64 len)
{ {
if (!file) if (!file)
{ {
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR); PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
return -1; return -1;
} }
const auto ret = std::fread(buf, 1, len, file); int64 r = file->read(buf, (int64) len);
if (ret == 0) if (r == 0)
{ {
if (std::feof(file)) if (file->isEOF())
{ {
PHYSFS_setErrorCode(PHYSFS_ERR_OK); PHYSFS_setErrorCode(PHYSFS_ERR_OK);
return 0; return 0;
@@ -117,85 +117,59 @@ int64_t StripSuffixIo::read(void* buf, uint64_t len)
return -1; return -1;
} }
} }
else if (ret < len && std::ferror(file))
{
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
return -1;
}
PHYSFS_setErrorCode(PHYSFS_ERR_OK); PHYSFS_setErrorCode(PHYSFS_ERR_OK);
return ret; return r;
} }
int64_t StripSuffixIo::write(const void* /*buf*/, uint64_t /*len*/) int64 StripSuffixIo::write(const void */*buf*/, uint64 /*len*/)
{ {
PHYSFS_setErrorCode(PHYSFS_ERR_READ_ONLY); PHYSFS_setErrorCode(PHYSFS_ERR_READ_ONLY);
return -1; return -1;
} }
int64_t StripSuffixIo::seek(uint64_t offset) int64 StripSuffixIo::seek(uint64 offset)
{ {
if (!file) if (!file)
{ {
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR); PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
return 0; return 0;
} }
const auto ret = std::fseek(file, offset, SEEK_SET); bool success = file->seek(offset);
PHYSFS_setErrorCode(ret != 0 ? PHYSFS_ERR_OS_ERROR : PHYSFS_ERR_OK); PHYSFS_setErrorCode(success ? PHYSFS_ERR_OK : PHYSFS_ERR_OS_ERROR);
return ret == 0 ? 1 : 0; return success ? 1 : 0;
} }
int64_t StripSuffixIo::tell() int64 StripSuffixIo::tell()
{ {
if (!file) if (!file)
{ {
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR); PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
return -1; return -1;
} }
return std::ftell(file); return file->tell();
} }
int64_t StripSuffixIo::length() int64 StripSuffixIo::length()
{ {
return strippedLength_; return strippedLength_;
} }
int64_t StripSuffixIo::flush() int64 StripSuffixIo::flush()
{ {
if (!file) if (!file)
{ {
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR); PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
return 0; return 0;
} }
return std::fflush(file) == 0 ? 1 : 0; try
} {
return file->flush() ? 1 : 0;
int64_t StripSuffixIo::fullLength() }
{ catch (love::Exception &)
assert(file);
const auto cur = std::ftell(file);
if (cur == -1)
{ {
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR); PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
return -1; return 0;
} }
if (std::fseek(file, 0, SEEK_END) != 0)
{
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
return -1;
}
const auto len = std::ftell(file);
if (len == -1)
{
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
return -1;
}
if (std::fseek(file, cur, SEEK_SET) != 0)
{
// We do have the length now, but something is wrong, so we return an error anyways
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
return -1;
}
return len;
} }
} // physfs } // physfs
+43 -29
View File
@@ -21,11 +21,11 @@
#ifndef LOVE_FILESYSTEM_PHYSFS_PHYSFSIO_H #ifndef LOVE_FILESYSTEM_PHYSFS_PHYSFSIO_H
#define LOVE_FILESYSTEM_PHYSFS_PHYSFSIO_H #define LOVE_FILESYSTEM_PHYSFS_PHYSFSIO_H
#include <cstdint>
#include <cstdio>
#include <string>
#include "libraries/physfs/physfs.h" #include "libraries/physfs/physfs.h"
#include "common/int.h"
#include "filesystem/DroppedFile.h"
#include <string>
namespace love namespace love
{ {
@@ -61,54 +61,54 @@ protected:
private: private:
// Returns: number of bytes read, 0 on EOF, -1 on failure // Returns: number of bytes read, 0 on EOF, -1 on failure
static PHYSFS_sint64 staticRead(struct PHYSFS_Io* io, void* buf, PHYSFS_uint64 len) static PHYSFS_sint64 staticRead(struct PHYSFS_Io *io, void *buf, PHYSFS_uint64 len)
{ {
return derived(io)->read(buf, len); return derived(io)->read(buf, len);
} }
// Returns: number of bytes written, -1 on failure // Returns: number of bytes written, -1 on failure
static PHYSFS_sint64 staticWrite(struct PHYSFS_Io* io, const void* buf, PHYSFS_uint64 len) static PHYSFS_sint64 staticWrite(struct PHYSFS_Io *io, const void *buf, PHYSFS_uint64 len)
{ {
return derived(io)->write(buf, len); return derived(io)->write(buf, len);
} }
// Returns: non-zero on success, zero on error // Returns: non-zero on success, zero on error
static int staticSeek(struct PHYSFS_Io* io, PHYSFS_uint64 offset) static int staticSeek(struct PHYSFS_Io *io, PHYSFS_uint64 offset)
{ {
return derived(io)->seek(offset); return derived(io)->seek(offset);
} }
// Returns: current offset from start, -1 on error // Returns: current offset from start, -1 on error
static PHYSFS_sint64 staticTell(struct PHYSFS_Io* io) static PHYSFS_sint64 staticTell(struct PHYSFS_Io *io)
{ {
return derived(io)->tell(); return derived(io)->tell();
} }
// Returns: total size in bytes, -1 on error // Returns: total size in bytes, -1 on error
static PHYSFS_sint64 staticLength(struct PHYSFS_Io* io) static PHYSFS_sint64 staticLength(struct PHYSFS_Io *io)
{ {
return derived(io)->length(); return derived(io)->length();
} }
static struct PHYSFS_Io* staticDuplicate(struct PHYSFS_Io* io) static struct PHYSFS_Io *staticDuplicate(struct PHYSFS_Io *io)
{ {
// Just use copy constructor // Just use copy constructor
return new Derived(*derived(io)); return new Derived(*derived(io));
} }
// Returns: non-zero on success, zero on error // Returns: non-zero on success, zero on error
static int staticFlush(struct PHYSFS_Io* io) static int staticFlush(struct PHYSFS_Io *io)
{ {
return derived(io)->flush(); return derived(io)->flush();
} }
static void staticDestroy(struct PHYSFS_Io* io) static void staticDestroy(struct PHYSFS_Io *io)
{ {
// Just use destructor // Just use destructor
delete derived(io); delete derived(io);
} }
static Derived* derived(PHYSFS_Io* io) static Derived* derived(PHYSFS_Io *io)
{ {
return static_cast<Derived*>(reinterpret_cast<PhysfsIo*>(io->opaque)); return static_cast<Derived*>(reinterpret_cast<PhysfsIo*>(io->opaque));
} }
@@ -116,46 +116,60 @@ private:
struct StripSuffixIo : public PhysfsIo<StripSuffixIo> struct StripSuffixIo : public PhysfsIo<StripSuffixIo>
{ {
static const uint32_t version = 0; static const uint32 version = 0;
std::string filename; std::string filename;
FILE* file = nullptr; DroppedFile *file = nullptr;
// The constructor is private in favor of this function to prevent stack allocation // The constructor is private in favor of this function to prevent stack allocation
// because Physfs will take ownership of this object and call destroy on it later. // because Physfs will take ownership of this object and call destroy on it later.
static StripSuffixIo* create(std::string f) { return new StripSuffixIo(f); } static StripSuffixIo *create(const std::string &f) { return new StripSuffixIo(f); }
virtual ~StripSuffixIo() virtual ~StripSuffixIo()
{ {
if (file) if (file)
{ {
std::fclose(file); file->release();
} }
} }
StripSuffixIo(const StripSuffixIo& other) StripSuffixIo(const StripSuffixIo &other)
: StripSuffixIo(other.filename) : StripSuffixIo(other.filename)
{ {
} }
bool determineStrippedLength(); bool determineStrippedLength();
int64_t read(void* buf, uint64_t len); int64 read(void *buf, uint64 len);
int64_t write(const void* buf, uint64_t len); int64 write(const void *buf, uint64 len);
int64_t seek(uint64_t offset); int64 seek(uint64 offset);
int64_t tell(); int64 tell();
int64_t length(); int64 length();
int64_t flush(); int64 flush();
private: private:
StripSuffixIo(std::string f) StripSuffixIo(const std::string &f)
: filename(std::move(f)) : filename(f)
, file(std::fopen(filename.c_str(), "rb")) , file(new DroppedFile(f))
{ {
} bool success = false;
int64_t fullLength(); try
{
success = file->open(File::MODE_READ);
}
catch (love::Exception &)
{
success = false;
}
if (!success)
{
file->release();
file = nullptr;
}
}
int64_t strippedLength_ = -1; int64_t strippedLength_ = -1;
}; };