diff --git a/include/error.hpp b/include/error.hpp index 4769005..aabbfc9 100644 --- a/include/error.hpp +++ b/include/error.hpp @@ -9,4 +9,7 @@ namespace error /// @brief Logs and returns if an fslib function fails. bool fslib(bool result, const std::source_location &location = std::source_location::current()); + + /// @brief Returns whether or not the pointer passed is null. Records the location in which this occurred. + bool is_null(const void *pointer, const std::source_location &location = std::source_location::current()); } diff --git a/include/fs/MiniZip.hpp b/include/fs/MiniZip.hpp new file mode 100644 index 0000000..ee02607 --- /dev/null +++ b/include/fs/MiniZip.hpp @@ -0,0 +1,43 @@ +#pragma once +#include "fslib.hpp" + +#include +#include + +namespace fs +{ + class MiniZip + { + public: + MiniZip() = default; + + /// @brief Constructor. Calls open upon construction; + /// @param path + MiniZip(const fslib::Path &path); + + /// @brief Closes the zipFile. + ~MiniZip(); + + /// @brief Opens a Zip file at path + bool open(const fslib::Path &path); + + /// @brief Manual call for closing the zipFile. + void close(); + + /// @brief Opens a new file with filename as the path. + bool open_new_file(std::string_view filename, bool trimPath = false, size_t trimPlaces = 0); + + /// @brief Closes the currently open file in the Zip. + bool close_current_file(); + + /// @brief Attempts to write the buffer passed to the currently opened file. + bool write(const void *buffer, size_t dataSize); + + private: + /// @brief Stores whether or not the zipFile was opened successfully. + bool m_isOpen{}; + + /// @brief Underlying ZIP file. + zipFile m_zip{}; + }; +} diff --git a/source/error.cpp b/source/error.cpp index 819ad57..748195f 100644 --- a/source/error.cpp +++ b/source/error.cpp @@ -37,6 +37,18 @@ bool error::fslib(bool result, const std::source_location &location) return true; } +bool error::is_null(const void *pointer, const std::source_location &location) +{ + if (pointer) { return false; } + + std::string_view file{}, function{}; + prep_locations(file, function, location); + + logger::log("%s::%s::%u::%u::%s", file.data(), function.data(), location.line(), location.column(), "nullptr received!"); + + return true; +} + static void prep_locations(std::string_view &file, std::string_view &function, const std::source_location &location) { file = location.file_name(); diff --git a/source/fs/MiniZip.cpp b/source/fs/MiniZip.cpp new file mode 100644 index 0000000..01ba932 --- /dev/null +++ b/source/fs/MiniZip.cpp @@ -0,0 +1,53 @@ +#include "fs/MiniZip.hpp" + +#include "config.hpp" +#include "error.hpp" + +#include + +fs::MiniZip::MiniZip(const fslib::Path &path) { MiniZip::open(path); } + +fs::MiniZip::~MiniZip() { MiniZip::close(); } + +bool fs::MiniZip::open(const fslib::Path &path) +{ + MiniZip::close(); + m_zip = zipOpen64(path.full_path(), APPEND_STATUS_CREATE); + if (error::is_null(m_zip)) { return false; } + m_isOpen = true; + return true; +} + +void fs::MiniZip::close() +{ + if (!m_isOpen) { return; } + zipClose(m_zip, nullptr) == ZIP_OK; + m_isOpen = false; +} + +bool fs::MiniZip::open_new_file(std::string_view filename, bool trimPath, size_t trimPlaces) +{ + const uint8_t zipLevel = config::get_by_key(config::keys::ZIP_COMPRESSION_LEVEL); + + const size_t pathBegin = filename.find_first_of('/'); + if (pathBegin != filename.npos) { filename = filename.substr(pathBegin + 1); } + + const std::time_t currentTime = std::time(nullptr); + const std::tm *local = std::localtime(¤tTime); + const zip_fileinfo fileInfo = {.tmz_date = {.tm_sec = local->tm_sec, + .tm_min = local->tm_min, + .tm_hour = local->tm_hour, + .tm_mday = local->tm_mday, + .tm_mon = local->tm_mon, + .tm_year = local->tm_year + 1900}, + .dosDate = 0, + .internal_fa = 0, + .external_fa = 0}; + + return zipOpenNewFileInZip64(m_zip, filename.data(), &fileInfo, nullptr, 0, nullptr, 0, nullptr, Z_DEFLATED, zipLevel, 0) == + ZIP_OK; +} + +bool fs::MiniZip::close_current_file() { return zipCloseFileInZip(m_zip) == ZIP_OK; } + +bool fs::MiniZip::write(const void *buffer, size_t dataSize) { return zipWriteInFileInZip(m_zip, buffer, dataSize) == ZIP_OK; } diff --git a/source/tasks/backup.cpp b/source/tasks/backup.cpp index 9df7cc4..68bfb1f 100644 --- a/source/tasks/backup.cpp +++ b/source/tasks/backup.cpp @@ -1,9 +1,28 @@ #include "tasks/backup.hpp" +#include "config.hpp" +#include "error.hpp" +#include "fs/fs.hpp" + +#include + void tasks::backup::create_new_backup(sys::ProgressTask *task, data::User *user, data::TitleInfo *titleInfo, fslib::Path target, BackupMenuState *spawningState) { + const bool exportZip = config::get_by_key(config::keys::EXPORT_TO_ZIP); + const bool autoUpload = config::get_by_key(config::keys::AUTO_UPLOAD); + const bool hasZipExt = std::strstr(target.full_path(), ".zip"); + const const bool uint64_t applicationID = titleInfo->get_application_id(); + const FsSaveDataInfo *saveInfo = user->get_save_info_by_id(applicationID); + if (error::is_null(saveInfo)) + { + task->finished(); + return; + } + + fs::SaveMetaData saveMeta{}; + const bool hasValidMeta = fs::fill_save_meta_data(saveInfo, saveMeta); }