More renaming, initial implementation of manual file access for both VFS backends

This commit is contained in:
Henrik Rydgård committed 2023-03-07 19:37:19 +01:00
1 parent 23b310f59a
commit 97cf5f8d81
5 files changed
+148 -58

No files matched your search

+90 -24
View File
@@ -34,18 +34,29 @@ static uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) {
return contents;
}
ZipFileReader::ZipFileReader(const Path &zipFile, const char *inZipPath) {
ZipFileReader *ZipFileReader::Create(const Path &zipFile, const char *inZipPath) {
int error = 0;
zip *zip_file;
if (zipFile.Type() == PathType::CONTENT_URI) {
int fd = File::OpenFD(zipFile, File::OPEN_READ);
zip_file_ = zip_fdopen(fd, 0, &error);
if (!fd) {
ERROR_LOG(IO, "Failed to open FD for %s as zip file", zipFile.c_str());
return nullptr;
}
zip_file = zip_fdopen(fd, 0, &error);
} else {
zip_file_ = zip_open(zipFile.c_str(), 0, &error);
zip_file = zip_open(zipFile.c_str(), 0, &error);
}
truncate_cpy(inZipPath_, inZipPath);
if (!zip_file_) {
if (!zip_file) {
ERROR_LOG(IO, "Failed to open %s as a zip file", zipFile.c_str());
return nullptr;
}
ZipFileReader *reader = new ZipFileReader();
reader->zip_file_ = zip_file;
truncate_cpy(reader->inZipPath_, inZipPath);
return reader;
}
ZipFileReader::~ZipFileReader() {
@@ -78,6 +89,7 @@ bool ZipFileReader::GetFileListing(const char *orig_path, std::vector<File::File
filter++;
}
}
if (tmp.size())
filters.insert("." + tmp);
@@ -149,12 +161,16 @@ bool ZipFileReader::GetFileInfo(const char *path, File::FileInfo *info) {
struct zip_stat zstat;
char temp_path[1024];
snprintf(temp_path, sizeof(temp_path), "%s%s", inZipPath_, path);
if (0 != zip_stat(zip_file_, temp_path, ZIP_FL_NOCASE | ZIP_FL_UNCHANGED, &zstat)) {
// ZIP files do not have real directories, so we'll end up here if we
// try to stat one. For now that's fine.
info->exists = false;
info->size = 0;
return false;
{
std::lock_guard<std::mutex> guard(lock_);
if (0 != zip_stat(zip_file_, temp_path, ZIP_FL_NOCASE | ZIP_FL_UNCHANGED, &zstat)) {
// ZIP files do not have real directories, so we'll end up here if we
// try to stat one. For now that's fine.
info->exists = false;
info->size = 0;
return false;
}
}
info->fullName = Path(path);
@@ -167,34 +183,84 @@ bool ZipFileReader::GetFileInfo(const char *path, File::FileInfo *info) {
class ZipFileReaderFileReference : public VFSFileReference {
public:
int zi;
};
class ZipFileReaderOpenFile : public VFSOpenFile {
public:
ZipFileReaderFileReference *reference;
zip_file_t *zf;
};
static constexpr zip_uint64_t INVALID_ZIP_SIZE = 0xFFFFFFFFFFFFFFFFULL;
VFSFileReference *ZipFileReader::GetFile(const char *path) {
return nullptr;
std::lock_guard<std::mutex> guard(lock_);
int zi = zip_name_locate(zip_file_, path, ZIP_FL_NOCASE);
if (zi < 0) {
// Not found.
return nullptr;
}
ZipFileReaderFileReference *ref = new ZipFileReaderFileReference();
ref->zi = zi;
return ref;
}
void ZipFileReader::ReleaseFile(VFSFileReference *reference) {
ZipFileReaderFileReference *file = (ZipFileReaderFileReference *)reference;
bool ZipFileReader::GetFileInfo(VFSFileReference *vfsReference, File::FileInfo *fileInfo) {
ZipFileReaderFileReference *reference = (ZipFileReaderFileReference *)vfsReference;
// If you crash here, you called this while having the lock held by having the file open.
// Don't do that, check the info before you open the file.
std::lock_guard<std::mutex> guard(lock_);
zip_stat_t zstat;
if (zip_stat_index(zip_file_, reference->zi, 0, &zstat) != 0)
return false;
*fileInfo = File::FileInfo{};
fileInfo->size = 0;
if (zstat.valid & ZIP_STAT_SIZE)
fileInfo->size = zstat.size;
return zstat.size;
}
VFSOpenFile *ZipFileReader::OpenFileForRead(VFSFileReference *reference) {
ZipFileReaderFileReference *file = (ZipFileReaderFileReference *)reference;
return nullptr;
void ZipFileReader::ReleaseFile(VFSFileReference *vfsReference) {
ZipFileReaderFileReference *reference = (ZipFileReaderFileReference *)vfsReference;
// Don't do anything other than deleting it.
delete reference;
}
void ZipFileReader::Rewind(VFSOpenFile *openFile) {
ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)openFile;
VFSOpenFile *ZipFileReader::OpenFileForRead(VFSFileReference *vfsReference) {
ZipFileReaderFileReference *reference = (ZipFileReaderFileReference *)vfsReference;
ZipFileReaderOpenFile *openFile = new ZipFileReaderOpenFile();
openFile->reference = reference;
// We only allow one file to be open for read concurrently. It's possible that this can be improved,
// especially if we only access by index like this.
lock_.lock();
openFile->zf = zip_fopen_index(zip_file_, reference->zi, 0);
if (!openFile->zf) {
WARN_LOG(G3D, "File with index %d not found in zip", reference->zi);
lock_.unlock();
return nullptr;
}
return openFile;
}
size_t ZipFileReader::Read(VFSOpenFile *openFile, uint8_t *buffer, size_t length) {
ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)openFile;
return 0;
void ZipFileReader::Rewind(VFSOpenFile *vfsOpenFile) {
ZipFileReaderOpenFile *openFile = (ZipFileReaderOpenFile *)vfsOpenFile;
// Close and re-open.
zip_fclose(openFile->zf);
openFile->zf = zip_fopen_index(zip_file_, openFile->reference->zi, 0);
}
void ZipFileReader::CloseFile(VFSOpenFile *openFile) {
ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)openFile;
size_t ZipFileReader::Read(VFSOpenFile *vfsOpenFile, void *buffer, size_t length) {
ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)vfsOpenFile;
return zip_fread(file->zf, buffer, length);
}
void ZipFileReader::CloseFile(VFSOpenFile *vfsOpenFile) {
ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)vfsOpenFile;
_dbg_assert_(file->zf != nullptr);
zip_fclose(file->zf);
lock_.unlock();
delete file;
}