mirror of
https://github.com/love2d/love.git
synced 2026-08-20 04:30:09 +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.
|
* 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
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user