summaryrefslogtreecommitdiff
path: root/src/fs/physfs/virtfsphys.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs/physfs/virtfsphys.cpp')
-rw-r--r--src/fs/physfs/virtfsphys.cpp327
1 files changed, 327 insertions, 0 deletions
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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 <iostream>
+#include <unistd.h>
+
+#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<void(*)()>(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