From 0f172abb004bed203f8bf329e4f43eb174a8a58c Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Wed, 1 Mar 2017 02:19:37 +0300 Subject: Fix compilation without physfs. Also split fs related files to virtfs and physfs. --- src/CMakeLists.txt | 44 +-- src/Makefile.am | 45 ++- src/fs/physfs/virtfileprivate.cpp | 28 ++ src/fs/physfs/virtfileprivate.h | 43 ++ src/fs/physfs/virtfs.cpp | 207 ++++++++++ src/fs/physfs/virtfsphys.cpp | 327 +++++++++++++++ src/fs/physfs/virtfsphys.h | 80 ++++ src/fs/physfs/virtfsphys_unittest.cc | 539 +++++++++++++++++++++++++ src/fs/virtdirentry.cpp | 34 -- src/fs/virtdirentry.h | 41 -- src/fs/virtfile.cpp | 7 +- src/fs/virtfileprivate.cpp | 73 ---- src/fs/virtfileprivate.h | 60 --- src/fs/virtfs.cpp | 251 ------------ src/fs/virtfs.h | 8 +- src/fs/virtfs/virtdirentry.cpp | 34 ++ src/fs/virtfs/virtdirentry.h | 41 ++ src/fs/virtfs/virtfileprivate.cpp | 59 +++ src/fs/virtfs/virtfileprivate.h | 50 +++ src/fs/virtfs/virtfs.cpp | 257 ++++++++++++ src/fs/virtfs/virtfsdir.cpp | 651 ++++++++++++++++++++++++++++++ src/fs/virtfs/virtfsdir.h | 89 +++++ src/fs/virtfs/virtfsdir_unittest.cc | 717 +++++++++++++++++++++++++++++++++ src/fs/virtfs/virtfszip.cpp | 555 ++++++++++++++++++++++++++ src/fs/virtfs/virtfszip.h | 88 +++++ src/fs/virtfs/virtfszip_unittest.cc | 745 +++++++++++++++++++++++++++++++++++ src/fs/virtfs/virtzipentry.cpp | 38 ++ src/fs/virtfs/virtzipentry.h | 45 +++ src/fs/virtfs/zip.cpp | 291 ++++++++++++++ src/fs/virtfs/zip.h | 42 ++ src/fs/virtfs/zip_unittest.cc | 280 +++++++++++++ src/fs/virtfs/ziplocalheader.cpp | 39 ++ src/fs/virtfs/ziplocalheader.h | 44 +++ src/fs/virtfsdir.cpp | 626 ----------------------------- src/fs/virtfsdir.h | 86 ---- src/fs/virtfsdir_unittest.cc | 717 --------------------------------- src/fs/virtfsphys.cpp | 326 --------------- src/fs/virtfsphys.h | 80 ---- src/fs/virtfsphys_unittest.cc | 538 ------------------------- src/fs/virtfstools.cpp | 8 +- src/fs/virtfszip.cpp | 540 ------------------------- src/fs/virtfszip.h | 84 ---- src/fs/virtfszip_unittest.cc | 744 ---------------------------------- src/fs/virtzipentry.cpp | 38 -- src/fs/virtzipentry.h | 45 --- src/fs/zip.cpp | 290 -------------- src/fs/zip.h | 42 -- src/fs/zip_unittest.cc | 279 ------------- src/fs/ziplocalheader.cpp | 39 -- src/fs/ziplocalheader.h | 44 --- src/integrity_unittest.cc | 4 + src/utils/dumplibs.cpp | 7 + src/utils/dumplibs_unittest.cc | 4 + 53 files changed, 5354 insertions(+), 5039 deletions(-) create mode 100644 src/fs/physfs/virtfileprivate.cpp create mode 100644 src/fs/physfs/virtfileprivate.h create mode 100644 src/fs/physfs/virtfs.cpp create mode 100644 src/fs/physfs/virtfsphys.cpp create mode 100644 src/fs/physfs/virtfsphys.h create mode 100644 src/fs/physfs/virtfsphys_unittest.cc delete mode 100644 src/fs/virtdirentry.cpp delete mode 100644 src/fs/virtdirentry.h delete mode 100644 src/fs/virtfileprivate.cpp delete mode 100644 src/fs/virtfileprivate.h delete mode 100644 src/fs/virtfs.cpp create mode 100644 src/fs/virtfs/virtdirentry.cpp create mode 100644 src/fs/virtfs/virtdirentry.h create mode 100644 src/fs/virtfs/virtfileprivate.cpp create mode 100644 src/fs/virtfs/virtfileprivate.h create mode 100644 src/fs/virtfs/virtfs.cpp create mode 100644 src/fs/virtfs/virtfsdir.cpp create mode 100644 src/fs/virtfs/virtfsdir.h create mode 100644 src/fs/virtfs/virtfsdir_unittest.cc create mode 100644 src/fs/virtfs/virtfszip.cpp create mode 100644 src/fs/virtfs/virtfszip.h create mode 100644 src/fs/virtfs/virtfszip_unittest.cc create mode 100644 src/fs/virtfs/virtzipentry.cpp create mode 100644 src/fs/virtfs/virtzipentry.h create mode 100644 src/fs/virtfs/zip.cpp create mode 100644 src/fs/virtfs/zip.h create mode 100644 src/fs/virtfs/zip_unittest.cc create mode 100644 src/fs/virtfs/ziplocalheader.cpp create mode 100644 src/fs/virtfs/ziplocalheader.h delete mode 100644 src/fs/virtfsdir.cpp delete mode 100644 src/fs/virtfsdir.h delete mode 100644 src/fs/virtfsdir_unittest.cc delete mode 100644 src/fs/virtfsphys.cpp delete mode 100644 src/fs/virtfsphys.h delete mode 100644 src/fs/virtfsphys_unittest.cc delete mode 100644 src/fs/virtfszip.cpp delete mode 100644 src/fs/virtfszip.h delete mode 100644 src/fs/virtfszip_unittest.cc delete mode 100644 src/fs/virtzipentry.cpp delete mode 100644 src/fs/virtzipentry.h delete mode 100644 src/fs/zip.cpp delete mode 100644 src/fs/zip.h delete mode 100644 src/fs/zip_unittest.cc delete mode 100644 src/fs/ziplocalheader.cpp delete mode 100644 src/fs/ziplocalheader.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a7e2c3c28..bf2e2e46d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -887,27 +887,17 @@ SET(SRCS utils/perfomance.cpp utils/perfomance.h utils/debugmemoryobject.h - fs/virtfsdir.cpp - fs/virtfsdir.h fs/virtfsfuncs.h - fs/virtfsphys.cpp - fs/virtfsphys.h + fs/physfs/virtfsphys.cpp + fs/physfs/virtfsphys.h fs/virtfsrwops.cpp fs/virtfsrwops.h fs/virtfstools.cpp fs/virtfstools.h - fs/virtfszip.cpp - fs/virtfszip.h fs/virtlist.cpp fs/virtlist.h - fs/virtzipentry.cpp - fs/virtzipentry.h - fs/virtfs.cpp + fs/physfs/virtfs.cpp fs/virtfs.h - fs/zip.cpp - fs/zip.h - fs/ziplocalheader.cpp - fs/ziplocalheader.h utils/process.cpp utils/process.h utils/sdl2helper.cpp @@ -923,12 +913,10 @@ SET(SRCS utils/stringvector.h utils/timer.cpp utils/timer.h - fs/virtdirentry.cpp - fs/virtdirentry.h fs/virtfile.cpp fs/virtfile.h - fs/virtfileprivate.cpp - fs/virtfileprivate.h + fs/physfs/virtfileprivate.cpp + fs/physfs/virtfileprivate.h utils/mutex.h utils/naclmessages.cpp utils/naclmessages.h @@ -1788,27 +1776,17 @@ SET(DYE_CMD_SRCS fs/paths.h utils/perfomance.cpp utils/perfomance.h - fs/virtfsdir.cpp - fs/virtfsdir.h fs/virtfsfuncs.h - fs/virtfsphys.cpp - fs/virtfsphys.h + fs/physfs/virtfsphys.cpp + fs/physfs/virtfsphys.h fs/virtfsrwops.cpp fs/virtfsrwops.h fs/virtfstools.cpp fs/virtfstools.h - fs/virtfszip.cpp - fs/virtfszip.h fs/virtlist.cpp fs/virtlist.h - fs/virtzipentry.cpp - fs/virtzipentry.h - fs/virtfs.cpp + fs/physfs/virtfs.cpp fs/virtfs.h - fs/zip.cpp - fs/zip.h - fs/ziplocalheader.cpp - fs/ziplocalheader.h utils/sdl2helper.cpp utils/sdl2helper.h utils/sdlcheckutils.cpp @@ -1820,12 +1798,10 @@ SET(DYE_CMD_SRCS utils/stringutils.h utils/timer.cpp utils/timer.h - fs/virtdirentry.cpp - fs/virtdirentry.h fs/virtfile.cpp fs/virtfile.h - fs/virtfileprivate.cpp - fs/virtfileprivate.h + fs/physfs/virtfileprivate.cpp + fs/physfs/virtfileprivate.h utils/xml.cpp utils/xml.h utils/xml.inc diff --git a/src/Makefile.am b/src/Makefile.am index 31d78afe7..22ef18bee 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -563,7 +563,6 @@ BASE_SRC += events/actionevent.h \ fs/virtfstools.h \ fs/virtlist.cpp \ fs/virtlist.h \ - fs/virtfs.cpp \ fs/virtfs.h \ utils/process.cpp \ utils/process.h \ @@ -584,8 +583,6 @@ BASE_SRC += events/actionevent.h \ utils/timer.h \ fs/virtfile.cpp \ fs/virtfile.h \ - fs/virtfileprivate.cpp \ - fs/virtfileprivate.h \ utils/mutex.h \ utils/naclmessages.cpp \ utils/naclmessages.h \ @@ -828,22 +825,28 @@ BASE_SRC += events/actionevent.h \ if USE_PHYSFS BASE_SRC += \ - fs/virtfsphys.cpp \ - fs/virtfsphys.h + fs/physfs/virtfileprivate.cpp \ + fs/physfs/virtfileprivate.h \ + fs/physfs/virtfs.cpp \ + fs/physfs/virtfsphys.cpp \ + fs/physfs/virtfsphys.h else BASE_SRC += \ - fs/virtdirentry.cpp \ - fs/virtdirentry.h \ - fs/virtfsdir.cpp \ - fs/virtfsdir.h \ - fs/virtfszip.cpp \ - fs/virtfszip.h \ - fs/virtzipentry.cpp \ - fs/virtzipentry.h \ - fs/zip.cpp \ - fs/zip.h \ - fs/ziplocalheader.cpp \ - fs/ziplocalheader.h + fs/virtfs/virtdirentry.cpp \ + fs/virtfs/virtdirentry.h \ + fs/virtfs/virtfileprivate.cpp \ + fs/virtfs/virtfileprivate.h \ + fs/virtfs/virtfs.cpp \ + fs/virtfs/virtfsdir.cpp \ + fs/virtfs/virtfsdir.h \ + fs/virtfs/virtfszip.cpp \ + fs/virtfs/virtfszip.h \ + fs/virtfs/virtzipentry.cpp \ + fs/virtfs/virtzipentry.h \ + fs/virtfs/zip.cpp \ + fs/virtfs/zip.h \ + fs/virtfs/ziplocalheader.cpp \ + fs/virtfs/ziplocalheader.h endif if ENABLE_PUGIXML @@ -1951,12 +1954,12 @@ manaplustests_SOURCES = ${SRC} \ if USE_PHYSFS manaplustests_SOURCES += \ - fs/virtfsphys_unittest.cc + fs/physfs/virtfsphys_unittest.cc else manaplustests_SOURCES += \ - fs/virtfsdir_unittest.cc \ - fs/zip_unittest.cc \ - fs/virtfszip_unittest.cc + fs/virtfs/virtfsdir_unittest.cc \ + fs/virtfs/zip_unittest.cc \ + fs/virtfs/virtfszip_unittest.cc endif manaplustests_SOURCES += \ diff --git a/src/fs/physfs/virtfileprivate.cpp b/src/fs/physfs/virtfileprivate.cpp new file mode 100644 index 000000000..9df6e9578 --- /dev/null +++ b/src/fs/physfs/virtfileprivate.cpp @@ -0,0 +1,28 @@ +/* + * The ManaPlus Client + * Copyright (C) 2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "fs/physfs/virtfileprivate.h" + +#include "debug.h" + +VirtFilePrivate::VirtFilePrivate(PHYSFS_file *restrict const file) : + mFile(file) +{ +} diff --git a/src/fs/physfs/virtfileprivate.h b/src/fs/physfs/virtfileprivate.h new file mode 100644 index 000000000..75ad6a337 --- /dev/null +++ b/src/fs/physfs/virtfileprivate.h @@ -0,0 +1,43 @@ +/* + * The ManaPlus Client + * Copyright (C) 2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef UTILS_VIRTFILEPRIVATE_H +#define UTILS_VIRTFILEPRIVATE_H + +#include "localconsts.h" + +PRAGMA45(GCC diagnostic push) +PRAGMA45(GCC diagnostic ignored "-Wlong-long") +#include +PRAGMA45(GCC diagnostic pop) + +struct VirtFilePrivate final +{ + explicit VirtFilePrivate(PHYSFS_file *restrict const file); + + A_DELETE_COPY(VirtFilePrivate) + + ~VirtFilePrivate(); + + // physfs fields + PHYSFS_file *mFile; +}; + +#endif // UTILS_VIRTFILEPRIVATE_H diff --git a/src/fs/physfs/virtfs.cpp b/src/fs/physfs/virtfs.cpp new file mode 100644 index 000000000..7a1484081 --- /dev/null +++ b/src/fs/physfs/virtfs.cpp @@ -0,0 +1,207 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013-2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "fs/virtfs.h" + +#include "fs/physfs/virtfsphys.h" +#include "fs/virtfile.h" +#include "fs/virtfsfuncs.h" +#include "fs/virtlist.h" + +#include "debug.h" + +const char *dirSeparator = nullptr; + +namespace VirtFs +{ + void init(const std::string &restrict name) + { + VirtFsPhys::init(name); + updateDirSeparator(); + } + + void updateDirSeparator() + { + dirSeparator = VirtFsPhys::getDirSeparator(); + } + + const char *getDirSeparator() + { + return dirSeparator; + } + + const char *getBaseDir() + { + return VirtFsPhys::getBaseDir(); + } + + const char *getUserDir() + { + return VirtFsPhys::getUserDir(); + } + + bool exists(const std::string &restrict name) + { + return VirtFsPhys::exists(name); + } + + VirtList *enumerateFiles(std::string dirName) + { + return VirtFsPhys::enumerateFiles(dirName); + } + + bool isDirectory(std::string name) + { + return VirtFsPhys::isDirectory(name); + } + + bool isSymbolicLink(const std::string &restrict name) + { + return VirtFsPhys::isSymbolicLink(name); + } + + void freeList(VirtList *restrict const handle) + { + delete handle; + } + + VirtFile *openRead(std::string filename) + { + return VirtFsPhys::openRead(filename); + } + + VirtFile *openWrite(const std::string &restrict filename) + { + return VirtFsPhys::openWrite(filename); + } + + VirtFile *openAppend(const std::string &restrict filename) + { + return VirtFsPhys::openAppend(filename); + } + + bool setWriteDir(const std::string &restrict newDir) + { + return VirtFsPhys::setWriteDir(newDir); + } + + bool addDirToSearchPath(const std::string &restrict newDir, + const Append append) + { + return VirtFsPhys::addDirToSearchPath(newDir, append); + } + + bool removeDirFromSearchPath(const std::string &restrict oldDir) + { + return VirtFsPhys::removeDirFromSearchPath(oldDir); + } + + bool addZipToSearchPath(const std::string &restrict newDir, + const Append append) + { + return VirtFsPhys::addZipToSearchPath(newDir, append); + } + + bool removeZipFromSearchPath(const std::string &restrict oldDir) + { + return VirtFsPhys::removeZipFromSearchPath(oldDir); + } + + std::string getRealDir(std::string filename) + { + return VirtFsPhys::getRealDir(filename); + } + + bool mkdir(const std::string &restrict dirname) + { + return VirtFsPhys::mkdir(dirname); + } + + bool remove(const std::string &restrict filename) + { + return VirtFsPhys::remove(filename); + } + + bool deinit() + { + return VirtFsPhys::deinit(); + } + + void permitLinks(const bool val) + { + VirtFsPhys::permitLinks(val); + } + + const char *getLastError() + { + return VirtFsPhys::getLastError(); + } + + int close(VirtFile *restrict const file) + { + if (file == nullptr) + return 0; + return file->funcs->close(file); + } + + int64_t read(VirtFile *restrict const file, + void *restrict const buffer, + const uint32_t objSize, + const uint32_t objCount) + { + return file->funcs->read(file, + buffer, + objSize, + objCount); + } + + int64_t write(VirtFile *restrict const file, + const void *restrict const buffer, + const uint32_t objSize, + const uint32_t objCount) + { + return file->funcs->write(file, + buffer, + objSize, + objCount); + } + + int64_t fileLength(VirtFile *restrict const file) + { + return file->funcs->fileLength(file); + } + + int64_t tell(VirtFile *restrict const file) + { + return file->funcs->tell(file); + } + + int seek(VirtFile *restrict const file, + const uint64_t pos) + { + return file->funcs->seek(file, + pos); + } + + int eof(VirtFile *restrict const file) + { + return file->funcs->eof(file); + } +} // namespace VirtFs diff --git a/src/fs/physfs/virtfsphys.cpp b/src/fs/physfs/virtfsphys.cpp new file mode 100644 index 000000000..3cb044277 --- /dev/null +++ b/src/fs/physfs/virtfsphys.cpp @@ -0,0 +1,327 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013-2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "fs/physfs/virtfsphys.h" + +#include "fs/virtfile.h" +#include "fs/virtfsfuncs.h" +#include "fs/virtlist.h" + +#include "fs/physfs/virtfileprivate.h" + +#include "utils/checkutils.h" + +#include +#include + +#ifdef ANDROID +#include "fs/paths.h" +#endif // ANDROID + +#include "debug.h" + +namespace +{ + const char *dirSeparator = nullptr; + VirtFsFuncs funcs; +} // namespace + +namespace VirtFsPhys +{ +#if defined(__native_client__) + void init(const std::string &restrict name A_UNUSED) + { + if (!PHYSFS_init("/fakebinary")) +#elif defined(ANDROID) + void init(const std::string &restrict name A_UNUSED) + { + if (!PHYSFS_init((getRealPath(".").append("/fakebinary")).c_str())) +#else // defined(__native_client__) + + void init(const std::string &restrict name) + { + if (!PHYSFS_init(name.c_str())) +#endif // defined(__native_client__) + { + std::cout << "Error while initializing PhysFS: " + << VirtFsPhys::getLastError() << std::endl; + _exit(1); + } + updateDirSeparator(); + atexit(reinterpret_cast(PHYSFS_deinit)); + initFuncs(&funcs); + } + + void initFuncs() + { + initFuncs(&funcs); + } + + void initFuncs(VirtFsFuncs *restrict const ptr) + { + ptr->close = &VirtFsPhys::close; + ptr->read = &VirtFsPhys::read; + ptr->write = &VirtFsPhys::write; + ptr->fileLength = &VirtFsPhys::fileLength; + ptr->tell = &VirtFsPhys::tell; + ptr->seek = &VirtFsPhys::seek; + ptr->eof = &VirtFsPhys::eof; + } + + void updateDirSeparator() + { + dirSeparator = PHYSFS_getDirSeparator(); + } + + const char *getDirSeparator() + { + return dirSeparator; + } + + const char *getBaseDir() + { + return PHYSFS_getBaseDir(); + } + + const char *getUserDir() + { + return PHYSFS_getUserDir(); + } + + bool exists(const std::string &restrict name) + { + return PHYSFS_exists(name.c_str()); + } + + VirtList *enumerateFiles(const std::string &restrict dir) + { + char ** handle = PHYSFS_enumerateFiles(dir.c_str()); + VirtList *const files = new VirtList; + if (handle == nullptr) + return files; + for (const char *const *i = handle; *i; i++) + { + std::string str = *i; + files->names.push_back(str); + } + PHYSFS_freeList(handle); + return files; + } + + bool isDirectory(const std::string &restrict name) + { + return PHYSFS_isDirectory(name.c_str()); + } + + bool isSymbolicLink(const std::string &restrict name) + { + return PHYSFS_isSymbolicLink(name.c_str()); + } + + void freeList(VirtList *restrict const handle) + { + delete handle; + } + + VirtFile *openRead(const std::string &restrict filename) + { + PHYSFS_file *restrict const handle = PHYSFS_openRead( + filename.c_str()); + if (!handle) + return nullptr; + VirtFile *restrict const file = new VirtFile(&funcs); + file->mPrivate = new VirtFilePrivate(handle); + return file; + } + + VirtFile *openWrite(const std::string &restrict filename) + { + PHYSFS_file *restrict const handle = PHYSFS_openWrite( + filename.c_str()); + if (!handle) + return nullptr; + VirtFile *restrict const file = new VirtFile(&funcs); + file->mPrivate = new VirtFilePrivate(handle); + return file; + } + + VirtFile *openAppend(const std::string &restrict filename) + { + PHYSFS_file *restrict const handle = PHYSFS_openAppend( + filename.c_str()); + if (!handle) + return nullptr; + VirtFile *restrict const file = new VirtFile(&funcs); + file->mPrivate = new VirtFilePrivate(handle); + return file; + } + + bool setWriteDir(const std::string &restrict newDir) + { + return PHYSFS_setWriteDir(newDir.c_str()); + } + + bool addDirToSearchPath(const std::string &restrict newDir, + const Append append) + { + logger->log("Add virtual directory: " + newDir); + if (newDir.find(".zip") != std::string::npos) + { + reportAlways("Called addDirToSearchPath with zip archive"); + return false; + } + return PHYSFS_addToSearchPath(newDir.c_str(), + append == Append_true ? 1 : 0); + } + + bool removeDirFromSearchPath(const std::string &restrict oldDir) + { + logger->log("Remove virtual directory: " + oldDir); + if (oldDir.find(".zip") != std::string::npos) + { + reportAlways("Called removeDirFromSearchPath with zip archive"); + return false; + } + return PHYSFS_removeFromSearchPath(oldDir.c_str()); + } + + bool addZipToSearchPath(const std::string &restrict newDir, + const Append append) + { + logger->log("Add virtual zip: " + newDir); + if (newDir.find(".zip") == std::string::npos) + { + reportAlways("Called addZipToSearchPath without zip archive"); + return false; + } + return PHYSFS_addToSearchPath(newDir.c_str(), + append == Append_true ? 1 : 0); + } + + bool removeZipFromSearchPath(const std::string &restrict oldDir) + { + logger->log("Remove virtual zip: " + oldDir); + if (oldDir.find(".zip") == std::string::npos) + { + reportAlways("Called removeZipFromSearchPath without zip archive"); + return false; + } + return PHYSFS_removeFromSearchPath(oldDir.c_str()); + } + + std::string getRealDir(const std::string &restrict filename) + { + const char *const str = PHYSFS_getRealDir(filename.c_str()); + if (str == nullptr) + return std::string(); + return str; + } + + bool mkdir(const std::string &restrict dirname) + { + return PHYSFS_mkdir(dirname.c_str()); + } + + bool remove(const std::string &restrict filename) + { + return PHYSFS_delete(filename.c_str()); + } + + bool deinit() + { + if (PHYSFS_deinit() != 0) + { + logger->log("Physfs deinit error: %s", + VirtFsPhys::getLastError()); + return false; + } + return true; + } + + void permitLinks(const bool val) + { + PHYSFS_permitSymbolicLinks(val ? 1 : 0); + } + + const char *getLastError() + { + return PHYSFS_getLastError(); + } + + int close(VirtFile *restrict const file) + { + if (file == nullptr) + return 0; + delete file; + return 1; + } + + int64_t read(VirtFile *restrict const file, + void *restrict const buffer, + const uint32_t objSize, + const uint32_t objCount) + { + if (file == nullptr) + return 0; + return PHYSFS_read(file->mPrivate->mFile, + buffer, + objSize, + objCount); + } + + int64_t write(VirtFile *restrict const file, + const void *restrict const buffer, + const uint32_t objSize, + const uint32_t objCount) + { + if (file == nullptr) + return 0; + return PHYSFS_write(file->mPrivate->mFile, + buffer, + objSize, + objCount); + } + + int64_t fileLength(VirtFile *restrict const file) + { + if (file == nullptr) + return -1; + return PHYSFS_fileLength(file->mPrivate->mFile); + } + + int64_t tell(VirtFile *restrict const file) + { + if (file == nullptr) + return -1; + return PHYSFS_tell(file->mPrivate->mFile); + } + + int seek(VirtFile *restrict const file, + const uint64_t pos) + { + return PHYSFS_seek(file->mPrivate->mFile, + pos); + } + + int eof(VirtFile *restrict const file) + { + return PHYSFS_eof(file->mPrivate->mFile); + } +} // namespace VirtFsPhys diff --git a/src/fs/physfs/virtfsphys.h b/src/fs/physfs/virtfsphys.h new file mode 100644 index 000000000..743530c6c --- /dev/null +++ b/src/fs/physfs/virtfsphys.h @@ -0,0 +1,80 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013-2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef UTILS_VIRTFSPHYS_H +#define UTILS_VIRTFSPHYS_H + +#include "enums/simpletypes/append.h" + +#include "localconsts.h" + +#include + +struct VirtFile; +struct VirtFsFuncs; +struct VirtList; + +namespace VirtFsPhys +{ + void init(const std::string &restrict name); + void initFuncs(VirtFsFuncs *restrict const ptr); + void initFuncs(); + void updateDirSeparator(); + const char *getDirSeparator(); + const char *getBaseDir(); + const char *getUserDir(); + bool exists(const std::string &restrict name); + VirtList *enumerateFiles(const std::string &restrict dir) RETURNS_NONNULL; + bool isDirectory(const std::string &restrict name); + bool isSymbolicLink(const std::string &restrict name); + void freeList(VirtList *restrict const handle); + VirtFile *openRead(const std::string &restrict filename); + VirtFile *openWrite(const std::string &restrict filename); + VirtFile *openAppend(const std::string &restrict filename); + bool setWriteDir(const std::string &restrict newDir); + bool addDirToSearchPath(const std::string &restrict newDir, + const Append append); + bool removeDirFromSearchPath(const std::string &restrict oldDir); + bool addZipToSearchPath(const std::string &restrict newDir, + const Append append); + bool removeZipFromSearchPath(const std::string &restrict oldDir); + std::string getRealDir(const std::string &restrict filename); + bool mkdir(const std::string &restrict dirName); + bool remove(const std::string &restrict filename); + bool deinit(); + void permitLinks(const bool val); + const char *getLastError(); + int64_t read(VirtFile *restrict const handle, + void *restrict const buffer, + const uint32_t objSize, + const uint32_t objCount); + int64_t write(VirtFile *restrict const file, + const void *restrict const buffer, + const uint32_t objSize, + const uint32_t objCount); + int close(VirtFile *restrict const file); + int64_t fileLength(VirtFile *restrict const file); + int64_t tell(VirtFile *restrict const file); + int seek(VirtFile *restrict const file, + const uint64_t pos); + int eof(VirtFile *restrict const file); +} // namespace VirtFsPhys + +#endif // UTILS_VIRTFSPHYS_H diff --git a/src/fs/physfs/virtfsphys_unittest.cc b/src/fs/physfs/virtfsphys_unittest.cc new file mode 100644 index 000000000..8e81cfe2b --- /dev/null +++ b/src/fs/physfs/virtfsphys_unittest.cc @@ -0,0 +1,539 @@ +/* + * The ManaPlus Client + * Copyright (C) 2016-2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "catch.hpp" + +#include "fs/paths.h" +#include "fs/virtfs.h" +#include "fs/virtfstools.h" +#include "fs/virtlist.h" + +#include "fs/physfs/virtfsphys.h" + +#include "utils/checkutils.h" +#include "utils/delete2.h" + +#include "debug.h" + +TEST_CASE("VirtFsPhys dirSeparator") +{ + VirtFsPhys::initFuncs(); + REQUIRE(VirtFs::getDirSeparator() != nullptr); + REQUIRE(VirtFsPhys::getDirSeparator() == + std::string(VirtFs::getDirSeparator())); + VirtFsPhys::updateDirSeparator(); + REQUIRE(VirtFs::getDirSeparator() != nullptr); + REQUIRE(VirtFsPhys::getDirSeparator() == + std::string(VirtFs::getDirSeparator())); +} + +TEST_CASE("VirtFsPhys getBaseDir") +{ + VirtFsPhys::initFuncs(); + REQUIRE(VirtFsPhys::getBaseDir() != nullptr); +} + +TEST_CASE("VirtFsPhys getUserDir") +{ + VirtFsPhys::initFuncs(); + REQUIRE(VirtFsPhys::getUserDir() != nullptr); + REQUIRE(VirtFsPhys::getUserDir() == getHomePath()); +} + +TEST_CASE("VirtFsPhys exists") +{ + VirtFsPhys::initFuncs(); + logger = new Logger(); + VirtFsPhys::addDirToSearchPath("data", Append_false); + VirtFsPhys::addDirToSearchPath("../data", Append_false); + + REQUIRE(VirtFsPhys::exists("test/units.xml") == true); + REQUIRE(VirtFsPhys::exists("test/units123.xml") == false); + REQUIRE(VirtFsPhys::exists("tesQ/units.xml") == false); + REQUIRE(VirtFsPhys::exists("units.xml") == false); + + VirtFsPhys::addDirToSearchPath("data/test", Append_false); + VirtFsPhys::addDirToSearchPath("../data/test", Append_false); + + REQUIRE(VirtFsPhys::exists("test/units.xml") == true); + REQUIRE(VirtFsPhys::exists("test/units123.xml") == false); + REQUIRE(VirtFsPhys::exists("tesQ/units.xml") == false); + REQUIRE(VirtFsPhys::exists("units.xml") == true); + + VirtFsPhys::removeDirFromSearchPath("data/test"); + VirtFsPhys::removeDirFromSearchPath("../data/test"); + + REQUIRE(VirtFsPhys::exists("test/units.xml") == true); + REQUIRE(VirtFsPhys::exists("test/units123.xml") == false); + REQUIRE(VirtFsPhys::exists("tesQ/units.xml") == false); + REQUIRE(VirtFsPhys::exists("units.xml") == false); + + VirtFsPhys::removeDirFromSearchPath("data"); + VirtFsPhys::removeDirFromSearchPath("../data"); + delete2(logger); +} + +TEST_CASE("VirtFsPhys exists2") +{ + VirtFsPhys::initFuncs(); + logger = new Logger(); + VirtFsPhys::addZipToSearchPath("data/test/test2.zip", Append_false); + VirtFsPhys::addZipToSearchPath("../data/test/test2.zip", Append_false); + + REQUIRE(VirtFsPhys::exists("test/units.xml") == false); + REQUIRE(VirtFsPhys::exists("test.txt") == true); + REQUIRE(VirtFsPhys::exists("units123.xml") == false); + REQUIRE(VirtFsPhys::exists("tesQ/units.xml") == false); + REQUIRE(VirtFsPhys::exists("units.xml") == true); + + VirtFsPhys::removeZipFromSearchPath("data/test/test2.zip"); + VirtFsPhys::removeZipFromSearchPath("../data/test/test2.zip"); + delete2(logger); +} + +static void removeTemp(StringVect &restrict list) +{ + int cnt = 0; + std::sort(list.begin(), list.end()); + + FOR_EACH (StringVectIter, it, list) + { + if (*it != "serverlistplus.xml.part") + { + logger->log("file: %d %s", + cnt, + (*it).c_str()); + cnt ++; + } + } + + FOR_EACH (StringVectIter, it, list) + { + if (*it == "serverlistplus.xml.part") + { + list.erase(it); + return; + } + } +} + +TEST_CASE("VirtFsPhys enumerateFiles1") +{ + VirtFsPhys::initFuncs(); + logger = new Logger; + + VirtFsPhys::addDirToSearchPath("data", Append_false); + VirtFsPhys::addDirToSearchPath("../data", Append_false); + + VirtList *list = nullptr; + + const int cnt1 = VirtFsPhys::exists("test/test2.txt") ? 27 : 26; + const int cnt2 = 27; + + VirtFsPhys::permitLinks(false); + list = VirtFsPhys::enumerateFiles("test"); + removeTemp(list->names); + const size_t sz = list->names.size(); + REQUIRE(sz == cnt1); + VirtFsPhys::freeList(list); + + VirtFsPhys::permitLinks(true); + list = VirtFsPhys::enumerateFiles("test"); + removeTemp(list->names); + REQUIRE(list->names.size() == cnt2); + VirtFsPhys::freeList(list); + + VirtFsPhys::permitLinks(false); + list = VirtFsPhys::enumerateFiles("test"); + removeTemp(list->names); + REQUIRE(list->names.size() == cnt1); + VirtFsPhys::freeList(list); + + VirtFsPhys::removeDirFromSearchPath("data"); + VirtFsPhys::removeDirFromSearchPath("../data"); + delete2(logger); +} + +TEST_CASE("VirtFsPhys enumerateFiles2") +{ + VirtFsPhys::initFuncs(); + logger = new Logger; + + VirtFsPhys::addDirToSearchPath("data/test/dir1", + Append_false); + VirtFsPhys::addDirToSearchPath("../data/test/dir1", + Append_false); + + VirtList *list = nullptr; + + list = VirtFsPhys::enumerateFiles("/"); + const size_t sz = list->names.size(); + REQUIRE(list->names.size() == 5); + VirtFsPhys::freeList(list); + + VirtFsPhys::removeDirFromSearchPath("data/test/dir1"); + VirtFsPhys::removeDirFromSearchPath("../data/test/dir1"); + delete2(logger); +} + +static bool inList(VirtList *list, + const std::string &name) +{ + FOR_EACH (StringVectCIter, it, list->names) + { + if (*it == name) + return true; + } + return false; +} + +TEST_CASE("VirtFsPhys enumerateFiles3") +{ + VirtFsPhys::initFuncs(); + logger = new Logger; + + VirtFsPhys::addZipToSearchPath("data/test/test.zip", + Append_false); + VirtFsPhys::addZipToSearchPath("../data/test/test.zip", + Append_false); + + VirtList *list = nullptr; + + list = VirtFsPhys::enumerateFiles("/"); + REQUIRE(inList(list, "units.xml") == false); + REQUIRE(inList(list, "test.txt") == false); + VirtFsPhys::freeList(list); + + VirtFsPhys::removeZipFromSearchPath("data/test/test.zip"); + VirtFsPhys::removeZipFromSearchPath("../data/test/test.zip"); + delete2(logger); +} + +TEST_CASE("VirtFsPhys enumerateFiles4") +{ + VirtFsPhys::initFuncs(); + logger = new Logger; + + VirtFsPhys::addZipToSearchPath("data/test/test2.zip", + Append_false); + VirtFsPhys::addZipToSearchPath("../data/test/test2.zip", + Append_false); + + VirtList *list = nullptr; + + list = VirtFsPhys::enumerateFiles("/"); + REQUIRE(inList(list, "units.xml") == true); + REQUIRE(inList(list, "test.txt") == true); + VirtFsPhys::freeList(list); + + VirtFsPhys::removeZipFromSearchPath("data/test/test2.zip"); + VirtFsPhys::removeZipFromSearchPath("../data/test/test2.zip"); + delete2(logger); +} + +TEST_CASE("VirtFsPhys isDirectory") +{ + VirtFsPhys::initFuncs(); + logger = new Logger(); + VirtFsPhys::addDirToSearchPath("data", Append_false); + VirtFsPhys::addDirToSearchPath("../data", Append_false); + + REQUIRE(VirtFsPhys::isDirectory("test/units.xml") == false); + REQUIRE(VirtFsPhys::isDirectory("test/units.xml/") == false); + REQUIRE(VirtFsPhys::isDirectory("test//units.xml") == false); + REQUIRE(VirtFsPhys::isDirectory("test/units123.xml") == false); + REQUIRE(VirtFsPhys::isDirectory("test//units123.xml") == false); + REQUIRE(VirtFsPhys::isDirectory("tesQ/units.xml") == false); + REQUIRE(VirtFsPhys::isDirectory("tesQ//units.xml") == false); + REQUIRE(VirtFsPhys::isDirectory("units.xml") == false); + REQUIRE(VirtFsPhys::isDirectory("test") == true); + REQUIRE(VirtFsPhys::isDirectory("test/") == true); + REQUIRE(VirtFsPhys::isDirectory("test//") == true); + REQUIRE(VirtFsPhys::isDirectory("test/dir1") == true); + REQUIRE(VirtFsPhys::isDirectory("test//dir1") == true); + REQUIRE(VirtFsPhys::isDirectory("test//dir1/") == true); + REQUIRE(VirtFsPhys::isDirectory("test//dir1//") == true); + REQUIRE(VirtFsPhys::isDirectory("test/dir1/") == true); + REQUIRE(VirtFsPhys::isDirectory("test/dir1//") == true); + REQUIRE(VirtFsPhys::isDirectory("testQ") == false); + REQUIRE(VirtFsPhys::isDirectory("testQ/") == false); + REQUIRE(VirtFsPhys::isDirectory("testQ//") == false); + + VirtFsPhys::addDirToSearchPath("data/test", Append_false); + VirtFsPhys::addDirToSearchPath("../data/test", Append_false); + + REQUIRE(VirtFsPhys::isDirectory("test/units.xml") == false); + REQUIRE(VirtFsPhys::isDirectory("test/units.xml/") == false); + REQUIRE(VirtFsPhys::isDirectory("test//units.xml") == false); + REQUIRE(VirtFsPhys::isDirectory("test/units123.xml") == false); + REQUIRE(VirtFsPhys::isDirectory("tesQ/units.xml") == false); + REQUIRE(VirtFsPhys::isDirectory("units.xml") == false); + REQUIRE(VirtFsPhys::isDirectory("test") == true); + REQUIRE(VirtFsPhys::isDirectory("testQ") == false); + REQUIRE(VirtFsPhys::isDirectory("test/dir1") == true); + + VirtFsPhys::removeDirFromSearchPath("data/test"); + VirtFsPhys::removeDirFromSearchPath("../data/test"); + + REQUIRE(VirtFsPhys::isDirectory("test/units.xml") == false); + REQUIRE(VirtFsPhys::isDirectory("test/units123.xml") == false); + REQUIRE(VirtFsPhys::isDirectory("tesQ/units.xml") == false); + REQUIRE(VirtFsPhys::isDirectory("units.xml") == false); + REQUIRE(VirtFsPhys::isDirectory("units.xml/") == false); + REQUIRE(VirtFsPhys::isDirectory("test") == true); + REQUIRE(VirtFsPhys::isDirectory("test/") == true); + REQUIRE(VirtFsPhys::isDirectory("testQ") == false); + REQUIRE(VirtFsPhys::isDirectory("test/dir1") == true); + + VirtFsPhys::removeDirFromSearchPath("data"); + VirtFsPhys::removeDirFromSearchPath("../data"); + delete2(logger); +} + +TEST_CASE("VirtFsPhys openRead") +{ + VirtFsPhys::initFuncs(); + logger = new Logger(); + VirtFsPhys::addDirToSearchPath("data", Append_false); + VirtFsPhys::addDirToSearchPath("../data", Append_false); + + VirtFile *file = nullptr; + + file = VirtFsPhys::openRead("test/units.xml"); + REQUIRE(file != nullptr); + VirtFsPhys::close(file); + file = VirtFsPhys::openRead("test/units123.xml"); + REQUIRE(file == nullptr); + file = VirtFsPhys::openRead("tesQ/units.xml"); + REQUIRE(file == nullptr); + file = VirtFsPhys::openRead("units.xml"); + REQUIRE(file == nullptr); +// file = VirtFsPhys::openRead("test"); +// REQUIRE(file == nullptr); + file = VirtFsPhys::openRead("testQ"); + REQUIRE(file == nullptr); + + VirtFsPhys::addDirToSearchPath("data/test", Append_false); + VirtFsPhys::addDirToSearchPath("../data/test", Append_false); + + file = VirtFsPhys::openRead("test/units.xml"); + REQUIRE(file != nullptr); + VirtFsPhys::close(file); + file = VirtFsPhys::openRead("test/units123.xml"); + REQUIRE(file == nullptr); + file = VirtFsPhys::openRead("tesQ/units.xml"); + REQUIRE(file == nullptr); + file = VirtFsPhys::openRead("units.xml"); + REQUIRE(file != nullptr); + VirtFsPhys::close(file); +// file = VirtFsPhys::openRead("test"); +// REQUIRE(file == nullptr); + file = VirtFsPhys::openRead("testQ"); + REQUIRE(file == nullptr); + + VirtFsPhys::removeDirFromSearchPath("data/test"); + VirtFsPhys::removeDirFromSearchPath("../data/test"); + + file = VirtFsPhys::openRead("test/units.xml"); + REQUIRE(file != nullptr); + VirtFsPhys::close(file); + file = VirtFsPhys::openRead("test/units123.xml"); + REQUIRE(file == nullptr); + file = VirtFsPhys::openRead("tesQ/units.xml"); + REQUIRE(file == nullptr); + file = VirtFsPhys::openRead("units.xml"); + REQUIRE(file == nullptr); +// file = VirtFsPhys::openRead("test"); +// REQUIRE(file == nullptr); + file = VirtFsPhys::openRead("testQ"); + REQUIRE(file == nullptr); + + VirtFsPhys::removeDirFromSearchPath("data"); + VirtFsPhys::removeDirFromSearchPath("../data"); + delete2(logger); +} + +TEST_CASE("VirtFsPhys addZipToSearchPath") +{ + // +++ need implement +} + +TEST_CASE("VirtFsPhys removeZipFromSearchPath") +{ + // +++ need implement +} + +TEST_CASE("VirtFsPhys getRealDir") +{ + VirtFsPhys::initFuncs(); + logger = new Logger(); + REQUIRE(VirtFsPhys::getRealDir(".") == ""); + REQUIRE(VirtFsPhys::getRealDir("..") == ""); + const bool dir1 = VirtFsPhys::addDirToSearchPath("data", Append_false); + REQUIRE((dir1 || VirtFsPhys::addDirToSearchPath( + "../data", Append_false)) == true); + if (dir1 == true) + { + REQUIRE(VirtFsPhys::getRealDir("test") == "data"); + REQUIRE(VirtFsPhys::getRealDir("test/test.txt") == + "data"); + } + else + { + REQUIRE(VirtFsPhys::getRealDir("test") == "../data"); + REQUIRE(VirtFsPhys::getRealDir("test/test.txt") == + "../data"); + } + REQUIRE(VirtFsPhys::getRealDir("zzz") == ""); + + VirtFsPhys::addDirToSearchPath("data/test", Append_false); + VirtFsPhys::addDirToSearchPath("../data/test", Append_false); + if (dir1 == true) + { + REQUIRE(VirtFsPhys::getRealDir("test") == "data"); + REQUIRE(VirtFsPhys::getRealDir("test/test.txt") == + "data"); + REQUIRE(VirtFsPhys::getRealDir("test.txt") == + "data/test"); + } + else + { + REQUIRE(VirtFsPhys::getRealDir("test") == "../data"); + REQUIRE(VirtFsPhys::getRealDir("test/test.txt") == + "../data"); + REQUIRE(VirtFsPhys::getRealDir("test.txt") == + "../data/test"); + } + REQUIRE(VirtFsPhys::getRealDir("zzz") == ""); + + if (dir1 == true) + { + VirtFsPhys::addZipToSearchPath("data/test/test.zip", Append_false); + REQUIRE(VirtFsPhys::getRealDir("dir/brimmedhat.png") == + "data/test/test.zip"); + REQUIRE(VirtFsPhys::getRealDir("hide.png") == "data/test"); + } + else + { + VirtFsPhys::addZipToSearchPath("../data/test/test.zip", Append_false); + REQUIRE(VirtFsPhys::getRealDir("dir/brimmedhat.png") == + "../data/test/test.zip"); + REQUIRE(VirtFsPhys::getRealDir("hide.png") == "../data/test"); + } + + VirtFsPhys::removeDirFromSearchPath("data/test"); + VirtFsPhys::removeDirFromSearchPath("../data/test"); + + if (dir1 == true) + { + REQUIRE(VirtFsPhys::getRealDir("test") == "data"); + REQUIRE(VirtFsPhys::getRealDir("test/test.txt") == + "data"); + REQUIRE(VirtFsPhys::getRealDir("dir/hide.png") == + "data/test/test.zip"); + } + else + { + REQUIRE(VirtFsPhys::getRealDir("test") == "../data"); + REQUIRE(VirtFsPhys::getRealDir("test/test.txt") == + "../data"); + REQUIRE(VirtFsPhys::getRealDir("dir/hide.png") == + "../data/test/test.zip"); + } + REQUIRE(VirtFsPhys::exists("dir/hide.png")); + REQUIRE(VirtFsPhys::getRealDir("zzz") == ""); + + VirtFsPhys::removeDirFromSearchPath("data"); + VirtFsPhys::removeDirFromSearchPath("../data"); + VirtFsPhys::removeZipFromSearchPath("data/test/test.zip"); + VirtFsPhys::removeZipFromSearchPath("../data/test/test.zip"); + delete2(logger); +} + +TEST_CASE("VirtFsPhys permitLinks") +{ + VirtFsPhys::initFuncs(); + logger = new Logger(); + VirtFsPhys::addDirToSearchPath("data", Append_false); + VirtFsPhys::addDirToSearchPath("../data", Append_false); + + const int cnt1 = VirtFsPhys::exists("test/test2.txt") ? 25 : 24; + const int cnt2 = 25; + + StringVect list; + VirtFsPhys::permitLinks(false); + VirtFsPhys::getFiles("test", list); + removeTemp(list); + const size_t sz = list.size(); + REQUIRE(sz == cnt1); + + list.clear(); + VirtFsPhys::permitLinks(true); + VirtFsPhys::getFiles("test", list); + removeTemp(list); + REQUIRE(list.size() == cnt2); + + list.clear(); + VirtFsPhys::permitLinks(false); + VirtFsPhys::getFiles("test", list); + removeTemp(list); + REQUIRE(list.size() == cnt1); + + VirtFsPhys::removeDirFromSearchPath("data"); + VirtFsPhys::removeDirFromSearchPath("../data"); + delete2(logger); +} + +TEST_CASE("VirtFsPhys read") +{ + VirtFsPhys::initFuncs(); + logger = new Logger(); + VirtFsPhys::addDirToSearchPath("data", Append_false); + VirtFsPhys::addDirToSearchPath("../data", Append_false); + + VirtFile *file = VirtFsPhys::openRead("test/test.txt"); + REQUIRE(file != nullptr); + REQUIRE(VirtFsPhys::fileLength(file) == 23); + const int fileSize = VirtFsPhys::fileLength(file); + + void *restrict buffer = calloc(fileSize + 1, 1); + REQUIRE(VirtFsPhys::read(file, buffer, 1, fileSize) == fileSize); + REQUIRE(strcmp(static_cast(buffer), + "test line 1\ntest line 2") == 0); + REQUIRE(VirtFsPhys::tell(file) == fileSize); + REQUIRE(VirtFsPhys::eof(file) == true); + + free(buffer); + buffer = calloc(fileSize + 1, 1); + REQUIRE(VirtFsPhys::seek(file, 12) != 0); + REQUIRE(VirtFsPhys::eof(file) == false); + REQUIRE(VirtFsPhys::tell(file) == 12); + REQUIRE(VirtFsPhys::read(file, buffer, 1, 11) == 11); + REQUIRE(strcmp(static_cast(buffer), + "test line 2") == 0); + REQUIRE(VirtFsPhys::eof(file) == true); + + VirtFsPhys::close(file); + free(buffer); + + VirtFsPhys::removeDirFromSearchPath("data"); + VirtFsPhys::removeDirFromSearchPath("../data"); + delete2(logger); +} diff --git a/src/fs/virtdirentry.cpp b/src/fs/virtdirentry.cpp deleted file mode 100644 index 693aba6a3..000000000 --- a/src/fs/virtdirentry.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "fs/virtdirentry.h" - -#include "debug.h" - -VirtDirEntry::VirtDirEntry(const std::string &userDir, - const std::string &rootDir) : - mUserDir(userDir), - mRootDir(rootDir) -{ -} - -VirtDirEntry::~VirtDirEntry() -{ -} diff --git a/src/fs/virtdirentry.h b/src/fs/virtdirentry.h deleted file mode 100644 index b3d3faff6..000000000 --- a/src/fs/virtdirentry.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef UTILS_VIRTDIRENTRY_H -#define UTILS_VIRTDIRENTRY_H - -#include - -#include "localconsts.h" - -struct VirtDirEntry final -{ - VirtDirEntry(const std::string &userDir, - const std::string &rootDir); - - A_DELETE_COPY(VirtDirEntry) - - ~VirtDirEntry(); - - std::string mUserDir; - std::string mRootDir; -}; - -#endif // UTILS_VIRTDIRENTRY_H diff --git a/src/fs/virtfile.cpp b/src/fs/virtfile.cpp index 2fe475d4f..8a06be4e5 100644 --- a/src/fs/virtfile.cpp +++ b/src/fs/virtfile.cpp @@ -20,9 +20,14 @@ #include "fs/virtfile.h" -#include "fs/virtfileprivate.h" #include "fs/virtfsfuncs.h" +#ifdef USE_PHYSFS +#include "fs/physfs/virtfileprivate.h" +#else // USE_PHYSFS +#include "fs/virtfs/virtfileprivate.h" +#endif // USE_PHYSFS + #include "debug.h" VirtFile::VirtFile(const VirtFsFuncs *restrict const funcs0) : diff --git a/src/fs/virtfileprivate.cpp b/src/fs/virtfileprivate.cpp deleted file mode 100644 index 4be55fc1b..000000000 --- a/src/fs/virtfileprivate.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "fs/virtfileprivate.h" - -#include -#include - -#include "debug.h" - -VirtFilePrivate::VirtFilePrivate() : - mFile(nullptr), - mBuf(nullptr), - mPos(0U), - mSize(0U), - mFd(-1) -{ -} - -VirtFilePrivate::VirtFilePrivate(const int fd) : - mFile(nullptr), - mBuf(nullptr), - mPos(0U), - mSize(0U), - mFd(fd) -{ -} - -VirtFilePrivate::VirtFilePrivate(PHYSFS_file *restrict const file) : - mFile(file), - mBuf(nullptr), - mPos(0U), - mSize(0U), - mFd(-1) -{ -} - -VirtFilePrivate::VirtFilePrivate(uint8_t *restrict const buf, - const size_t sz) : - mFile(nullptr), - mBuf(buf), - mPos(0U), - mSize(sz), - mFd(-1) -{ -} - -VirtFilePrivate::~VirtFilePrivate() -{ - if (mFile != nullptr) - PHYSFS_close(mFile); - if (mFd != -1) - close(mFd); - if (mBuf) - delete [] mBuf; -} diff --git a/src/fs/virtfileprivate.h b/src/fs/virtfileprivate.h deleted file mode 100644 index 758c1b5aa..000000000 --- a/src/fs/virtfileprivate.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef UTILS_VIRTFILEPRIVATE_H -#define UTILS_VIRTFILEPRIVATE_H - -#include "localconsts.h" - -PRAGMA45(GCC diagnostic push) -PRAGMA45(GCC diagnostic ignored "-Wlong-long") -#include -PRAGMA45(GCC diagnostic pop) - -struct VirtFilePrivate final -{ - VirtFilePrivate(); - - explicit VirtFilePrivate(PHYSFS_file *restrict const file); - - explicit VirtFilePrivate(const int fd); - - VirtFilePrivate(uint8_t *restrict const buf, - const size_t sz); - - A_DELETE_COPY(VirtFilePrivate) - - ~VirtFilePrivate(); - - // physfs fields - PHYSFS_file *mFile; - - // zipfs fields - uint8_t *mBuf; - - // zipfs fields - size_t mPos; - size_t mSize; - - // dirfs fields - int mFd; -}; - -#endif // UTILS_VIRTFILEPRIVATE_H diff --git a/src/fs/virtfs.cpp b/src/fs/virtfs.cpp deleted file mode 100644 index 69f379a08..000000000 --- a/src/fs/virtfs.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2013-2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "fs/virtfs.h" - -#ifdef USE_PHYSFS -#include "fs/virtfsphys.h" -#else // USE_PHYSFS -#include "fs/virtfsdir.h" -#endif // USE_PHYSFS -#include "fs/virtfile.h" -#include "fs/virtfsfuncs.h" -#include "fs/virtlist.h" - -#include "debug.h" - -const char *dirSeparator = nullptr; - -namespace VirtFs -{ - void init(const std::string &restrict name) - { -#ifdef USE_PHYSFS - VirtFsPhys::init(name); -#else // USE_PHYSFS - VirtFsDir::init(name); -#endif // USE_PHYSFS - updateDirSeparator(); - } - - void updateDirSeparator() - { -#ifdef USE_PHYSFS - dirSeparator = VirtFsPhys::getDirSeparator(); -#else // USE_PHYSFS -#ifdef WIN32 - dirSeparator = "\\"; -#else // WIN32 - dirSeparator = "/"; -#endif // WIN32 -#endif // USE_PHYSFS - } - - const char *getDirSeparator() - { -#ifdef USE_PHYSFS - return VirtFsPhys::getDirSeparator(); -#else // USE_PHYSFS - return dirSeparator; -#endif // USE_PHYSFS - } - - const char *getBaseDir() - { -#ifdef USE_PHYSFS - return VirtFsPhys::getBaseDir(); -#else // USE_PHYSFS - return VirtFsDir::getBaseDir(); -#endif // USE_PHYSFS - } - - const char *getUserDir() - { -#ifdef USE_PHYSFS - return VirtFsPhys::getUserDir(); -#else // USE_PHYSFS - return VirtFsDir::getUserDir(); -#endif // USE_PHYSFS - } - - bool exists(const std::string &restrict name) - { -#ifdef USE_PHYSFS - return VirtFsPhys::exists(name); -#else // USE_PHYSFS - return VirtFsDir::exists(name) || VirtFsZip::exists(name); -#endif // USE_PHYSFS - } - - VirtList *enumerateFiles(const std::string &restrict dirName) - { -#ifdef USE_PHYSFS - return VirtFsPhys::enumerateFiles(dir); -#else // USE_PHYSFS - VirtList *const list = new VirtList; - VirtFsDir::enumerateFiles(dirName, list); - VirtFsZip::enumerateFiles(dirName, list); - return list; -#endif // USE_PHYSFS - } - - bool isDirectory(const std::string &restrict name) - { - return VirtFsPhys::isDirectory(name); - } - - bool isSymbolicLink(const std::string &restrict name) - { - return VirtFsPhys::isSymbolicLink(name); - } - - void freeList(VirtList *restrict const handle) - { - delete handle; - } - - VirtFile *openRead(const std::string &restrict filename) - { - return VirtFsPhys::openRead(filename); - } - - VirtFile *openWrite(const std::string &restrict filename) - { - return VirtFsPhys::openWrite(filename); - } - - VirtFile *openAppend(const std::string &restrict filename) - { - return VirtFsPhys::openAppend(filename); - } - - bool setWriteDir(const std::string &restrict newDir) - { - return VirtFsPhys::setWriteDir(newDir); - } - - bool addDirToSearchPath(const std::string &restrict newDir, - const Append append) - { - return VirtFsPhys::addDirToSearchPath(newDir, append); - } - - bool removeDirFromSearchPath(const std::string &restrict oldDir) - { - return VirtFsPhys::removeDirFromSearchPath(oldDir); - } - - bool addZipToSearchPath(const std::string &restrict newDir, - const Append append) - { - return VirtFsPhys::addZipToSearchPath(newDir, append); - } - - bool removeZipFromSearchPath(const std::string &restrict oldDir) - { - return VirtFsPhys::removeZipFromSearchPath(oldDir); - } - - std::string getRealDir(const std::string &restrict filename) - { - return VirtFsPhys::getRealDir(filename); - } - - bool mkdir(const std::string &restrict dirname) - { - return VirtFsPhys::mkdir(dirname); - } - - bool remove(const std::string &restrict filename) - { - return VirtFsPhys::remove(filename); - } - - bool deinit() - { -#ifdef USE_PHYSFS - return VirtFsPhys::deinit(); -#else // USE_PHYSFS - VirtFsDir::deinit(); - return true; -#endif // USE_PHYSFS - } - - void permitLinks(const bool val) - { - VirtFsPhys::permitLinks(val); - } - - const char *getLastError() - { - return VirtFsPhys::getLastError(); - } - - int close(VirtFile *restrict const file) - { - if (file == nullptr) - return 0; - return file->funcs->close(file); - } - - int64_t read(VirtFile *restrict const file, - void *restrict const buffer, - const uint32_t objSize, - const uint32_t objCount) - { - return file->funcs->read(file, - buffer, - objSize, - objCount); - } - - int64_t write(VirtFile *restrict const file, - const void *restrict const buffer, - const uint32_t objSize, - const uint32_t objCount) - { - return file->funcs->write(file, - buffer, - objSize, - objCount); - } - - int64_t fileLength(VirtFile *restrict const file) - { - return file->funcs->fileLength(file); - } - - int64_t tell(VirtFile *restrict const file) - { - return file->funcs->tell(file); - } - - int seek(VirtFile *restrict const file, - const uint64_t pos) - { - return file->funcs->seek(file, - pos); - } - - int eof(VirtFile *restrict const file) - { - return file->funcs->eof(file); - } -} // namespace VirtFs diff --git a/src/fs/virtfs.h b/src/fs/virtfs.h index e0f188cfb..9a24ad8ba 100644 --- a/src/fs/virtfs.h +++ b/src/fs/virtfs.h @@ -38,11 +38,11 @@ namespace VirtFs const char *getBaseDir(); const char *getUserDir(); bool exists(const std::string &restrict name); - VirtList *enumerateFiles(const std::string &restrict dir) RETURNS_NONNULL; - bool isDirectory(const std::string &restrict name); + VirtList *enumerateFiles(std::string dir) RETURNS_NONNULL; + bool isDirectory(std::string name); bool isSymbolicLink(const std::string &restrict name); void freeList(VirtList *restrict const handle); - VirtFile *openRead(const std::string &restrict filename); + VirtFile *openRead(std::string filename); VirtFile *openWrite(const std::string &restrict filename); VirtFile *openAppend(const std::string &restrict filename); bool setWriteDir(const std::string &restrict newDir); @@ -52,7 +52,7 @@ namespace VirtFs bool addZipToSearchPath(const std::string &restrict newDir, const Append append); bool removeZipFromSearchPath(const std::string &restrict oldDir); - std::string getRealDir(const std::string &restrict filename); + std::string getRealDir(std::string filename); bool mkdir(const std::string &restrict dirName); bool remove(const std::string &restrict filename); bool deinit(); diff --git a/src/fs/virtfs/virtdirentry.cpp b/src/fs/virtfs/virtdirentry.cpp new file mode 100644 index 000000000..73d2dc175 --- /dev/null +++ b/src/fs/virtfs/virtdirentry.cpp @@ -0,0 +1,34 @@ +/* + * The ManaPlus Client + * Copyright (C) 2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "fs/virtfs/virtdirentry.h" + +#include "debug.h" + +VirtDirEntry::VirtDirEntry(const std::string &userDir, + const std::string &rootDir) : + mUserDir(userDir), + mRootDir(rootDir) +{ +} + +VirtDirEntry::~VirtDirEntry() +{ +} diff --git a/src/fs/virtfs/virtdirentry.h b/src/fs/virtfs/virtdirentry.h new file mode 100644 index 000000000..b3d3faff6 --- /dev/null +++ b/src/fs/virtfs/virtdirentry.h @@ -0,0 +1,41 @@ +/* + * The ManaPlus Client + * Copyright (C) 2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef UTILS_VIRTDIRENTRY_H +#define UTILS_VIRTDIRENTRY_H + +#include + +#include "localconsts.h" + +struct VirtDirEntry final +{ + VirtDirEntry(const std::string &userDir, + const std::string &rootDir); + + A_DELETE_COPY(VirtDirEntry) + + ~VirtDirEntry(); + + std::string mUserDir; + std::string mRootDir; +}; + +#endif // UTILS_VIRTDIRENTRY_H diff --git a/src/fs/virtfs/virtfileprivate.cpp b/src/fs/virtfs/virtfileprivate.cpp new file mode 100644 index 000000000..06e0418bb --- /dev/null +++ b/src/fs/virtfs/virtfileprivate.cpp @@ -0,0 +1,59 @@ +/* + * The ManaPlus Client + * Copyright (C) 2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "fs/virtfs/virtfileprivate.h" + +#include +#include + +#include "debug.h" + +VirtFilePrivate::VirtFilePrivate() : + mBuf(nullptr), + mPos(0U), + mSize(0U), + mFd(-1) +{ +} + +VirtFilePrivate::VirtFilePrivate(const int fd) : + mBuf(nullptr), + mPos(0U), + mSize(0U), + mFd(fd) +{ +} + +VirtFilePrivate::VirtFilePrivate(uint8_t *restrict const buf, + const size_t sz) : + mBuf(buf), + mPos(0U), + mSize(sz), + mFd(-1) +{ +} + +VirtFilePrivate::~VirtFilePrivate() +{ + if (mFd != -1) + close(mFd); + if (mBuf) + delete [] mBuf; +} diff --git a/src/fs/virtfs/virtfileprivate.h b/src/fs/virtfs/virtfileprivate.h new file mode 100644 index 000000000..0af9f66e8 --- /dev/null +++ b/src/fs/virtfs/virtfileprivate.h @@ -0,0 +1,50 @@ +/* + * The ManaPlus Client + * Copyright (C) 2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef UTILS_VIRTFILEPRIVATE_H +#define UTILS_VIRTFILEPRIVATE_H + +#include "localconsts.h" + +struct VirtFilePrivate final +{ + VirtFilePrivate(); + + explicit VirtFilePrivate(const int fd); + + VirtFilePrivate(uint8_t *restrict const buf, + const size_t sz); + + A_DELETE_COPY(VirtFilePrivate) + + ~VirtFilePrivate(); + + // zipfs fields + uint8_t *mBuf; + + // zipfs fields + size_t mPos; + size_t mSize; + + // dirfs fields + int mFd; +}; + +#endif // UTILS_VIRTFILEPRIVATE_H diff --git a/src/fs/virtfs/virtfs.cpp b/src/fs/virtfs/virtfs.cpp new file mode 100644 index 000000000..3d223ccba --- /dev/null +++ b/src/fs/virtfs/virtfs.cpp @@ -0,0 +1,257 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013-2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "fs/virtfs.h" + +#include "fs/paths.h" +#include "fs/virtfile.h" +#include "fs/virtfsfuncs.h" +#include "fs/virtlist.h" + +#include "fs/virtfs/virtdirentry.h" +#include "fs/virtfs/virtfsdir.h" +#include "fs/virtfs/virtfszip.h" + +#include "utils/checkutils.h" + +#include "debug.h" + +const char *dirSeparator = nullptr; + +namespace VirtFs +{ + void init(const std::string &restrict name) + { + VirtFsDir::init(name); + updateDirSeparator(); + } + + void updateDirSeparator() + { +#ifdef WIN32 + dirSeparator = "\\"; +#else // WIN32 + dirSeparator = "/"; +#endif // WIN32 + } + + const char *getDirSeparator() + { + return dirSeparator; + } + + const char *getBaseDir() + { + return VirtFsDir::getBaseDir(); + } + + const char *getUserDir() + { + return VirtFsDir::getUserDir(); + } + + bool exists(const std::string &restrict name) + { + return VirtFsDir::exists(name) || VirtFsZip::exists(name); + } + + VirtList *enumerateFiles(std::string dirName) + { + VirtList *const list = new VirtList; + prepareFsPath(dirName); + if (checkPath(dirName) == false) + { + reportAlways("VirtFs::enumerateFiles invalid path: %s", + dirName.c_str()); + return list; + } + + VirtFsDir::enumerateFiles(dirName, list); + VirtFsZip::enumerateFiles(dirName, list); + return list; + } + + bool isDirectory(std::string name) + { + prepareFsPath(name); + if (checkPath(name) == false) + { + reportAlways("VirtFs::isDirectory invalid path: %s", + name.c_str()); + return false; + } + return VirtFsDir::isDirectoryInternal(name) || + VirtFsZip::isDirectoryInternal(name); + } + + bool isSymbolicLink(const std::string &restrict name) + { + return VirtFsDir::isSymbolicLink(name); + } + + void freeList(VirtList *restrict const handle) + { + delete handle; + } + + VirtFile *openRead(std::string filename) + { + prepareFsPath(filename); + if (checkPath(filename) == false) + { + reportAlways("VirtFs::openRead invalid path: %s", + filename.c_str()); + return nullptr; + } + VirtDirEntry *const entry = VirtFsDir::searchEntryByPath(filename); + if (entry == nullptr) + return VirtFsZip::openReadInternal(filename); + return VirtFsDir::openReadDirEntry(entry, filename); + } + + VirtFile *openWrite(const std::string &restrict filename) + { + return VirtFsDir::openWrite(filename); + } + + VirtFile *openAppend(const std::string &restrict filename) + { + return VirtFsDir::openAppend(filename); + } + + bool setWriteDir(const std::string &restrict newDir) + { + return VirtFsDir::setWriteDir(newDir); + } + + bool addDirToSearchPath(const std::string &restrict newDir, + const Append append) + { + return VirtFsDir::addToSearchPath(newDir, append); + } + + bool removeDirFromSearchPath(const std::string &restrict oldDir) + { + return VirtFsDir::removeFromSearchPath(oldDir); + } + + bool addZipToSearchPath(const std::string &restrict newDir, + const Append append) + { + return VirtFsZip::addToSearchPath(newDir, append); + } + + bool removeZipFromSearchPath(const std::string &restrict oldDir) + { + return VirtFsZip::removeFromSearchPath(oldDir); + } + + std::string getRealDir(std::string filename) + { + prepareFsPath(filename); + if (checkPath(filename) == false) + { + reportAlways("VirtFs::getRealDir invalid path: %s", + filename.c_str()); + return std::string(); + } + VirtDirEntry *const entry = VirtFsDir::searchEntryByPath(filename); + if (entry == nullptr) + return VirtFsZip::getRealDirInternal(filename); + return entry->mUserDir; + } + + bool mkdir(const std::string &restrict dirname) + { + return VirtFsDir::mkdir(dirname); + } + + bool remove(const std::string &restrict filename) + { + return VirtFsDir::remove(filename); + } + + bool deinit() + { + VirtFsDir::deinit(); + return true; + } + + void permitLinks(const bool val) + { + VirtFsDir::permitLinks(val); + } + + const char *getLastError() + { + return ""; + } + + int close(VirtFile *restrict const file) + { + if (file == nullptr) + return 0; + return file->funcs->close(file); + } + + int64_t read(VirtFile *restrict const file, + void *restrict const buffer, + const uint32_t objSize, + const uint32_t objCount) + { + return file->funcs->read(file, + buffer, + objSize, + objCount); + } + + int64_t write(VirtFile *restrict const file, + const void *restrict const buffer, + const uint32_t objSize, + const uint32_t objCount) + { + return file->funcs->write(file, + buffer, + objSize, + objCount); + } + + int64_t fileLength(VirtFile *restrict const file) + { + return file->funcs->fileLength(file); + } + + int64_t tell(VirtFile *restrict const file) + { + return file->funcs->tell(file); + } + + int seek(VirtFile *restrict const file, + const uint64_t pos) + { + return file->funcs->seek(file, + pos); + } + + int eof(VirtFile *restrict const file) + { + return file->funcs->eof(file); + } +} // namespace VirtFs diff --git a/src/fs/virtfs/virtfsdir.cpp b/src/fs/virtfs/virtfsdir.cpp new file mode 100644 index 000000000..13c2f9ba4 --- /dev/null +++ b/src/fs/virtfs/virtfsdir.cpp @@ -0,0 +1,651 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013-2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "fs/virtfs/virtfsdir.h" + +#include "fs/files.h" +#include "fs/mkdir.h" +#include "fs/paths.h" +#include "fs/virtfs.h" +#include "fs/virtfile.h" +#include "fs/virtfsfuncs.h" +#include "fs/virtlist.h" + +#include "fs/virtfs/virtdirentry.h" +#include "fs/virtfs/virtfileprivate.h" + +#include "utils/checkutils.h" +#include "utils/dtor.h" +#include "utils/stringutils.h" + +#include +#include +#include +#include + +#include +#include + +#include "debug.h" + +extern const char *dirSeparator; + +namespace +{ + std::vector mEntries; + std::string mWriteDir; + std::string mBaseDir; + std::string mUserDir; + bool mPermitLinks = false; + VirtFsFuncs funcs; +} // namespace + +namespace VirtFsDir +{ + namespace + { + static VirtFile *openFile(std::string filename, + const int mode) + { + prepareFsPath(filename); + if (checkPath(filename) == false) + { + reportAlways("VirtFsDir::openFile invalid path: %s", + filename.c_str()); + return nullptr; + } + VirtDirEntry *const entry = searchEntryByPath(filename); + if (entry == nullptr) + return nullptr; + + const std::string path = entry->mRootDir + filename; + const int fd = open(path.c_str(), + mode, + S_IRUSR | S_IWUSR); + if (fd == -1) + { + reportAlways("VirtFsDir::openFile file open error: %s", + filename.c_str()); + return nullptr; + } + VirtFile *restrict const file = new VirtFile(&funcs); + file->mPrivate = new VirtFilePrivate(fd); + + return file; + } + } // namespace + + VirtFile *openReadDirEntry(VirtDirEntry *const entry, + const std::string &filename) + { + const std::string path = entry->mRootDir + filename; + const int fd = open(path.c_str(), + O_RDONLY, + S_IRUSR | S_IWUSR); + if (fd == -1) + { + reportAlways("VirtFsDir::openReadDirEntry file open error: %s", + filename.c_str()); + return nullptr; + } + VirtFile *restrict const file = new VirtFile(&funcs); + file->mPrivate = new VirtFilePrivate(fd); + + return file; + } + + VirtDirEntry *searchEntryByRoot(const std::string &restrict root) + { + FOR_EACH (std::vector::const_iterator, it, mEntries) + { + if ((*it)->mRootDir == root) + return *it; + } + return nullptr; + } + + VirtDirEntry *searchEntryByPath(const std::string &restrict path) + { + FOR_EACH (std::vector::const_iterator, it, mEntries) + { + VirtDirEntry *const entry = *it; + if (Files::existsLocal(entry->mRootDir + path)) + return entry; + } + return nullptr; + } + + bool addToSearchPathSilent(std::string newDir, + const Append append, + const SkipError skipError) + { + prepareFsPath(newDir); + if (skipError == SkipError_false && + Files::existsLocal(newDir) == false) + { + logger->log("VirtFsDir::addToSearchPath directory not exists: %s", + newDir.c_str()); + return false; + } + if (newDir.find(".zip") != std::string::npos) + { + reportAlways("Called VirtFsDir::addToSearchPath with zip archive"); + return false; + } + std::string rootDir = newDir; + if (findLast(rootDir, std::string(dirSeparator)) == false) + rootDir += dirSeparator; + VirtDirEntry *const entry = VirtFsDir::searchEntryByRoot(rootDir); + if (entry != nullptr) + { + reportAlways("VirtFsDir::addToSearchPath already exists: %s", + newDir.c_str()); + return false; + } + logger->log("Add virtual directory: " + newDir); + if (append == Append_true) + { + mEntries.push_back(new VirtDirEntry(newDir, + rootDir)); + } + else + { + mEntries.insert(mEntries.begin(), + new VirtDirEntry(newDir, + rootDir)); + } + return true; + } + + bool addToSearchPath(std::string newDir, + const Append append) + { + prepareFsPath(newDir); + if (Files::existsLocal(newDir) == false) + { + reportAlways("VirtFsDir::addToSearchPath directory not exists: %s", + newDir.c_str()); + return false; + } + if (newDir.find(".zip") != std::string::npos) + { + reportAlways("Called VirtFsDir::addToSearchPath with zip archive"); + return false; + } + std::string rootDir = newDir; + if (findLast(rootDir, std::string(dirSeparator)) == false) + rootDir += dirSeparator; + VirtDirEntry *const entry = VirtFsDir::searchEntryByRoot(rootDir); + if (entry != nullptr) + { + reportAlways("VirtFsDir::addToSearchPath already exists: %s", + newDir.c_str()); + return false; + } + logger->log("Add virtual directory: " + newDir); + if (append == Append_true) + { + mEntries.push_back(new VirtDirEntry(newDir, + rootDir)); + } + else + { + mEntries.insert(mEntries.begin(), + new VirtDirEntry(newDir, + rootDir)); + } + return true; + } + + bool removeFromSearchPathSilent(std::string oldDir) + { + prepareFsPath(oldDir); + if (oldDir.find(".zip") != std::string::npos) + { + reportAlways("Called removeFromSearchPath with zip archive"); + return false; + } + if (findLast(oldDir, std::string(dirSeparator)) == false) + oldDir += dirSeparator; + FOR_EACH (std::vector::iterator, it, mEntries) + { + VirtDirEntry *const entry = *it; + if (entry->mRootDir == oldDir) + { + logger->log("Remove virtual directory: " + oldDir); + mEntries.erase(it); + delete entry; + return true; + } + } + + logger->log("VirtFsDir::removeFromSearchPath not exists: %s", + oldDir.c_str()); + return false; + } + + bool removeFromSearchPath(std::string oldDir) + { + prepareFsPath(oldDir); + if (oldDir.find(".zip") != std::string::npos) + { + reportAlways("Called removeFromSearchPath with zip archive"); + return false; + } + if (findLast(oldDir, std::string(dirSeparator)) == false) + oldDir += dirSeparator; + FOR_EACH (std::vector::iterator, it, mEntries) + { + VirtDirEntry *const entry = *it; + if (entry->mRootDir == oldDir) + { + logger->log("Remove virtual directory: " + oldDir); + mEntries.erase(it); + delete entry; + return true; + } + } + + reportAlways("VirtFsDir::removeFromSearchPath not exists: %s", + oldDir.c_str()); + return false; + } + + std::vector &getEntries() + { + return mEntries; + } + + void deinit() + { + delete_all(mEntries); + mEntries.clear(); + } + +#if defined(__native_client__) + void init(const std::string &restrict name A_UNUSED) + { + mBaseDir = "/"; +#elif defined(ANDROID) + void init(const std::string &restrict name A_UNUSED) + { + mBaseDir = getRealPath("."); +#else // defined(__native_client__) + + void init(const std::string &restrict name) + { + mBaseDir = getRealPath(getFileDir(name)); +#endif // defined(__native_client__) + + prepareFsPath(mBaseDir); + mUserDir = getHomePath(); + prepareFsPath(mUserDir); + initFuncs(&funcs); + } + + void initFuncs(VirtFsFuncs *restrict const ptr) + { + ptr->close = &VirtFsDir::close; + ptr->read = &VirtFsDir::read; + ptr->write = &VirtFsDir::write; + ptr->fileLength = &VirtFsDir::fileLength; + ptr->tell = &VirtFsDir::tell; + ptr->seek = &VirtFsDir::seek; + ptr->eof = &VirtFsDir::eof; + } + + const char *getBaseDir() + { + return mBaseDir.c_str(); + } + + const char *getUserDir() + { + return mUserDir.c_str(); + } + + std::string getRealDir(std::string filename) + { + prepareFsPath(filename); + if (checkPath(filename) == false) + { + reportAlways("VirtFsDir::exists invalid path: %s", + filename.c_str()); + return std::string(); + } + FOR_EACH (std::vector::iterator, it, mEntries) + { + VirtDirEntry *const entry = *it; + const std::string path = entry->mRootDir + filename; + if (Files::existsLocal(path)) + return entry->mUserDir; + } + return std::string(); + } + + bool exists(std::string name) + { + prepareFsPath(name); + if (checkPath(name) == false) + { + reportAlways("VirtFsDir::exists invalid path: %s", + name.c_str()); + return false; + } + FOR_EACH (std::vector::iterator, it, mEntries) + { + VirtDirEntry *const entry = *it; + if (Files::existsLocal(entry->mRootDir + name)) + return true; + } + return false; + } + + VirtList *enumerateFiles(std::string dirName) + { + VirtList *const list = new VirtList; + prepareFsPath(dirName); + if (checkPath(dirName) == false) + { + reportAlways("VirtFsDir::enumerateFiles invalid path: %s", + dirName.c_str()); + return list; + } + return enumerateFiles(dirName, list); + } + + VirtList *enumerateFiles(const std::string &restrict dirName, + VirtList *restrict const list) + { + StringVect &names = list->names; + FOR_EACH (std::vector::iterator, it, mEntries) + { + VirtDirEntry *const entry = *it; + StringVect files; + std::string path = entry->mRootDir + dirName; + if (findLast(path, std::string(dirSeparator)) == false) + path += dirSeparator; + const struct dirent *next_file = nullptr; + DIR *const dir = opendir(path.c_str()); + if (dir) + { + while ((next_file = readdir(dir))) + { + const std::string file = next_file->d_name; + if (file == "." || file == "..") + continue; + if (mPermitLinks == false) + { + struct stat statbuf; + if (lstat(path.c_str(), &statbuf) == 0 && + S_ISLNK(statbuf.st_mode) != 0) + { + continue; + } + } + bool found(false); + FOR_EACH (StringVectCIter, itn, names) + { + if (*itn == file) + { + found = true; + break; + } + } + if (found == false) + names.push_back(file); + } + closedir(dir); + } + } + return list; + } + + bool isDirectory(std::string dirName) + { + prepareFsPath(dirName); + if (checkPath(dirName) == false) + { + reportAlways("VirtFsDir::isDirectory invalid path: %s", + dirName.c_str()); + return false; + } + return isDirectoryInternal(dirName); + } + + bool isDirectoryInternal(const std::string &restrict dirName) + { + FOR_EACH (std::vector::iterator, it, mEntries) + { + VirtDirEntry *const entry = *it; + std::string path = entry->mRootDir + dirName; + if (findLast(path, std::string(dirSeparator)) == false) + path += dirSeparator; + + struct stat statbuf; + if (stat(path.c_str(), &statbuf) == 0 && + S_ISDIR(statbuf.st_mode) != 0) + { + return true; + } + } + return false; + } + + bool isSymbolicLink(std::string name) + { + prepareFsPath(name); + if (checkPath(name) == false) + { + reportAlways("VirtFsDir::isSymbolicLink invalid path: %s", + name.c_str()); + return false; + } + if (mPermitLinks == false) + return false; + + struct stat statbuf; + return lstat(name.c_str(), &statbuf) == 0 && + S_ISLNK(statbuf.st_mode) != 0; + } + + void freeList(VirtList *restrict const handle) + { + delete handle; + } + + VirtFile *openRead(const std::string &restrict filename) + { + return openFile(filename, O_RDONLY); + } + + VirtFile *openWrite(const std::string &restrict filename) + { + return openFile(filename, O_WRONLY | O_CREAT | O_TRUNC); + } + + VirtFile *openAppend(const std::string &restrict filename) + { + return openFile(filename, O_WRONLY | O_CREAT | O_APPEND); + } + + bool setWriteDir(std::string newDir) + { + prepareFsPath(newDir); + mWriteDir = newDir; + if (findLast(mWriteDir, std::string(dirSeparator)) == false) + mWriteDir += dirSeparator; + return true; + } + + bool mkdir(std::string dirname) + { + prepareFsPath(dirname); + if (mWriteDir.empty()) + { + reportAlways("VirtFsDir::mkdir write dir is empty"); + return false; + } + return mkdir_r((mWriteDir + dirname).c_str()) != -1; + } + + bool remove(std::string filename) + { + prepareFsPath(filename); + if (mWriteDir.empty()) + { + reportAlways("VirtFsDir::remove write dir is empty"); + return false; + } + return ::remove((mWriteDir + filename).c_str()) != 0; + } + + void permitLinks(const bool val) + { + mPermitLinks = val; + } + + const char *getLastError() + { + return nullptr; + } + + int close(VirtFile *restrict const file) + { + if (file == nullptr) + return 0; + delete file; + return 1; + } + + int64_t read(VirtFile *restrict const file, + void *restrict const buffer, + const uint32_t objSize, + const uint32_t objCount) + { + if (file == nullptr) + return 0; + const int fd = file->mPrivate->mFd; + if (fd == -1) + { + reportAlways("VirtFsDir::read file not opened."); + return 0; + } + int max = objSize * objCount; + int cnt = ::read(fd, buffer, max); + if (cnt <= 0) + return cnt; + return cnt / objSize; + } + + int64_t write(VirtFile *restrict const file, + const void *restrict const buffer, + const uint32_t objSize, + const uint32_t objCount) + { + if (file == nullptr) + return 0; + const int fd = file->mPrivate->mFd; + if (fd == -1) + { + reportAlways("VirtFsDir::write file not opened."); + return 0; + } + int max = objSize * objCount; + int cnt = ::write(fd, buffer, max); + if (cnt <= 0) + return cnt; + return cnt / objSize; + } + + int64_t fileLength(VirtFile *restrict const file) + { + if (file == nullptr) + return -1; + const int fd = file->mPrivate->mFd; + if (fd == -1) + { + reportAlways("VirtFsDir::fileLength file not opened."); + return 0; + } + struct stat statbuf; + if (fstat(fd, &statbuf) == -1) + { + reportAlways("VirtFsDir::fileLength error."); + return -1; + } + return static_cast(statbuf.st_size); + } + + int64_t tell(VirtFile *restrict const file) + { + if (file == nullptr) + return -1; + + const int fd = file->mPrivate->mFd; + if (fd == -1) + { + reportAlways("VirtFsDir::tell file not opened."); + return 0; + } + const int64_t pos = lseek(fd, 0, SEEK_CUR); + return pos; + } + + int seek(VirtFile *restrict const file, + const uint64_t pos) + { + if (file == nullptr) + return 0; + + const int fd = file->mPrivate->mFd; + if (fd == -1) + { + reportAlways("VirtFsDir::seek file not opened."); + return 0; + } + const int64_t res = lseek(fd, pos, SEEK_SET); + if (res == -1) + return 0; + return 1; + } + + int eof(VirtFile *restrict const file) + { + if (file == nullptr) + return -1; + + const int fd = file->mPrivate->mFd; + if (fd == -1) + { + reportAlways("VirtFsDir::eof file not opened."); + return 0; + } + const int64_t pos = lseek(fd, 0, SEEK_CUR); + struct stat statbuf; + if (fstat(fd, &statbuf) == -1) + { + reportAlways("VirtFsDir::fileLength error."); + return -1; + } + const int64_t len = static_cast(statbuf.st_size); + return pos < 0 || len < 0 || pos >= len; + } +} // namespace VirtFs diff --git a/src/fs/virtfs/virtfsdir.h b/src/fs/virtfs/virtfsdir.h new file mode 100644 index 000000000..75df7fb18 --- /dev/null +++ b/src/fs/virtfs/virtfsdir.h @@ -0,0 +1,89 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013-2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef UTILS_VIRTFSDIR_H +#define UTILS_VIRTFSDIR_H + +#include "enums/simpletypes/append.h" +#include "enums/simpletypes/skiperror.h" + +#include "localconsts.h" + +#include +#include + +struct VirtDirEntry; +struct VirtFile; +struct VirtFsFuncs; +struct VirtList; + +namespace VirtFsDir +{ + VirtDirEntry *searchEntryByRoot(const std::string &restrict root); + VirtDirEntry *searchEntryByPath(const std::string &restrict path); + VirtFile *openReadDirEntry(VirtDirEntry *const entry, + const std::string &filename); + const char *getBaseDir(); + const char *getUserDir(); + bool addToSearchPath(std::string newDir, + const Append append); + bool addToSearchPathSilent(std::string newDir, + const Append append, + const SkipError skipError); + bool removeFromSearchPath(std::string oldDir); + bool removeFromSearchPathSilent(std::string oldDir); + void init(const std::string &restrict name); + void initFuncs(VirtFsFuncs *restrict const ptr); + void deinit(); + std::vector &getEntries(); + bool exists(std::string name); + VirtList *enumerateFiles(std::string dirName) RETURNS_NONNULL; + VirtList *enumerateFiles(const std::string &restrict dirName, + VirtList *restrict const list) RETURNS_NONNULL; + bool isDirectory(std::string dirName); + bool isDirectoryInternal(const std::string &restrict dirName); + bool isSymbolicLink(std::string name); + void freeList(VirtList *restrict const handle); + VirtFile *openRead(const std::string &restrict filename); + VirtFile *openWrite(const std::string &restrict filename); + VirtFile *openAppend(const std::string &restrict filename); + bool setWriteDir(std::string newDir); + std::string getRealDir(std::string filename); + bool mkdir(std::string dirName); + bool remove(std::string filename); + void permitLinks(const bool val); + const char *getLastError(); + int64_t read(VirtFile *restrict const handle, + void *restrict const buffer, + const uint32_t objSize, + const uint32_t objCount); + int64_t write(VirtFile *restrict const file, + const void *restrict const buffer, + const uint32_t objSize, + const uint32_t objCount); + int close(VirtFile *restrict const file); + int64_t fileLength(VirtFile *restrict const file); + int64_t tell(VirtFile *restrict const file); + int seek(VirtFile *restrict const file, + const uint64_t pos); + int eof(VirtFile *restrict const file); +} // namespace VirtFsDir + +#endif // UTILS_VIRTFSDIR_H diff --git a/src/fs/virtfs/virtfsdir_unittest.cc b/src/fs/virtfs/virtfsdir_unittest.cc new file mode 100644 index 000000000..ad55acf2e --- /dev/null +++ b/src/fs/virtfs/virtfsdir_unittest.cc @@ -0,0 +1,717 @@ +/* + * The ManaPlus Client + * Copyright (C) 2016-2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "catch.hpp" + +#include "fs/virtfs/virtdirentry.h" +#include "fs/virtfs/virtfsdir.h" +#include "fs/virtfstools.h" +#include "fs/virtlist.h" + +#include "utils/checkutils.h" +#include "utils/delete2.h" + +#include "debug.h" + +TEST_CASE("VirtFsDir getEntries") +{ + VirtFsDir::init("."); + REQUIRE(VirtFsDir::getEntries().empty()); + REQUIRE(VirtFsDir::searchEntryByRoot("test") == nullptr); + VirtFsDir::deinit(); +} + +TEST_CASE("VirtFsDir getBaseDir") +{ + VirtFsDir::init("."); + REQUIRE(VirtFsDir::getBaseDir() != nullptr); + VirtFsDir::deinit(); +} + +TEST_CASE("VirtFsDir addToSearchPath") +{ + VirtFsDir::init("."); + logger = new Logger(); + SECTION("simple 1") + { + REQUIRE(VirtFsDir::addToSearchPathSilent("dir1", + Append_false, + SkipError_true)); + REQUIRE(VirtFsDir::searchEntryByRoot("dir1/") != nullptr); + REQUIRE(VirtFsDir::searchEntryByRoot("test/") == nullptr); + REQUIRE(VirtFsDir::getEntries().size() == 1); + REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir1/"); + REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir1"); + } + + SECTION("simple 2") + { + REQUIRE(VirtFsDir::addToSearchPathSilent("dir1/", + Append_true, + SkipError_true)); + REQUIRE(VirtFsDir::searchEntryByRoot("dir1/") != nullptr); + REQUIRE(VirtFsDir::searchEntryByRoot("test/") == nullptr); + REQUIRE(VirtFsDir::getEntries().size() == 1); + REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir1/"); + REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir1/"); + } + + SECTION("simple 3") + { + REQUIRE(VirtFsDir::addToSearchPathSilent("dir1", + Append_false, + SkipError_true)); + REQUIRE(VirtFsDir::addToSearchPathSilent("dir2", + Append_false, + SkipError_true)); + REQUIRE(VirtFsDir::searchEntryByRoot("dir1/") != nullptr); + REQUIRE(VirtFsDir::searchEntryByRoot("dir2/") != nullptr); + REQUIRE(VirtFsDir::searchEntryByRoot("test/") == nullptr); + REQUIRE(VirtFsDir::getEntries().size() == 2); + REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir2/"); + REQUIRE(VirtFsDir::getEntries()[1]->mRootDir == "dir1/"); + REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir2"); + REQUIRE(VirtFsDir::getEntries()[1]->mUserDir == "dir1"); + } + + SECTION("simple 4") + { + REQUIRE(VirtFsDir::addToSearchPathSilent("dir1\\", + Append_true, + SkipError_true)); + REQUIRE(VirtFsDir::addToSearchPathSilent("dir2", + Append_true, + SkipError_true)); + REQUIRE(VirtFsDir::searchEntryByRoot("dir1/") != nullptr); + REQUIRE(VirtFsDir::searchEntryByRoot("dir2/") != nullptr); + REQUIRE(VirtFsDir::searchEntryByRoot("test/") == nullptr); + REQUIRE(VirtFsDir::getEntries().size() == 2); + REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir1/"); + REQUIRE(VirtFsDir::getEntries()[1]->mRootDir == "dir2/"); + REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir1/"); + REQUIRE(VirtFsDir::getEntries()[1]->mUserDir == "dir2"); + } + + SECTION("simple 5") + { + REQUIRE(VirtFsDir::addToSearchPathSilent("dir1", + Append_true, + SkipError_true)); + REQUIRE(VirtFsDir::addToSearchPathSilent("dir2", + Append_true, + SkipError_true)); + REQUIRE(VirtFsDir::addToSearchPathSilent("dir3/test", + Append_true, + SkipError_true)); + REQUIRE(VirtFsDir::searchEntryByRoot("dir1/") != nullptr); + REQUIRE(VirtFsDir::searchEntryByRoot("dir2/") != nullptr); + REQUIRE(VirtFsDir::searchEntryByRoot("dir3/test/") != nullptr); + REQUIRE(VirtFsDir::searchEntryByRoot("test/") == nullptr); + REQUIRE(VirtFsDir::getEntries().size() == 3); + REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir1/"); + REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir1"); + REQUIRE(VirtFsDir::getEntries()[1]->mRootDir == "dir2/"); + REQUIRE(VirtFsDir::getEntries()[1]->mUserDir == "dir2"); + REQUIRE(VirtFsDir::getEntries()[2]->mRootDir == "dir3/test/"); + REQUIRE(VirtFsDir::getEntries()[2]->mUserDir == "dir3/test"); + } + + SECTION("simple 6") + { + REQUIRE(VirtFsDir::addToSearchPathSilent("dir1", + Append_true, + SkipError_true)); + REQUIRE(VirtFsDir::addToSearchPathSilent("dir2", + Append_true, + SkipError_true)); + REQUIRE(VirtFsDir::addToSearchPathSilent("dir3/test", + Append_false, + SkipError_true)); + REQUIRE(VirtFsDir::searchEntryByRoot("dir1/") != nullptr); + REQUIRE(VirtFsDir::searchEntryByRoot("dir2/") != nullptr); + REQUIRE(VirtFsDir::searchEntryByRoot("dir3/test/") != nullptr); + REQUIRE(VirtFsDir::searchEntryByRoot("test/") == nullptr); + REQUIRE(VirtFsDir::getEntries().size() == 3); + REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir3/test/"); + REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir3/test"); + REQUIRE(VirtFsDir::getEntries()[1]->mRootDir == "dir1/"); + REQUIRE(VirtFsDir::getEntries()[1]->mUserDir == "dir1"); + REQUIRE(VirtFsDir::getEntries()[2]->mRootDir == "dir2/"); + REQUIRE(VirtFsDir::getEntries()[2]->mUserDir == "dir2"); + } + + VirtFsDir::deinit(); + delete2(logger); +} + +TEST_CASE("VirtFsDir removeFromSearchPath") +{ + VirtFsDir::init("."); + logger = new Logger(); + + SECTION("simple 1") + { + REQUIRE_THROWS(VirtFsDir::removeFromSearchPath("dir1")); + REQUIRE_THROWS(VirtFsDir::removeFromSearchPath("dir1/")); + } + + SECTION("simple 2") + { + REQUIRE(VirtFsDir::addToSearchPathSilent("dir1", + Append_true, + SkipError_true)); + REQUIRE_THROWS(VirtFsDir::removeFromSearchPath("dir2")); + REQUIRE(VirtFsDir::removeFromSearchPath("dir1")); + } + + SECTION("simple 3") + { + REQUIRE(VirtFsDir::addToSearchPathSilent("dir1", + Append_true, + SkipError_true)); + REQUIRE(VirtFsDir::addToSearchPathSilent("dir2//dir3", + Append_true, + SkipError_true)); + REQUIRE(VirtFsDir::addToSearchPathSilent("dir3", + Append_false, + SkipError_true)); + REQUIRE(VirtFsDir::getEntries().size() == 3); + REQUIRE_THROWS(VirtFsDir::removeFromSearchPath("dir2")); + REQUIRE(VirtFsDir::removeFromSearchPath("dir1")); + REQUIRE(VirtFsDir::getEntries().size() == 2); + REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir3/"); + REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir3"); + REQUIRE(VirtFsDir::getEntries()[1]->mRootDir == "dir2/dir3/"); + REQUIRE(VirtFsDir::getEntries()[1]->mUserDir == "dir2/dir3"); + REQUIRE_THROWS(VirtFsDir::removeFromSearchPath("dir1")); + REQUIRE(VirtFsDir::getEntries().size() == 2); + REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir3/"); + REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir3"); + REQUIRE(VirtFsDir::getEntries()[1]->mRootDir == "dir2/dir3/"); + REQUIRE(VirtFsDir::getEntries()[1]->mUserDir == "dir2/dir3"); + REQUIRE(VirtFsDir::removeFromSearchPath("dir2/dir3")); + REQUIRE_THROWS(VirtFsDir::removeFromSearchPath("dir2/dir3/")); + REQUIRE(VirtFsDir::getEntries().size() == 1); + REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir3/"); + REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir3"); + } + + SECTION("simple 4") + { + REQUIRE(VirtFsDir::addToSearchPathSilent("dir1", + Append_true, + SkipError_true)); + REQUIRE(VirtFsDir::getEntries().size() == 1); + REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir1/"); + REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir1"); + REQUIRE_THROWS(VirtFsDir::removeFromSearchPath("dir2")); + REQUIRE(VirtFsDir::removeFromSearchPath("dir1")); + REQUIRE(VirtFsDir::getEntries().size() == 0); + REQUIRE(VirtFsDir::addToSearchPathSilent("dir1", + Append_true, + SkipError_true)); + REQUIRE(VirtFsDir::getEntries().size() == 1); + REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir1/"); + REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir1"); + } + + VirtFsDir::deinit(); + delete2(logger); +} + +TEST_CASE("VirtFsDir exists") +{ + VirtFsDir::init("."); + logger = new Logger(); + VirtFsDir::addToSearchPathSilent("data/", + Append_false, + SkipError_false); + VirtFsDir::addToSearchPathSilent("..\\data", + Append_false, + SkipError_false); + + REQUIRE(VirtFsDir::exists("test//units.xml") == true); + REQUIRE(VirtFsDir::exists("test/\\units123.xml") == false); + REQUIRE(VirtFsDir::exists("tesQ/units.xml") == false); + REQUIRE(VirtFsDir::exists("units.xml") == false); + + VirtFsDir::addToSearchPathSilent("data//test", + Append_false, + SkipError_false); + VirtFsDir::addToSearchPathSilent("..//data\\test", + Append_false, + SkipError_false); + + REQUIRE(VirtFsDir::exists("test\\units.xml") == true); + REQUIRE(VirtFsDir::exists("test/units123.xml") == false); + REQUIRE(VirtFsDir::exists("tesQ/units.xml") == false); + REQUIRE(VirtFsDir::exists("units.xml") == true); + + VirtFsDir::removeFromSearchPathSilent("data/test"); + VirtFsDir::removeFromSearchPathSilent("../data/test"); + + REQUIRE(VirtFsDir::exists("test\\units.xml") == true); + REQUIRE(VirtFsDir::exists("test/units123.xml") == false); + REQUIRE(VirtFsDir::exists("tesQ/units.xml") == false); + REQUIRE(VirtFsDir::exists("units.xml") == false); + + REQUIRE_THROWS(VirtFsDir::exists("test/../units.xml")); + + VirtFsDir::deinit(); + delete2(logger); +} + +static void removeTemp(StringVect &restrict list) +{ + int cnt = 0; + std::sort(list.begin(), list.end()); + + FOR_EACH (StringVectIter, it, list) + { + if (*it != "serverlistplus.xml.part") + { + logger->log("file: %d %s", + cnt, + (*it).c_str()); + cnt ++; + } + } + + FOR_EACH (StringVectIter, it, list) + { + if (*it == "serverlistplus.xml.part") + { + list.erase(it); + return; + } + } +} + +TEST_CASE("VirtFsDir getRealDir") +{ + VirtFsDir::init("."); + logger = new Logger(); + REQUIRE(VirtFsDir::getRealDir(".") == ""); + REQUIRE(VirtFsDir::getRealDir("..") == ""); + const bool dir1 = VirtFsDir::addToSearchPathSilent("data", + Append_false, + SkipError_false); + REQUIRE((dir1 || VirtFsDir::addToSearchPathSilent("../data", + Append_false, + SkipError_false)) == true); + if (dir1 == true) + { + REQUIRE(VirtFsDir::getRealDir("test") == "data"); + REQUIRE(VirtFsDir::getRealDir("test/test.txt") == + "data"); + REQUIRE(VirtFsDir::getRealDir("test\\test.txt") == + "data"); + REQUIRE(VirtFsDir::getRealDir("test//test.txt") == + "data"); + } + else + { + REQUIRE(VirtFsDir::getRealDir("test") == "../data"); + REQUIRE(VirtFsDir::getRealDir("test/test.txt") == + "../data"); + REQUIRE(VirtFsDir::getRealDir("test\\test.txt") == + "../data"); + REQUIRE(VirtFsDir::getRealDir("test//test.txt") == + "../data"); + } + REQUIRE(VirtFsDir::getRealDir("zzz") == ""); + + VirtFsDir::addToSearchPathSilent("data/test", + Append_false, + SkipError_false); + VirtFsDir::addToSearchPathSilent("../data/test", + Append_false, + SkipError_false); + if (dir1 == true) + { + REQUIRE(VirtFsDir::getRealDir("test") == "data"); + REQUIRE(VirtFsDir::getRealDir("test/test.txt") == + "data"); + REQUIRE(VirtFsDir::getRealDir("test\\test.txt") == + "data"); + REQUIRE(VirtFsDir::getRealDir("test.txt") == + "data/test"); + } + else + { + REQUIRE(VirtFsDir::getRealDir("test") == "../data"); + REQUIRE(VirtFsDir::getRealDir("test/test.txt") == + "../data"); + REQUIRE(VirtFsDir::getRealDir("test\\test.txt") == + "../data"); + REQUIRE(VirtFsDir::getRealDir("test.txt") == + "../data/test"); + } + REQUIRE(VirtFsDir::getRealDir("zzz") == ""); + + VirtFsDir::removeFromSearchPathSilent("data/test"); + VirtFsDir::removeFromSearchPathSilent("../data/test"); + + if (dir1 == true) + { + REQUIRE(VirtFsDir::getRealDir("test") == "data"); + REQUIRE(VirtFsDir::getRealDir("test/test.txt") == + "data"); + } + else + { + REQUIRE(VirtFsDir::getRealDir("test") == "../data"); + REQUIRE(VirtFsDir::getRealDir("test/test.txt") == + "../data"); + } + REQUIRE(VirtFsDir::getRealDir("zzz") == ""); + + VirtFsDir::removeFromSearchPathSilent("data"); + VirtFsDir::removeFromSearchPathSilent("../data"); + VirtFsDir::deinit(); + delete2(logger); +} + +static bool inList(VirtList *list, + const std::string &name) +{ + FOR_EACH (StringVectCIter, it, list->names) + { + if (*it == name) + return true; + } + return false; +} + +TEST_CASE("VirtFsDir enumerateFiles1") +{ + VirtFsDir::init("."); + logger = new Logger; + + VirtFsDir::addToSearchPathSilent("data", + Append_false, + SkipError_false); + VirtFsDir::addToSearchPathSilent("../data", + Append_false, + SkipError_false); + + VirtList *list = nullptr; + + const int cnt1 = VirtFsDir::exists("test/test2.txt") ? 27 : 26; + const int cnt2 = 27; + + VirtFsDir::permitLinks(false); + list = VirtFsDir::enumerateFiles("test"); + removeTemp(list->names); + const size_t sz = list->names.size(); + REQUIRE(sz == cnt1); + VirtFsDir::freeList(list); + + VirtFsDir::permitLinks(true); + list = VirtFsDir::enumerateFiles("test/"); + removeTemp(list->names); + REQUIRE(list->names.size() == cnt2); + VirtFsDir::freeList(list); + + VirtFsDir::permitLinks(false); + list = VirtFsDir::enumerateFiles("test\\"); + removeTemp(list->names); + REQUIRE(list->names.size() == cnt1); + VirtFsDir::freeList(list); + + VirtFsDir::removeFromSearchPathSilent("data"); + VirtFsDir::removeFromSearchPathSilent("../data"); + VirtFsDir::deinit(); + delete2(logger); +} + +TEST_CASE("VirtFsDir enumerateFiles2") +{ + VirtFsDir::init("."); + logger = new Logger; + + VirtFsDir::addToSearchPathSilent("data/test/dir1", + Append_false, + SkipError_false); + VirtFsDir::addToSearchPathSilent("../data/test/dir1", + Append_false, + SkipError_false); + + VirtList *list = nullptr; + + list = VirtFsDir::enumerateFiles("/"); + const size_t sz = list->names.size(); + REQUIRE(list->names.size() == 5); + REQUIRE(inList(list, "file1.txt")); + REQUIRE_FALSE(inList(list, "file2.txt")); + VirtFsDir::freeList(list); + VirtFsDir::deinit(); + delete2(logger); +} + +TEST_CASE("VirtFsDir enumerateFiles3") +{ + VirtFsDir::init("."); + logger = new Logger; + + VirtFsDir::addToSearchPathSilent("data/test/dir1", + Append_false, + SkipError_false); + VirtFsDir::addToSearchPathSilent("../data/test/dir1", + Append_false, + SkipError_false); + VirtFsDir::addToSearchPathSilent("data/test/dir2", + Append_false, + SkipError_false); + VirtFsDir::addToSearchPathSilent("../data/test/dir2", + Append_false, + SkipError_false); + + VirtList *list = nullptr; + + list = VirtFsDir::enumerateFiles("/"); + const size_t sz = list->names.size(); + REQUIRE(list->names.size() == 6); + REQUIRE(inList(list, "file1.txt")); + REQUIRE(inList(list, "file2.txt")); + VirtFsDir::freeList(list); + VirtFsDir::deinit(); + delete2(logger); +} + +TEST_CASE("VirtFsDir isDirectory") +{ + VirtFsDir::init("."); + logger = new Logger(); + VirtFsDir::addToSearchPathSilent("data", + Append_false, + SkipError_false); + VirtFsDir::addToSearchPathSilent("../data", + Append_false, + SkipError_false); + + REQUIRE(VirtFsDir::isDirectory("test/units.xml") == false); + REQUIRE(VirtFsDir::isDirectory("test/units.xml/") == false); + REQUIRE(VirtFsDir::isDirectory("test//units.xml") == false); + REQUIRE(VirtFsDir::isDirectory("test/units123.xml") == false); + REQUIRE(VirtFsDir::isDirectory("test//units123.xml") == false); + REQUIRE(VirtFsDir::isDirectory("tesQ/units.xml") == false); + REQUIRE(VirtFsDir::isDirectory("tesQ//units.xml") == false); + REQUIRE(VirtFsDir::isDirectory("units.xml") == false); + REQUIRE(VirtFsDir::isDirectory("test") == true); + REQUIRE(VirtFsDir::isDirectory("test/") == true); + REQUIRE(VirtFsDir::isDirectory("test//") == true); + REQUIRE(VirtFsDir::isDirectory("test/dir1") == true); + REQUIRE(VirtFsDir::isDirectory("test//dir1") == true); + REQUIRE(VirtFsDir::isDirectory("test//dir1/") == true); + REQUIRE(VirtFsDir::isDirectory("test//dir1//") == true); + REQUIRE(VirtFsDir::isDirectory("test\\dir1/") == true); + REQUIRE(VirtFsDir::isDirectory("test/dir1//") == true); + REQUIRE(VirtFsDir::isDirectory("testQ") == false); + REQUIRE(VirtFsDir::isDirectory("testQ/") == false); + REQUIRE(VirtFsDir::isDirectory("testQ//") == false); + + VirtFsDir::addToSearchPathSilent("data/test", + Append_false, + SkipError_false); + VirtFsDir::addToSearchPathSilent("../data/test", + Append_false, + SkipError_false); + + REQUIRE(VirtFsDir::isDirectory("test/units.xml") == false); + REQUIRE(VirtFsDir::isDirectory("test/units.xml/") == false); + REQUIRE(VirtFsDir::isDirectory("test//units.xml") == false); + REQUIRE(VirtFsDir::isDirectory("test/units123.xml") == false); + REQUIRE(VirtFsDir::isDirectory("tesQ/units.xml") == false); + REQUIRE(VirtFsDir::isDirectory("units.xml") == false); + REQUIRE(VirtFsDir::isDirectory("test") == true); + REQUIRE(VirtFsDir::isDirectory("testQ") == false); + REQUIRE(VirtFsDir::isDirectory("test/dir1") == true); + REQUIRE(VirtFsDir::isDirectory("test\\dir1") == true); + + VirtFsDir::removeFromSearchPathSilent("data/test"); + VirtFsDir::removeFromSearchPathSilent("../data/test"); + + REQUIRE(VirtFsDir::isDirectory("test/units.xml") == false); + REQUIRE(VirtFsDir::isDirectory("test/units123.xml") == false); + REQUIRE(VirtFsDir::isDirectory("tesQ/units.xml") == false); + REQUIRE(VirtFsDir::isDirectory("units.xml") == false); + REQUIRE(VirtFsDir::isDirectory("units.xml/") == false); + REQUIRE(VirtFsDir::isDirectory("test") == true); + REQUIRE(VirtFsDir::isDirectory("test/") == true); + REQUIRE(VirtFsDir::isDirectory("testQ") == false); + REQUIRE(VirtFsDir::isDirectory("test/dir1") == true); + + VirtFsDir::removeFromSearchPathSilent("data"); + VirtFsDir::removeFromSearchPathSilent("../data"); + VirtFsDir::deinit(); + delete2(logger); +} + +TEST_CASE("VirtFsDir openRead") +{ + VirtFsDir::init("."); + logger = new Logger(); + VirtFsDir::addToSearchPathSilent("data", + Append_false, + SkipError_false); + VirtFsDir::addToSearchPathSilent("../data", + Append_false, + SkipError_false); + + VirtFile *file = nullptr; + + file = VirtFsDir::openRead("test/units.xml"); + REQUIRE(file != nullptr); + VirtFsDir::close(file); + file = VirtFsDir::openRead("test\\units.xml"); + REQUIRE(file != nullptr); + VirtFsDir::close(file); + file = VirtFsDir::openRead("test/units123.xml"); + REQUIRE(file == nullptr); + file = VirtFsDir::openRead("tesQ/units.xml"); + REQUIRE(file == nullptr); + file = VirtFsDir::openRead("units.xml"); + REQUIRE(file == nullptr); + file = VirtFsDir::openRead("testQ"); + REQUIRE(file == nullptr); + + VirtFsDir::addToSearchPathSilent("data/test", + Append_false, + SkipError_false); + VirtFsDir::addToSearchPathSilent("../data/test", + Append_false, + SkipError_false); + + file = VirtFsDir::openRead("test/units.xml"); + REQUIRE(file != nullptr); + VirtFsDir::close(file); + file = VirtFsDir::openRead("test/units123.xml"); + REQUIRE(file == nullptr); + file = VirtFsDir::openRead("tesQ/units.xml"); + REQUIRE(file == nullptr); + file = VirtFsDir::openRead("units.xml"); + REQUIRE(file != nullptr); + VirtFsDir::close(file); + file = VirtFsDir::openRead("testQ"); + REQUIRE(file == nullptr); + + VirtFsDir::removeFromSearchPathSilent("data/test"); + VirtFsDir::removeFromSearchPathSilent("../data/test"); + + file = VirtFsDir::openRead("test/units.xml"); + REQUIRE(file != nullptr); + VirtFsDir::close(file); + file = VirtFsDir::openRead("test/units123.xml"); + REQUIRE(file == nullptr); + file = VirtFsDir::openRead("tesQ/units.xml"); + REQUIRE(file == nullptr); + file = VirtFsDir::openRead("units.xml"); + REQUIRE(file == nullptr); + file = VirtFsDir::openRead("testQ"); + REQUIRE(file == nullptr); + + VirtFsDir::removeFromSearchPathSilent("data"); + VirtFsDir::removeFromSearchPathSilent("../data"); + VirtFsDir::deinit(); + delete2(logger); +} + + +TEST_CASE("VirtFsDir permitLinks") +{ + VirtFsDir::init("."); + logger = new Logger(); + VirtFsDir::addToSearchPathSilent("data", + Append_false, + SkipError_false); + VirtFsDir::addToSearchPathSilent("../data", + Append_false, + SkipError_false); + + const int cnt1 = VirtFsDir::exists("test/test2.txt") ? 25 : 24; + const int cnt2 = 25; + + StringVect list; + VirtFsDir::permitLinks(false); + VirtFsDir::getFiles("test", list); + removeTemp(list); + const size_t sz = list.size(); + REQUIRE(sz == cnt1); + + list.clear(); + VirtFsDir::permitLinks(true); + VirtFsDir::getFiles("test", list); + removeTemp(list); + REQUIRE(list.size() == cnt2); + + list.clear(); + VirtFsDir::permitLinks(false); + VirtFsDir::getFiles("test", list); + removeTemp(list); + REQUIRE(list.size() == cnt1); + + VirtFsDir::removeFromSearchPathSilent("data"); + VirtFsDir::removeFromSearchPathSilent("../data"); + VirtFsDir::deinit(); + delete2(logger); +} + +TEST_CASE("VirtFsDir read") +{ + VirtFsDir::init("."); + logger = new Logger(); + VirtFsDir::addToSearchPathSilent("data", + Append_false, + SkipError_false); + VirtFsDir::addToSearchPathSilent("../data", + Append_false, + SkipError_false); + + VirtFile *file = VirtFsDir::openRead("test/test.txt"); + REQUIRE(file != nullptr); + REQUIRE(VirtFsDir::fileLength(file) == 23); + const int fileSize = VirtFsDir::fileLength(file); + + void *restrict buffer = calloc(fileSize + 1, 1); + REQUIRE(VirtFsDir::read(file, buffer, 1, fileSize) == fileSize); + REQUIRE(strcmp(static_cast(buffer), + "test line 1\ntest line 2") == 0); + REQUIRE(VirtFsDir::tell(file) == fileSize); + REQUIRE(VirtFsDir::eof(file) == true); + + free(buffer); + buffer = calloc(fileSize + 1, 1); + REQUIRE(VirtFsDir::seek(file, 12) != 0); + REQUIRE(VirtFsDir::eof(file) == false); + REQUIRE(VirtFsDir::tell(file) == 12); + REQUIRE(VirtFsDir::read(file, buffer, 1, 11) == 11); + REQUIRE(strcmp(static_cast(buffer), + "test line 2") == 0); + REQUIRE(VirtFsDir::eof(file) == true); + + VirtFsDir::close(file); + free(buffer); + + VirtFsDir::removeFromSearchPathSilent("data"); + VirtFsDir::removeFromSearchPathSilent("../data"); + VirtFsDir::deinit(); + delete2(logger); +} diff --git a/src/fs/virtfs/virtfszip.cpp b/src/fs/virtfs/virtfszip.cpp new file mode 100644 index 000000000..c4ce6f9e8 --- /dev/null +++ b/src/fs/virtfs/virtfszip.cpp @@ -0,0 +1,555 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013-2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "fs/virtfs/virtfszip.h" + +#include "fs/files.h" +#include "fs/paths.h" +#include "fs/virtfsfuncs.h" +#include "fs/virtfile.h" +#include "fs/virtlist.h" + +#include "fs/virtfs/virtfileprivate.h" +#include "fs/virtfs/virtzipentry.h" +#include "fs/virtfs/zip.h" +#include "fs/virtfs/ziplocalheader.h" + +#include "utils/checkutils.h" +#include "utils/dtor.h" +#include "utils/stringutils.h" + +#include "debug.h" + +extern const char *dirSeparator; + +namespace +{ + std::vector mEntries; + VirtFsFuncs funcs; +} // namespace + +namespace VirtFsZip +{ + VirtZipEntry *searchEntryByArchive(const std::string &restrict archiveName) + { + FOR_EACH (std::vector::const_iterator, it, mEntries) + { + if ((*it)->mArchiveName == archiveName) + return *it; + } + return nullptr; + } + + ZipLocalHeader *searchHeaderByName(const std::string &restrict filename) + { + FOR_EACH (std::vector::const_iterator, it, mEntries) + { + VirtZipEntry *const entry = *it; + FOR_EACH (std::vector::const_iterator, + it2, + entry->mHeaders) + { + if ((*it2)->fileName == filename) + return *it2;; + } + } + return nullptr; + } + + bool addToSearchPathSilent(std::string newDir, + const Append append) + { + prepareFsPath(newDir); + if (Files::existsLocal(newDir) == false) + { + logger->log("VirtFsZip::addToSearchPath file not exists: %s", + newDir.c_str()); + return false; + } + if (findLast(newDir, ".zip") == false) + { + reportAlways("Called VirtFsZip::addToSearchPath without " + "zip archive"); + return false; + } + VirtZipEntry *entry = VirtFsZip::searchEntryByArchive(newDir); + if (entry != nullptr) + { + reportAlways("VirtFsZip::addToSearchPath already exists: %s", + newDir.c_str()); + return false; + } + entry = new VirtZipEntry(newDir); + if (Zip::readArchiveInfo(entry) == false) + { + delete entry; + return false; + } + + logger->log("Add virtual zip: " + newDir); + if (append == Append_true) + mEntries.push_back(entry); + else + { + mEntries.insert(mEntries.begin(), + entry); + } + return true; + } + + bool addToSearchPath(std::string newDir, + const Append append) + { + prepareFsPath(newDir); + if (Files::existsLocal(newDir) == false) + { + reportAlways("VirtFsZip::addToSearchPath directory not exists: %s", + newDir.c_str()); + return false; + } + if (findLast(newDir, ".zip") == false) + { + reportAlways("Called VirtFsZip::addToSearchPath without " + "zip archive"); + return false; + } + VirtZipEntry *entry = VirtFsZip::searchEntryByArchive(newDir); + if (entry != nullptr) + { + reportAlways("VirtFsZip::addToSearchPath already exists: %s", + newDir.c_str()); + return false; + } + entry = new VirtZipEntry(newDir); + if (Zip::readArchiveInfo(entry) == false) + { + delete entry; + return false; + } + + logger->log("Add virtual zip: " + newDir); + if (append == Append_true) + mEntries.push_back(entry); + else + { + mEntries.insert(mEntries.begin(), + entry); + } + return true; + } + + bool removeFromSearchPathSilent(std::string oldDir) + { + prepareFsPath(oldDir); + if (findLast(oldDir, ".zip") == false) + { + reportAlways("Called removeFromSearchPath without zip archive"); + return false; + } + FOR_EACH (std::vector::iterator, it, mEntries) + { + VirtZipEntry *const entry = *it; + if (entry->mArchiveName == oldDir) + { + logger->log("Remove virtual zip: " + oldDir); + mEntries.erase(it); + delete entry; + return true; + } + } + + logger->log("VirtFsZip::removeFromSearchPath not exists: %s", + oldDir.c_str()); + return false; + } + + bool removeFromSearchPath(std::string oldDir) + { + prepareFsPath(oldDir); + if (findLast(oldDir, ".zip") == false) + { + reportAlways("Called removeFromSearchPath without zip archive"); + return false; + } + FOR_EACH (std::vector::iterator, it, mEntries) + { + VirtZipEntry *const entry = *it; + if (entry->mArchiveName == oldDir) + { + logger->log("Remove virtual zip: " + oldDir); + mEntries.erase(it); + delete entry; + return true; + } + } + + reportAlways("VirtFsZip::removeFromSearchPath not exists: %s", + oldDir.c_str()); + return false; + } + + std::vector &getEntries() + { + return mEntries; + } + + void deinit() + { + delete_all(mEntries); + mEntries.clear(); + } + + void init() + { + initFuncs(&funcs); + } + + void initFuncs(VirtFsFuncs *restrict const ptr) + { + ptr->close = &VirtFsZip::close; + ptr->read = &VirtFsZip::read; + ptr->write = &VirtFsZip::write; + ptr->fileLength = &VirtFsZip::fileLength; + ptr->tell = &VirtFsZip::tell; + ptr->seek = &VirtFsZip::seek; + ptr->eof = &VirtFsZip::eof; + } + + std::string getRealDir(std::string filename) + { + prepareFsPath(filename); + if (checkPath(filename) == false) + { + reportAlways("VirtFsZip::exists invalid path: %s", + filename.c_str()); + return std::string(); + } + return getRealDirInternal(filename); + } + + std::string getRealDirInternal(const std::string &filename) + { + ZipLocalHeader *restrict const header = searchHeaderByName(filename); + if (header != nullptr) + return header->zipEntry->mArchiveName; + return std::string(); + } + + bool exists(std::string name) + { + prepareFsPath(name); + if (checkPath(name) == false) + { + reportAlways("VirtFsZip::exists invalid path: %s", + name.c_str()); + return false; + } + ZipLocalHeader *restrict const header = searchHeaderByName(name); + if (header != nullptr) + return true; + return false; + } + + VirtList *enumerateFiles(std::string dirName) + { + VirtList *const list = new VirtList; + prepareFsPath(dirName); + if (checkPath(dirName) == false) + { + reportAlways("VirtFsZip::enumerateFiles invalid path: %s", + dirName.c_str()); + return list; + } + return enumerateFiles(dirName, list); + } + + VirtList *enumerateFiles(std::string dirName, + VirtList *restrict const list) + { + if (findLast(dirName, std::string(dirSeparator)) == false) + dirName += dirSeparator; + StringVect &names = list->names; + if (dirName == "/") + { + FOR_EACH (std::vector::const_iterator, it, mEntries) + { + VirtZipEntry *const entry = *it; + FOR_EACH (std::vector::const_iterator, + it2, + entry->mHeaders) + { + ZipLocalHeader *const header = *it2; + std::string fileName = header->fileName; + // skip subdirs from enumeration + const size_t idx = fileName.find(dirSeparator); + if (idx != std::string::npos) + fileName.erase(idx); + bool found(false); + FOR_EACH (StringVectCIter, itn, names) + { + if (*itn == fileName) + { + found = true; + break; + } + } + if (found == false) + names.push_back(fileName); + } + } + } + else + { + FOR_EACH (std::vector::const_iterator, it, mEntries) + { + VirtZipEntry *const entry = *it; + FOR_EACH (std::vector::const_iterator, + it2, + entry->mHeaders) + { + ZipLocalHeader *const header = *it2; + std::string fileName = header->fileName; + if (findCutFirst(fileName, dirName) == true) + { + // skip subdirs from enumeration + const size_t idx = fileName.find(dirSeparator); + if (idx != std::string::npos) + fileName.erase(idx); + bool found(false); + FOR_EACH (StringVectCIter, itn, names) + { + if (*itn == fileName) + { + found = true; + break; + } + } + if (found == false) + names.push_back(fileName); + } + } + } + } + + return list; + } + + bool isDirectory(std::string dirName) + { + prepareFsPath(dirName); + if (checkPath(dirName) == false) + { + reportAlways("VirtFsZip::isDirectory invalid path: %s", + dirName.c_str()); + return false; + } + return isDirectoryInternal(dirName); + } + + bool isDirectoryInternal(std::string dirName) + { + if (findLast(dirName, std::string(dirSeparator)) == false) + dirName += dirSeparator; + FOR_EACH (std::vector::const_iterator, it, mEntries) + { + VirtZipEntry *const entry = *it; + FOR_EACH (std::vector::const_iterator, + it2, + entry->mDirs) + { + if (*it2 == dirName) + return true; + } + } + return false; + } + + bool isSymbolicLink(std::string name) + { + prepareFsPath(name); + if (checkPath(name) == false) + { + reportAlways("VirtFsZip::isSymbolicLink invalid path: %s", + name.c_str()); + return false; + } + // look like in zip files can be symlinks, but here they useless + return false; + } + + void freeList(VirtList *restrict const handle) + { + delete handle; + } + + VirtFile *openRead(std::string filename) + { + prepareFsPath(filename); + if (checkPath(filename) == false) + { + reportAlways("VirtFsZip::openRead invalid path: %s", + filename.c_str()); + return nullptr; + } + return openReadInternal(filename); + } + + VirtFile *openReadInternal(const std::string &filename) + { + ZipLocalHeader *restrict const header = searchHeaderByName(filename); + if (header != nullptr) + { + uint8_t *restrict const buf = Zip::readFile(header); + if (buf == nullptr) + return nullptr; + VirtFile *restrict const file = new VirtFile(&funcs); + file->mPrivate = new VirtFilePrivate(buf, + header->uncompressSize); + return file; + } + return nullptr; + } + + VirtFile *openWrite(const std::string &restrict filename A_UNUSED) + { + return nullptr; + } + + VirtFile *openAppend(const std::string &restrict filename A_UNUSED) + { + return nullptr; + } + + bool setWriteDir(const std::string &restrict newDir A_UNUSED) + { + return false; + } + + bool mkdir(const std::string &restrict dirname A_UNUSED) + { + return false; + } + + bool remove(const std::string &restrict filename A_UNUSED) + { + return false; + } + + void permitLinks(const bool val A_UNUSED) + { + } + + const char *getLastError() + { + return nullptr; + } + + int close(VirtFile *restrict const file) + { + if (file == nullptr) + return 0; + delete file; + return 1; + } + + int64_t read(VirtFile *restrict const file, + void *restrict const buffer, + const uint32_t objSize, + const uint32_t objCount) + { + if (file == nullptr || + objSize == 0 || + objCount == 0) + { + return 0; + } + if (buffer == nullptr) + { + reportAlways("VirtFsZip::read buffer is null"); + return 0; + } + VirtFilePrivate *restrict const priv = file->mPrivate; + const uint32_t pos = priv->mPos; + const uint32_t sz = priv->mSize; + // if outside of buffer, return + if (pos >= sz) + return 0; + // pointer to start for buffer ready to read + const uint8_t *restrict const memPtr = priv->mBuf + pos; + // left buffer size from pos to end + const uint32_t memSize = sz - pos; + // number of objects possible to read + uint32_t memCount = memSize / objSize; + if (memCount == 0) + return 0; + // limit number of possible objects to read to objCount + if (memCount > objCount) + memCount = objCount; + // number of bytes to read from buffer + const uint32_t memEnd = memCount * objSize; + memcpy(buffer, memPtr, memEnd); + priv->mPos += memEnd; + return memCount; + } + + int64_t write(VirtFile *restrict const file A_UNUSED, + const void *restrict const buffer A_UNUSED, + const uint32_t objSize A_UNUSED, + const uint32_t objCount A_UNUSED) + { + return 0; + } + + int64_t fileLength(VirtFile *restrict const file) + { + if (file == nullptr) + return -1; + + return file->mPrivate->mSize; + } + + int64_t tell(VirtFile *restrict const file) + { + if (file == nullptr) + return -1; + + return file->mPrivate->mPos; + } + + int seek(VirtFile *restrict const file, + const uint64_t pos) + { + if (file == nullptr) + return 0; + + if (pos > file->mPrivate->mSize) + return 0; + file->mPrivate->mPos = pos; + return 1; + } + + int eof(VirtFile *restrict const file) + { + if (file == nullptr) + return -1; + + return file->mPrivate->mPos >= file->mPrivate->mSize; + } +} // namespace VirtFsZip diff --git a/src/fs/virtfs/virtfszip.h b/src/fs/virtfs/virtfszip.h new file mode 100644 index 000000000..c1ed7b05c --- /dev/null +++ b/src/fs/virtfs/virtfszip.h @@ -0,0 +1,88 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013-2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef UTILS_VIRTFSZIP_H +#define UTILS_VIRTFSZIP_H + +#include "enums/simpletypes/append.h" +#include "enums/simpletypes/skiperror.h" + +#include "localconsts.h" + +#include +#include + +struct VirtFile; +struct VirtList; +struct VirtFsFuncs; +struct VirtZipEntry; +struct ZipLocalHeader; + +namespace VirtFsZip +{ + VirtZipEntry *searchEntryByArchive(const std::string &restrict + archiveName); + ZipLocalHeader *searchHeaderByName(const std::string &restrict filename); + bool addToSearchPath(std::string newDir, + const Append append); + bool addToSearchPathSilent(std::string newDir, + const Append append); + bool removeFromSearchPath(std::string oldDir); + bool removeFromSearchPathSilent(std::string oldDir); + void init(); + void initFuncs(VirtFsFuncs *restrict const ptr); + void deinit(); + std::vector &getEntries(); + bool exists(std::string name); + VirtList *enumerateFiles(std::string dirName) RETURNS_NONNULL; + VirtList *enumerateFiles(std::string dirName, + VirtList *restrict const list) RETURNS_NONNULL; + bool isDirectory(std::string dirName); + bool isDirectoryInternal(std::string dirName); + bool isSymbolicLink(std::string name); + void freeList(VirtList *restrict const handle); + VirtFile *openRead(std::string filename); + VirtFile *openReadInternal(const std::string &filename); + VirtFile *openWrite(const std::string &restrict filename); + VirtFile *openAppend(const std::string &restrict filename); + bool setWriteDir(const std::string &restrict newDir); + std::string getRealDir(std::string filename); + std::string getRealDirInternal(const std::string &filename); + bool mkdir(const std::string &restrict dirName); + bool remove(const std::string &restrict filename); + void permitLinks(const bool val); + const char *getLastError(); + int64_t read(VirtFile *restrict const handle, + void *restrict const buffer, + const uint32_t objSize, + const uint32_t objCount); + int64_t write(VirtFile *restrict const file, + const void *restrict const buffer, + const uint32_t objSize, + const uint32_t objCount); + int close(VirtFile *restrict const file); + int64_t fileLength(VirtFile *restrict const file); + int64_t tell(VirtFile *restrict const file); + int seek(VirtFile *restrict const file, + const uint64_t pos); + int eof(VirtFile *restrict const file); +} // namespace VirtFsZip + +#endif // UTILS_VIRTFSZIP_H diff --git a/src/fs/virtfs/virtfszip_unittest.cc b/src/fs/virtfs/virtfszip_unittest.cc new file mode 100644 index 000000000..7ac442c78 --- /dev/null +++ b/src/fs/virtfs/virtfszip_unittest.cc @@ -0,0 +1,745 @@ +/* + * The ManaPlus Client + * Copyright (C) 2016-2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "catch.hpp" + +#include "fs/files.h" +#include "fs/virtlist.h" + +#include "fs/virtfs/virtfszip.h" +#include "fs/virtfs/virtzipentry.h" + +#include "utils/checkutils.h" +#include "utils/delete2.h" + +#include "debug.h" + +TEST_CASE("VirtFsZip getEntries") +{ + VirtFsZip::init(); + REQUIRE(VirtFsZip::getEntries().empty()); + REQUIRE(VirtFsZip::searchEntryByArchive("test.zip") == nullptr); + VirtFsZip::deinit(); +} + +TEST_CASE("VirtFsZip addToSearchPath") +{ + VirtFsZip::init(); + logger = new Logger(); + std::string name("data/test/test.zip"); + std::string prefix("data/test/"); + std::vector headers; + if (Files::existsLocal(name) == false) + prefix = "../" + prefix; + + SECTION("simple 1") + { + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "/test.zip", + Append_false)); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "test.zip") != nullptr); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "file2.zip") == nullptr); + REQUIRE(VirtFsZip::getEntries().size() == 1); + REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == + prefix + "test.zip"); + } + + SECTION("simple 2") + { + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "\\test.zip", + Append_true)); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "test.zip") != nullptr); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "file2.zip") == nullptr); + REQUIRE(VirtFsZip::getEntries().size() == 1); + REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == + prefix + "test.zip"); + } + + SECTION("simple 3") + { + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test.zip", + Append_false)); + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", + Append_false)); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "test.zip") != nullptr); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "test2.zip") != nullptr); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "test3.zip") == nullptr); + REQUIRE(VirtFsZip::getEntries().size() == 2); + REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == + prefix + "test2.zip"); + REQUIRE(VirtFsZip::getEntries()[1]->mArchiveName == + prefix + "test.zip"); + } + + SECTION("simple 4") + { + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test.zip", + Append_true)); + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", + Append_true)); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "test.zip") != nullptr); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "test2.zip") != nullptr); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "test3.zip") == nullptr); + REQUIRE(VirtFsZip::getEntries().size() == 2); + REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == + prefix + "test.zip"); + REQUIRE(VirtFsZip::getEntries()[1]->mArchiveName == + prefix + "test2.zip"); + } + + SECTION("simple 5") + { + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test.zip", + Append_true)); + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", + Append_true)); + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test3.zip", + Append_true)); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "test.zip") != nullptr); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "test2.zip") != nullptr); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "test3.zip") != nullptr); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "test4.zip") == nullptr); + REQUIRE(VirtFsZip::getEntries().size() == 3); + REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == + prefix + "test.zip"); + REQUIRE(VirtFsZip::getEntries()[1]->mArchiveName == + prefix + "test2.zip"); + REQUIRE(VirtFsZip::getEntries()[2]->mArchiveName == + prefix + "test3.zip"); + } + + SECTION("simple 6") + { + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test.zip", + Append_true)); + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", + Append_true)); + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test3.zip", + Append_false)); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "test.zip") != nullptr); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "test2.zip") != nullptr); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "test3.zip") != nullptr); + REQUIRE(VirtFsZip::searchEntryByArchive( + prefix + "test4.zip") == nullptr); + REQUIRE(VirtFsZip::getEntries().size() == 3); + REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == + prefix + "test3.zip"); + REQUIRE(VirtFsZip::getEntries()[1]->mArchiveName == + prefix + "test.zip"); + REQUIRE(VirtFsZip::getEntries()[2]->mArchiveName == + prefix + "test2.zip"); + } + + VirtFsZip::deinit(); + delete2(logger); +} + +TEST_CASE("VirtFsZip removeFromSearchPath") +{ + VirtFsZip::init(); + logger = new Logger(); + std::string name("data/test/test.zip"); + std::string prefix("data/test/"); + std::vector headers; + if (Files::existsLocal(name) == false) + prefix = "../" + prefix; + + SECTION("simple 1") + { + REQUIRE_THROWS(VirtFsZip::removeFromSearchPath( + prefix + "test123.zip")); + } + + SECTION("simple 2") + { + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test.zip", + Append_true)); + REQUIRE_THROWS(VirtFsZip::removeFromSearchPath(prefix + "test2.zip")); + REQUIRE(VirtFsZip::removeFromSearchPath(prefix + "test.zip")); + } + + SECTION("simple 3") + { + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test.zip", + Append_true)); + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", + Append_true)); + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test3.zip", + Append_false)); + REQUIRE(VirtFsZip::getEntries().size() == 3); + REQUIRE_THROWS(VirtFsZip::removeFromSearchPath(prefix + "test4.zip")); + REQUIRE(VirtFsZip::removeFromSearchPath(prefix + "test.zip")); + REQUIRE(VirtFsZip::getEntries().size() == 2); + REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == + prefix + "test3.zip"); + REQUIRE(VirtFsZip::getEntries()[1]->mArchiveName == + prefix + "test2.zip"); + REQUIRE_THROWS(VirtFsZip::removeFromSearchPath(prefix + "test.zip")); + REQUIRE(VirtFsZip::getEntries().size() == 2); + REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == + prefix + "test3.zip"); + REQUIRE(VirtFsZip::getEntries()[1]->mArchiveName == + prefix + "test2.zip"); + REQUIRE(VirtFsZip::removeFromSearchPath(prefix + "//test2.zip")); + REQUIRE_THROWS(VirtFsZip::removeFromSearchPath(prefix + "test2.zip")); + REQUIRE(VirtFsZip::getEntries().size() == 1); + REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == + prefix + "test3.zip"); + } + + SECTION("simple 4") + { + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "\\test.zip", + Append_true)); + REQUIRE(VirtFsZip::getEntries().size() == 1); + REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == + prefix + "test.zip"); + REQUIRE_THROWS(VirtFsZip::removeFromSearchPath(prefix + "test2.zip")); + REQUIRE(VirtFsZip::removeFromSearchPath(prefix + "\\test.zip")); + REQUIRE(VirtFsZip::getEntries().size() == 0); + REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test.zip", + Append_true)); + REQUIRE(VirtFsZip::getEntries().size() == 1); + REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == + prefix + "test.zip"); + } + + VirtFsZip::deinit(); + delete2(logger); +} + +TEST_CASE("VirtFsZip exists") +{ + VirtFsZip::init(); + logger = new Logger(); + VirtFsZip::addToSearchPathSilent("data\\test/test2.zip", + Append_false); + VirtFsZip::addToSearchPathSilent("../data\\test/test2.zip", + Append_false); + + REQUIRE(VirtFsZip::exists("dir2//units.xml") == true); + REQUIRE(VirtFsZip::exists("test/units123.xml") == false); + REQUIRE(VirtFsZip::exists("tesQ/units.xml") == false); + REQUIRE(VirtFsZip::exists("units1.xml") == false); + REQUIRE(VirtFsZip::exists("dir/hide.png") == true); + REQUIRE(VirtFsZip::exists("dir/brimmedhat.png") == false); + + VirtFsZip::addToSearchPathSilent("data/test/test.zip", + Append_false); + VirtFsZip::addToSearchPathSilent("../data/test/test.zip", + Append_false); + + REQUIRE(VirtFsZip::exists("dir2\\units.xml") == true); + REQUIRE(VirtFsZip::exists("test/units123.xml") == false); + REQUIRE(VirtFsZip::exists("tesQ/units.xml") == false); + REQUIRE(VirtFsZip::exists("units1.xml") == false); + REQUIRE(VirtFsZip::exists("dir/hide.png") == true); + REQUIRE(VirtFsZip::exists("dir/brimmedhat.png") == true); + + VirtFsZip::removeFromSearchPathSilent("data/test/test2.zip"); + VirtFsZip::removeFromSearchPathSilent("../data/test/test2.zip"); + + REQUIRE(VirtFsZip::exists("dir2//units.xml") == false); + REQUIRE(VirtFsZip::exists("test/units123.xml") == false); + REQUIRE(VirtFsZip::exists("tesQ/units.xml") == false); + REQUIRE(VirtFsZip::exists("units1.xml") == false); + REQUIRE(VirtFsZip::exists("dir/\\/hide.png") == true); + REQUIRE(VirtFsZip::exists("dir/brimmedhat.png") == true); + + REQUIRE_THROWS(VirtFsZip::exists("test/../units.xml")); + + VirtFsZip::deinit(); + delete2(logger); +} + +TEST_CASE("VirtFsZip getRealDir") +{ + VirtFsZip::init(); + logger = new Logger(); + std::string name("data/test/test.zip"); + std::string prefix("data/test/"); + if (Files::existsLocal(name) == false) + prefix = "../" + prefix; + VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", + Append_false); + + REQUIRE(VirtFsZip::getRealDir(".") == ""); + REQUIRE(VirtFsZip::getRealDir("..") == ""); + REQUIRE(VirtFsZip::getRealDir("test.txt") == prefix + "test2.zip"); + REQUIRE(VirtFsZip::getRealDir("dir\\dye.png") == + prefix + "test2.zip"); + REQUIRE(VirtFsZip::getRealDir("zzz") == ""); + + VirtFsZip::addToSearchPathSilent(prefix + "test.zip", + Append_false); + REQUIRE(VirtFsZip::getRealDir("dir//dye.png") == + prefix + "test2.zip"); + REQUIRE(VirtFsZip::getRealDir("dir///hide.png") == + prefix + "test.zip"); + REQUIRE(VirtFsZip::getRealDir("dir\\\\brimmedhat.png") == + prefix + "test.zip"); + REQUIRE(VirtFsZip::getRealDir("zzz") == ""); + + VirtFsZip::removeFromSearchPathSilent(prefix + "test.zip"); + + REQUIRE(VirtFsZip::getRealDir("dir/brimmedhat.png") == ""); + REQUIRE(VirtFsZip::getRealDir("test.txt") == prefix + "test2.zip"); + REQUIRE(VirtFsZip::getRealDir("dir//dye.png") == + prefix + "test2.zip"); + REQUIRE(VirtFsZip::getRealDir("zzz") == ""); + + VirtFsZip::removeFromSearchPathSilent(prefix + "test2.zip"); + VirtFsZip::deinit(); + delete2(logger); +} + +static bool inList(VirtList *list, + const std::string &name) +{ + FOR_EACH (StringVectCIter, it, list->names) + { + if (*it == name) + return true; + } + return false; +} + +TEST_CASE("VirtFsZip enumerateFiles1") +{ + VirtFsZip::init(); + logger = new Logger; + std::string name("data/test/test.zip"); + std::string prefix("data\\test/"); + if (Files::existsLocal(name) == false) + prefix = "../" + prefix; + + VirtFsZip::addToSearchPathSilent(prefix + "test.zip", + Append_false); + + VirtList *list = nullptr; + + list = VirtFsZip::enumerateFiles("dir"); + REQUIRE(list->names.size() == 2); + REQUIRE(inList(list, "brimmedhat.png")); + REQUIRE(inList(list, "hide.png")); + VirtFsZip::freeList(list); + + VirtFsZip::removeFromSearchPathSilent(prefix + "test.zip"); + VirtFsZip::deinit(); + delete2(logger); +} + +TEST_CASE("VirtFsZip enumerateFiles2") +{ + VirtFsZip::init(); + logger = new Logger; + std::string name("data/test/test.zip"); + std::string prefix("data//test/"); + if (Files::existsLocal(name) == false) + prefix = "../" + prefix; + + VirtFsZip::addToSearchPathSilent(prefix + "test.zip", + Append_true); + VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", + Append_true); + + VirtList *list = nullptr; + + list = VirtFsZip::enumerateFiles("dir"); + FOR_EACH (StringVectCIter, it, list->names) + { + logger->log("filename: " + *it); + } + + REQUIRE(list->names.size() == 5); + REQUIRE(inList(list, "brimmedhat.png")); + REQUIRE(inList(list, "hide.png")); + REQUIRE(inList(list, "1")); + REQUIRE(inList(list, "gpl")); + REQUIRE(inList(list, "dye.png")); + VirtFsZip::freeList(list); + + VirtFsZip::removeFromSearchPathSilent(prefix + "test.zip"); + VirtFsZip::removeFromSearchPathSilent(prefix + "test2.zip"); + VirtFsZip::deinit(); + delete2(logger); +} + +TEST_CASE("VirtFsZip enumerateFiles3") +{ + VirtFsZip::init(); + logger = new Logger; + std::string name("data/test/test.zip"); + std::string prefix("data\\test/"); + if (Files::existsLocal(name) == false) + prefix = "../" + prefix; + + VirtFsZip::addToSearchPathSilent(prefix + "test.zip", + Append_false); + + VirtList *list = nullptr; + + list = VirtFsZip::enumerateFiles("/"); + REQUIRE(list->names.size() == 1); + REQUIRE(inList(list, "dir")); + VirtFsZip::freeList(list); + + VirtFsZip::removeFromSearchPathSilent(prefix + "test.zip"); + VirtFsZip::deinit(); + delete2(logger); +} + +TEST_CASE("VirtFsZip enumerateFiles4") +{ + VirtFsZip::init(); + logger = new Logger; + std::string name("data/test/test.zip"); + std::string prefix("data\\test/"); + if (Files::existsLocal(name) == false) + prefix = "../" + prefix; + + VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", + Append_false); + + VirtList *list = nullptr; + + list = VirtFsZip::enumerateFiles("/"); + REQUIRE(list->names.size() == 4); + REQUIRE(inList(list, "dir")); + REQUIRE(inList(list, "dir2")); + REQUIRE(inList(list, "test.txt")); + REQUIRE(inList(list, "units.xml")); + VirtFsZip::freeList(list); + + VirtFsZip::removeFromSearchPathSilent(prefix + "test2.zip"); + VirtFsZip::deinit(); + delete2(logger); +} + +TEST_CASE("VirtFsZip isDirectory") +{ + VirtFsZip::init(); + logger = new Logger(); + std::string name("data/test/test.zip"); + std::string prefix("data/test/"); + if (Files::existsLocal(name) == false) + prefix = "../" + prefix; + + VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", + Append_false); + + REQUIRE(VirtFsZip::isDirectory("dir2/units.xml") == false); + REQUIRE(VirtFsZip::isDirectory("dir2/units.xml/") == false); + REQUIRE(VirtFsZip::isDirectory("dir2//units.xml") == false); + REQUIRE(VirtFsZip::isDirectory("dir2/units123.xml") == false); + REQUIRE(VirtFsZip::isDirectory("dir2//units123.xml") == false); + REQUIRE(VirtFsZip::isDirectory("tesQ/units.xml") == false); + REQUIRE(VirtFsZip::isDirectory("tesQ//units.xml") == false); + REQUIRE(VirtFsZip::isDirectory("units.xml") == false); + REQUIRE(VirtFsZip::isDirectory("dir") == true); + REQUIRE(VirtFsZip::isDirectory("dir2/") == true); + REQUIRE(VirtFsZip::isDirectory("dir2//") == true); + REQUIRE(VirtFsZip::isDirectory("dir/1") == true); + REQUIRE(VirtFsZip::isDirectory("dir//1") == true); + REQUIRE(VirtFsZip::isDirectory("dir\\1/") == true); + REQUIRE(VirtFsZip::isDirectory("dir/1") == true); + REQUIRE(VirtFsZip::isDirectory("dir/1/zzz") == false); + REQUIRE(VirtFsZip::isDirectory("test/dir1\\") == false); + REQUIRE(VirtFsZip::isDirectory("testQ") == false); + REQUIRE(VirtFsZip::isDirectory("testQ/") == false); + REQUIRE(VirtFsZip::isDirectory("testQ//") == false); + + VirtFsZip::addToSearchPathSilent(prefix + "test.zip", + Append_false); + + REQUIRE(VirtFsZip::isDirectory("dir2/units.xml") == false); + REQUIRE(VirtFsZip::isDirectory("dir2/units.xml/") == false); + REQUIRE(VirtFsZip::isDirectory("dir2\\units.xml") == false); + REQUIRE(VirtFsZip::isDirectory("dir2/units123.xml") == false); + REQUIRE(VirtFsZip::isDirectory("dir2//units123.xml") == false); + REQUIRE(VirtFsZip::isDirectory("tesQ/units.xml") == false); + REQUIRE(VirtFsZip::isDirectory("tesQ//units.xml") == false); + REQUIRE(VirtFsZip::isDirectory("units.xml") == false); + REQUIRE(VirtFsZip::isDirectory("dir") == true); + REQUIRE(VirtFsZip::isDirectory("dir2/") == true); + REQUIRE(VirtFsZip::isDirectory("dir2\\") == true); + REQUIRE(VirtFsZip::isDirectory("dir/1") == true); + REQUIRE(VirtFsZip::isDirectory("dir//1") == true); + REQUIRE(VirtFsZip::isDirectory("dir//1/") == true); + REQUIRE(VirtFsZip::isDirectory("dir/1") == true); + REQUIRE(VirtFsZip::isDirectory("dir/1/zzz") == false); + REQUIRE(VirtFsZip::isDirectory("test/dir1//") == false); + REQUIRE(VirtFsZip::isDirectory("testQ") == false); + REQUIRE(VirtFsZip::isDirectory("testQ/") == false); + REQUIRE(VirtFsZip::isDirectory("testQ//") == false); + + VirtFsZip::removeFromSearchPathSilent(prefix + "test2.zip"); + + REQUIRE(VirtFsZip::isDirectory("dir2/units.xml") == false); + REQUIRE(VirtFsZip::isDirectory("dir2/units.xml/") == false); + REQUIRE(VirtFsZip::isDirectory("dir2//units.xml") == false); + REQUIRE(VirtFsZip::isDirectory("dir2/units123.xml") == false); + REQUIRE(VirtFsZip::isDirectory("dir2//units123.xml") == false); + REQUIRE(VirtFsZip::isDirectory("tesQ/units.xml") == false); + REQUIRE(VirtFsZip::isDirectory("tesQ//units.xml") == false); + REQUIRE(VirtFsZip::isDirectory("units.xml") == false); + REQUIRE(VirtFsZip::isDirectory("dir") == true); + REQUIRE(VirtFsZip::isDirectory("dir2/") == false); + REQUIRE(VirtFsZip::isDirectory("dir2//") == false); + REQUIRE(VirtFsZip::isDirectory("dir/1") == false); + REQUIRE(VirtFsZip::isDirectory("dir\\1") == false); + REQUIRE(VirtFsZip::isDirectory("dir//1/") == false); + REQUIRE(VirtFsZip::isDirectory("dir/1") == false); + REQUIRE(VirtFsZip::isDirectory("dir/1/zzz") == false); + REQUIRE(VirtFsZip::isDirectory("test/dir1//") == false); + REQUIRE(VirtFsZip::isDirectory("testQ") == false); + REQUIRE(VirtFsZip::isDirectory("testQ/") == false); + REQUIRE(VirtFsZip::isDirectory("testQ//") == false); + + VirtFsZip::removeFromSearchPathSilent(prefix + "test.zip"); + VirtFsZip::deinit(); + delete2(logger); +} + +TEST_CASE("VirtFsZip openRead") +{ + VirtFsZip::init(); + logger = new Logger(); + std::string name("data/test/test.zip"); + std::string prefix("data/test/"); + if (Files::existsLocal(name) == false) + prefix = "../" + prefix; + + VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", + Append_false); + + VirtFile *file = nullptr; + + file = VirtFsZip::openRead("dir2/units.xml"); + REQUIRE(file != nullptr); + VirtFsZip::close(file); + file = VirtFsZip::openRead("dir2\\units.xml"); + REQUIRE(file != nullptr); + VirtFsZip::close(file); + file = VirtFsZip::openRead("dir2/units123.xml"); + REQUIRE(file == nullptr); + file = VirtFsZip::openRead("tesQ/units.xml"); + REQUIRE(file == nullptr); + file = VirtFsZip::openRead("units.xml1"); + REQUIRE(file == nullptr); + file = VirtFsZip::openRead("testQ"); + REQUIRE(file == nullptr); + file = VirtFsZip::openRead("dir/brimmedhat.png"); + REQUIRE(file == nullptr); + file = VirtFsZip::openRead("dir//brimmedhat.png"); + REQUIRE(file == nullptr); + + VirtFsZip::addToSearchPathSilent(prefix + "test.zip", + Append_false); + + file = VirtFsZip::openRead("dir2/units.xml"); + REQUIRE(file != nullptr); + VirtFsZip::close(file); + file = VirtFsZip::openRead("dir2//units.xml"); + REQUIRE(file != nullptr); + VirtFsZip::close(file); + file = VirtFsZip::openRead("dir2/units123.xml"); + REQUIRE(file == nullptr); + file = VirtFsZip::openRead("tesQ/units.xml"); + REQUIRE(file == nullptr); + file = VirtFsZip::openRead("units.xml1"); + REQUIRE(file == nullptr); + file = VirtFsZip::openRead("testQ"); + REQUIRE(file == nullptr); + file = VirtFsZip::openRead("dir/brimmedhat.png"); + REQUIRE(file != nullptr); + VirtFsZip::close(file); + + VirtFsZip::removeFromSearchPathSilent(prefix + "test.zip"); + + file = VirtFsZip::openRead("dir2/units.xml"); + REQUIRE(file != nullptr); + VirtFsZip::close(file); + file = VirtFsZip::openRead("dir2\\/\\units.xml"); + REQUIRE(file != nullptr); + VirtFsZip::close(file); + file = VirtFsZip::openRead("dir2/units123.xml"); + REQUIRE(file == nullptr); + file = VirtFsZip::openRead("tesQ/units.xml"); + REQUIRE(file == nullptr); + file = VirtFsZip::openRead("units.xml1"); + REQUIRE(file == nullptr); + file = VirtFsZip::openRead("testQ"); + REQUIRE(file == nullptr); + file = VirtFsZip::openRead("dir/brimmedhat.png"); + REQUIRE(file == nullptr); + + VirtFsZip::removeFromSearchPathSilent(prefix + "test2.zip"); + + VirtFsZip::deinit(); + delete2(logger); +} + +TEST_CASE("VirtFsZip read") +{ + VirtFsZip::init(); + logger = new Logger(); + std::string name("data/test/test.zip"); + std::string prefix("data/test/"); + if (Files::existsLocal(name) == false) + prefix = "../" + prefix; + + VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", + Append_false); + VirtFile *file = nullptr; + void *restrict buffer = nullptr; + + SECTION("test 1") + { + file = VirtFsZip::openRead("dir2//test.txt"); + REQUIRE(file != nullptr); + REQUIRE(VirtFsZip::fileLength(file) == 23); + const int fileSize = VirtFsZip::fileLength(file); + + buffer = calloc(fileSize + 1, 1); + REQUIRE(VirtFsZip::read(file, buffer, 1, fileSize) == fileSize); + REQUIRE(strcmp(static_cast(buffer), + "test line 1\ntest line 2") == 0); + REQUIRE(VirtFsZip::tell(file) == fileSize); + REQUIRE(VirtFsZip::eof(file) == true); + } + + SECTION("test 2") + { + file = VirtFsZip::openRead("dir2\\/test.txt"); + REQUIRE(file != nullptr); + REQUIRE(VirtFsZip::fileLength(file) == 23); + const int fileSize = VirtFsZip::fileLength(file); + + buffer = calloc(fileSize + 1, 1); + REQUIRE(VirtFsZip::seek(file, 12) != 0); + REQUIRE(VirtFsZip::eof(file) == false); + REQUIRE(VirtFsZip::tell(file) == 12); + REQUIRE(VirtFsZip::read(file, buffer, 1, 11) == 11); + REQUIRE(strcmp(static_cast(buffer), + "test line 2") == 0); + REQUIRE(VirtFsZip::eof(file) == true); + } + + SECTION("test 3") + { + file = VirtFsZip::openRead("dir2//test.txt"); + REQUIRE(file != nullptr); + const int fileSize = VirtFsZip::fileLength(file); + + buffer = calloc(fileSize + 1, 1); + for (int f = 0; f < fileSize; f ++) + { + REQUIRE(VirtFsZip::seek(file, f) != 0); + REQUIRE(VirtFsZip::eof(file) == false); + REQUIRE(VirtFsZip::tell(file) == f); + } + } + + SECTION("test 4") + { + file = VirtFsZip::openRead("dir2/test.txt"); + REQUIRE(file != nullptr); + const int fileSize = VirtFsZip::fileLength(file); + const char *restrict const str = "test line 1\ntest line 2"; + buffer = calloc(fileSize + 1, 1); + for (int f = 0; f < fileSize - 1; f ++) + { + REQUIRE(VirtFsZip::read(file, buffer, 1, 1) == 1); + REQUIRE(static_cast(buffer)[0] == str[f]); + REQUIRE(VirtFsZip::eof(file) == false); + REQUIRE(VirtFsZip::tell(file) == f + 1); + } + REQUIRE(VirtFsZip::read(file, buffer, 1, 1) == 1); + REQUIRE(static_cast(buffer)[0] == str[22]); + REQUIRE(VirtFsZip::eof(file) == true); + REQUIRE(VirtFsZip::tell(file) == fileSize); + } + + SECTION("test 5") + { + file = VirtFsZip::openRead("dir2\\\\test.txt"); + REQUIRE(file != nullptr); + const int fileSize = VirtFsZip::fileLength(file); + const char *restrict const str = "test line 1\ntest line 2"; + buffer = calloc(fileSize + 1, 1); + for (int f = 0; f < fileSize - 1; f += 2) + { + REQUIRE(VirtFsZip::read(file, buffer, 2, 1) == 1); + REQUIRE(static_cast(buffer)[0] == str[f]); + REQUIRE(static_cast(buffer)[1] == str[f + 1]); + REQUIRE(VirtFsZip::eof(file) == false); + REQUIRE(VirtFsZip::tell(file) == f + 2); + } + REQUIRE(VirtFsZip::eof(file) == false); + REQUIRE(VirtFsZip::tell(file) == 22); + REQUIRE(VirtFsZip::read(file, buffer, 2, 1) == 0); + REQUIRE(VirtFsZip::eof(file) == false); + } + + SECTION("test 6") + { + file = VirtFsZip::openRead("dir2//test.txt"); + REQUIRE(file != nullptr); + const int fileSize = VirtFsZip::fileLength(file); + const char *restrict const str = "test line 1\ntest line 2"; + buffer = calloc(fileSize + 1, 1); + for (int f = 0; f < fileSize - 1; f += 2) + { + REQUIRE(VirtFsZip::read(file, buffer, 1, 2) == 2); + REQUIRE(static_cast(buffer)[0] == str[f]); + REQUIRE(static_cast(buffer)[1] == str[f + 1]); + REQUIRE(VirtFsZip::eof(file) == false); + REQUIRE(VirtFsZip::tell(file) == f + 2); + } + REQUIRE(VirtFsZip::eof(file) == false); + REQUIRE(VirtFsZip::tell(file) == 22); + REQUIRE(VirtFsZip::read(file, buffer, 1, 2) == 1); + REQUIRE(static_cast(buffer)[0] == str[22]); + REQUIRE(VirtFsZip::eof(file) == true); + } + + VirtFsZip::close(file); + free(buffer); + VirtFsZip::removeFromSearchPathSilent(prefix + "test2.zip"); + VirtFsZip::deinit(); + delete2(logger); +} diff --git a/src/fs/virtfs/virtzipentry.cpp b/src/fs/virtfs/virtzipentry.cpp new file mode 100644 index 000000000..bed925d2f --- /dev/null +++ b/src/fs/virtfs/virtzipentry.cpp @@ -0,0 +1,38 @@ +/* + * The ManaPlus Client + * Copyright (C) 2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "fs/virtfs/virtzipentry.h" + +#include "fs/virtfs/ziplocalheader.h" + +#include "utils/dtor.h" + +#include "debug.h" + +VirtZipEntry::VirtZipEntry(const std::string &restrict archiveName) : + mArchiveName(archiveName), + mHeaders() +{ +} + +VirtZipEntry::~VirtZipEntry() +{ + delete_all(mHeaders); +} diff --git a/src/fs/virtfs/virtzipentry.h b/src/fs/virtfs/virtzipentry.h new file mode 100644 index 000000000..fac36cc2d --- /dev/null +++ b/src/fs/virtfs/virtzipentry.h @@ -0,0 +1,45 @@ +/* + * The ManaPlus Client + * Copyright (C) 2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef UTILS_VIRTZIPENTRY_H +#define UTILS_VIRTZIPENTRY_H + +#include +#include + +#include "localconsts.h" + +struct ZipLocalHeader; + +struct VirtZipEntry final +{ + explicit VirtZipEntry(const std::string &restrict archiveName); + + A_DELETE_COPY(VirtZipEntry) + + ~VirtZipEntry(); + + std::string mArchiveName; + + std::vector mHeaders; + std::vector mDirs; +}; + +#endif // UTILS_VIRTZIPENTRY_H diff --git a/src/fs/virtfs/zip.cpp b/src/fs/virtfs/zip.cpp new file mode 100644 index 000000000..f27dd05d0 --- /dev/null +++ b/src/fs/virtfs/zip.cpp @@ -0,0 +1,291 @@ +/* + * The ManaPlus Client + * Copyright (C) 2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "fs/virtfs/zip.h" + +#include "fs/paths.h" + +#include "fs/virtfs/virtzipentry.h" +#include "fs/virtfs/ziplocalheader.h" + +#include "utils/checkutils.h" +#include "utils/stringutils.h" + +#include +#include +#include + +#include "debug.h" + +#define readVal(val, sz, msg) \ + cnt = fread(static_cast(val), 1, sz, arcFile); \ + if (cnt != sz) \ + { \ + reportAlways("Error reading " msg " in file %s", \ + archiveName.c_str()); \ + delete header; \ + delete [] buf; \ + fclose(arcFile); \ + return false; \ + } \ + +namespace Zip +{ + bool readArchiveInfo(VirtZipEntry *const entry) + { + if (entry == nullptr) + { + reportAlways("Entry is null."); + return false; + } + const std::string archiveName = entry->mArchiveName; + std::vector &restrict headers = entry->mHeaders; + std::vector &restrict dirs = entry->mDirs; + FILE *restrict const arcFile = fopen(archiveName.c_str(), + "r"); + if (arcFile == nullptr) + { + reportAlways("Can't open zip file %s", + archiveName.c_str()); + return false; + } + size_t cnt = 0U; + uint8_t *const buf = new uint8_t[65535 + 10]; + uint16_t val16 = 0U; + uint16_t method = 0U; + ZipLocalHeader *header = nullptr; + + logger->log("Read archive: %s", archiveName.c_str()); + // format source https://en.wikipedia.org/wiki/Zip_%28file_format%29 + while (feof(arcFile) == 0) + { + // file header pointer on 0 + // read file header signature + readVal(buf, 4, "zip file header"); // + 4 + // pointer on 4 + + if (buf[0] == 0x50 && + buf[1] == 0x4B && + buf[2] == 0x03 && + buf[3] == 0x04) + { // local file header + header = new ZipLocalHeader; + header->zipEntry = entry; + // skip useless fields + fseek(arcFile, 4, SEEK_CUR); // + 4 + // file header pointer on 8 + // +++ need add endian specific decoding for method + readVal(&method, 2, "compression method") // + 2 + header->compressed = (method != 0); + // file header pointer on 10 + fseek(arcFile, 8, SEEK_CUR); // + 8 + // file header pointer on 18 + readVal(&header->compressSize, 4, + "zip compressed size") // + 4 + // file header pointer on 22 + // +++ need add endian specific decoding for val32 + readVal(&header->uncompressSize, 4, + "zip uncompressed size") // + 4 + // file header pointer on 26 + // +++ need add endian specific decoding for val32 + readVal(&val16, 2, "file name length") // + 2 + // file header pointer on 28 + const uint32_t fileNameLen = CAST_U32(val16); + if (fileNameLen > 1000) + { + reportAlways("Error too long file name in file %s", + archiveName.c_str()); + delete header; + delete [] buf; + fclose(arcFile); + return false; + } + readVal(&val16, 2, "extra field length") // + 2 + // file header pointer on 30 + const uint32_t extraFieldLen = CAST_U32(val16); + readVal(buf, fileNameLen, "file name"); + // file header pointer on 30 + fileNameLen + buf[fileNameLen] = 0; + header->fileName = std::string( + reinterpret_cast(buf)); + prepareFsPath(header->fileName); + header->dataOffset = ftell(arcFile) + extraFieldLen; + fseek(arcFile, extraFieldLen + header->compressSize, SEEK_CUR); + // pointer on 30 + fileNameLen + extraFieldLen + compressSize + if (findLast(header->fileName, "/") == false) + { + headers.push_back(header); + logger->log(" file name: %s", + header->fileName.c_str()); + logger->log(" compression method: %u", + CAST_U32(method)); + logger->log(" compressed size: %u", + header->compressSize); + logger->log(" uncompressed size: %u", + header->uncompressSize); + } + else + { + dirs.push_back(header->fileName); + delete header; + } + } + else if (buf[0] == 0x50 && + buf[1] == 0x4B && + buf[2] == 0x01 && + buf[3] == 0x02) + { // central directory file header + // !!! This is quick way for read zip archives. !!! + // !!! It ignore modified files in archive. !!! + // ignoring central directory entries + break; + } + else if (buf[0] == 0x50 && + buf[1] == 0x4B && + buf[2] == 0x05 && + buf[3] == 0x06) + { // end of central directory + // !!! This is quick way for read zip archives. !!! + // !!! It ignore modified files in archive. !!! + // ignoring end of central directory + break; + } + else + { + reportAlways("Error in header signature (0x%02x%02x%02x%02x)" + " in file %s", + buf[0], + buf[1], + buf[2], + buf[3], + archiveName.c_str()); + delete [] buf; + fclose(arcFile); + return false; + } + } + delete [] buf; + fclose(arcFile); + return true; + } + + void reportZlibError(const std::string &text, + const int err) + { + reportAlways("Zlib error: '%s' in %s", + text.c_str(), + getZlibError(err).c_str()); + } + + std::string getZlibError(const int err) + { + switch (err) + { + case Z_OK: + return std::string(); + default: + return "unknown zlib error"; + } + } + + uint8_t *readCompressedFile(const ZipLocalHeader *restrict const header) + { + if (header == nullptr) + { + reportAlways("Zip::readCompressedFile: header is null"); + return nullptr; + } + FILE *restrict const arcFile = fopen( + header->zipEntry->mArchiveName.c_str(), + "r"); + if (arcFile == nullptr) + { + reportAlways("Can't open zip file %s", + header->zipEntry->mArchiveName.c_str()); + return nullptr; + } + + fseek(arcFile, header->dataOffset, SEEK_SET); + const uint32_t compressSize = header->compressSize; + uint8_t *const buf = new uint8_t[compressSize]; + if (fread(static_cast(buf), 1, compressSize, arcFile) != + compressSize) + { + reportAlways("Read zip compressed file error from archive: %s", + header->zipEntry->mArchiveName.c_str()); + fclose(arcFile); + delete [] buf; + return nullptr; + } + fclose(arcFile); + return buf; + } + + uint8_t *readFile(const ZipLocalHeader *restrict const header) + { + if (header == nullptr) + { + reportAlways("Open zip file error. header is null."); + return nullptr; + } + uint8_t *restrict const in = readCompressedFile(header); + if (in == nullptr) + return nullptr; + if (header->compressed == false) + return in; // return as is if data not compressed + const size_t outSize = header->uncompressSize; + uint8_t *restrict const out = new uint8_t[outSize]; + if (outSize == 0) + return out; + + z_stream strm; + strm.zalloc = nullptr; + strm.zfree = nullptr; + strm.opaque = nullptr; + strm.next_in = in; + strm.avail_in = header->compressSize; + strm.next_out = out; + strm.avail_out = outSize; + + int ret = inflateInit2(&strm, -MAX_WBITS); + if (ret != Z_OK) + { + reportZlibError(header->zipEntry->mArchiveName, ret); + delete [] in; + delete [] out; + return nullptr; + } + ret = inflate(&strm, Z_FINISH); +// ret = inflate(&strm, Z_SYNC_FLUSH); + if (ret != Z_OK && + ret != Z_STREAM_END) + { + reportZlibError("file decompression error", + ret); + inflateEnd(&strm); + delete [] in; + delete [] out; + return nullptr; + } + inflateEnd(&strm); + delete [] in; + return out; + } +} // namespace Zip diff --git a/src/fs/virtfs/zip.h b/src/fs/virtfs/zip.h new file mode 100644 index 000000000..412dbcef9 --- /dev/null +++ b/src/fs/virtfs/zip.h @@ -0,0 +1,42 @@ +/* + * The ManaPlus Client + * Copyright (C) 2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef UTILS_ZIP_H +#define UTILS_ZIP_H + +#include "localconsts.h" + +#include +#include + +struct VirtZipEntry; +struct ZipLocalHeader; + +namespace Zip +{ + bool readArchiveInfo(VirtZipEntry *const entry); + std::string getZlibError(const int err); + void reportZlibError(const std::string &text, + const int err); + uint8_t *readCompressedFile(const ZipLocalHeader *restrict const header); + uint8_t *readFile(const ZipLocalHeader *restrict const header); +} // namespace Zip + +#endif // UTILS_ZIP_H diff --git a/src/fs/virtfs/zip_unittest.cc b/src/fs/virtfs/zip_unittest.cc new file mode 100644 index 000000000..7ac74f66b --- /dev/null +++ b/src/fs/virtfs/zip_unittest.cc @@ -0,0 +1,280 @@ +/* + * The ManaPlus Client + * Copyright (C) 2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "catch.hpp" + +#include "logger.h" + +#include "fs/files.h" + +#include "fs/virtfs/virtzipentry.h" +#include "fs/virtfs/zip.h" +#include "fs/virtfs/ziplocalheader.h" + +#include "utils/delete2.h" + +#include "debug.h" + +TEST_CASE("Zip readArchiveInfo") +{ + logger = new Logger(); + std::string name("data/test/test.zip"); + std::string prefix; + if (Files::existsLocal(name) == false) + prefix = "../"; + + SECTION("test.zip") + { + name = prefix + "data/test/test.zip"; + + VirtZipEntry *const entry = new VirtZipEntry(name); + std::vector &headers = entry->mHeaders; + + REQUIRE(Zip::readArchiveInfo(entry)); + REQUIRE(headers.size() == 2); + REQUIRE(entry->mArchiveName == name); + REQUIRE(headers[0]->fileName == "dir/hide.png"); + REQUIRE(headers[0]->compressSize == 365); + REQUIRE(headers[0]->uncompressSize == 368); + REQUIRE(headers[1]->fileName == "dir/brimmedhat.png"); + REQUIRE(headers[1]->compressSize == 1959); + REQUIRE(headers[1]->uncompressSize == 1959); + + delete entry; + } + + SECTION("test2.zip") + { + name = prefix + "data/test/test2.zip"; + + VirtZipEntry *const entry = new VirtZipEntry(name); + std::vector &headers = entry->mHeaders; + + REQUIRE(Zip::readArchiveInfo(entry)); + REQUIRE(headers.size() == 11); + REQUIRE(entry->mArchiveName == name); + REQUIRE(headers[0]->fileName == "test.txt"); + REQUIRE(headers[0]->compressSize == 17); + REQUIRE(headers[0]->uncompressSize == 23); + + REQUIRE(headers[1]->fileName == "dir2/hide.png"); + REQUIRE(headers[1]->compressSize == 365); + REQUIRE(headers[1]->uncompressSize == 368); + + REQUIRE(headers[2]->fileName == "dir2/test.txt"); + REQUIRE(headers[2]->compressSize == 17); + REQUIRE(headers[2]->uncompressSize == 23); + + REQUIRE(headers[3]->fileName == "dir2/paths.xml"); + REQUIRE(headers[3]->compressSize == 154); + REQUIRE(headers[3]->uncompressSize == 185); + + REQUIRE(headers[4]->fileName == "dir2/units.xml"); + REQUIRE(headers[4]->compressSize == 202); + REQUIRE(headers[4]->uncompressSize == 306); + + REQUIRE(headers[5]->fileName == "dir/hide.png"); + REQUIRE(headers[5]->compressSize == 365); + REQUIRE(headers[5]->uncompressSize == 368); + + REQUIRE(headers[6]->fileName == "dir/1/test.txt"); + REQUIRE(headers[6]->compressSize == 17); + REQUIRE(headers[6]->uncompressSize == 23); + + REQUIRE(headers[7]->fileName == "dir/1/file1.txt"); + REQUIRE(headers[7]->compressSize == 17); + REQUIRE(headers[7]->uncompressSize == 23); + + REQUIRE(headers[8]->fileName == "dir/gpl/palette.gpl"); + REQUIRE(headers[8]->compressSize == 128); + REQUIRE(headers[8]->uncompressSize == 213); + + REQUIRE(headers[9]->fileName == "dir/dye.png"); + REQUIRE(headers[9]->compressSize == 794); + REQUIRE(headers[9]->uncompressSize == 794); + + REQUIRE(headers[10]->fileName == "units.xml"); + REQUIRE(headers[10]->compressSize == 202); + REQUIRE(headers[10]->uncompressSize == 306); + + delete entry; + } + + SECTION("test3.zip") + { + name = prefix + "data/test/test3.zip"; + + VirtZipEntry *const entry = new VirtZipEntry(name); + std::vector &headers = entry->mHeaders; + + REQUIRE(Zip::readArchiveInfo(entry)); + REQUIRE(headers.size() == 2); + REQUIRE(entry->mArchiveName == name); + REQUIRE(headers[0]->fileName == "test.txt"); + REQUIRE(headers[0]->compressSize == 17); + REQUIRE(headers[0]->uncompressSize == 23); + REQUIRE(headers[1]->fileName == "units.xml"); + REQUIRE(headers[1]->compressSize == 202); + REQUIRE(headers[1]->uncompressSize == 306); + + delete entry; + } + + SECTION("test4.zip") + { + name = prefix + "data/test/test4.zip"; + + VirtZipEntry *const entry = new VirtZipEntry(name); + std::vector &headers = entry->mHeaders; + + REQUIRE(Zip::readArchiveInfo(entry)); + REQUIRE(entry->mArchiveName == name); + REQUIRE(headers.size() == 0); + + delete entry; + } + + delete2(logger); +} + +TEST_CASE("Zip readCompressedFile") +{ + logger = new Logger(); + std::string name("data/test/test.zip"); + std::string prefix; + if (Files::existsLocal(name) == false) + prefix = "../"; + + SECTION("empty") + { + REQUIRE_THROWS(Zip::readCompressedFile(nullptr)); + } + + SECTION("test2.zip") + { + name = prefix + "data/test/test2.zip"; + + VirtZipEntry *const entry = new VirtZipEntry(name); + std::vector &headers = entry->mHeaders; + + REQUIRE(Zip::readArchiveInfo(entry)); + REQUIRE(headers.size() == 11); + REQUIRE(entry->mArchiveName == name); + // test.txt + uint8_t *const buf = Zip::readCompressedFile(headers[0]); + REQUIRE(buf != nullptr); + delete [] buf; + delete entry; + } + + delete2(logger); +} + +TEST_CASE("Zip readFile") +{ + logger = new Logger(); + std::string name("data/test/test.zip"); + std::string prefix; + if (Files::existsLocal(name) == false) + prefix = "../"; + + SECTION("empty") + { + REQUIRE_THROWS(Zip::readFile(nullptr)); + } + + SECTION("test.zip") + { + name = prefix + "data/test/test.zip"; + + VirtZipEntry *const entry = new VirtZipEntry(name); + std::vector &headers = entry->mHeaders; + + REQUIRE(Zip::readArchiveInfo(entry)); + REQUIRE(headers.size() == 2); + REQUIRE(entry->mArchiveName == name); + for (int f = 0; f < 2; f ++) + { + logger->log("test header: %s, %u, %u", + headers[f]->fileName.c_str(), + headers[f]->compressSize, + headers[f]->uncompressSize); + uint8_t *const buf = Zip::readFile(headers[f]); + REQUIRE(buf != nullptr); + delete [] buf; + } + delete entry; + } + + SECTION("test2.zip") + { + name = prefix + "data/test/test2.zip"; + + VirtZipEntry *const entry = new VirtZipEntry(name); + std::vector &headers = entry->mHeaders; + + REQUIRE(Zip::readArchiveInfo(entry)); + REQUIRE(headers.size() == 11); + REQUIRE(entry->mArchiveName == name); + // test.txt + uint8_t *buf = Zip::readFile(headers[0]); + REQUIRE(buf != nullptr); + const std::string str = std::string(reinterpret_cast(buf), + headers[0]->uncompressSize); + REQUIRE(str == "test line 1\ntest line 2"); + delete [] buf; + for (int f = 0; f < 11; f ++) + { + logger->log("test header: %s, %u, %u", + headers[f]->fileName.c_str(), + headers[f]->compressSize, + headers[f]->uncompressSize); + buf = Zip::readFile(headers[f]); + REQUIRE(buf != nullptr); + delete [] buf; + } + delete entry; + } + + SECTION("test3.zip") + { + name = prefix + "data/test/test3.zip"; + + VirtZipEntry *const entry = new VirtZipEntry(name); + std::vector &headers = entry->mHeaders; + + REQUIRE(Zip::readArchiveInfo(entry)); + REQUIRE(headers.size() == 2); + REQUIRE(entry->mArchiveName == name); + for (int f = 0; f < 2; f ++) + { + logger->log("test header: %s, %u, %u", + headers[f]->fileName.c_str(), + headers[f]->compressSize, + headers[f]->uncompressSize); + uint8_t *const buf = Zip::readFile(headers[f]); + REQUIRE(buf != nullptr); + delete [] buf; + } + delete entry; + } + + delete2(logger); +} diff --git a/src/fs/virtfs/ziplocalheader.cpp b/src/fs/virtfs/ziplocalheader.cpp new file mode 100644 index 000000000..1fed2afd8 --- /dev/null +++ b/src/fs/virtfs/ziplocalheader.cpp @@ -0,0 +1,39 @@ +/* + * The ManaPlus Client + * Copyright (C) 2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "fs/virtfs/ziplocalheader.h" + +#include "fs/virtfs/virtzipentry.h" + +#include "localconsts.h" + +#include + +#include "debug.h" + +ZipLocalHeader::ZipLocalHeader() : + fileName(), + zipEntry(nullptr), + dataOffset(0U), + compressSize(0U), + uncompressSize(0U), + compressed(false) +{ +} diff --git a/src/fs/virtfs/ziplocalheader.h b/src/fs/virtfs/ziplocalheader.h new file mode 100644 index 000000000..f3a1894ce --- /dev/null +++ b/src/fs/virtfs/ziplocalheader.h @@ -0,0 +1,44 @@ +/* + * The ManaPlus Client + * Copyright (C) 2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef UTILS_ZIPLOCALHEADER_H +#define UTILS_ZIPLOCALHEADER_H + +#include "localconsts.h" + +#include + +struct VirtZipEntry; + +struct ZipLocalHeader final +{ + ZipLocalHeader(); + + A_DELETE_COPY(ZipLocalHeader) + + std::string fileName; + VirtZipEntry *zipEntry; + uint32_t dataOffset; + uint32_t compressSize; + uint32_t uncompressSize; + bool compressed; +}; + +#endif // UTILS_ZIPLOCALHEADER_H diff --git a/src/fs/virtfsdir.cpp b/src/fs/virtfsdir.cpp deleted file mode 100644 index cb512f2ca..000000000 --- a/src/fs/virtfsdir.cpp +++ /dev/null @@ -1,626 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2013-2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "fs/virtfsdir.h" - -#include "fs/files.h" -#include "fs/mkdir.h" -#include "fs/paths.h" -#include "fs/virtdirentry.h" -#include "fs/virtfs.h" -#include "fs/virtfile.h" -#include "fs/virtfileprivate.h" -#include "fs/virtfsfuncs.h" -#include "fs/virtlist.h" - -#include "utils/checkutils.h" -#include "utils/dtor.h" -#include "utils/stringutils.h" - -#include -#include -#include -#include - -#include -#include - -#include "debug.h" - -extern const char *dirSeparator; - -namespace -{ - std::vector mEntries; - std::string mWriteDir; - std::string mBaseDir; - std::string mUserDir; - bool mPermitLinks = false; - VirtFsFuncs funcs; -} // namespace - -namespace VirtFsDir -{ - namespace - { - static VirtFile *openFile(std::string filename, - const int mode) - { - if (checkPath(filename) == false) - { - reportAlways("VirtFsDir::openFile invalid path: %s", - filename.c_str()); - return nullptr; - } - prepareFsPath(filename); - VirtDirEntry *const entry = searchEntryByPath(filename); - if (entry == nullptr) - return nullptr; - - const std::string path = entry->mRootDir + filename; - const int fd = open(path.c_str(), - mode, - S_IRUSR | S_IWUSR); - if (fd == -1) - { - reportAlways("VirtFsDir::openFile file open error: %s", - filename.c_str()); - return nullptr; - } - VirtFile *restrict const file = new VirtFile(&funcs); - file->mPrivate = new VirtFilePrivate(fd); - - return file; - } - } // namespace - - VirtDirEntry *searchEntryByRoot(const std::string &restrict root) - { - FOR_EACH (std::vector::const_iterator, it, mEntries) - { - if ((*it)->mRootDir == root) - return *it; - } - return nullptr; - } - - VirtDirEntry *searchEntryByPath(const std::string &restrict path) - { - FOR_EACH (std::vector::const_iterator, it, mEntries) - { - VirtDirEntry *const entry = *it; - if (Files::existsLocal(entry->mRootDir + path)) - return entry; - } - return nullptr; - } - - bool addToSearchPathSilent(std::string newDir, - const Append append, - const SkipError skipError) - { - prepareFsPath(newDir); - if (skipError == SkipError_false && - Files::existsLocal(newDir) == false) - { - logger->log("VirtFsDir::addToSearchPath directory not exists: %s", - newDir.c_str()); - return false; - } - if (newDir.find(".zip") != std::string::npos) - { - reportAlways("Called VirtFsDir::addToSearchPath with zip archive"); - return false; - } - std::string rootDir = newDir; - if (findLast(rootDir, std::string(dirSeparator)) == false) - rootDir += dirSeparator; - VirtDirEntry *const entry = VirtFsDir::searchEntryByRoot(rootDir); - if (entry != nullptr) - { - reportAlways("VirtFsDir::addToSearchPath already exists: %s", - newDir.c_str()); - return false; - } - logger->log("Add virtual directory: " + newDir); - if (append == Append_true) - { - mEntries.push_back(new VirtDirEntry(newDir, - rootDir)); - } - else - { - mEntries.insert(mEntries.begin(), - new VirtDirEntry(newDir, - rootDir)); - } - return true; - } - - bool addToSearchPath(std::string newDir, - const Append append) - { - prepareFsPath(newDir); - if (Files::existsLocal(newDir) == false) - { - reportAlways("VirtFsDir::addToSearchPath directory not exists: %s", - newDir.c_str()); - return false; - } - if (newDir.find(".zip") != std::string::npos) - { - reportAlways("Called VirtFsDir::addToSearchPath with zip archive"); - return false; - } - std::string rootDir = newDir; - if (findLast(rootDir, std::string(dirSeparator)) == false) - rootDir += dirSeparator; - VirtDirEntry *const entry = VirtFsDir::searchEntryByRoot(rootDir); - if (entry != nullptr) - { - reportAlways("VirtFsDir::addToSearchPath already exists: %s", - newDir.c_str()); - return false; - } - logger->log("Add virtual directory: " + newDir); - if (append == Append_true) - { - mEntries.push_back(new VirtDirEntry(newDir, - rootDir)); - } - else - { - mEntries.insert(mEntries.begin(), - new VirtDirEntry(newDir, - rootDir)); - } - return true; - } - - bool removeFromSearchPathSilent(std::string oldDir) - { - prepareFsPath(oldDir); - if (oldDir.find(".zip") != std::string::npos) - { - reportAlways("Called removeFromSearchPath with zip archive"); - return false; - } - if (findLast(oldDir, std::string(dirSeparator)) == false) - oldDir += dirSeparator; - FOR_EACH (std::vector::iterator, it, mEntries) - { - VirtDirEntry *const entry = *it; - if (entry->mRootDir == oldDir) - { - logger->log("Remove virtual directory: " + oldDir); - mEntries.erase(it); - delete entry; - return true; - } - } - - logger->log("VirtFsDir::removeFromSearchPath not exists: %s", - oldDir.c_str()); - return false; - } - - bool removeFromSearchPath(std::string oldDir) - { - prepareFsPath(oldDir); - if (oldDir.find(".zip") != std::string::npos) - { - reportAlways("Called removeFromSearchPath with zip archive"); - return false; - } - if (findLast(oldDir, std::string(dirSeparator)) == false) - oldDir += dirSeparator; - FOR_EACH (std::vector::iterator, it, mEntries) - { - VirtDirEntry *const entry = *it; - if (entry->mRootDir == oldDir) - { - logger->log("Remove virtual directory: " + oldDir); - mEntries.erase(it); - delete entry; - return true; - } - } - - reportAlways("VirtFsDir::removeFromSearchPath not exists: %s", - oldDir.c_str()); - return false; - } - - std::vector &getEntries() - { - return mEntries; - } - - void deinit() - { - delete_all(mEntries); - mEntries.clear(); - } - -#if defined(__native_client__) - void init(const std::string &restrict name A_UNUSED) - { - mBaseDir = "/"; -#elif defined(ANDROID) - void init(const std::string &restrict name A_UNUSED) - { - mBaseDir = getRealPath("."); -#else // defined(__native_client__) - - void init(const std::string &restrict name) - { - mBaseDir = getRealPath(getFileDir(name)); -#endif // defined(__native_client__) - - prepareFsPath(mBaseDir); - mUserDir = getHomePath(); - prepareFsPath(mUserDir); - initFuncs(&funcs); - } - - void initFuncs(VirtFsFuncs *restrict const ptr) - { - ptr->close = &VirtFsDir::close; - ptr->read = &VirtFsDir::read; - ptr->write = &VirtFsDir::write; - ptr->fileLength = &VirtFsDir::fileLength; - ptr->tell = &VirtFsDir::tell; - ptr->seek = &VirtFsDir::seek; - ptr->eof = &VirtFsDir::eof; - } - - const char *getBaseDir() - { - return mBaseDir.c_str(); - } - - const char *getUserDir() - { - return mUserDir.c_str(); - } - - std::string getRealDir(std::string filename) - { - prepareFsPath(filename); - if (checkPath(filename) == false) - { - reportAlways("VirtFsDir::exists invalid path: %s", - filename.c_str()); - return std::string(); - } - FOR_EACH (std::vector::iterator, it, mEntries) - { - VirtDirEntry *const entry = *it; - const std::string path = entry->mRootDir + filename; - if (Files::existsLocal(path)) - return entry->mUserDir; - } - return std::string(); - } - - bool exists(std::string name) - { - prepareFsPath(name); - if (checkPath(name) == false) - { - reportAlways("VirtFsDir::exists invalid path: %s", - name.c_str()); - return false; - } - FOR_EACH (std::vector::iterator, it, mEntries) - { - VirtDirEntry *const entry = *it; - if (Files::existsLocal(entry->mRootDir + name)) - return true; - } - return false; - } - - VirtList *enumerateFiles(const std::string &dirName) - { - VirtList *const list = new VirtList; - return enumerateFiles(dirName, list); - } - - VirtList *enumerateFiles(std::string dirName, - VirtList *const list) - { - prepareFsPath(dirName); - if (checkPath(dirName) == false) - { - reportAlways("VirtFsDir::enumerateFiles invalid path: %s", - dirName.c_str()); - return list; - } - StringVect &names = list->names; - FOR_EACH (std::vector::iterator, it, mEntries) - { - VirtDirEntry *const entry = *it; - StringVect files; - std::string path = entry->mRootDir + dirName; - if (findLast(path, std::string(dirSeparator)) == false) - path += dirSeparator; - const struct dirent *next_file = nullptr; - DIR *const dir = opendir(path.c_str()); - if (dir) - { - while ((next_file = readdir(dir))) - { - const std::string file = next_file->d_name; - if (file == "." || file == "..") - continue; - if (mPermitLinks == false) - { - struct stat statbuf; - if (lstat(path.c_str(), &statbuf) == 0 && - S_ISLNK(statbuf.st_mode) != 0) - { - continue; - } - } - bool found(false); - FOR_EACH (StringVectCIter, itn, names) - { - if (*itn == file) - { - found = true; - break; - } - } - if (found == false) - names.push_back(file); - } - closedir(dir); - } - } - return list; - } - - bool isDirectory(std::string dirName) - { - prepareFsPath(dirName); - if (checkPath(dirName) == false) - { - reportAlways("VirtFsDir::isDirectory invalid path: %s", - dirName.c_str()); - return false; - } - FOR_EACH (std::vector::iterator, it, mEntries) - { - VirtDirEntry *const entry = *it; - std::string path = entry->mRootDir + dirName; - if (findLast(path, std::string(dirSeparator)) == false) - path += dirSeparator; - - struct stat statbuf; - if (stat(path.c_str(), &statbuf) == 0 && - S_ISDIR(statbuf.st_mode) != 0) - { - return true; - } - } - return false; - } - - bool isSymbolicLink(std::string name) - { - prepareFsPath(name); - if (checkPath(name) == false) - { - reportAlways("VirtFsDir::isSymbolicLink invalid path: %s", - name.c_str()); - return false; - } - if (mPermitLinks == false) - return false; - - struct stat statbuf; - return lstat(name.c_str(), &statbuf) == 0 && - S_ISLNK(statbuf.st_mode) != 0; - } - - void freeList(VirtList *restrict const handle) - { - delete handle; - } - - VirtFile *openRead(const std::string &restrict filename) - { - return openFile(filename, O_RDONLY); - } - - VirtFile *openWrite(const std::string &restrict filename) - { - return openFile(filename, O_WRONLY | O_CREAT | O_TRUNC); - } - - VirtFile *openAppend(const std::string &restrict filename) - { - return openFile(filename, O_WRONLY | O_CREAT | O_APPEND); - } - - bool setWriteDir(std::string newDir) - { - prepareFsPath(newDir); - mWriteDir = newDir; - if (findLast(mWriteDir, std::string(dirSeparator)) == false) - mWriteDir += dirSeparator; - return true; - } - - bool mkdir(std::string dirname) - { - prepareFsPath(dirname); - if (mWriteDir.empty()) - { - reportAlways("VirtFsDir::mkdir write dir is empty"); - return false; - } - return mkdir_r((mWriteDir + dirname).c_str()) != -1; - } - - bool remove(std::string filename) - { - prepareFsPath(filename); - if (mWriteDir.empty()) - { - reportAlways("VirtFsDir::remove write dir is empty"); - return false; - } - return ::remove((mWriteDir + filename).c_str()) != 0; - } - - void permitLinks(const bool val) - { - mPermitLinks = val; - } - - const char *getLastError() - { - return nullptr; - } - - int close(VirtFile *restrict const file) - { - if (file == nullptr) - return 0; - delete file; - return 1; - } - - int64_t read(VirtFile *restrict const file, - void *restrict const buffer, - const uint32_t objSize, - const uint32_t objCount) - { - if (file == nullptr) - return 0; - const int fd = file->mPrivate->mFd; - if (fd == -1) - { - reportAlways("VirtFsDir::read file not opened."); - return 0; - } - int max = objSize * objCount; - int cnt = ::read(fd, buffer, max); - if (cnt <= 0) - return cnt; - return cnt / objSize; - } - - int64_t write(VirtFile *restrict const file, - const void *restrict const buffer, - const uint32_t objSize, - const uint32_t objCount) - { - if (file == nullptr) - return 0; - const int fd = file->mPrivate->mFd; - if (fd == -1) - { - reportAlways("VirtFsDir::write file not opened."); - return 0; - } - int max = objSize * objCount; - int cnt = ::write(fd, buffer, max); - if (cnt <= 0) - return cnt; - return cnt / objSize; - } - - int64_t fileLength(VirtFile *restrict const file) - { - if (file == nullptr) - return -1; - const int fd = file->mPrivate->mFd; - if (fd == -1) - { - reportAlways("VirtFsDir::fileLength file not opened."); - return 0; - } - struct stat statbuf; - if (fstat(fd, &statbuf) == -1) - { - reportAlways("VirtFsDir::fileLength error."); - return -1; - } - return static_cast(statbuf.st_size); - } - - int64_t tell(VirtFile *restrict const file) - { - if (file == nullptr) - return -1; - - const int fd = file->mPrivate->mFd; - if (fd == -1) - { - reportAlways("VirtFsDir::tell file not opened."); - return 0; - } - const int64_t pos = lseek(fd, 0, SEEK_CUR); - return pos; - } - - int seek(VirtFile *restrict const file, - const uint64_t pos) - { - if (file == nullptr) - return 0; - - const int fd = file->mPrivate->mFd; - if (fd == -1) - { - reportAlways("VirtFsDir::seek file not opened."); - return 0; - } - const int64_t res = lseek(fd, pos, SEEK_SET); - if (res == -1) - return 0; - return 1; - } - - int eof(VirtFile *restrict const file) - { - if (file == nullptr) - return -1; - - const int fd = file->mPrivate->mFd; - if (fd == -1) - { - reportAlways("VirtFsDir::eof file not opened."); - return 0; - } - const int64_t pos = lseek(fd, 0, SEEK_CUR); - struct stat statbuf; - if (fstat(fd, &statbuf) == -1) - { - reportAlways("VirtFsDir::fileLength error."); - return -1; - } - const int64_t len = static_cast(statbuf.st_size); - return pos < 0 || len < 0 || pos >= len; - } -} // namespace VirtFs diff --git a/src/fs/virtfsdir.h b/src/fs/virtfsdir.h deleted file mode 100644 index 0ec2f466d..000000000 --- a/src/fs/virtfsdir.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2013-2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef UTILS_VIRTFSDIR_H -#define UTILS_VIRTFSDIR_H - -#include "enums/simpletypes/append.h" -#include "enums/simpletypes/skiperror.h" - -#include "localconsts.h" - -#include -#include - -struct VirtDirEntry; -struct VirtFile; -struct VirtFsFuncs; -struct VirtList; - -namespace VirtFsDir -{ - VirtDirEntry *searchEntryByRoot(const std::string &restrict root); - VirtDirEntry *searchEntryByPath(const std::string &restrict path); - const char *getBaseDir(); - const char *getUserDir(); - bool addToSearchPath(std::string newDir, - const Append append); - bool addToSearchPathSilent(std::string newDir, - const Append append, - const SkipError skipError); - bool removeFromSearchPath(std::string oldDir); - bool removeFromSearchPathSilent(std::string oldDir); - void init(const std::string &restrict name); - void initFuncs(VirtFsFuncs *restrict const ptr); - void deinit(); - std::vector &getEntries(); - bool exists(std::string name); - VirtList *enumerateFiles(const std::string &dirName) RETURNS_NONNULL; - VirtList *enumerateFiles(std::string dirName, - VirtList *const list) RETURNS_NONNULL; - bool isDirectory(std::string dirName); - bool isSymbolicLink(std::string name); - void freeList(VirtList *restrict const handle); - VirtFile *openRead(const std::string &restrict filename); - VirtFile *openWrite(const std::string &restrict filename); - VirtFile *openAppend(const std::string &restrict filename); - bool setWriteDir(std::string newDir); - std::string getRealDir(std::string filename); - bool mkdir(std::string dirName); - bool remove(std::string filename); - void permitLinks(const bool val); - const char *getLastError(); - int64_t read(VirtFile *restrict const handle, - void *restrict const buffer, - const uint32_t objSize, - const uint32_t objCount); - int64_t write(VirtFile *restrict const file, - const void *restrict const buffer, - const uint32_t objSize, - const uint32_t objCount); - int close(VirtFile *restrict const file); - int64_t fileLength(VirtFile *restrict const file); - int64_t tell(VirtFile *restrict const file); - int seek(VirtFile *restrict const file, - const uint64_t pos); - int eof(VirtFile *restrict const file); -} // namespace VirtFsDir - -#endif // UTILS_VIRTFSDIR_H diff --git a/src/fs/virtfsdir_unittest.cc b/src/fs/virtfsdir_unittest.cc deleted file mode 100644 index 589b10e4c..000000000 --- a/src/fs/virtfsdir_unittest.cc +++ /dev/null @@ -1,717 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2016-2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "catch.hpp" - -#include "fs/virtdirentry.h" -#include "fs/virtfsdir.h" -#include "fs/virtfstools.h" -#include "fs/virtlist.h" - -#include "utils/checkutils.h" -#include "utils/delete2.h" - -#include "debug.h" - -TEST_CASE("VirtFsDir getEntries") -{ - VirtFsDir::init("."); - REQUIRE(VirtFsDir::getEntries().empty()); - REQUIRE(VirtFsDir::searchEntryByRoot("test") == nullptr); - VirtFsDir::deinit(); -} - -TEST_CASE("VirtFsDir getBaseDir") -{ - VirtFsDir::init("."); - REQUIRE(VirtFsDir::getBaseDir() != nullptr); - VirtFsDir::deinit(); -} - -TEST_CASE("VirtFsDir addToSearchPath") -{ - VirtFsDir::init("."); - logger = new Logger(); - SECTION("simple 1") - { - REQUIRE(VirtFsDir::addToSearchPathSilent("dir1", - Append_false, - SkipError_true)); - REQUIRE(VirtFsDir::searchEntryByRoot("dir1/") != nullptr); - REQUIRE(VirtFsDir::searchEntryByRoot("test/") == nullptr); - REQUIRE(VirtFsDir::getEntries().size() == 1); - REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir1/"); - REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir1"); - } - - SECTION("simple 2") - { - REQUIRE(VirtFsDir::addToSearchPathSilent("dir1/", - Append_true, - SkipError_true)); - REQUIRE(VirtFsDir::searchEntryByRoot("dir1/") != nullptr); - REQUIRE(VirtFsDir::searchEntryByRoot("test/") == nullptr); - REQUIRE(VirtFsDir::getEntries().size() == 1); - REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir1/"); - REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir1/"); - } - - SECTION("simple 3") - { - REQUIRE(VirtFsDir::addToSearchPathSilent("dir1", - Append_false, - SkipError_true)); - REQUIRE(VirtFsDir::addToSearchPathSilent("dir2", - Append_false, - SkipError_true)); - REQUIRE(VirtFsDir::searchEntryByRoot("dir1/") != nullptr); - REQUIRE(VirtFsDir::searchEntryByRoot("dir2/") != nullptr); - REQUIRE(VirtFsDir::searchEntryByRoot("test/") == nullptr); - REQUIRE(VirtFsDir::getEntries().size() == 2); - REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir2/"); - REQUIRE(VirtFsDir::getEntries()[1]->mRootDir == "dir1/"); - REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir2"); - REQUIRE(VirtFsDir::getEntries()[1]->mUserDir == "dir1"); - } - - SECTION("simple 4") - { - REQUIRE(VirtFsDir::addToSearchPathSilent("dir1\\", - Append_true, - SkipError_true)); - REQUIRE(VirtFsDir::addToSearchPathSilent("dir2", - Append_true, - SkipError_true)); - REQUIRE(VirtFsDir::searchEntryByRoot("dir1/") != nullptr); - REQUIRE(VirtFsDir::searchEntryByRoot("dir2/") != nullptr); - REQUIRE(VirtFsDir::searchEntryByRoot("test/") == nullptr); - REQUIRE(VirtFsDir::getEntries().size() == 2); - REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir1/"); - REQUIRE(VirtFsDir::getEntries()[1]->mRootDir == "dir2/"); - REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir1/"); - REQUIRE(VirtFsDir::getEntries()[1]->mUserDir == "dir2"); - } - - SECTION("simple 5") - { - REQUIRE(VirtFsDir::addToSearchPathSilent("dir1", - Append_true, - SkipError_true)); - REQUIRE(VirtFsDir::addToSearchPathSilent("dir2", - Append_true, - SkipError_true)); - REQUIRE(VirtFsDir::addToSearchPathSilent("dir3/test", - Append_true, - SkipError_true)); - REQUIRE(VirtFsDir::searchEntryByRoot("dir1/") != nullptr); - REQUIRE(VirtFsDir::searchEntryByRoot("dir2/") != nullptr); - REQUIRE(VirtFsDir::searchEntryByRoot("dir3/test/") != nullptr); - REQUIRE(VirtFsDir::searchEntryByRoot("test/") == nullptr); - REQUIRE(VirtFsDir::getEntries().size() == 3); - REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir1/"); - REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir1"); - REQUIRE(VirtFsDir::getEntries()[1]->mRootDir == "dir2/"); - REQUIRE(VirtFsDir::getEntries()[1]->mUserDir == "dir2"); - REQUIRE(VirtFsDir::getEntries()[2]->mRootDir == "dir3/test/"); - REQUIRE(VirtFsDir::getEntries()[2]->mUserDir == "dir3/test"); - } - - SECTION("simple 6") - { - REQUIRE(VirtFsDir::addToSearchPathSilent("dir1", - Append_true, - SkipError_true)); - REQUIRE(VirtFsDir::addToSearchPathSilent("dir2", - Append_true, - SkipError_true)); - REQUIRE(VirtFsDir::addToSearchPathSilent("dir3/test", - Append_false, - SkipError_true)); - REQUIRE(VirtFsDir::searchEntryByRoot("dir1/") != nullptr); - REQUIRE(VirtFsDir::searchEntryByRoot("dir2/") != nullptr); - REQUIRE(VirtFsDir::searchEntryByRoot("dir3/test/") != nullptr); - REQUIRE(VirtFsDir::searchEntryByRoot("test/") == nullptr); - REQUIRE(VirtFsDir::getEntries().size() == 3); - REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir3/test/"); - REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir3/test"); - REQUIRE(VirtFsDir::getEntries()[1]->mRootDir == "dir1/"); - REQUIRE(VirtFsDir::getEntries()[1]->mUserDir == "dir1"); - REQUIRE(VirtFsDir::getEntries()[2]->mRootDir == "dir2/"); - REQUIRE(VirtFsDir::getEntries()[2]->mUserDir == "dir2"); - } - - VirtFsDir::deinit(); - delete2(logger); -} - -TEST_CASE("VirtFsDir removeFromSearchPath") -{ - VirtFsDir::init("."); - logger = new Logger(); - - SECTION("simple 1") - { - REQUIRE_THROWS(VirtFsDir::removeFromSearchPath("dir1")); - REQUIRE_THROWS(VirtFsDir::removeFromSearchPath("dir1/")); - } - - SECTION("simple 2") - { - REQUIRE(VirtFsDir::addToSearchPathSilent("dir1", - Append_true, - SkipError_true)); - REQUIRE_THROWS(VirtFsDir::removeFromSearchPath("dir2")); - REQUIRE(VirtFsDir::removeFromSearchPath("dir1")); - } - - SECTION("simple 3") - { - REQUIRE(VirtFsDir::addToSearchPathSilent("dir1", - Append_true, - SkipError_true)); - REQUIRE(VirtFsDir::addToSearchPathSilent("dir2//dir3", - Append_true, - SkipError_true)); - REQUIRE(VirtFsDir::addToSearchPathSilent("dir3", - Append_false, - SkipError_true)); - REQUIRE(VirtFsDir::getEntries().size() == 3); - REQUIRE_THROWS(VirtFsDir::removeFromSearchPath("dir2")); - REQUIRE(VirtFsDir::removeFromSearchPath("dir1")); - REQUIRE(VirtFsDir::getEntries().size() == 2); - REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir3/"); - REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir3"); - REQUIRE(VirtFsDir::getEntries()[1]->mRootDir == "dir2/dir3/"); - REQUIRE(VirtFsDir::getEntries()[1]->mUserDir == "dir2/dir3"); - REQUIRE_THROWS(VirtFsDir::removeFromSearchPath("dir1")); - REQUIRE(VirtFsDir::getEntries().size() == 2); - REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir3/"); - REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir3"); - REQUIRE(VirtFsDir::getEntries()[1]->mRootDir == "dir2/dir3/"); - REQUIRE(VirtFsDir::getEntries()[1]->mUserDir == "dir2/dir3"); - REQUIRE(VirtFsDir::removeFromSearchPath("dir2/dir3")); - REQUIRE_THROWS(VirtFsDir::removeFromSearchPath("dir2/dir3/")); - REQUIRE(VirtFsDir::getEntries().size() == 1); - REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir3/"); - REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir3"); - } - - SECTION("simple 4") - { - REQUIRE(VirtFsDir::addToSearchPathSilent("dir1", - Append_true, - SkipError_true)); - REQUIRE(VirtFsDir::getEntries().size() == 1); - REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir1/"); - REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir1"); - REQUIRE_THROWS(VirtFsDir::removeFromSearchPath("dir2")); - REQUIRE(VirtFsDir::removeFromSearchPath("dir1")); - REQUIRE(VirtFsDir::getEntries().size() == 0); - REQUIRE(VirtFsDir::addToSearchPathSilent("dir1", - Append_true, - SkipError_true)); - REQUIRE(VirtFsDir::getEntries().size() == 1); - REQUIRE(VirtFsDir::getEntries()[0]->mRootDir == "dir1/"); - REQUIRE(VirtFsDir::getEntries()[0]->mUserDir == "dir1"); - } - - VirtFsDir::deinit(); - delete2(logger); -} - -TEST_CASE("VirtFsDir exists") -{ - VirtFsDir::init("."); - logger = new Logger(); - VirtFsDir::addToSearchPathSilent("data/", - Append_false, - SkipError_false); - VirtFsDir::addToSearchPathSilent("..\\data", - Append_false, - SkipError_false); - - REQUIRE(VirtFsDir::exists("test//units.xml") == true); - REQUIRE(VirtFsDir::exists("test/\\units123.xml") == false); - REQUIRE(VirtFsDir::exists("tesQ/units.xml") == false); - REQUIRE(VirtFsDir::exists("units.xml") == false); - - VirtFsDir::addToSearchPathSilent("data//test", - Append_false, - SkipError_false); - VirtFsDir::addToSearchPathSilent("..//data\\test", - Append_false, - SkipError_false); - - REQUIRE(VirtFsDir::exists("test\\units.xml") == true); - REQUIRE(VirtFsDir::exists("test/units123.xml") == false); - REQUIRE(VirtFsDir::exists("tesQ/units.xml") == false); - REQUIRE(VirtFsDir::exists("units.xml") == true); - - VirtFsDir::removeFromSearchPathSilent("data/test"); - VirtFsDir::removeFromSearchPathSilent("../data/test"); - - REQUIRE(VirtFsDir::exists("test\\units.xml") == true); - REQUIRE(VirtFsDir::exists("test/units123.xml") == false); - REQUIRE(VirtFsDir::exists("tesQ/units.xml") == false); - REQUIRE(VirtFsDir::exists("units.xml") == false); - - REQUIRE_THROWS(VirtFsDir::exists("test/../units.xml")); - - VirtFsDir::deinit(); - delete2(logger); -} - -static void removeTemp(StringVect &restrict list) -{ - int cnt = 0; - std::sort(list.begin(), list.end()); - - FOR_EACH (StringVectIter, it, list) - { - if (*it != "serverlistplus.xml.part") - { - logger->log("file: %d %s", - cnt, - (*it).c_str()); - cnt ++; - } - } - - FOR_EACH (StringVectIter, it, list) - { - if (*it == "serverlistplus.xml.part") - { - list.erase(it); - return; - } - } -} - -TEST_CASE("VirtFsDir getRealDir") -{ - VirtFsDir::init("."); - logger = new Logger(); - REQUIRE(VirtFsDir::getRealDir(".") == ""); - REQUIRE(VirtFsDir::getRealDir("..") == ""); - const bool dir1 = VirtFsDir::addToSearchPathSilent("data", - Append_false, - SkipError_false); - REQUIRE((dir1 || VirtFsDir::addToSearchPathSilent("../data", - Append_false, - SkipError_false)) == true); - if (dir1 == true) - { - REQUIRE(VirtFsDir::getRealDir("test") == "data"); - REQUIRE(VirtFsDir::getRealDir("test/test.txt") == - "data"); - REQUIRE(VirtFsDir::getRealDir("test\\test.txt") == - "data"); - REQUIRE(VirtFsDir::getRealDir("test//test.txt") == - "data"); - } - else - { - REQUIRE(VirtFsDir::getRealDir("test") == "../data"); - REQUIRE(VirtFsDir::getRealDir("test/test.txt") == - "../data"); - REQUIRE(VirtFsDir::getRealDir("test\\test.txt") == - "../data"); - REQUIRE(VirtFsDir::getRealDir("test//test.txt") == - "../data"); - } - REQUIRE(VirtFsDir::getRealDir("zzz") == ""); - - VirtFsDir::addToSearchPathSilent("data/test", - Append_false, - SkipError_false); - VirtFsDir::addToSearchPathSilent("../data/test", - Append_false, - SkipError_false); - if (dir1 == true) - { - REQUIRE(VirtFsDir::getRealDir("test") == "data"); - REQUIRE(VirtFsDir::getRealDir("test/test.txt") == - "data"); - REQUIRE(VirtFsDir::getRealDir("test\\test.txt") == - "data"); - REQUIRE(VirtFsDir::getRealDir("test.txt") == - "data/test"); - } - else - { - REQUIRE(VirtFsDir::getRealDir("test") == "../data"); - REQUIRE(VirtFsDir::getRealDir("test/test.txt") == - "../data"); - REQUIRE(VirtFsDir::getRealDir("test\\test.txt") == - "../data"); - REQUIRE(VirtFsDir::getRealDir("test.txt") == - "../data/test"); - } - REQUIRE(VirtFsDir::getRealDir("zzz") == ""); - - VirtFsDir::removeFromSearchPathSilent("data/test"); - VirtFsDir::removeFromSearchPathSilent("../data/test"); - - if (dir1 == true) - { - REQUIRE(VirtFsDir::getRealDir("test") == "data"); - REQUIRE(VirtFsDir::getRealDir("test/test.txt") == - "data"); - } - else - { - REQUIRE(VirtFsDir::getRealDir("test") == "../data"); - REQUIRE(VirtFsDir::getRealDir("test/test.txt") == - "../data"); - } - REQUIRE(VirtFsDir::getRealDir("zzz") == ""); - - VirtFsDir::removeFromSearchPathSilent("data"); - VirtFsDir::removeFromSearchPathSilent("../data"); - VirtFsDir::deinit(); - delete2(logger); -} - -static bool inList(VirtList *list, - const std::string &name) -{ - FOR_EACH (StringVectCIter, it, list->names) - { - if (*it == name) - return true; - } - return false; -} - -TEST_CASE("VirtFsDir enumerateFiles1") -{ - VirtFsDir::init("."); - logger = new Logger; - - VirtFsDir::addToSearchPathSilent("data", - Append_false, - SkipError_false); - VirtFsDir::addToSearchPathSilent("../data", - Append_false, - SkipError_false); - - VirtList *list = nullptr; - - const int cnt1 = VirtFsDir::exists("test/test2.txt") ? 27 : 26; - const int cnt2 = 27; - - VirtFsDir::permitLinks(false); - list = VirtFsDir::enumerateFiles("test"); - removeTemp(list->names); - const size_t sz = list->names.size(); - REQUIRE(sz == cnt1); - VirtFsDir::freeList(list); - - VirtFsDir::permitLinks(true); - list = VirtFsDir::enumerateFiles("test/"); - removeTemp(list->names); - REQUIRE(list->names.size() == cnt2); - VirtFsDir::freeList(list); - - VirtFsDir::permitLinks(false); - list = VirtFsDir::enumerateFiles("test\\"); - removeTemp(list->names); - REQUIRE(list->names.size() == cnt1); - VirtFsDir::freeList(list); - - VirtFsDir::removeFromSearchPathSilent("data"); - VirtFsDir::removeFromSearchPathSilent("../data"); - VirtFsDir::deinit(); - delete2(logger); -} - -TEST_CASE("VirtFsDir enumerateFiles2") -{ - VirtFsDir::init("."); - logger = new Logger; - - VirtFsDir::addToSearchPathSilent("data/test/dir1", - Append_false, - SkipError_false); - VirtFsDir::addToSearchPathSilent("../data/test/dir1", - Append_false, - SkipError_false); - - VirtList *list = nullptr; - - list = VirtFsDir::enumerateFiles("/"); - const size_t sz = list->names.size(); - REQUIRE(list->names.size() == 5); - REQUIRE(inList(list, "file1.txt")); - REQUIRE_FALSE(inList(list, "file2.txt")); - VirtFsDir::freeList(list); - VirtFsDir::deinit(); - delete2(logger); -} - -TEST_CASE("VirtFsDir enumerateFiles3") -{ - VirtFsDir::init("."); - logger = new Logger; - - VirtFsDir::addToSearchPathSilent("data/test/dir1", - Append_false, - SkipError_false); - VirtFsDir::addToSearchPathSilent("../data/test/dir1", - Append_false, - SkipError_false); - VirtFsDir::addToSearchPathSilent("data/test/dir2", - Append_false, - SkipError_false); - VirtFsDir::addToSearchPathSilent("../data/test/dir2", - Append_false, - SkipError_false); - - VirtList *list = nullptr; - - list = VirtFsDir::enumerateFiles("/"); - const size_t sz = list->names.size(); - REQUIRE(list->names.size() == 6); - REQUIRE(inList(list, "file1.txt")); - REQUIRE(inList(list, "file2.txt")); - VirtFsDir::freeList(list); - VirtFsDir::deinit(); - delete2(logger); -} - -TEST_CASE("VirtFsDir isDirectory") -{ - VirtFsDir::init("."); - logger = new Logger(); - VirtFsDir::addToSearchPathSilent("data", - Append_false, - SkipError_false); - VirtFsDir::addToSearchPathSilent("../data", - Append_false, - SkipError_false); - - REQUIRE(VirtFsDir::isDirectory("test/units.xml") == false); - REQUIRE(VirtFsDir::isDirectory("test/units.xml/") == false); - REQUIRE(VirtFsDir::isDirectory("test//units.xml") == false); - REQUIRE(VirtFsDir::isDirectory("test/units123.xml") == false); - REQUIRE(VirtFsDir::isDirectory("test//units123.xml") == false); - REQUIRE(VirtFsDir::isDirectory("tesQ/units.xml") == false); - REQUIRE(VirtFsDir::isDirectory("tesQ//units.xml") == false); - REQUIRE(VirtFsDir::isDirectory("units.xml") == false); - REQUIRE(VirtFsDir::isDirectory("test") == true); - REQUIRE(VirtFsDir::isDirectory("test/") == true); - REQUIRE(VirtFsDir::isDirectory("test//") == true); - REQUIRE(VirtFsDir::isDirectory("test/dir1") == true); - REQUIRE(VirtFsDir::isDirectory("test//dir1") == true); - REQUIRE(VirtFsDir::isDirectory("test//dir1/") == true); - REQUIRE(VirtFsDir::isDirectory("test//dir1//") == true); - REQUIRE(VirtFsDir::isDirectory("test\\dir1/") == true); - REQUIRE(VirtFsDir::isDirectory("test/dir1//") == true); - REQUIRE(VirtFsDir::isDirectory("testQ") == false); - REQUIRE(VirtFsDir::isDirectory("testQ/") == false); - REQUIRE(VirtFsDir::isDirectory("testQ//") == false); - - VirtFsDir::addToSearchPathSilent("data/test", - Append_false, - SkipError_false); - VirtFsDir::addToSearchPathSilent("../data/test", - Append_false, - SkipError_false); - - REQUIRE(VirtFsDir::isDirectory("test/units.xml") == false); - REQUIRE(VirtFsDir::isDirectory("test/units.xml/") == false); - REQUIRE(VirtFsDir::isDirectory("test//units.xml") == false); - REQUIRE(VirtFsDir::isDirectory("test/units123.xml") == false); - REQUIRE(VirtFsDir::isDirectory("tesQ/units.xml") == false); - REQUIRE(VirtFsDir::isDirectory("units.xml") == false); - REQUIRE(VirtFsDir::isDirectory("test") == true); - REQUIRE(VirtFsDir::isDirectory("testQ") == false); - REQUIRE(VirtFsDir::isDirectory("test/dir1") == true); - REQUIRE(VirtFsDir::isDirectory("test\\dir1") == true); - - VirtFsDir::removeFromSearchPathSilent("data/test"); - VirtFsDir::removeFromSearchPathSilent("../data/test"); - - REQUIRE(VirtFsDir::isDirectory("test/units.xml") == false); - REQUIRE(VirtFsDir::isDirectory("test/units123.xml") == false); - REQUIRE(VirtFsDir::isDirectory("tesQ/units.xml") == false); - REQUIRE(VirtFsDir::isDirectory("units.xml") == false); - REQUIRE(VirtFsDir::isDirectory("units.xml/") == false); - REQUIRE(VirtFsDir::isDirectory("test") == true); - REQUIRE(VirtFsDir::isDirectory("test/") == true); - REQUIRE(VirtFsDir::isDirectory("testQ") == false); - REQUIRE(VirtFsDir::isDirectory("test/dir1") == true); - - VirtFsDir::removeFromSearchPathSilent("data"); - VirtFsDir::removeFromSearchPathSilent("../data"); - VirtFsDir::deinit(); - delete2(logger); -} - -TEST_CASE("VirtFsDir openRead") -{ - VirtFsDir::init("."); - logger = new Logger(); - VirtFsDir::addToSearchPathSilent("data", - Append_false, - SkipError_false); - VirtFsDir::addToSearchPathSilent("../data", - Append_false, - SkipError_false); - - VirtFile *file = nullptr; - - file = VirtFsDir::openRead("test/units.xml"); - REQUIRE(file != nullptr); - VirtFsDir::close(file); - file = VirtFsDir::openRead("test\\units.xml"); - REQUIRE(file != nullptr); - VirtFsDir::close(file); - file = VirtFsDir::openRead("test/units123.xml"); - REQUIRE(file == nullptr); - file = VirtFsDir::openRead("tesQ/units.xml"); - REQUIRE(file == nullptr); - file = VirtFsDir::openRead("units.xml"); - REQUIRE(file == nullptr); - file = VirtFsDir::openRead("testQ"); - REQUIRE(file == nullptr); - - VirtFsDir::addToSearchPathSilent("data/test", - Append_false, - SkipError_false); - VirtFsDir::addToSearchPathSilent("../data/test", - Append_false, - SkipError_false); - - file = VirtFsDir::openRead("test/units.xml"); - REQUIRE(file != nullptr); - VirtFsDir::close(file); - file = VirtFsDir::openRead("test/units123.xml"); - REQUIRE(file == nullptr); - file = VirtFsDir::openRead("tesQ/units.xml"); - REQUIRE(file == nullptr); - file = VirtFsDir::openRead("units.xml"); - REQUIRE(file != nullptr); - VirtFsDir::close(file); - file = VirtFsDir::openRead("testQ"); - REQUIRE(file == nullptr); - - VirtFsDir::removeFromSearchPathSilent("data/test"); - VirtFsDir::removeFromSearchPathSilent("../data/test"); - - file = VirtFsDir::openRead("test/units.xml"); - REQUIRE(file != nullptr); - VirtFsDir::close(file); - file = VirtFsDir::openRead("test/units123.xml"); - REQUIRE(file == nullptr); - file = VirtFsDir::openRead("tesQ/units.xml"); - REQUIRE(file == nullptr); - file = VirtFsDir::openRead("units.xml"); - REQUIRE(file == nullptr); - file = VirtFsDir::openRead("testQ"); - REQUIRE(file == nullptr); - - VirtFsDir::removeFromSearchPathSilent("data"); - VirtFsDir::removeFromSearchPathSilent("../data"); - VirtFsDir::deinit(); - delete2(logger); -} - - -TEST_CASE("VirtFsDir permitLinks") -{ - VirtFsDir::init("."); - logger = new Logger(); - VirtFsDir::addToSearchPathSilent("data", - Append_false, - SkipError_false); - VirtFsDir::addToSearchPathSilent("../data", - Append_false, - SkipError_false); - - const int cnt1 = VirtFsDir::exists("test/test2.txt") ? 25 : 24; - const int cnt2 = 25; - - StringVect list; - VirtFsDir::permitLinks(false); - VirtFsDir::getFiles("test", list); - removeTemp(list); - const size_t sz = list.size(); - REQUIRE(sz == cnt1); - - list.clear(); - VirtFsDir::permitLinks(true); - VirtFsDir::getFiles("test", list); - removeTemp(list); - REQUIRE(list.size() == cnt2); - - list.clear(); - VirtFsDir::permitLinks(false); - VirtFsDir::getFiles("test", list); - removeTemp(list); - REQUIRE(list.size() == cnt1); - - VirtFsDir::removeFromSearchPathSilent("data"); - VirtFsDir::removeFromSearchPathSilent("../data"); - VirtFsDir::deinit(); - delete2(logger); -} - -TEST_CASE("VirtFsDir read") -{ - VirtFsDir::init("."); - logger = new Logger(); - VirtFsDir::addToSearchPathSilent("data", - Append_false, - SkipError_false); - VirtFsDir::addToSearchPathSilent("../data", - Append_false, - SkipError_false); - - VirtFile *file = VirtFsDir::openRead("test/test.txt"); - REQUIRE(file != nullptr); - REQUIRE(VirtFsDir::fileLength(file) == 23); - const int fileSize = VirtFsDir::fileLength(file); - - void *restrict buffer = calloc(fileSize + 1, 1); - REQUIRE(VirtFsDir::read(file, buffer, 1, fileSize) == fileSize); - REQUIRE(strcmp(static_cast(buffer), - "test line 1\ntest line 2") == 0); - REQUIRE(VirtFsDir::tell(file) == fileSize); - REQUIRE(VirtFsDir::eof(file) == true); - - free(buffer); - buffer = calloc(fileSize + 1, 1); - REQUIRE(VirtFsDir::seek(file, 12) != 0); - REQUIRE(VirtFsDir::eof(file) == false); - REQUIRE(VirtFsDir::tell(file) == 12); - REQUIRE(VirtFsDir::read(file, buffer, 1, 11) == 11); - REQUIRE(strcmp(static_cast(buffer), - "test line 2") == 0); - REQUIRE(VirtFsDir::eof(file) == true); - - VirtFsDir::close(file); - free(buffer); - - VirtFsDir::removeFromSearchPathSilent("data"); - VirtFsDir::removeFromSearchPathSilent("../data"); - VirtFsDir::deinit(); - delete2(logger); -} diff --git a/src/fs/virtfsphys.cpp b/src/fs/virtfsphys.cpp deleted file mode 100644 index d5cb1c1a2..000000000 --- a/src/fs/virtfsphys.cpp +++ /dev/null @@ -1,326 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2013-2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "fs/virtfsphys.h" - -#include "fs/virtfile.h" -#include "fs/virtfileprivate.h" -#include "fs/virtfsfuncs.h" -#include "fs/virtlist.h" - -#include "utils/checkutils.h" - -#include -#include - -#ifdef ANDROID -#include "fs/paths.h" -#endif // ANDROID - -#include "debug.h" - -namespace -{ - const char *dirSeparator = nullptr; - VirtFsFuncs funcs; -} // namespace - -namespace VirtFsPhys -{ -#if defined(__native_client__) - void init(const std::string &restrict name A_UNUSED) - { - if (!PHYSFS_init("/fakebinary")) -#elif defined(ANDROID) - void init(const std::string &restrict name A_UNUSED) - { - if (!PHYSFS_init((getRealPath(".").append("/fakebinary")).c_str())) -#else // defined(__native_client__) - - void init(const std::string &restrict name) - { - if (!PHYSFS_init(name.c_str())) -#endif // defined(__native_client__) - { - std::cout << "Error while initializing PhysFS: " - << VirtFsPhys::getLastError() << std::endl; - _exit(1); - } - updateDirSeparator(); - atexit(reinterpret_cast(PHYSFS_deinit)); - initFuncs(&funcs); - } - - void initFuncs() - { - initFuncs(&funcs); - } - - void initFuncs(VirtFsFuncs *restrict const ptr) - { - ptr->close = &VirtFsPhys::close; - ptr->read = &VirtFsPhys::read; - ptr->write = &VirtFsPhys::write; - ptr->fileLength = &VirtFsPhys::fileLength; - ptr->tell = &VirtFsPhys::tell; - ptr->seek = &VirtFsPhys::seek; - ptr->eof = &VirtFsPhys::eof; - } - - void updateDirSeparator() - { - dirSeparator = PHYSFS_getDirSeparator(); - } - - const char *getDirSeparator() - { - return dirSeparator; - } - - const char *getBaseDir() - { - return PHYSFS_getBaseDir(); - } - - const char *getUserDir() - { - return PHYSFS_getUserDir(); - } - - bool exists(const std::string &restrict name) - { - return PHYSFS_exists(name.c_str()); - } - - VirtList *enumerateFiles(const std::string &restrict dir) - { - char ** handle = PHYSFS_enumerateFiles(dir.c_str()); - VirtList *const files = new VirtList; - if (handle == nullptr) - return files; - for (const char *const *i = handle; *i; i++) - { - std::string str = *i; - files->names.push_back(str); - } - PHYSFS_freeList(handle); - return files; - } - - bool isDirectory(const std::string &restrict name) - { - return PHYSFS_isDirectory(name.c_str()); - } - - bool isSymbolicLink(const std::string &restrict name) - { - return PHYSFS_isSymbolicLink(name.c_str()); - } - - void freeList(VirtList *restrict const handle) - { - delete handle; - } - - VirtFile *openRead(const std::string &restrict filename) - { - PHYSFS_file *restrict const handle = PHYSFS_openRead( - filename.c_str()); - if (!handle) - return nullptr; - VirtFile *restrict const file = new VirtFile(&funcs); - file->mPrivate = new VirtFilePrivate(handle); - return file; - } - - VirtFile *openWrite(const std::string &restrict filename) - { - PHYSFS_file *restrict const handle = PHYSFS_openWrite( - filename.c_str()); - if (!handle) - return nullptr; - VirtFile *restrict const file = new VirtFile(&funcs); - file->mPrivate = new VirtFilePrivate(handle); - return file; - } - - VirtFile *openAppend(const std::string &restrict filename) - { - PHYSFS_file *restrict const handle = PHYSFS_openAppend( - filename.c_str()); - if (!handle) - return nullptr; - VirtFile *restrict const file = new VirtFile(&funcs); - file->mPrivate = new VirtFilePrivate(handle); - return file; - } - - bool setWriteDir(const std::string &restrict newDir) - { - return PHYSFS_setWriteDir(newDir.c_str()); - } - - bool addDirToSearchPath(const std::string &restrict newDir, - const Append append) - { - logger->log("Add virtual directory: " + newDir); - if (newDir.find(".zip") != std::string::npos) - { - reportAlways("Called addDirToSearchPath with zip archive"); - return false; - } - return PHYSFS_addToSearchPath(newDir.c_str(), - append == Append_true ? 1 : 0); - } - - bool removeDirFromSearchPath(const std::string &restrict oldDir) - { - logger->log("Remove virtual directory: " + oldDir); - if (oldDir.find(".zip") != std::string::npos) - { - reportAlways("Called removeDirFromSearchPath with zip archive"); - return false; - } - return PHYSFS_removeFromSearchPath(oldDir.c_str()); - } - - bool addZipToSearchPath(const std::string &restrict newDir, - const Append append) - { - logger->log("Add virtual zip: " + newDir); - if (newDir.find(".zip") == std::string::npos) - { - reportAlways("Called addZipToSearchPath without zip archive"); - return false; - } - return PHYSFS_addToSearchPath(newDir.c_str(), - append == Append_true ? 1 : 0); - } - - bool removeZipFromSearchPath(const std::string &restrict oldDir) - { - logger->log("Remove virtual zip: " + oldDir); - if (oldDir.find(".zip") == std::string::npos) - { - reportAlways("Called removeZipFromSearchPath without zip archive"); - return false; - } - return PHYSFS_removeFromSearchPath(oldDir.c_str()); - } - - std::string getRealDir(const std::string &restrict filename) - { - const char *const str = PHYSFS_getRealDir(filename.c_str()); - if (str == nullptr) - return std::string(); - return str; - } - - bool mkdir(const std::string &restrict dirname) - { - return PHYSFS_mkdir(dirname.c_str()); - } - - bool remove(const std::string &restrict filename) - { - return PHYSFS_delete(filename.c_str()); - } - - bool deinit() - { - if (PHYSFS_deinit() != 0) - { - logger->log("Physfs deinit error: %s", - VirtFsPhys::getLastError()); - return false; - } - return true; - } - - void permitLinks(const bool val) - { - PHYSFS_permitSymbolicLinks(val ? 1 : 0); - } - - const char *getLastError() - { - return PHYSFS_getLastError(); - } - - int close(VirtFile *restrict const file) - { - if (file == nullptr) - return 0; - delete file; - return 1; - } - - int64_t read(VirtFile *restrict const file, - void *restrict const buffer, - const uint32_t objSize, - const uint32_t objCount) - { - if (file == nullptr) - return 0; - return PHYSFS_read(file->mPrivate->mFile, - buffer, - objSize, - objCount); - } - - int64_t write(VirtFile *restrict const file, - const void *restrict const buffer, - const uint32_t objSize, - const uint32_t objCount) - { - if (file == nullptr) - return 0; - return PHYSFS_write(file->mPrivate->mFile, - buffer, - objSize, - objCount); - } - - int64_t fileLength(VirtFile *restrict const file) - { - if (file == nullptr) - return -1; - return PHYSFS_fileLength(file->mPrivate->mFile); - } - - int64_t tell(VirtFile *restrict const file) - { - if (file == nullptr) - return -1; - return PHYSFS_tell(file->mPrivate->mFile); - } - - int seek(VirtFile *restrict const file, - const uint64_t pos) - { - return PHYSFS_seek(file->mPrivate->mFile, - pos); - } - - int eof(VirtFile *restrict const file) - { - return PHYSFS_eof(file->mPrivate->mFile); - } -} // namespace VirtFsPhys diff --git a/src/fs/virtfsphys.h b/src/fs/virtfsphys.h deleted file mode 100644 index 743530c6c..000000000 --- a/src/fs/virtfsphys.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2013-2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef UTILS_VIRTFSPHYS_H -#define UTILS_VIRTFSPHYS_H - -#include "enums/simpletypes/append.h" - -#include "localconsts.h" - -#include - -struct VirtFile; -struct VirtFsFuncs; -struct VirtList; - -namespace VirtFsPhys -{ - void init(const std::string &restrict name); - void initFuncs(VirtFsFuncs *restrict const ptr); - void initFuncs(); - void updateDirSeparator(); - const char *getDirSeparator(); - const char *getBaseDir(); - const char *getUserDir(); - bool exists(const std::string &restrict name); - VirtList *enumerateFiles(const std::string &restrict dir) RETURNS_NONNULL; - bool isDirectory(const std::string &restrict name); - bool isSymbolicLink(const std::string &restrict name); - void freeList(VirtList *restrict const handle); - VirtFile *openRead(const std::string &restrict filename); - VirtFile *openWrite(const std::string &restrict filename); - VirtFile *openAppend(const std::string &restrict filename); - bool setWriteDir(const std::string &restrict newDir); - bool addDirToSearchPath(const std::string &restrict newDir, - const Append append); - bool removeDirFromSearchPath(const std::string &restrict oldDir); - bool addZipToSearchPath(const std::string &restrict newDir, - const Append append); - bool removeZipFromSearchPath(const std::string &restrict oldDir); - std::string getRealDir(const std::string &restrict filename); - bool mkdir(const std::string &restrict dirName); - bool remove(const std::string &restrict filename); - bool deinit(); - void permitLinks(const bool val); - const char *getLastError(); - int64_t read(VirtFile *restrict const handle, - void *restrict const buffer, - const uint32_t objSize, - const uint32_t objCount); - int64_t write(VirtFile *restrict const file, - const void *restrict const buffer, - const uint32_t objSize, - const uint32_t objCount); - int close(VirtFile *restrict const file); - int64_t fileLength(VirtFile *restrict const file); - int64_t tell(VirtFile *restrict const file); - int seek(VirtFile *restrict const file, - const uint64_t pos); - int eof(VirtFile *restrict const file); -} // namespace VirtFsPhys - -#endif // UTILS_VIRTFSPHYS_H diff --git a/src/fs/virtfsphys_unittest.cc b/src/fs/virtfsphys_unittest.cc deleted file mode 100644 index cb7013248..000000000 --- a/src/fs/virtfsphys_unittest.cc +++ /dev/null @@ -1,538 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2016-2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "catch.hpp" - -#include "fs/paths.h" -#include "fs/virtfs.h" -#include "fs/virtfsphys.h" -#include "fs/virtfstools.h" -#include "fs/virtlist.h" - -#include "utils/checkutils.h" -#include "utils/delete2.h" - -#include "debug.h" - -TEST_CASE("VirtFsPhys dirSeparator") -{ - VirtFsPhys::initFuncs(); - REQUIRE(VirtFs::getDirSeparator() != nullptr); - REQUIRE(VirtFsPhys::getDirSeparator() == - std::string(VirtFs::getDirSeparator())); - VirtFsPhys::updateDirSeparator(); - REQUIRE(VirtFs::getDirSeparator() != nullptr); - REQUIRE(VirtFsPhys::getDirSeparator() == - std::string(VirtFs::getDirSeparator())); -} - -TEST_CASE("VirtFsPhys getBaseDir") -{ - VirtFsPhys::initFuncs(); - REQUIRE(VirtFsPhys::getBaseDir() != nullptr); -} - -TEST_CASE("VirtFsPhys getUserDir") -{ - VirtFsPhys::initFuncs(); - REQUIRE(VirtFsPhys::getUserDir() != nullptr); - REQUIRE(VirtFsPhys::getUserDir() == getHomePath()); -} - -TEST_CASE("VirtFsPhys exists") -{ - VirtFsPhys::initFuncs(); - logger = new Logger(); - VirtFsPhys::addDirToSearchPath("data", Append_false); - VirtFsPhys::addDirToSearchPath("../data", Append_false); - - REQUIRE(VirtFsPhys::exists("test/units.xml") == true); - REQUIRE(VirtFsPhys::exists("test/units123.xml") == false); - REQUIRE(VirtFsPhys::exists("tesQ/units.xml") == false); - REQUIRE(VirtFsPhys::exists("units.xml") == false); - - VirtFsPhys::addDirToSearchPath("data/test", Append_false); - VirtFsPhys::addDirToSearchPath("../data/test", Append_false); - - REQUIRE(VirtFsPhys::exists("test/units.xml") == true); - REQUIRE(VirtFsPhys::exists("test/units123.xml") == false); - REQUIRE(VirtFsPhys::exists("tesQ/units.xml") == false); - REQUIRE(VirtFsPhys::exists("units.xml") == true); - - VirtFsPhys::removeDirFromSearchPath("data/test"); - VirtFsPhys::removeDirFromSearchPath("../data/test"); - - REQUIRE(VirtFsPhys::exists("test/units.xml") == true); - REQUIRE(VirtFsPhys::exists("test/units123.xml") == false); - REQUIRE(VirtFsPhys::exists("tesQ/units.xml") == false); - REQUIRE(VirtFsPhys::exists("units.xml") == false); - - VirtFsPhys::removeDirFromSearchPath("data"); - VirtFsPhys::removeDirFromSearchPath("../data"); - delete2(logger); -} - -TEST_CASE("VirtFsPhys exists2") -{ - VirtFsPhys::initFuncs(); - logger = new Logger(); - VirtFsPhys::addZipToSearchPath("data/test/test2.zip", Append_false); - VirtFsPhys::addZipToSearchPath("../data/test/test2.zip", Append_false); - - REQUIRE(VirtFsPhys::exists("test/units.xml") == false); - REQUIRE(VirtFsPhys::exists("test.txt") == true); - REQUIRE(VirtFsPhys::exists("units123.xml") == false); - REQUIRE(VirtFsPhys::exists("tesQ/units.xml") == false); - REQUIRE(VirtFsPhys::exists("units.xml") == true); - - VirtFsPhys::removeZipFromSearchPath("data/test/test2.zip"); - VirtFsPhys::removeZipFromSearchPath("../data/test/test2.zip"); - delete2(logger); -} - -static void removeTemp(StringVect &restrict list) -{ - int cnt = 0; - std::sort(list.begin(), list.end()); - - FOR_EACH (StringVectIter, it, list) - { - if (*it != "serverlistplus.xml.part") - { - logger->log("file: %d %s", - cnt, - (*it).c_str()); - cnt ++; - } - } - - FOR_EACH (StringVectIter, it, list) - { - if (*it == "serverlistplus.xml.part") - { - list.erase(it); - return; - } - } -} - -TEST_CASE("VirtFsPhys enumerateFiles1") -{ - VirtFsPhys::initFuncs(); - logger = new Logger; - - VirtFsPhys::addDirToSearchPath("data", Append_false); - VirtFsPhys::addDirToSearchPath("../data", Append_false); - - VirtList *list = nullptr; - - const int cnt1 = VirtFsPhys::exists("test/test2.txt") ? 27 : 26; - const int cnt2 = 27; - - VirtFsPhys::permitLinks(false); - list = VirtFsPhys::enumerateFiles("test"); - removeTemp(list->names); - const size_t sz = list->names.size(); - REQUIRE(sz == cnt1); - VirtFsPhys::freeList(list); - - VirtFsPhys::permitLinks(true); - list = VirtFsPhys::enumerateFiles("test"); - removeTemp(list->names); - REQUIRE(list->names.size() == cnt2); - VirtFsPhys::freeList(list); - - VirtFsPhys::permitLinks(false); - list = VirtFsPhys::enumerateFiles("test"); - removeTemp(list->names); - REQUIRE(list->names.size() == cnt1); - VirtFsPhys::freeList(list); - - VirtFsPhys::removeDirFromSearchPath("data"); - VirtFsPhys::removeDirFromSearchPath("../data"); - delete2(logger); -} - -TEST_CASE("VirtFsPhys enumerateFiles2") -{ - VirtFsPhys::initFuncs(); - logger = new Logger; - - VirtFsPhys::addDirToSearchPath("data/test/dir1", - Append_false); - VirtFsPhys::addDirToSearchPath("../data/test/dir1", - Append_false); - - VirtList *list = nullptr; - - list = VirtFsPhys::enumerateFiles("/"); - const size_t sz = list->names.size(); - REQUIRE(list->names.size() == 5); - VirtFsPhys::freeList(list); - - VirtFsPhys::removeDirFromSearchPath("data/test/dir1"); - VirtFsPhys::removeDirFromSearchPath("../data/test/dir1"); - delete2(logger); -} - -static bool inList(VirtList *list, - const std::string &name) -{ - FOR_EACH (StringVectCIter, it, list->names) - { - if (*it == name) - return true; - } - return false; -} - -TEST_CASE("VirtFsPhys enumerateFiles3") -{ - VirtFsPhys::initFuncs(); - logger = new Logger; - - VirtFsPhys::addZipToSearchPath("data/test/test.zip", - Append_false); - VirtFsPhys::addZipToSearchPath("../data/test/test.zip", - Append_false); - - VirtList *list = nullptr; - - list = VirtFsPhys::enumerateFiles("/"); - REQUIRE(inList(list, "units.xml") == false); - REQUIRE(inList(list, "test.txt") == false); - VirtFsPhys::freeList(list); - - VirtFsPhys::removeZipFromSearchPath("data/test/test.zip"); - VirtFsPhys::removeZipFromSearchPath("../data/test/test.zip"); - delete2(logger); -} - -TEST_CASE("VirtFsPhys enumerateFiles4") -{ - VirtFsPhys::initFuncs(); - logger = new Logger; - - VirtFsPhys::addZipToSearchPath("data/test/test2.zip", - Append_false); - VirtFsPhys::addZipToSearchPath("../data/test/test2.zip", - Append_false); - - VirtList *list = nullptr; - - list = VirtFsPhys::enumerateFiles("/"); - REQUIRE(inList(list, "units.xml") == true); - REQUIRE(inList(list, "test.txt") == true); - VirtFsPhys::freeList(list); - - VirtFsPhys::removeZipFromSearchPath("data/test/test2.zip"); - VirtFsPhys::removeZipFromSearchPath("../data/test/test2.zip"); - delete2(logger); -} - -TEST_CASE("VirtFsPhys isDirectory") -{ - VirtFsPhys::initFuncs(); - logger = new Logger(); - VirtFsPhys::addDirToSearchPath("data", Append_false); - VirtFsPhys::addDirToSearchPath("../data", Append_false); - - REQUIRE(VirtFsPhys::isDirectory("test/units.xml") == false); - REQUIRE(VirtFsPhys::isDirectory("test/units.xml/") == false); - REQUIRE(VirtFsPhys::isDirectory("test//units.xml") == false); - REQUIRE(VirtFsPhys::isDirectory("test/units123.xml") == false); - REQUIRE(VirtFsPhys::isDirectory("test//units123.xml") == false); - REQUIRE(VirtFsPhys::isDirectory("tesQ/units.xml") == false); - REQUIRE(VirtFsPhys::isDirectory("tesQ//units.xml") == false); - REQUIRE(VirtFsPhys::isDirectory("units.xml") == false); - REQUIRE(VirtFsPhys::isDirectory("test") == true); - REQUIRE(VirtFsPhys::isDirectory("test/") == true); - REQUIRE(VirtFsPhys::isDirectory("test//") == true); - REQUIRE(VirtFsPhys::isDirectory("test/dir1") == true); - REQUIRE(VirtFsPhys::isDirectory("test//dir1") == true); - REQUIRE(VirtFsPhys::isDirectory("test//dir1/") == true); - REQUIRE(VirtFsPhys::isDirectory("test//dir1//") == true); - REQUIRE(VirtFsPhys::isDirectory("test/dir1/") == true); - REQUIRE(VirtFsPhys::isDirectory("test/dir1//") == true); - REQUIRE(VirtFsPhys::isDirectory("testQ") == false); - REQUIRE(VirtFsPhys::isDirectory("testQ/") == false); - REQUIRE(VirtFsPhys::isDirectory("testQ//") == false); - - VirtFsPhys::addDirToSearchPath("data/test", Append_false); - VirtFsPhys::addDirToSearchPath("../data/test", Append_false); - - REQUIRE(VirtFsPhys::isDirectory("test/units.xml") == false); - REQUIRE(VirtFsPhys::isDirectory("test/units.xml/") == false); - REQUIRE(VirtFsPhys::isDirectory("test//units.xml") == false); - REQUIRE(VirtFsPhys::isDirectory("test/units123.xml") == false); - REQUIRE(VirtFsPhys::isDirectory("tesQ/units.xml") == false); - REQUIRE(VirtFsPhys::isDirectory("units.xml") == false); - REQUIRE(VirtFsPhys::isDirectory("test") == true); - REQUIRE(VirtFsPhys::isDirectory("testQ") == false); - REQUIRE(VirtFsPhys::isDirectory("test/dir1") == true); - - VirtFsPhys::removeDirFromSearchPath("data/test"); - VirtFsPhys::removeDirFromSearchPath("../data/test"); - - REQUIRE(VirtFsPhys::isDirectory("test/units.xml") == false); - REQUIRE(VirtFsPhys::isDirectory("test/units123.xml") == false); - REQUIRE(VirtFsPhys::isDirectory("tesQ/units.xml") == false); - REQUIRE(VirtFsPhys::isDirectory("units.xml") == false); - REQUIRE(VirtFsPhys::isDirectory("units.xml/") == false); - REQUIRE(VirtFsPhys::isDirectory("test") == true); - REQUIRE(VirtFsPhys::isDirectory("test/") == true); - REQUIRE(VirtFsPhys::isDirectory("testQ") == false); - REQUIRE(VirtFsPhys::isDirectory("test/dir1") == true); - - VirtFsPhys::removeDirFromSearchPath("data"); - VirtFsPhys::removeDirFromSearchPath("../data"); - delete2(logger); -} - -TEST_CASE("VirtFsPhys openRead") -{ - VirtFsPhys::initFuncs(); - logger = new Logger(); - VirtFsPhys::addDirToSearchPath("data", Append_false); - VirtFsPhys::addDirToSearchPath("../data", Append_false); - - VirtFile *file = nullptr; - - file = VirtFsPhys::openRead("test/units.xml"); - REQUIRE(file != nullptr); - VirtFsPhys::close(file); - file = VirtFsPhys::openRead("test/units123.xml"); - REQUIRE(file == nullptr); - file = VirtFsPhys::openRead("tesQ/units.xml"); - REQUIRE(file == nullptr); - file = VirtFsPhys::openRead("units.xml"); - REQUIRE(file == nullptr); -// file = VirtFsPhys::openRead("test"); -// REQUIRE(file == nullptr); - file = VirtFsPhys::openRead("testQ"); - REQUIRE(file == nullptr); - - VirtFsPhys::addDirToSearchPath("data/test", Append_false); - VirtFsPhys::addDirToSearchPath("../data/test", Append_false); - - file = VirtFsPhys::openRead("test/units.xml"); - REQUIRE(file != nullptr); - VirtFsPhys::close(file); - file = VirtFsPhys::openRead("test/units123.xml"); - REQUIRE(file == nullptr); - file = VirtFsPhys::openRead("tesQ/units.xml"); - REQUIRE(file == nullptr); - file = VirtFsPhys::openRead("units.xml"); - REQUIRE(file != nullptr); - VirtFsPhys::close(file); -// file = VirtFsPhys::openRead("test"); -// REQUIRE(file == nullptr); - file = VirtFsPhys::openRead("testQ"); - REQUIRE(file == nullptr); - - VirtFsPhys::removeDirFromSearchPath("data/test"); - VirtFsPhys::removeDirFromSearchPath("../data/test"); - - file = VirtFsPhys::openRead("test/units.xml"); - REQUIRE(file != nullptr); - VirtFsPhys::close(file); - file = VirtFsPhys::openRead("test/units123.xml"); - REQUIRE(file == nullptr); - file = VirtFsPhys::openRead("tesQ/units.xml"); - REQUIRE(file == nullptr); - file = VirtFsPhys::openRead("units.xml"); - REQUIRE(file == nullptr); -// file = VirtFsPhys::openRead("test"); -// REQUIRE(file == nullptr); - file = VirtFsPhys::openRead("testQ"); - REQUIRE(file == nullptr); - - VirtFsPhys::removeDirFromSearchPath("data"); - VirtFsPhys::removeDirFromSearchPath("../data"); - delete2(logger); -} - -TEST_CASE("VirtFsPhys addZipToSearchPath") -{ - // +++ need implement -} - -TEST_CASE("VirtFsPhys removeZipFromSearchPath") -{ - // +++ need implement -} - -TEST_CASE("VirtFsPhys getRealDir") -{ - VirtFsPhys::initFuncs(); - logger = new Logger(); - REQUIRE(VirtFsPhys::getRealDir(".") == ""); - REQUIRE(VirtFsPhys::getRealDir("..") == ""); - const bool dir1 = VirtFsPhys::addDirToSearchPath("data", Append_false); - REQUIRE((dir1 || VirtFsPhys::addDirToSearchPath( - "../data", Append_false)) == true); - if (dir1 == true) - { - REQUIRE(VirtFsPhys::getRealDir("test") == "data"); - REQUIRE(VirtFsPhys::getRealDir("test/test.txt") == - "data"); - } - else - { - REQUIRE(VirtFsPhys::getRealDir("test") == "../data"); - REQUIRE(VirtFsPhys::getRealDir("test/test.txt") == - "../data"); - } - REQUIRE(VirtFsPhys::getRealDir("zzz") == ""); - - VirtFsPhys::addDirToSearchPath("data/test", Append_false); - VirtFsPhys::addDirToSearchPath("../data/test", Append_false); - if (dir1 == true) - { - REQUIRE(VirtFsPhys::getRealDir("test") == "data"); - REQUIRE(VirtFsPhys::getRealDir("test/test.txt") == - "data"); - REQUIRE(VirtFsPhys::getRealDir("test.txt") == - "data/test"); - } - else - { - REQUIRE(VirtFsPhys::getRealDir("test") == "../data"); - REQUIRE(VirtFsPhys::getRealDir("test/test.txt") == - "../data"); - REQUIRE(VirtFsPhys::getRealDir("test.txt") == - "../data/test"); - } - REQUIRE(VirtFsPhys::getRealDir("zzz") == ""); - - if (dir1 == true) - { - VirtFsPhys::addZipToSearchPath("data/test/test.zip", Append_false); - REQUIRE(VirtFsPhys::getRealDir("dir/brimmedhat.png") == - "data/test/test.zip"); - REQUIRE(VirtFsPhys::getRealDir("hide.png") == "data/test"); - } - else - { - VirtFsPhys::addZipToSearchPath("../data/test/test.zip", Append_false); - REQUIRE(VirtFsPhys::getRealDir("dir/brimmedhat.png") == - "../data/test/test.zip"); - REQUIRE(VirtFsPhys::getRealDir("hide.png") == "../data/test"); - } - - VirtFsPhys::removeDirFromSearchPath("data/test"); - VirtFsPhys::removeDirFromSearchPath("../data/test"); - - if (dir1 == true) - { - REQUIRE(VirtFsPhys::getRealDir("test") == "data"); - REQUIRE(VirtFsPhys::getRealDir("test/test.txt") == - "data"); - REQUIRE(VirtFsPhys::getRealDir("dir/hide.png") == - "data/test/test.zip"); - } - else - { - REQUIRE(VirtFsPhys::getRealDir("test") == "../data"); - REQUIRE(VirtFsPhys::getRealDir("test/test.txt") == - "../data"); - REQUIRE(VirtFsPhys::getRealDir("dir/hide.png") == - "../data/test/test.zip"); - } - REQUIRE(VirtFsPhys::exists("dir/hide.png")); - REQUIRE(VirtFsPhys::getRealDir("zzz") == ""); - - VirtFsPhys::removeDirFromSearchPath("data"); - VirtFsPhys::removeDirFromSearchPath("../data"); - VirtFsPhys::removeZipFromSearchPath("data/test/test.zip"); - VirtFsPhys::removeZipFromSearchPath("../data/test/test.zip"); - delete2(logger); -} - -TEST_CASE("VirtFsPhys permitLinks") -{ - VirtFsPhys::initFuncs(); - logger = new Logger(); - VirtFsPhys::addDirToSearchPath("data", Append_false); - VirtFsPhys::addDirToSearchPath("../data", Append_false); - - const int cnt1 = VirtFsPhys::exists("test/test2.txt") ? 25 : 24; - const int cnt2 = 25; - - StringVect list; - VirtFsPhys::permitLinks(false); - VirtFsPhys::getFiles("test", list); - removeTemp(list); - const size_t sz = list.size(); - REQUIRE(sz == cnt1); - - list.clear(); - VirtFsPhys::permitLinks(true); - VirtFsPhys::getFiles("test", list); - removeTemp(list); - REQUIRE(list.size() == cnt2); - - list.clear(); - VirtFsPhys::permitLinks(false); - VirtFsPhys::getFiles("test", list); - removeTemp(list); - REQUIRE(list.size() == cnt1); - - VirtFsPhys::removeDirFromSearchPath("data"); - VirtFsPhys::removeDirFromSearchPath("../data"); - delete2(logger); -} - -TEST_CASE("VirtFsPhys read") -{ - VirtFsPhys::initFuncs(); - logger = new Logger(); - VirtFsPhys::addDirToSearchPath("data", Append_false); - VirtFsPhys::addDirToSearchPath("../data", Append_false); - - VirtFile *file = VirtFsPhys::openRead("test/test.txt"); - REQUIRE(file != nullptr); - REQUIRE(VirtFsPhys::fileLength(file) == 23); - const int fileSize = VirtFsPhys::fileLength(file); - - void *restrict buffer = calloc(fileSize + 1, 1); - REQUIRE(VirtFsPhys::read(file, buffer, 1, fileSize) == fileSize); - REQUIRE(strcmp(static_cast(buffer), - "test line 1\ntest line 2") == 0); - REQUIRE(VirtFsPhys::tell(file) == fileSize); - REQUIRE(VirtFsPhys::eof(file) == true); - - free(buffer); - buffer = calloc(fileSize + 1, 1); - REQUIRE(VirtFsPhys::seek(file, 12) != 0); - REQUIRE(VirtFsPhys::eof(file) == false); - REQUIRE(VirtFsPhys::tell(file) == 12); - REQUIRE(VirtFsPhys::read(file, buffer, 1, 11) == 11); - REQUIRE(strcmp(static_cast(buffer), - "test line 2") == 0); - REQUIRE(VirtFsPhys::eof(file) == true); - - VirtFsPhys::close(file); - free(buffer); - - VirtFsPhys::removeDirFromSearchPath("data"); - VirtFsPhys::removeDirFromSearchPath("../data"); - delete2(logger); -} diff --git a/src/fs/virtfstools.cpp b/src/fs/virtfstools.cpp index 39f1ed413..cf3da4b7a 100644 --- a/src/fs/virtfstools.cpp +++ b/src/fs/virtfstools.cpp @@ -24,8 +24,12 @@ #include "fs/paths.h" #include "fs/virtfs.h" -#include "fs/virtfsdir.h" -#include "fs/virtfsphys.h" + +#ifdef USE_PHYSFS +#include "fs/physfs/virtfsphys.h" +#else // USE_PHYSFS +#include "fs/virtfs/virtfsdir.h" +#endif // USE_PHYSFS #include "fs/virtlist.h" #include "utils/stringutils.h" diff --git a/src/fs/virtfszip.cpp b/src/fs/virtfszip.cpp deleted file mode 100644 index 538eb7513..000000000 --- a/src/fs/virtfszip.cpp +++ /dev/null @@ -1,540 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2013-2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "fs/virtfszip.h" - -#include "fs/files.h" -#include "fs/paths.h" -#include "fs/virtfile.h" -#include "fs/virtfileprivate.h" -#include "fs/virtfsfuncs.h" -#include "fs/virtlist.h" -#include "fs/virtzipentry.h" -#include "fs/zip.h" -#include "fs/ziplocalheader.h" - -#include "utils/checkutils.h" -#include "utils/dtor.h" -#include "utils/stringutils.h" - -#include "debug.h" - -extern const char *dirSeparator; - -namespace -{ - std::vector mEntries; - VirtFsFuncs funcs; -} // namespace - -namespace VirtFsZip -{ - VirtZipEntry *searchEntryByArchive(const std::string &restrict archiveName) - { - FOR_EACH (std::vector::const_iterator, it, mEntries) - { - if ((*it)->mArchiveName == archiveName) - return *it; - } - return nullptr; - } - - ZipLocalHeader *searchHeaderByName(const std::string &restrict filename) - { - FOR_EACH (std::vector::const_iterator, it, mEntries) - { - VirtZipEntry *const entry = *it; - FOR_EACH (std::vector::const_iterator, - it2, - entry->mHeaders) - { - if ((*it2)->fileName == filename) - return *it2;; - } - } - return nullptr; - } - - bool addToSearchPathSilent(std::string newDir, - const Append append) - { - prepareFsPath(newDir); - if (Files::existsLocal(newDir) == false) - { - logger->log("VirtFsZip::addToSearchPath file not exists: %s", - newDir.c_str()); - return false; - } - if (findLast(newDir, ".zip") == false) - { - reportAlways("Called VirtFsZip::addToSearchPath without " - "zip archive"); - return false; - } - VirtZipEntry *entry = VirtFsZip::searchEntryByArchive(newDir); - if (entry != nullptr) - { - reportAlways("VirtFsZip::addToSearchPath already exists: %s", - newDir.c_str()); - return false; - } - entry = new VirtZipEntry(newDir); - if (Zip::readArchiveInfo(entry) == false) - { - delete entry; - return false; - } - - logger->log("Add virtual zip: " + newDir); - if (append == Append_true) - mEntries.push_back(entry); - else - { - mEntries.insert(mEntries.begin(), - entry); - } - return true; - } - - bool addToSearchPath(std::string newDir, - const Append append) - { - prepareFsPath(newDir); - if (Files::existsLocal(newDir) == false) - { - reportAlways("VirtFsZip::addToSearchPath directory not exists: %s", - newDir.c_str()); - return false; - } - if (findLast(newDir, ".zip") == false) - { - reportAlways("Called VirtFsZip::addToSearchPath without " - "zip archive"); - return false; - } - VirtZipEntry *entry = VirtFsZip::searchEntryByArchive(newDir); - if (entry != nullptr) - { - reportAlways("VirtFsZip::addToSearchPath already exists: %s", - newDir.c_str()); - return false; - } - entry = new VirtZipEntry(newDir); - if (Zip::readArchiveInfo(entry) == false) - { - delete entry; - return false; - } - - logger->log("Add virtual zip: " + newDir); - if (append == Append_true) - mEntries.push_back(entry); - else - { - mEntries.insert(mEntries.begin(), - entry); - } - return true; - } - - bool removeFromSearchPathSilent(std::string oldDir) - { - prepareFsPath(oldDir); - if (findLast(oldDir, ".zip") == false) - { - reportAlways("Called removeFromSearchPath without zip archive"); - return false; - } - FOR_EACH (std::vector::iterator, it, mEntries) - { - VirtZipEntry *const entry = *it; - if (entry->mArchiveName == oldDir) - { - logger->log("Remove virtual zip: " + oldDir); - mEntries.erase(it); - delete entry; - return true; - } - } - - logger->log("VirtFsZip::removeFromSearchPath not exists: %s", - oldDir.c_str()); - return false; - } - - bool removeFromSearchPath(std::string oldDir) - { - prepareFsPath(oldDir); - if (findLast(oldDir, ".zip") == false) - { - reportAlways("Called removeFromSearchPath without zip archive"); - return false; - } - FOR_EACH (std::vector::iterator, it, mEntries) - { - VirtZipEntry *const entry = *it; - if (entry->mArchiveName == oldDir) - { - logger->log("Remove virtual zip: " + oldDir); - mEntries.erase(it); - delete entry; - return true; - } - } - - reportAlways("VirtFsZip::removeFromSearchPath not exists: %s", - oldDir.c_str()); - return false; - } - - std::vector &getEntries() - { - return mEntries; - } - - void deinit() - { - delete_all(mEntries); - mEntries.clear(); - } - - void init() - { - initFuncs(&funcs); - } - - void initFuncs(VirtFsFuncs *restrict const ptr) - { - ptr->close = &VirtFsZip::close; - ptr->read = &VirtFsZip::read; - ptr->write = &VirtFsZip::write; - ptr->fileLength = &VirtFsZip::fileLength; - ptr->tell = &VirtFsZip::tell; - ptr->seek = &VirtFsZip::seek; - ptr->eof = &VirtFsZip::eof; - } - - std::string getRealDir(std::string filename) - { - prepareFsPath(filename); - if (checkPath(filename) == false) - { - reportAlways("VirtFsZip::exists invalid path: %s", - filename.c_str()); - return std::string(); - } - ZipLocalHeader *restrict const header = searchHeaderByName(filename); - if (header != nullptr) - return header->zipEntry->mArchiveName; - return std::string(); - } - - bool exists(std::string name) - { - prepareFsPath(name); - if (checkPath(name) == false) - { - reportAlways("VirtFsZip::exists invalid path: %s", - name.c_str()); - return false; - } - ZipLocalHeader *restrict const header = searchHeaderByName(name); - if (header != nullptr) - return true; - return false; - } - - VirtList *enumerateFiles(const std::string &dirName) - { - VirtList *const list = new VirtList; - return enumerateFiles(dirName, list); - } - - VirtList *enumerateFiles(std::string dirName, - VirtList *const list) - { - prepareFsPath(dirName); - VirtList *const list = new VirtList; - if (checkPath(dirName) == false) - { - reportAlways("VirtFsZip::enumerateFiles invalid path: %s", - dirName.c_str()); - return list; - } - if (findLast(dirName, std::string(dirSeparator)) == false) - dirName += dirSeparator; - StringVect &names = list->names; - if (dirName == "/") - { - FOR_EACH (std::vector::const_iterator, it, mEntries) - { - VirtZipEntry *const entry = *it; - FOR_EACH (std::vector::const_iterator, - it2, - entry->mHeaders) - { - ZipLocalHeader *const header = *it2; - std::string fileName = header->fileName; - // skip subdirs from enumeration - const size_t idx = fileName.find(dirSeparator); - if (idx != std::string::npos) - fileName.erase(idx); - bool found(false); - FOR_EACH (StringVectCIter, itn, names) - { - if (*itn == fileName) - { - found = true; - break; - } - } - if (found == false) - names.push_back(fileName); - } - } - } - else - { - FOR_EACH (std::vector::const_iterator, it, mEntries) - { - VirtZipEntry *const entry = *it; - FOR_EACH (std::vector::const_iterator, - it2, - entry->mHeaders) - { - ZipLocalHeader *const header = *it2; - std::string fileName = header->fileName; - if (findCutFirst(fileName, dirName) == true) - { - // skip subdirs from enumeration - const size_t idx = fileName.find(dirSeparator); - if (idx != std::string::npos) - fileName.erase(idx); - bool found(false); - FOR_EACH (StringVectCIter, itn, names) - { - if (*itn == fileName) - { - found = true; - break; - } - } - if (found == false) - names.push_back(fileName); - } - } - } - } - - return list; - } - - bool isDirectory(std::string dirName) - { - prepareFsPath(dirName); - if (checkPath(dirName) == false) - { - reportAlways("VirtFsZip::isDirectory invalid path: %s", - dirName.c_str()); - return false; - } - if (findLast(dirName, std::string(dirSeparator)) == false) - dirName += dirSeparator; - FOR_EACH (std::vector::const_iterator, it, mEntries) - { - VirtZipEntry *const entry = *it; - FOR_EACH (std::vector::const_iterator, - it2, - entry->mDirs) - { - if (*it2 == dirName) - return true; - } - } - return false; - } - - bool isSymbolicLink(std::string name) - { - prepareFsPath(name); - if (checkPath(name) == false) - { - reportAlways("VirtFsZip::isSymbolicLink invalid path: %s", - name.c_str()); - return false; - } - // look like in zip files can be symlinks, but here they useless - return false; - } - - void freeList(VirtList *restrict const handle) - { - delete handle; - } - - VirtFile *openRead(std::string filename) - { - prepareFsPath(filename); - if (checkPath(filename) == false) - { - reportAlways("VirtFsZip::openRead invalid path: %s", - filename.c_str()); - return nullptr; - } - ZipLocalHeader *restrict const header = searchHeaderByName(filename); - if (header != nullptr) - { - uint8_t *restrict const buf = Zip::readFile(header); - if (buf == nullptr) - return nullptr; - VirtFile *restrict const file = new VirtFile(&funcs); - file->mPrivate = new VirtFilePrivate(buf, - header->uncompressSize); - return file; - } - return nullptr; - } - - VirtFile *openWrite(const std::string &restrict filename A_UNUSED) - { - return nullptr; - } - - VirtFile *openAppend(const std::string &restrict filename A_UNUSED) - { - return nullptr; - } - - bool setWriteDir(const std::string &restrict newDir A_UNUSED) - { - return false; - } - - bool mkdir(const std::string &restrict dirname A_UNUSED) - { - return false; - } - - bool remove(const std::string &restrict filename A_UNUSED) - { - return false; - } - - void permitLinks(const bool val A_UNUSED) - { - } - - const char *getLastError() - { - return nullptr; - } - - int close(VirtFile *restrict const file) - { - if (file == nullptr) - return 0; - delete file; - return 1; - } - - int64_t read(VirtFile *restrict const file, - void *restrict const buffer, - const uint32_t objSize, - const uint32_t objCount) - { - if (file == nullptr || - objSize == 0 || - objCount == 0) - { - return 0; - } - if (buffer == nullptr) - { - reportAlways("VirtFsZip::read buffer is null"); - return 0; - } - VirtFilePrivate *restrict const priv = file->mPrivate; - const uint32_t pos = priv->mPos; - const uint32_t sz = priv->mSize; - // if outside of buffer, return - if (pos >= sz) - return 0; - // pointer to start for buffer ready to read - const uint8_t *restrict const memPtr = priv->mBuf + pos; - // left buffer size from pos to end - const uint32_t memSize = sz - pos; - // number of objects possible to read - uint32_t memCount = memSize / objSize; - if (memCount == 0) - return 0; - // limit number of possible objects to read to objCount - if (memCount > objCount) - memCount = objCount; - // number of bytes to read from buffer - const uint32_t memEnd = memCount * objSize; - memcpy(buffer, memPtr, memEnd); - priv->mPos += memEnd; - return memCount; - } - - int64_t write(VirtFile *restrict const file A_UNUSED, - const void *restrict const buffer A_UNUSED, - const uint32_t objSize A_UNUSED, - const uint32_t objCount A_UNUSED) - { - return 0; - } - - int64_t fileLength(VirtFile *restrict const file) - { - if (file == nullptr) - return -1; - - return file->mPrivate->mSize; - } - - int64_t tell(VirtFile *restrict const file) - { - if (file == nullptr) - return -1; - - return file->mPrivate->mPos; - } - - int seek(VirtFile *restrict const file, - const uint64_t pos) - { - if (file == nullptr) - return 0; - - if (pos > file->mPrivate->mSize) - return 0; - file->mPrivate->mPos = pos; - return 1; - } - - int eof(VirtFile *restrict const file) - { - if (file == nullptr) - return -1; - - return file->mPrivate->mPos >= file->mPrivate->mSize; - } -} // namespace VirtFsZip diff --git a/src/fs/virtfszip.h b/src/fs/virtfszip.h deleted file mode 100644 index fd7a0568b..000000000 --- a/src/fs/virtfszip.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2013-2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef UTILS_VIRTFSZIP_H -#define UTILS_VIRTFSZIP_H - -#include "enums/simpletypes/append.h" -#include "enums/simpletypes/skiperror.h" - -#include "localconsts.h" - -#include -#include - -struct VirtFile; -struct VirtList; -struct VirtFsFuncs; -struct VirtZipEntry; -struct ZipLocalHeader; - -namespace VirtFsZip -{ - VirtZipEntry *searchEntryByArchive(const std::string &restrict archiveName); - ZipLocalHeader *searchHeaderByName(const std::string &restrict filename); - bool addToSearchPath(std::string newDir, - const Append append); - bool addToSearchPathSilent(std::string newDir, - const Append append); - bool removeFromSearchPath(std::string oldDir); - bool removeFromSearchPathSilent(std::string oldDir); - void init(); - void initFuncs(VirtFsFuncs *restrict const ptr); - void deinit(); - std::vector &getEntries(); - bool exists(std::string name); - VirtList *enumerateFiles(const std::string &dirName) RETURNS_NONNULL; - VirtList *enumerateFiles(std::string dirName, - VirtList *const list) RETURNS_NONNULL; - bool isDirectory(std::string dirName); - bool isSymbolicLink(std::string name); - void freeList(VirtList *restrict const handle); - VirtFile *openRead(std::string filename); - VirtFile *openWrite(const std::string &restrict filename); - VirtFile *openAppend(const std::string &restrict filename); - bool setWriteDir(const std::string &restrict newDir); - std::string getRealDir(std::string filename); - bool mkdir(const std::string &restrict dirName); - bool remove(const std::string &restrict filename); - void permitLinks(const bool val); - const char *getLastError(); - int64_t read(VirtFile *restrict const handle, - void *restrict const buffer, - const uint32_t objSize, - const uint32_t objCount); - int64_t write(VirtFile *restrict const file, - const void *restrict const buffer, - const uint32_t objSize, - const uint32_t objCount); - int close(VirtFile *restrict const file); - int64_t fileLength(VirtFile *restrict const file); - int64_t tell(VirtFile *restrict const file); - int seek(VirtFile *restrict const file, - const uint64_t pos); - int eof(VirtFile *restrict const file); -} // namespace VirtFsZip - -#endif // UTILS_VIRTFSZIP_H diff --git a/src/fs/virtfszip_unittest.cc b/src/fs/virtfszip_unittest.cc deleted file mode 100644 index 4840a23a9..000000000 --- a/src/fs/virtfszip_unittest.cc +++ /dev/null @@ -1,744 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2016-2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "catch.hpp" - -#include "fs/files.h" -#include "fs/virtlist.h" -#include "fs/virtfszip.h" -#include "fs/virtzipentry.h" - -#include "utils/checkutils.h" -#include "utils/delete2.h" - -#include "debug.h" - -TEST_CASE("VirtFsZip getEntries") -{ - VirtFsZip::init(); - REQUIRE(VirtFsZip::getEntries().empty()); - REQUIRE(VirtFsZip::searchEntryByArchive("test.zip") == nullptr); - VirtFsZip::deinit(); -} - -TEST_CASE("VirtFsZip addToSearchPath") -{ - VirtFsZip::init(); - logger = new Logger(); - std::string name("data/test/test.zip"); - std::string prefix("data/test/"); - std::vector headers; - if (Files::existsLocal(name) == false) - prefix = "../" + prefix; - - SECTION("simple 1") - { - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "/test.zip", - Append_false)); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "test.zip") != nullptr); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "file2.zip") == nullptr); - REQUIRE(VirtFsZip::getEntries().size() == 1); - REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == - prefix + "test.zip"); - } - - SECTION("simple 2") - { - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "\\test.zip", - Append_true)); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "test.zip") != nullptr); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "file2.zip") == nullptr); - REQUIRE(VirtFsZip::getEntries().size() == 1); - REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == - prefix + "test.zip"); - } - - SECTION("simple 3") - { - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test.zip", - Append_false)); - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", - Append_false)); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "test.zip") != nullptr); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "test2.zip") != nullptr); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "test3.zip") == nullptr); - REQUIRE(VirtFsZip::getEntries().size() == 2); - REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == - prefix + "test2.zip"); - REQUIRE(VirtFsZip::getEntries()[1]->mArchiveName == - prefix + "test.zip"); - } - - SECTION("simple 4") - { - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test.zip", - Append_true)); - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", - Append_true)); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "test.zip") != nullptr); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "test2.zip") != nullptr); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "test3.zip") == nullptr); - REQUIRE(VirtFsZip::getEntries().size() == 2); - REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == - prefix + "test.zip"); - REQUIRE(VirtFsZip::getEntries()[1]->mArchiveName == - prefix + "test2.zip"); - } - - SECTION("simple 5") - { - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test.zip", - Append_true)); - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", - Append_true)); - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test3.zip", - Append_true)); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "test.zip") != nullptr); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "test2.zip") != nullptr); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "test3.zip") != nullptr); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "test4.zip") == nullptr); - REQUIRE(VirtFsZip::getEntries().size() == 3); - REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == - prefix + "test.zip"); - REQUIRE(VirtFsZip::getEntries()[1]->mArchiveName == - prefix + "test2.zip"); - REQUIRE(VirtFsZip::getEntries()[2]->mArchiveName == - prefix + "test3.zip"); - } - - SECTION("simple 6") - { - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test.zip", - Append_true)); - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", - Append_true)); - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test3.zip", - Append_false)); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "test.zip") != nullptr); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "test2.zip") != nullptr); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "test3.zip") != nullptr); - REQUIRE(VirtFsZip::searchEntryByArchive( - prefix + "test4.zip") == nullptr); - REQUIRE(VirtFsZip::getEntries().size() == 3); - REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == - prefix + "test3.zip"); - REQUIRE(VirtFsZip::getEntries()[1]->mArchiveName == - prefix + "test.zip"); - REQUIRE(VirtFsZip::getEntries()[2]->mArchiveName == - prefix + "test2.zip"); - } - - VirtFsZip::deinit(); - delete2(logger); -} - -TEST_CASE("VirtFsZip removeFromSearchPath") -{ - VirtFsZip::init(); - logger = new Logger(); - std::string name("data/test/test.zip"); - std::string prefix("data/test/"); - std::vector headers; - if (Files::existsLocal(name) == false) - prefix = "../" + prefix; - - SECTION("simple 1") - { - REQUIRE_THROWS(VirtFsZip::removeFromSearchPath( - prefix + "test123.zip")); - } - - SECTION("simple 2") - { - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test.zip", - Append_true)); - REQUIRE_THROWS(VirtFsZip::removeFromSearchPath(prefix + "test2.zip")); - REQUIRE(VirtFsZip::removeFromSearchPath(prefix + "test.zip")); - } - - SECTION("simple 3") - { - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test.zip", - Append_true)); - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", - Append_true)); - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test3.zip", - Append_false)); - REQUIRE(VirtFsZip::getEntries().size() == 3); - REQUIRE_THROWS(VirtFsZip::removeFromSearchPath(prefix + "test4.zip")); - REQUIRE(VirtFsZip::removeFromSearchPath(prefix + "test.zip")); - REQUIRE(VirtFsZip::getEntries().size() == 2); - REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == - prefix + "test3.zip"); - REQUIRE(VirtFsZip::getEntries()[1]->mArchiveName == - prefix + "test2.zip"); - REQUIRE_THROWS(VirtFsZip::removeFromSearchPath(prefix + "test.zip")); - REQUIRE(VirtFsZip::getEntries().size() == 2); - REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == - prefix + "test3.zip"); - REQUIRE(VirtFsZip::getEntries()[1]->mArchiveName == - prefix + "test2.zip"); - REQUIRE(VirtFsZip::removeFromSearchPath(prefix + "//test2.zip")); - REQUIRE_THROWS(VirtFsZip::removeFromSearchPath(prefix + "test2.zip")); - REQUIRE(VirtFsZip::getEntries().size() == 1); - REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == - prefix + "test3.zip"); - } - - SECTION("simple 4") - { - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "\\test.zip", - Append_true)); - REQUIRE(VirtFsZip::getEntries().size() == 1); - REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == - prefix + "test.zip"); - REQUIRE_THROWS(VirtFsZip::removeFromSearchPath(prefix + "test2.zip")); - REQUIRE(VirtFsZip::removeFromSearchPath(prefix + "\\test.zip")); - REQUIRE(VirtFsZip::getEntries().size() == 0); - REQUIRE(VirtFsZip::addToSearchPathSilent(prefix + "test.zip", - Append_true)); - REQUIRE(VirtFsZip::getEntries().size() == 1); - REQUIRE(VirtFsZip::getEntries()[0]->mArchiveName == - prefix + "test.zip"); - } - - VirtFsZip::deinit(); - delete2(logger); -} - -TEST_CASE("VirtFsZip exists") -{ - VirtFsZip::init(); - logger = new Logger(); - VirtFsZip::addToSearchPathSilent("data\\test/test2.zip", - Append_false); - VirtFsZip::addToSearchPathSilent("../data\\test/test2.zip", - Append_false); - - REQUIRE(VirtFsZip::exists("dir2//units.xml") == true); - REQUIRE(VirtFsZip::exists("test/units123.xml") == false); - REQUIRE(VirtFsZip::exists("tesQ/units.xml") == false); - REQUIRE(VirtFsZip::exists("units1.xml") == false); - REQUIRE(VirtFsZip::exists("dir/hide.png") == true); - REQUIRE(VirtFsZip::exists("dir/brimmedhat.png") == false); - - VirtFsZip::addToSearchPathSilent("data/test/test.zip", - Append_false); - VirtFsZip::addToSearchPathSilent("../data/test/test.zip", - Append_false); - - REQUIRE(VirtFsZip::exists("dir2\\units.xml") == true); - REQUIRE(VirtFsZip::exists("test/units123.xml") == false); - REQUIRE(VirtFsZip::exists("tesQ/units.xml") == false); - REQUIRE(VirtFsZip::exists("units1.xml") == false); - REQUIRE(VirtFsZip::exists("dir/hide.png") == true); - REQUIRE(VirtFsZip::exists("dir/brimmedhat.png") == true); - - VirtFsZip::removeFromSearchPathSilent("data/test/test2.zip"); - VirtFsZip::removeFromSearchPathSilent("../data/test/test2.zip"); - - REQUIRE(VirtFsZip::exists("dir2//units.xml") == false); - REQUIRE(VirtFsZip::exists("test/units123.xml") == false); - REQUIRE(VirtFsZip::exists("tesQ/units.xml") == false); - REQUIRE(VirtFsZip::exists("units1.xml") == false); - REQUIRE(VirtFsZip::exists("dir/\\/hide.png") == true); - REQUIRE(VirtFsZip::exists("dir/brimmedhat.png") == true); - - REQUIRE_THROWS(VirtFsZip::exists("test/../units.xml")); - - VirtFsZip::deinit(); - delete2(logger); -} - -TEST_CASE("VirtFsZip getRealDir") -{ - VirtFsZip::init(); - logger = new Logger(); - std::string name("data/test/test.zip"); - std::string prefix("data/test/"); - if (Files::existsLocal(name) == false) - prefix = "../" + prefix; - VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", - Append_false); - - REQUIRE(VirtFsZip::getRealDir(".") == ""); - REQUIRE(VirtFsZip::getRealDir("..") == ""); - REQUIRE(VirtFsZip::getRealDir("test.txt") == prefix + "test2.zip"); - REQUIRE(VirtFsZip::getRealDir("dir\\dye.png") == - prefix + "test2.zip"); - REQUIRE(VirtFsZip::getRealDir("zzz") == ""); - - VirtFsZip::addToSearchPathSilent(prefix + "test.zip", - Append_false); - REQUIRE(VirtFsZip::getRealDir("dir//dye.png") == - prefix + "test2.zip"); - REQUIRE(VirtFsZip::getRealDir("dir///hide.png") == - prefix + "test.zip"); - REQUIRE(VirtFsZip::getRealDir("dir\\\\brimmedhat.png") == - prefix + "test.zip"); - REQUIRE(VirtFsZip::getRealDir("zzz") == ""); - - VirtFsZip::removeFromSearchPathSilent(prefix + "test.zip"); - - REQUIRE(VirtFsZip::getRealDir("dir/brimmedhat.png") == ""); - REQUIRE(VirtFsZip::getRealDir("test.txt") == prefix + "test2.zip"); - REQUIRE(VirtFsZip::getRealDir("dir//dye.png") == - prefix + "test2.zip"); - REQUIRE(VirtFsZip::getRealDir("zzz") == ""); - - VirtFsZip::removeFromSearchPathSilent(prefix + "test2.zip"); - VirtFsZip::deinit(); - delete2(logger); -} - -static bool inList(VirtList *list, - const std::string &name) -{ - FOR_EACH (StringVectCIter, it, list->names) - { - if (*it == name) - return true; - } - return false; -} - -TEST_CASE("VirtFsZip enumerateFiles1") -{ - VirtFsZip::init(); - logger = new Logger; - std::string name("data/test/test.zip"); - std::string prefix("data\\test/"); - if (Files::existsLocal(name) == false) - prefix = "../" + prefix; - - VirtFsZip::addToSearchPathSilent(prefix + "test.zip", - Append_false); - - VirtList *list = nullptr; - - list = VirtFsZip::enumerateFiles("dir"); - REQUIRE(list->names.size() == 2); - REQUIRE(inList(list, "brimmedhat.png")); - REQUIRE(inList(list, "hide.png")); - VirtFsZip::freeList(list); - - VirtFsZip::removeFromSearchPathSilent(prefix + "test.zip"); - VirtFsZip::deinit(); - delete2(logger); -} - -TEST_CASE("VirtFsZip enumerateFiles2") -{ - VirtFsZip::init(); - logger = new Logger; - std::string name("data/test/test.zip"); - std::string prefix("data//test/"); - if (Files::existsLocal(name) == false) - prefix = "../" + prefix; - - VirtFsZip::addToSearchPathSilent(prefix + "test.zip", - Append_true); - VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", - Append_true); - - VirtList *list = nullptr; - - list = VirtFsZip::enumerateFiles("dir"); - FOR_EACH (StringVectCIter, it, list->names) - { - logger->log("filename: " + *it); - } - - REQUIRE(list->names.size() == 5); - REQUIRE(inList(list, "brimmedhat.png")); - REQUIRE(inList(list, "hide.png")); - REQUIRE(inList(list, "1")); - REQUIRE(inList(list, "gpl")); - REQUIRE(inList(list, "dye.png")); - VirtFsZip::freeList(list); - - VirtFsZip::removeFromSearchPathSilent(prefix + "test.zip"); - VirtFsZip::removeFromSearchPathSilent(prefix + "test2.zip"); - VirtFsZip::deinit(); - delete2(logger); -} - -TEST_CASE("VirtFsZip enumerateFiles3") -{ - VirtFsZip::init(); - logger = new Logger; - std::string name("data/test/test.zip"); - std::string prefix("data\\test/"); - if (Files::existsLocal(name) == false) - prefix = "../" + prefix; - - VirtFsZip::addToSearchPathSilent(prefix + "test.zip", - Append_false); - - VirtList *list = nullptr; - - list = VirtFsZip::enumerateFiles("/"); - REQUIRE(list->names.size() == 1); - REQUIRE(inList(list, "dir")); - VirtFsZip::freeList(list); - - VirtFsZip::removeFromSearchPathSilent(prefix + "test.zip"); - VirtFsZip::deinit(); - delete2(logger); -} - -TEST_CASE("VirtFsZip enumerateFiles4") -{ - VirtFsZip::init(); - logger = new Logger; - std::string name("data/test/test.zip"); - std::string prefix("data\\test/"); - if (Files::existsLocal(name) == false) - prefix = "../" + prefix; - - VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", - Append_false); - - VirtList *list = nullptr; - - list = VirtFsZip::enumerateFiles("/"); - REQUIRE(list->names.size() == 4); - REQUIRE(inList(list, "dir")); - REQUIRE(inList(list, "dir2")); - REQUIRE(inList(list, "test.txt")); - REQUIRE(inList(list, "units.xml")); - VirtFsZip::freeList(list); - - VirtFsZip::removeFromSearchPathSilent(prefix + "test2.zip"); - VirtFsZip::deinit(); - delete2(logger); -} - -TEST_CASE("VirtFsZip isDirectory") -{ - VirtFsZip::init(); - logger = new Logger(); - std::string name("data/test/test.zip"); - std::string prefix("data/test/"); - if (Files::existsLocal(name) == false) - prefix = "../" + prefix; - - VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", - Append_false); - - REQUIRE(VirtFsZip::isDirectory("dir2/units.xml") == false); - REQUIRE(VirtFsZip::isDirectory("dir2/units.xml/") == false); - REQUIRE(VirtFsZip::isDirectory("dir2//units.xml") == false); - REQUIRE(VirtFsZip::isDirectory("dir2/units123.xml") == false); - REQUIRE(VirtFsZip::isDirectory("dir2//units123.xml") == false); - REQUIRE(VirtFsZip::isDirectory("tesQ/units.xml") == false); - REQUIRE(VirtFsZip::isDirectory("tesQ//units.xml") == false); - REQUIRE(VirtFsZip::isDirectory("units.xml") == false); - REQUIRE(VirtFsZip::isDirectory("dir") == true); - REQUIRE(VirtFsZip::isDirectory("dir2/") == true); - REQUIRE(VirtFsZip::isDirectory("dir2//") == true); - REQUIRE(VirtFsZip::isDirectory("dir/1") == true); - REQUIRE(VirtFsZip::isDirectory("dir//1") == true); - REQUIRE(VirtFsZip::isDirectory("dir\\1/") == true); - REQUIRE(VirtFsZip::isDirectory("dir/1") == true); - REQUIRE(VirtFsZip::isDirectory("dir/1/zzz") == false); - REQUIRE(VirtFsZip::isDirectory("test/dir1\\") == false); - REQUIRE(VirtFsZip::isDirectory("testQ") == false); - REQUIRE(VirtFsZip::isDirectory("testQ/") == false); - REQUIRE(VirtFsZip::isDirectory("testQ//") == false); - - VirtFsZip::addToSearchPathSilent(prefix + "test.zip", - Append_false); - - REQUIRE(VirtFsZip::isDirectory("dir2/units.xml") == false); - REQUIRE(VirtFsZip::isDirectory("dir2/units.xml/") == false); - REQUIRE(VirtFsZip::isDirectory("dir2\\units.xml") == false); - REQUIRE(VirtFsZip::isDirectory("dir2/units123.xml") == false); - REQUIRE(VirtFsZip::isDirectory("dir2//units123.xml") == false); - REQUIRE(VirtFsZip::isDirectory("tesQ/units.xml") == false); - REQUIRE(VirtFsZip::isDirectory("tesQ//units.xml") == false); - REQUIRE(VirtFsZip::isDirectory("units.xml") == false); - REQUIRE(VirtFsZip::isDirectory("dir") == true); - REQUIRE(VirtFsZip::isDirectory("dir2/") == true); - REQUIRE(VirtFsZip::isDirectory("dir2\\") == true); - REQUIRE(VirtFsZip::isDirectory("dir/1") == true); - REQUIRE(VirtFsZip::isDirectory("dir//1") == true); - REQUIRE(VirtFsZip::isDirectory("dir//1/") == true); - REQUIRE(VirtFsZip::isDirectory("dir/1") == true); - REQUIRE(VirtFsZip::isDirectory("dir/1/zzz") == false); - REQUIRE(VirtFsZip::isDirectory("test/dir1//") == false); - REQUIRE(VirtFsZip::isDirectory("testQ") == false); - REQUIRE(VirtFsZip::isDirectory("testQ/") == false); - REQUIRE(VirtFsZip::isDirectory("testQ//") == false); - - VirtFsZip::removeFromSearchPathSilent(prefix + "test2.zip"); - - REQUIRE(VirtFsZip::isDirectory("dir2/units.xml") == false); - REQUIRE(VirtFsZip::isDirectory("dir2/units.xml/") == false); - REQUIRE(VirtFsZip::isDirectory("dir2//units.xml") == false); - REQUIRE(VirtFsZip::isDirectory("dir2/units123.xml") == false); - REQUIRE(VirtFsZip::isDirectory("dir2//units123.xml") == false); - REQUIRE(VirtFsZip::isDirectory("tesQ/units.xml") == false); - REQUIRE(VirtFsZip::isDirectory("tesQ//units.xml") == false); - REQUIRE(VirtFsZip::isDirectory("units.xml") == false); - REQUIRE(VirtFsZip::isDirectory("dir") == true); - REQUIRE(VirtFsZip::isDirectory("dir2/") == false); - REQUIRE(VirtFsZip::isDirectory("dir2//") == false); - REQUIRE(VirtFsZip::isDirectory("dir/1") == false); - REQUIRE(VirtFsZip::isDirectory("dir\\1") == false); - REQUIRE(VirtFsZip::isDirectory("dir//1/") == false); - REQUIRE(VirtFsZip::isDirectory("dir/1") == false); - REQUIRE(VirtFsZip::isDirectory("dir/1/zzz") == false); - REQUIRE(VirtFsZip::isDirectory("test/dir1//") == false); - REQUIRE(VirtFsZip::isDirectory("testQ") == false); - REQUIRE(VirtFsZip::isDirectory("testQ/") == false); - REQUIRE(VirtFsZip::isDirectory("testQ//") == false); - - VirtFsZip::removeFromSearchPathSilent(prefix + "test.zip"); - VirtFsZip::deinit(); - delete2(logger); -} - -TEST_CASE("VirtFsZip openRead") -{ - VirtFsZip::init(); - logger = new Logger(); - std::string name("data/test/test.zip"); - std::string prefix("data/test/"); - if (Files::existsLocal(name) == false) - prefix = "../" + prefix; - - VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", - Append_false); - - VirtFile *file = nullptr; - - file = VirtFsZip::openRead("dir2/units.xml"); - REQUIRE(file != nullptr); - VirtFsZip::close(file); - file = VirtFsZip::openRead("dir2\\units.xml"); - REQUIRE(file != nullptr); - VirtFsZip::close(file); - file = VirtFsZip::openRead("dir2/units123.xml"); - REQUIRE(file == nullptr); - file = VirtFsZip::openRead("tesQ/units.xml"); - REQUIRE(file == nullptr); - file = VirtFsZip::openRead("units.xml1"); - REQUIRE(file == nullptr); - file = VirtFsZip::openRead("testQ"); - REQUIRE(file == nullptr); - file = VirtFsZip::openRead("dir/brimmedhat.png"); - REQUIRE(file == nullptr); - file = VirtFsZip::openRead("dir//brimmedhat.png"); - REQUIRE(file == nullptr); - - VirtFsZip::addToSearchPathSilent(prefix + "test.zip", - Append_false); - - file = VirtFsZip::openRead("dir2/units.xml"); - REQUIRE(file != nullptr); - VirtFsZip::close(file); - file = VirtFsZip::openRead("dir2//units.xml"); - REQUIRE(file != nullptr); - VirtFsZip::close(file); - file = VirtFsZip::openRead("dir2/units123.xml"); - REQUIRE(file == nullptr); - file = VirtFsZip::openRead("tesQ/units.xml"); - REQUIRE(file == nullptr); - file = VirtFsZip::openRead("units.xml1"); - REQUIRE(file == nullptr); - file = VirtFsZip::openRead("testQ"); - REQUIRE(file == nullptr); - file = VirtFsZip::openRead("dir/brimmedhat.png"); - REQUIRE(file != nullptr); - VirtFsZip::close(file); - - VirtFsZip::removeFromSearchPathSilent(prefix + "test.zip"); - - file = VirtFsZip::openRead("dir2/units.xml"); - REQUIRE(file != nullptr); - VirtFsZip::close(file); - file = VirtFsZip::openRead("dir2\\/\\units.xml"); - REQUIRE(file != nullptr); - VirtFsZip::close(file); - file = VirtFsZip::openRead("dir2/units123.xml"); - REQUIRE(file == nullptr); - file = VirtFsZip::openRead("tesQ/units.xml"); - REQUIRE(file == nullptr); - file = VirtFsZip::openRead("units.xml1"); - REQUIRE(file == nullptr); - file = VirtFsZip::openRead("testQ"); - REQUIRE(file == nullptr); - file = VirtFsZip::openRead("dir/brimmedhat.png"); - REQUIRE(file == nullptr); - - VirtFsZip::removeFromSearchPathSilent(prefix + "test2.zip"); - - VirtFsZip::deinit(); - delete2(logger); -} - -TEST_CASE("VirtFsZip read") -{ - VirtFsZip::init(); - logger = new Logger(); - std::string name("data/test/test.zip"); - std::string prefix("data/test/"); - if (Files::existsLocal(name) == false) - prefix = "../" + prefix; - - VirtFsZip::addToSearchPathSilent(prefix + "test2.zip", - Append_false); - VirtFile *file = nullptr; - void *restrict buffer = nullptr; - - SECTION("test 1") - { - file = VirtFsZip::openRead("dir2//test.txt"); - REQUIRE(file != nullptr); - REQUIRE(VirtFsZip::fileLength(file) == 23); - const int fileSize = VirtFsZip::fileLength(file); - - buffer = calloc(fileSize + 1, 1); - REQUIRE(VirtFsZip::read(file, buffer, 1, fileSize) == fileSize); - REQUIRE(strcmp(static_cast(buffer), - "test line 1\ntest line 2") == 0); - REQUIRE(VirtFsZip::tell(file) == fileSize); - REQUIRE(VirtFsZip::eof(file) == true); - } - - SECTION("test 2") - { - file = VirtFsZip::openRead("dir2\\/test.txt"); - REQUIRE(file != nullptr); - REQUIRE(VirtFsZip::fileLength(file) == 23); - const int fileSize = VirtFsZip::fileLength(file); - - buffer = calloc(fileSize + 1, 1); - REQUIRE(VirtFsZip::seek(file, 12) != 0); - REQUIRE(VirtFsZip::eof(file) == false); - REQUIRE(VirtFsZip::tell(file) == 12); - REQUIRE(VirtFsZip::read(file, buffer, 1, 11) == 11); - REQUIRE(strcmp(static_cast(buffer), - "test line 2") == 0); - REQUIRE(VirtFsZip::eof(file) == true); - } - - SECTION("test 3") - { - file = VirtFsZip::openRead("dir2//test.txt"); - REQUIRE(file != nullptr); - const int fileSize = VirtFsZip::fileLength(file); - - buffer = calloc(fileSize + 1, 1); - for (int f = 0; f < fileSize; f ++) - { - REQUIRE(VirtFsZip::seek(file, f) != 0); - REQUIRE(VirtFsZip::eof(file) == false); - REQUIRE(VirtFsZip::tell(file) == f); - } - } - - SECTION("test 4") - { - file = VirtFsZip::openRead("dir2/test.txt"); - REQUIRE(file != nullptr); - const int fileSize = VirtFsZip::fileLength(file); - const char *restrict const str = "test line 1\ntest line 2"; - buffer = calloc(fileSize + 1, 1); - for (int f = 0; f < fileSize - 1; f ++) - { - REQUIRE(VirtFsZip::read(file, buffer, 1, 1) == 1); - REQUIRE(static_cast(buffer)[0] == str[f]); - REQUIRE(VirtFsZip::eof(file) == false); - REQUIRE(VirtFsZip::tell(file) == f + 1); - } - REQUIRE(VirtFsZip::read(file, buffer, 1, 1) == 1); - REQUIRE(static_cast(buffer)[0] == str[22]); - REQUIRE(VirtFsZip::eof(file) == true); - REQUIRE(VirtFsZip::tell(file) == fileSize); - } - - SECTION("test 5") - { - file = VirtFsZip::openRead("dir2\\\\test.txt"); - REQUIRE(file != nullptr); - const int fileSize = VirtFsZip::fileLength(file); - const char *restrict const str = "test line 1\ntest line 2"; - buffer = calloc(fileSize + 1, 1); - for (int f = 0; f < fileSize - 1; f += 2) - { - REQUIRE(VirtFsZip::read(file, buffer, 2, 1) == 1); - REQUIRE(static_cast(buffer)[0] == str[f]); - REQUIRE(static_cast(buffer)[1] == str[f + 1]); - REQUIRE(VirtFsZip::eof(file) == false); - REQUIRE(VirtFsZip::tell(file) == f + 2); - } - REQUIRE(VirtFsZip::eof(file) == false); - REQUIRE(VirtFsZip::tell(file) == 22); - REQUIRE(VirtFsZip::read(file, buffer, 2, 1) == 0); - REQUIRE(VirtFsZip::eof(file) == false); - } - - SECTION("test 6") - { - file = VirtFsZip::openRead("dir2//test.txt"); - REQUIRE(file != nullptr); - const int fileSize = VirtFsZip::fileLength(file); - const char *restrict const str = "test line 1\ntest line 2"; - buffer = calloc(fileSize + 1, 1); - for (int f = 0; f < fileSize - 1; f += 2) - { - REQUIRE(VirtFsZip::read(file, buffer, 1, 2) == 2); - REQUIRE(static_cast(buffer)[0] == str[f]); - REQUIRE(static_cast(buffer)[1] == str[f + 1]); - REQUIRE(VirtFsZip::eof(file) == false); - REQUIRE(VirtFsZip::tell(file) == f + 2); - } - REQUIRE(VirtFsZip::eof(file) == false); - REQUIRE(VirtFsZip::tell(file) == 22); - REQUIRE(VirtFsZip::read(file, buffer, 1, 2) == 1); - REQUIRE(static_cast(buffer)[0] == str[22]); - REQUIRE(VirtFsZip::eof(file) == true); - } - - VirtFsZip::close(file); - free(buffer); - VirtFsZip::removeFromSearchPathSilent(prefix + "test2.zip"); - VirtFsZip::deinit(); - delete2(logger); -} diff --git a/src/fs/virtzipentry.cpp b/src/fs/virtzipentry.cpp deleted file mode 100644 index e0189fccf..000000000 --- a/src/fs/virtzipentry.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "fs/virtzipentry.h" - -#include "fs/ziplocalheader.h" - -#include "utils/dtor.h" - -#include "debug.h" - -VirtZipEntry::VirtZipEntry(const std::string &restrict archiveName) : - mArchiveName(archiveName), - mHeaders() -{ -} - -VirtZipEntry::~VirtZipEntry() -{ - delete_all(mHeaders); -} diff --git a/src/fs/virtzipentry.h b/src/fs/virtzipentry.h deleted file mode 100644 index fac36cc2d..000000000 --- a/src/fs/virtzipentry.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef UTILS_VIRTZIPENTRY_H -#define UTILS_VIRTZIPENTRY_H - -#include -#include - -#include "localconsts.h" - -struct ZipLocalHeader; - -struct VirtZipEntry final -{ - explicit VirtZipEntry(const std::string &restrict archiveName); - - A_DELETE_COPY(VirtZipEntry) - - ~VirtZipEntry(); - - std::string mArchiveName; - - std::vector mHeaders; - std::vector mDirs; -}; - -#endif // UTILS_VIRTZIPENTRY_H diff --git a/src/fs/zip.cpp b/src/fs/zip.cpp deleted file mode 100644 index 1bdc22639..000000000 --- a/src/fs/zip.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "fs/zip.h" - -#include "fs/paths.h" -#include "fs/virtzipentry.h" -#include "fs/ziplocalheader.h" - -#include "utils/checkutils.h" -#include "utils/stringutils.h" - -#include -#include -#include - -#include "debug.h" - -#define readVal(val, sz, msg) \ - cnt = fread(static_cast(val), 1, sz, arcFile); \ - if (cnt != sz) \ - { \ - reportAlways("Error reading " msg " in file %s", \ - archiveName.c_str()); \ - delete header; \ - delete [] buf; \ - fclose(arcFile); \ - return false; \ - } \ - -namespace Zip -{ - bool readArchiveInfo(VirtZipEntry *const entry) - { - if (entry == nullptr) - { - reportAlways("Entry is null."); - return false; - } - const std::string archiveName = entry->mArchiveName; - std::vector &restrict headers = entry->mHeaders; - std::vector &restrict dirs = entry->mDirs; - FILE *restrict const arcFile = fopen(archiveName.c_str(), - "r"); - if (arcFile == nullptr) - { - reportAlways("Can't open zip file %s", - archiveName.c_str()); - return false; - } - size_t cnt = 0U; - uint8_t *const buf = new uint8_t[65535 + 10]; - uint16_t val16 = 0U; - uint16_t method = 0U; - ZipLocalHeader *header = nullptr; - - logger->log("Read archive: %s", archiveName.c_str()); - // format source https://en.wikipedia.org/wiki/Zip_%28file_format%29 - while (feof(arcFile) == 0) - { - // file header pointer on 0 - // read file header signature - readVal(buf, 4, "zip file header"); // + 4 - // pointer on 4 - - if (buf[0] == 0x50 && - buf[1] == 0x4B && - buf[2] == 0x03 && - buf[3] == 0x04) - { // local file header - header = new ZipLocalHeader; - header->zipEntry = entry; - // skip useless fields - fseek(arcFile, 4, SEEK_CUR); // + 4 - // file header pointer on 8 - // +++ need add endian specific decoding for method - readVal(&method, 2, "compression method") // + 2 - header->compressed = (method != 0); - // file header pointer on 10 - fseek(arcFile, 8, SEEK_CUR); // + 8 - // file header pointer on 18 - readVal(&header->compressSize, 4, - "zip compressed size") // + 4 - // file header pointer on 22 - // +++ need add endian specific decoding for val32 - readVal(&header->uncompressSize, 4, - "zip uncompressed size") // + 4 - // file header pointer on 26 - // +++ need add endian specific decoding for val32 - readVal(&val16, 2, "file name length") // + 2 - // file header pointer on 28 - const uint32_t fileNameLen = CAST_U32(val16); - if (fileNameLen > 1000) - { - reportAlways("Error too long file name in file %s", - archiveName.c_str()); - delete header; - delete [] buf; - fclose(arcFile); - return false; - } - readVal(&val16, 2, "extra field length") // + 2 - // file header pointer on 30 - const uint32_t extraFieldLen = CAST_U32(val16); - readVal(buf, fileNameLen, "file name"); - // file header pointer on 30 + fileNameLen - buf[fileNameLen] = 0; - header->fileName = std::string( - reinterpret_cast(buf)); - prepareFsPath(header->fileName); - header->dataOffset = ftell(arcFile) + extraFieldLen; - fseek(arcFile, extraFieldLen + header->compressSize, SEEK_CUR); - // pointer on 30 + fileNameLen + extraFieldLen + compressSize - if (findLast(header->fileName, "/") == false) - { - headers.push_back(header); - logger->log(" file name: %s", - header->fileName.c_str()); - logger->log(" compression method: %u", - CAST_U32(method)); - logger->log(" compressed size: %u", - header->compressSize); - logger->log(" uncompressed size: %u", - header->uncompressSize); - } - else - { - dirs.push_back(header->fileName); - delete header; - } - } - else if (buf[0] == 0x50 && - buf[1] == 0x4B && - buf[2] == 0x01 && - buf[3] == 0x02) - { // central directory file header - // !!! This is quick way for read zip archives. !!! - // !!! It ignore modified files in archive. !!! - // ignoring central directory entries - break; - } - else if (buf[0] == 0x50 && - buf[1] == 0x4B && - buf[2] == 0x05 && - buf[3] == 0x06) - { // end of central directory - // !!! This is quick way for read zip archives. !!! - // !!! It ignore modified files in archive. !!! - // ignoring end of central directory - break; - } - else - { - reportAlways("Error in header signature (0x%02x%02x%02x%02x)" - " in file %s", - buf[0], - buf[1], - buf[2], - buf[3], - archiveName.c_str()); - delete [] buf; - fclose(arcFile); - return false; - } - } - delete [] buf; - fclose(arcFile); - return true; - } - - void reportZlibError(const std::string &text, - const int err) - { - reportAlways("Zlib error: '%s' in %s", - text.c_str(), - getZlibError(err).c_str()); - } - - std::string getZlibError(const int err) - { - switch (err) - { - case Z_OK: - return std::string(); - default: - return "unknown zlib error"; - } - } - - uint8_t *readCompressedFile(const ZipLocalHeader *restrict const header) - { - if (header == nullptr) - { - reportAlways("Zip::readCompressedFile: header is null"); - return nullptr; - } - FILE *restrict const arcFile = fopen( - header->zipEntry->mArchiveName.c_str(), - "r"); - if (arcFile == nullptr) - { - reportAlways("Can't open zip file %s", - header->zipEntry->mArchiveName.c_str()); - return nullptr; - } - - fseek(arcFile, header->dataOffset, SEEK_SET); - const uint32_t compressSize = header->compressSize; - uint8_t *const buf = new uint8_t[compressSize]; - if (fread(static_cast(buf), 1, compressSize, arcFile) != - compressSize) - { - reportAlways("Read zip compressed file error from archive: %s", - header->zipEntry->mArchiveName.c_str()); - fclose(arcFile); - delete [] buf; - return nullptr; - } - fclose(arcFile); - return buf; - } - - uint8_t *readFile(const ZipLocalHeader *restrict const header) - { - if (header == nullptr) - { - reportAlways("Open zip file error. header is null."); - return nullptr; - } - uint8_t *restrict const in = readCompressedFile(header); - if (in == nullptr) - return nullptr; - if (header->compressed == false) - return in; // return as is if data not compressed - const size_t outSize = header->uncompressSize; - uint8_t *restrict const out = new uint8_t[outSize]; - if (outSize == 0) - return out; - - z_stream strm; - strm.zalloc = nullptr; - strm.zfree = nullptr; - strm.opaque = nullptr; - strm.next_in = in; - strm.avail_in = header->compressSize; - strm.next_out = out; - strm.avail_out = outSize; - - int ret = inflateInit2(&strm, -MAX_WBITS); - if (ret != Z_OK) - { - reportZlibError(header->zipEntry->mArchiveName, ret); - delete [] in; - delete [] out; - return nullptr; - } - ret = inflate(&strm, Z_FINISH); -// ret = inflate(&strm, Z_SYNC_FLUSH); - if (ret != Z_OK && - ret != Z_STREAM_END) - { - reportZlibError("file decompression error", - ret); - inflateEnd(&strm); - delete [] in; - delete [] out; - return nullptr; - } - inflateEnd(&strm); - delete [] in; - return out; - } -} // namespace Zip diff --git a/src/fs/zip.h b/src/fs/zip.h deleted file mode 100644 index 412dbcef9..000000000 --- a/src/fs/zip.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef UTILS_ZIP_H -#define UTILS_ZIP_H - -#include "localconsts.h" - -#include -#include - -struct VirtZipEntry; -struct ZipLocalHeader; - -namespace Zip -{ - bool readArchiveInfo(VirtZipEntry *const entry); - std::string getZlibError(const int err); - void reportZlibError(const std::string &text, - const int err); - uint8_t *readCompressedFile(const ZipLocalHeader *restrict const header); - uint8_t *readFile(const ZipLocalHeader *restrict const header); -} // namespace Zip - -#endif // UTILS_ZIP_H diff --git a/src/fs/zip_unittest.cc b/src/fs/zip_unittest.cc deleted file mode 100644 index 44cfb4757..000000000 --- a/src/fs/zip_unittest.cc +++ /dev/null @@ -1,279 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "catch.hpp" - -#include "logger.h" - -#include "fs/files.h" -#include "fs/virtzipentry.h" -#include "fs/zip.h" -#include "fs/ziplocalheader.h" - -#include "utils/delete2.h" - -#include "debug.h" - -TEST_CASE("Zip readArchiveInfo") -{ - logger = new Logger(); - std::string name("data/test/test.zip"); - std::string prefix; - if (Files::existsLocal(name) == false) - prefix = "../"; - - SECTION("test.zip") - { - name = prefix + "data/test/test.zip"; - - VirtZipEntry *const entry = new VirtZipEntry(name); - std::vector &headers = entry->mHeaders; - - REQUIRE(Zip::readArchiveInfo(entry)); - REQUIRE(headers.size() == 2); - REQUIRE(entry->mArchiveName == name); - REQUIRE(headers[0]->fileName == "dir/hide.png"); - REQUIRE(headers[0]->compressSize == 365); - REQUIRE(headers[0]->uncompressSize == 368); - REQUIRE(headers[1]->fileName == "dir/brimmedhat.png"); - REQUIRE(headers[1]->compressSize == 1959); - REQUIRE(headers[1]->uncompressSize == 1959); - - delete entry; - } - - SECTION("test2.zip") - { - name = prefix + "data/test/test2.zip"; - - VirtZipEntry *const entry = new VirtZipEntry(name); - std::vector &headers = entry->mHeaders; - - REQUIRE(Zip::readArchiveInfo(entry)); - REQUIRE(headers.size() == 11); - REQUIRE(entry->mArchiveName == name); - REQUIRE(headers[0]->fileName == "test.txt"); - REQUIRE(headers[0]->compressSize == 17); - REQUIRE(headers[0]->uncompressSize == 23); - - REQUIRE(headers[1]->fileName == "dir2/hide.png"); - REQUIRE(headers[1]->compressSize == 365); - REQUIRE(headers[1]->uncompressSize == 368); - - REQUIRE(headers[2]->fileName == "dir2/test.txt"); - REQUIRE(headers[2]->compressSize == 17); - REQUIRE(headers[2]->uncompressSize == 23); - - REQUIRE(headers[3]->fileName == "dir2/paths.xml"); - REQUIRE(headers[3]->compressSize == 154); - REQUIRE(headers[3]->uncompressSize == 185); - - REQUIRE(headers[4]->fileName == "dir2/units.xml"); - REQUIRE(headers[4]->compressSize == 202); - REQUIRE(headers[4]->uncompressSize == 306); - - REQUIRE(headers[5]->fileName == "dir/hide.png"); - REQUIRE(headers[5]->compressSize == 365); - REQUIRE(headers[5]->uncompressSize == 368); - - REQUIRE(headers[6]->fileName == "dir/1/test.txt"); - REQUIRE(headers[6]->compressSize == 17); - REQUIRE(headers[6]->uncompressSize == 23); - - REQUIRE(headers[7]->fileName == "dir/1/file1.txt"); - REQUIRE(headers[7]->compressSize == 17); - REQUIRE(headers[7]->uncompressSize == 23); - - REQUIRE(headers[8]->fileName == "dir/gpl/palette.gpl"); - REQUIRE(headers[8]->compressSize == 128); - REQUIRE(headers[8]->uncompressSize == 213); - - REQUIRE(headers[9]->fileName == "dir/dye.png"); - REQUIRE(headers[9]->compressSize == 794); - REQUIRE(headers[9]->uncompressSize == 794); - - REQUIRE(headers[10]->fileName == "units.xml"); - REQUIRE(headers[10]->compressSize == 202); - REQUIRE(headers[10]->uncompressSize == 306); - - delete entry; - } - - SECTION("test3.zip") - { - name = prefix + "data/test/test3.zip"; - - VirtZipEntry *const entry = new VirtZipEntry(name); - std::vector &headers = entry->mHeaders; - - REQUIRE(Zip::readArchiveInfo(entry)); - REQUIRE(headers.size() == 2); - REQUIRE(entry->mArchiveName == name); - REQUIRE(headers[0]->fileName == "test.txt"); - REQUIRE(headers[0]->compressSize == 17); - REQUIRE(headers[0]->uncompressSize == 23); - REQUIRE(headers[1]->fileName == "units.xml"); - REQUIRE(headers[1]->compressSize == 202); - REQUIRE(headers[1]->uncompressSize == 306); - - delete entry; - } - - SECTION("test4.zip") - { - name = prefix + "data/test/test4.zip"; - - VirtZipEntry *const entry = new VirtZipEntry(name); - std::vector &headers = entry->mHeaders; - - REQUIRE(Zip::readArchiveInfo(entry)); - REQUIRE(entry->mArchiveName == name); - REQUIRE(headers.size() == 0); - - delete entry; - } - - delete2(logger); -} - -TEST_CASE("Zip readCompressedFile") -{ - logger = new Logger(); - std::string name("data/test/test.zip"); - std::string prefix; - if (Files::existsLocal(name) == false) - prefix = "../"; - - SECTION("empty") - { - REQUIRE_THROWS(Zip::readCompressedFile(nullptr)); - } - - SECTION("test2.zip") - { - name = prefix + "data/test/test2.zip"; - - VirtZipEntry *const entry = new VirtZipEntry(name); - std::vector &headers = entry->mHeaders; - - REQUIRE(Zip::readArchiveInfo(entry)); - REQUIRE(headers.size() == 11); - REQUIRE(entry->mArchiveName == name); - // test.txt - uint8_t *const buf = Zip::readCompressedFile(headers[0]); - REQUIRE(buf != nullptr); - delete [] buf; - delete entry; - } - - delete2(logger); -} - -TEST_CASE("Zip readFile") -{ - logger = new Logger(); - std::string name("data/test/test.zip"); - std::string prefix; - if (Files::existsLocal(name) == false) - prefix = "../"; - - SECTION("empty") - { - REQUIRE_THROWS(Zip::readFile(nullptr)); - } - - SECTION("test.zip") - { - name = prefix + "data/test/test.zip"; - - VirtZipEntry *const entry = new VirtZipEntry(name); - std::vector &headers = entry->mHeaders; - - REQUIRE(Zip::readArchiveInfo(entry)); - REQUIRE(headers.size() == 2); - REQUIRE(entry->mArchiveName == name); - for (int f = 0; f < 2; f ++) - { - logger->log("test header: %s, %u, %u", - headers[f]->fileName.c_str(), - headers[f]->compressSize, - headers[f]->uncompressSize); - uint8_t *const buf = Zip::readFile(headers[f]); - REQUIRE(buf != nullptr); - delete [] buf; - } - delete entry; - } - - SECTION("test2.zip") - { - name = prefix + "data/test/test2.zip"; - - VirtZipEntry *const entry = new VirtZipEntry(name); - std::vector &headers = entry->mHeaders; - - REQUIRE(Zip::readArchiveInfo(entry)); - REQUIRE(headers.size() == 11); - REQUIRE(entry->mArchiveName == name); - // test.txt - uint8_t *buf = Zip::readFile(headers[0]); - REQUIRE(buf != nullptr); - const std::string str = std::string(reinterpret_cast(buf), - headers[0]->uncompressSize); - REQUIRE(str == "test line 1\ntest line 2"); - delete [] buf; - for (int f = 0; f < 11; f ++) - { - logger->log("test header: %s, %u, %u", - headers[f]->fileName.c_str(), - headers[f]->compressSize, - headers[f]->uncompressSize); - buf = Zip::readFile(headers[f]); - REQUIRE(buf != nullptr); - delete [] buf; - } - delete entry; - } - - SECTION("test3.zip") - { - name = prefix + "data/test/test3.zip"; - - VirtZipEntry *const entry = new VirtZipEntry(name); - std::vector &headers = entry->mHeaders; - - REQUIRE(Zip::readArchiveInfo(entry)); - REQUIRE(headers.size() == 2); - REQUIRE(entry->mArchiveName == name); - for (int f = 0; f < 2; f ++) - { - logger->log("test header: %s, %u, %u", - headers[f]->fileName.c_str(), - headers[f]->compressSize, - headers[f]->uncompressSize); - uint8_t *const buf = Zip::readFile(headers[f]); - REQUIRE(buf != nullptr); - delete [] buf; - } - delete entry; - } - - delete2(logger); -} diff --git a/src/fs/ziplocalheader.cpp b/src/fs/ziplocalheader.cpp deleted file mode 100644 index 8af552b0d..000000000 --- a/src/fs/ziplocalheader.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "fs/ziplocalheader.h" - -#include "fs/virtzipentry.h" - -#include "localconsts.h" - -#include - -#include "debug.h" - -ZipLocalHeader::ZipLocalHeader() : - fileName(), - zipEntry(nullptr), - dataOffset(0U), - compressSize(0U), - uncompressSize(0U), - compressed(false) -{ -} diff --git a/src/fs/ziplocalheader.h b/src/fs/ziplocalheader.h deleted file mode 100644 index f3a1894ce..000000000 --- a/src/fs/ziplocalheader.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2017 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef UTILS_ZIPLOCALHEADER_H -#define UTILS_ZIPLOCALHEADER_H - -#include "localconsts.h" - -#include - -struct VirtZipEntry; - -struct ZipLocalHeader final -{ - ZipLocalHeader(); - - A_DELETE_COPY(ZipLocalHeader) - - std::string fileName; - VirtZipEntry *zipEntry; - uint32_t dataOffset; - uint32_t compressSize; - uint32_t uncompressSize; - bool compressed; -}; - -#endif // UTILS_ZIPLOCALHEADER_H diff --git a/src/integrity_unittest.cc b/src/integrity_unittest.cc index b7b97321a..58e22772a 100644 --- a/src/integrity_unittest.cc +++ b/src/integrity_unittest.cc @@ -45,7 +45,9 @@ #include "utils/env.h" #include "utils/delete2.h" +#ifdef USE_PHYSFS #include +#endif // USE_PHYSFS #include #include "debug.h" @@ -260,6 +262,7 @@ TEST_CASE("integrity tests", "integrity") REQUIRE(compareBuffers(buf) == true); } +#ifdef USE_PHYSFS SECTION("integrity Loader::getImage test 5") { VirtFs::addZipToSearchPath("data/test/test.zip", Append_false); @@ -402,6 +405,7 @@ TEST_CASE("integrity tests", "integrity") VirtFs::removeZipFromSearchPath("../data/test/test.zip"); REQUIRE(compareBuffers(buf) == true); } +#endif // USE_PHYSFS SECTION("integrity Loader::getImage test 7") { diff --git a/src/utils/dumplibs.cpp b/src/utils/dumplibs.cpp index 34b63e71a..9a7f42c0c 100644 --- a/src/utils/dumplibs.cpp +++ b/src/utils/dumplibs.cpp @@ -118,6 +118,7 @@ void dumpLibs() logger->log(" libcurl: %s", LIBCURL_VERSION); logger->log(" libpng: %s", PNG_LIBPNG_VER_STRING); +#ifdef USE_PHYSFS PHYSFS_Version physfsVersion; PHYSFS_VERSION(&physfsVersion); const std::string physfsCompiled = strprintf("%d.%d.%d", @@ -125,6 +126,8 @@ void dumpLibs() physfsVersion.minor, physfsVersion.patch); logger->log(" libphysfs: %s", physfsCompiled.c_str()); +#endif // USE_PHYSFS + dumpCompiledSdlVersion("SDL", SDL); dumpCompiledSdlVersion("SDL_net", SDL_NET); dumpCompiledSdlVersion("SDL_image", SDL_IMAGE); @@ -135,12 +138,14 @@ void dumpLibs() #if ZLIB_VERNUM >= 0x1020 logger->log(" zLib: %s", zlibVersion()); #endif // ZLIB_VERNUM >= 0x1020 +#ifdef USE_PHYSFS PHYSFS_getLinkedVersion(&physfsVersion); const std::string physfsLinked = strprintf("%d.%d.%d", physfsVersion.major, physfsVersion.minor, physfsVersion.patch); logger->log(" libphysfs: %s", physfsLinked.c_str()); +#endif // USE_PHYSFS #ifdef LIBXML_TEST_VERSION LIBXML_TEST_VERSION #endif // LIBXML_TEST_VERSION @@ -160,7 +165,9 @@ void dumpLibs() dumpLinkedSdlVersion("SDL_ttf", TTF_Linked_Version()); compareVersions("zLib", ZLIB_VERSION, zlibVersion()); +#ifdef USE_PHYSFS compareVersions("libphysfs", physfsCompiled.c_str(), physfsLinked.c_str()); +#endif // USE_PHYSFS #ifdef USE_SDL2 compareSDLVersions("SDL", sdlVersionJoin(SDL), &sdlVersion); #else // USE_SDL2 diff --git a/src/utils/dumplibs_unittest.cc b/src/utils/dumplibs_unittest.cc index aca0f91f3..20f89f7b7 100644 --- a/src/utils/dumplibs_unittest.cc +++ b/src/utils/dumplibs_unittest.cc @@ -31,7 +31,9 @@ PRAGMACLANG6(GCC diagnostic ignored "-Wold-style-cast") #include PRAGMACLANG6(GCC diagnostic pop) #include +#ifdef USE_PHYSFS #include +#endif // USE_PHYSFS #include #include "debug.h" @@ -47,6 +49,7 @@ TEST_CASE("dumplibs tests") REQUIRE(build == link); } +#ifdef USE_PHYSFS SECTION("physfs") { PHYSFS_Version buildVersion; @@ -65,6 +68,7 @@ TEST_CASE("dumplibs tests") REQUIRE(build == link); } +#endif // USE_PHYSFS SECTION("sdl") { -- cgit v1.2.3-70-g09d2