mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
Fix loading code-signed games on Windows with non-ascii paths.
Use DroppedFile (renamed to NativeFile in love 12) instead of C file APIs. NativeFile properly handles unicode file paths on Windows.
This commit is contained in:
@@ -18,7 +18,6 @@
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
|
||||
#include "PhysfsIo.h"
|
||||
@@ -32,14 +31,15 @@ namespace physfs
|
||||
|
||||
bool StripSuffixIo::determineStrippedLength()
|
||||
{
|
||||
if (!file) {
|
||||
if (!file)
|
||||
return false;
|
||||
}
|
||||
const int64_t fullSize = fullLength();
|
||||
int64_t chunkSize = std::min(fullSize, (int64_t)8192);
|
||||
|
||||
const int64 fullSize = file->getSize();
|
||||
|
||||
int64 chunkSize = std::min(fullSize, (int64) 8192);
|
||||
std::string buffer;
|
||||
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
|
||||
// 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.
|
||||
@@ -64,7 +64,7 @@ bool StripSuffixIo::determineStrippedLength()
|
||||
}
|
||||
if (i == 0)
|
||||
break;
|
||||
i = std::max((int64_t)0, i - chunkSize);
|
||||
i = std::max((int64)0, i - chunkSize);
|
||||
}
|
||||
|
||||
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
|
||||
if (seek(i + 20) == 0)
|
||||
return false;
|
||||
uint8_t buffer[2];
|
||||
uint8 buffer[2];
|
||||
const auto n = read(buffer, 2);
|
||||
if (n <= 0)
|
||||
return false;
|
||||
@@ -96,17 +96,17 @@ bool StripSuffixIo::determineStrippedLength()
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t StripSuffixIo::read(void* buf, uint64_t len)
|
||||
int64 StripSuffixIo::read(void *buf, uint64 len)
|
||||
{
|
||||
if (!file)
|
||||
{
|
||||
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
|
||||
return -1;
|
||||
}
|
||||
const auto ret = std::fread(buf, 1, len, file);
|
||||
if (ret == 0)
|
||||
int64 r = file->read(buf, (int64) len);
|
||||
if (r == 0)
|
||||
{
|
||||
if (std::feof(file))
|
||||
if (file->isEOF())
|
||||
{
|
||||
PHYSFS_setErrorCode(PHYSFS_ERR_OK);
|
||||
return 0;
|
||||
@@ -117,85 +117,59 @@ int64_t StripSuffixIo::read(void* buf, uint64_t len)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (ret < len && std::ferror(file))
|
||||
{
|
||||
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int64_t StripSuffixIo::seek(uint64_t offset)
|
||||
int64 StripSuffixIo::seek(uint64 offset)
|
||||
{
|
||||
if (!file)
|
||||
{
|
||||
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
|
||||
return 0;
|
||||
}
|
||||
const auto ret = std::fseek(file, offset, SEEK_SET);
|
||||
PHYSFS_setErrorCode(ret != 0 ? PHYSFS_ERR_OS_ERROR : PHYSFS_ERR_OK);
|
||||
return ret == 0 ? 1 : 0;
|
||||
bool success = file->seek(offset);
|
||||
PHYSFS_setErrorCode(success ? PHYSFS_ERR_OK : PHYSFS_ERR_OS_ERROR);
|
||||
return success ? 1 : 0;
|
||||
}
|
||||
|
||||
int64_t StripSuffixIo::tell()
|
||||
int64 StripSuffixIo::tell()
|
||||
{
|
||||
if (!file)
|
||||
{
|
||||
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
|
||||
return -1;
|
||||
}
|
||||
return std::ftell(file);
|
||||
return file->tell();
|
||||
}
|
||||
|
||||
int64_t StripSuffixIo::length()
|
||||
int64 StripSuffixIo::length()
|
||||
{
|
||||
return strippedLength_;
|
||||
}
|
||||
|
||||
int64_t StripSuffixIo::flush()
|
||||
int64 StripSuffixIo::flush()
|
||||
{
|
||||
if (!file)
|
||||
{
|
||||
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
|
||||
return 0;
|
||||
}
|
||||
return std::fflush(file) == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
int64_t StripSuffixIo::fullLength()
|
||||
{
|
||||
assert(file);
|
||||
const auto cur = std::ftell(file);
|
||||
if (cur == -1)
|
||||
try
|
||||
{
|
||||
return file->flush() ? 1 : 0;
|
||||
}
|
||||
catch (love::Exception &)
|
||||
{
|
||||
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
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
#ifndef LOVE_FILESYSTEM_PHYSFS_PHYSFSIO_H
|
||||
#define LOVE_FILESYSTEM_PHYSFS_PHYSFSIO_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
#include "libraries/physfs/physfs.h"
|
||||
#include "common/int.h"
|
||||
#include "filesystem/DroppedFile.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -61,54 +61,54 @@ protected:
|
||||
private:
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
static struct PHYSFS_Io* staticDuplicate(struct PHYSFS_Io* io)
|
||||
static struct PHYSFS_Io *staticDuplicate(struct PHYSFS_Io *io)
|
||||
{
|
||||
// Just use copy constructor
|
||||
return new Derived(*derived(io));
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
static void staticDestroy(struct PHYSFS_Io* io)
|
||||
static void staticDestroy(struct PHYSFS_Io *io)
|
||||
{
|
||||
// Just use destructor
|
||||
delete derived(io);
|
||||
}
|
||||
|
||||
static Derived* derived(PHYSFS_Io* io)
|
||||
static Derived* derived(PHYSFS_Io *io)
|
||||
{
|
||||
return static_cast<Derived*>(reinterpret_cast<PhysfsIo*>(io->opaque));
|
||||
}
|
||||
@@ -116,46 +116,60 @@ private:
|
||||
|
||||
struct StripSuffixIo : public PhysfsIo<StripSuffixIo>
|
||||
{
|
||||
static const uint32_t version = 0;
|
||||
static const uint32 version = 0;
|
||||
|
||||
std::string filename;
|
||||
FILE* file = nullptr;
|
||||
DroppedFile *file = nullptr;
|
||||
|
||||
// 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.
|
||||
static StripSuffixIo* create(std::string f) { return new StripSuffixIo(f); }
|
||||
static StripSuffixIo *create(const std::string &f) { return new StripSuffixIo(f); }
|
||||
|
||||
virtual ~StripSuffixIo()
|
||||
{
|
||||
if (file)
|
||||
{
|
||||
std::fclose(file);
|
||||
file->release();
|
||||
}
|
||||
}
|
||||
|
||||
StripSuffixIo(const StripSuffixIo& other)
|
||||
StripSuffixIo(const StripSuffixIo &other)
|
||||
: StripSuffixIo(other.filename)
|
||||
{
|
||||
}
|
||||
|
||||
bool determineStrippedLength();
|
||||
|
||||
int64_t read(void* buf, uint64_t len);
|
||||
int64_t write(const void* buf, uint64_t len);
|
||||
int64_t seek(uint64_t offset);
|
||||
int64_t tell();
|
||||
int64_t length();
|
||||
int64_t flush();
|
||||
int64 read(void *buf, uint64 len);
|
||||
int64 write(const void *buf, uint64 len);
|
||||
int64 seek(uint64 offset);
|
||||
int64 tell();
|
||||
int64 length();
|
||||
int64 flush();
|
||||
|
||||
private:
|
||||
|
||||
StripSuffixIo(std::string f)
|
||||
: filename(std::move(f))
|
||||
, file(std::fopen(filename.c_str(), "rb"))
|
||||
StripSuffixIo(const std::string &f)
|
||||
: filename(f)
|
||||
, 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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user