mirror of
https://github.com/J-D-K/JKSV.git
synced 2026-03-21 17:24:37 -05:00
Update ZIP logic to include and detect directory entries. Fixes 289.
This commit is contained in:
parent
1095971895
commit
8b72f08dcc
2
Makefile
2
Makefile
|
|
@ -39,7 +39,7 @@ INCLUDES := include ./Libraries/FsLib/Switch/FsLib/include ./Libraries/SDLLib/SD
|
|||
EXEFS_SRC := exefs_src
|
||||
APP_TITLE := JKSV
|
||||
APP_AUTHOR := JK
|
||||
APP_VERSION := 08.25.2025
|
||||
APP_VERSION := 09.08.2025
|
||||
ROMFS := romfs
|
||||
ICON := icon.jpg
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,9 @@ namespace fs
|
|||
/// @brief Reads from the currently open file to the buffer passed.
|
||||
ssize_t read(void *buffer, size_t bufferSize);
|
||||
|
||||
/// @brief Returns if the entry is just a directory.
|
||||
bool is_directory() const noexcept;
|
||||
|
||||
/// @brief Returns the name of the current file.
|
||||
const char *get_filename() const noexcept;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@ namespace fs
|
|||
/// @brief Manual call for closing the zipFile.
|
||||
void close();
|
||||
|
||||
/// @brief Creates a new dummy directory entry in the ZIP.
|
||||
/// @param Path Path of the directory. Will be appended with a trailing slash if needed.
|
||||
void add_directory(std::string_view path);
|
||||
|
||||
/// @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);
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ namespace
|
|||
/// @brief Build month.
|
||||
constexpr uint8_t BUILD_MON = 9;
|
||||
/// @brief Build day.
|
||||
constexpr uint8_t BUILD_DAY = 6;
|
||||
constexpr uint8_t BUILD_DAY = 8;
|
||||
/// @brief Year.
|
||||
constexpr uint16_t BUILD_YEAR = 2025;
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,13 @@ bool fs::MiniUnzip::reset()
|
|||
|
||||
ssize_t fs::MiniUnzip::read(void *buffer, size_t bufferSize) { return unzReadCurrentFile(m_unz, buffer, bufferSize); }
|
||||
|
||||
bool fs::MiniUnzip::is_directory() const noexcept
|
||||
{
|
||||
const size_t length = std::char_traits<char>::length(m_filename);
|
||||
|
||||
return m_filename[length - 1] == '/';
|
||||
}
|
||||
|
||||
const char *fs::MiniUnzip::get_filename() const noexcept { return m_filename; }
|
||||
|
||||
uint64_t fs::MiniUnzip::get_compressed_size() const noexcept { return m_fileInfo.compressed_size; }
|
||||
|
|
|
|||
|
|
@ -37,6 +37,15 @@ void fs::MiniZip::close()
|
|||
m_isOpen = false;
|
||||
}
|
||||
|
||||
void fs::MiniZip::add_directory(std::string_view filename)
|
||||
{
|
||||
std::string zipPath{filename};
|
||||
if (zipPath.back() != '/') { zipPath.append("/"); }
|
||||
|
||||
MiniZip::open_new_file(zipPath);
|
||||
MiniZip::close_current_file();
|
||||
}
|
||||
|
||||
bool fs::MiniZip::open_new_file(std::string_view filename, bool trimPath, size_t trimPlaces)
|
||||
{
|
||||
const size_t pathBegin = filename.find_first_of('/');
|
||||
|
|
|
|||
|
|
@ -23,9 +23,6 @@ namespace
|
|||
|
||||
/// @brief Buffer size used for decompressing files from ZIP.
|
||||
constexpr size_t SIZE_UNZIP_BUFFER = 0x600000;
|
||||
|
||||
/// @brief This is the file written to ZIP backups to preserve empty directories.
|
||||
constexpr std::string_view NAME_SAVE_ME = ".save_me";
|
||||
} // namespace
|
||||
|
||||
// Shared struct for Zip/File IO
|
||||
|
|
@ -103,19 +100,14 @@ void fs::copy_directory_to_zip(const fslib::Path &source, fs::MiniZip &dest, sys
|
|||
fslib::Directory sourceDir{source};
|
||||
if (error::fslib(sourceDir.is_open())) { return; }
|
||||
|
||||
// This is needed to preserve empty directories.
|
||||
if (sourceDir.get_count() <= 0)
|
||||
{
|
||||
const fslib::Path saveMe{source / NAME_SAVE_ME};
|
||||
dest.open_new_file(saveMe.get_path());
|
||||
dest.close_current_file();
|
||||
return;
|
||||
}
|
||||
|
||||
for (const fslib::DirectoryEntry &entry : sourceDir)
|
||||
{
|
||||
const fslib::Path fullSource{source / entry};
|
||||
if (entry.is_directory()) { fs::copy_directory_to_zip(fullSource, dest, task); }
|
||||
if (entry.is_directory())
|
||||
{
|
||||
dest.add_directory(fullSource.string());
|
||||
fs::copy_directory_to_zip(fullSource, dest, task);
|
||||
}
|
||||
else
|
||||
{
|
||||
fslib::File sourceFile{fullSource, FsOpenMode_Read};
|
||||
|
|
@ -181,20 +173,27 @@ void fs::copy_zip_to_directory(fs::MiniUnzip &unzip, const fslib::Path &dest, in
|
|||
|
||||
do {
|
||||
if (unzip.get_filename() == fs::NAME_SAVE_META) { continue; }
|
||||
else if (unzip.is_directory())
|
||||
{
|
||||
// Just do this and continue.
|
||||
const fslib::Path dirPath{dest / unzip.get_filename()};
|
||||
error::fslib(fslib::create_directories_recursively(dirPath));
|
||||
continue;
|
||||
}
|
||||
|
||||
fslib::Path fullDest{dest / unzip.get_filename()};
|
||||
const size_t lastDir = fullDest.find_last_of('/');
|
||||
if (lastDir == fullDest.NOT_FOUND) { continue; }
|
||||
|
||||
const fslib::Path dirPath{fullDest.sub_path(lastDir)};
|
||||
const bool isValid = dirPath.is_valid();
|
||||
const bool exists = isValid && fslib::directory_exists(dirPath);
|
||||
const bool createError = isValid && !exists && error::fslib(fslib::create_directories_recursively(dirPath));
|
||||
bool commitError = !createError && error::fslib(fslib::commit_data_to_file_system(dirPath.get_device_name()));
|
||||
if (isValid && !exists && (createError || commitError)) { continue; }
|
||||
|
||||
// This is here so the directory still gets created if needed.
|
||||
if (fullDest.get_filename() == NAME_SAVE_ME) { continue; }
|
||||
if (lastDir > 0)
|
||||
{
|
||||
const fslib::Path dirPath{fullDest.sub_path(lastDir)};
|
||||
const bool isValid = dirPath.is_valid();
|
||||
const bool exists = isValid && fslib::directory_exists(dirPath);
|
||||
const bool createError = isValid && !exists && error::fslib(fslib::create_directories_recursively(dirPath));
|
||||
bool commitError = !createError && error::fslib(fslib::commit_data_to_file_system(dirPath.get_device_name()));
|
||||
if (isValid && !exists && (createError || commitError)) { continue; }
|
||||
}
|
||||
|
||||
const int64_t fileSize = unzip.get_uncompressed_size();
|
||||
fslib::File destFile{fullDest, FsOpenMode_Create | FsOpenMode_Write, fileSize};
|
||||
|
|
@ -237,7 +236,7 @@ void fs::copy_zip_to_directory(fs::MiniUnzip &unzip, const fslib::Path &dest, in
|
|||
if (commitNeeded)
|
||||
{
|
||||
destFile.close();
|
||||
commitError = error::fslib(fslib::commit_data_to_file_system(dest.get_device_name()));
|
||||
const bool commitError = error::fslib(fslib::commit_data_to_file_system(dest.get_device_name()));
|
||||
if (commitError) { ui::PopMessageManager::push_message(popTicks, popCommitFailed); } // To do: How to recover?
|
||||
|
||||
destFile.open(fullDest, FsOpenMode_Write);
|
||||
|
|
@ -254,7 +253,7 @@ void fs::copy_zip_to_directory(fs::MiniUnzip &unzip, const fslib::Path &dest, in
|
|||
readThread.join();
|
||||
destFile.close();
|
||||
|
||||
commitError = needCommits && error::fslib(fslib::commit_data_to_file_system(dest.get_device_name()));
|
||||
const bool commitError = needCommits && error::fslib(fslib::commit_data_to_file_system(dest.get_device_name()));
|
||||
if (commitError) { ui::PopMessageManager::push_message(popTicks, popCommitFailed); }
|
||||
} while (unzip.next_file());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user