Update ZIP logic to include and detect directory entries. Fixes 289.

This commit is contained in:
J-D-K 2025-09-08 12:51:15 -04:00
parent 1095971895
commit 8b72f08dcc
7 changed files with 48 additions and 26 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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; }

View File

@ -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('/');

View File

@ -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());
}