/* * Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG * Copyright (C) 2020 Rosalie Wanders * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "Unzip.hpp" #include "Error.hpp" #include #include #include #include // // Local Defines // #define UNZIP_READ_SIZE 67108860 /* 64 MiB */ // // Exported Functions // bool CoreUnzip(std::filesystem::path file, std::filesystem::path path) { std::string error; unzFile zipFile; unz_global_info zipInfo; std::ofstream outputStream; char* read_buffer = (char*)malloc(UNZIP_READ_SIZE); size_t bytes_read = 0; if (read_buffer == nullptr) { error = "CoreUnzip: malloc Failed!"; CoreSetError(error); return false; } zipFile = unzOpen(file.string().c_str()); if (zipFile == nullptr) { free(read_buffer); error = "CoreUnzip: unzOpen Failed!"; CoreSetError(error); return false; } if (unzGetGlobalInfo(zipFile, &zipInfo) != UNZ_OK) { free(read_buffer); error = "CoreUnzip: unzGetGlobalInfo Failed!"; CoreSetError(error); return false; } for (int i = 0; i < zipInfo.number_entry; i++) { unz_file_info fileInfo; char fileName[PATH_MAX]; std::filesystem::path targetPath; // ensure we can retrieve the current file info if (unzGetCurrentFileInfo(zipFile, &fileInfo, fileName, PATH_MAX, nullptr, 0, nullptr, 0) != UNZ_OK) { free(read_buffer); unzClose(zipFile); error = "CoreUnzip: unzGetCurrentFileInfo Failed!"; CoreSetError(error); return false; } targetPath = path; targetPath += "/"; targetPath += fileName; if (targetPath.string().ends_with("/")) { // directory try { if (!std::filesystem::is_directory(targetPath) && !std::filesystem::create_directory(targetPath)) { throw std::exception(); } } catch (...) { free(read_buffer); unzClose(zipFile); error = "CoreUnzip: std::filesystem::create_directory("; error += targetPath.string(); error += ") Failed!"; CoreSetError(error); return false; } } else { // file if (unzOpenCurrentFile(zipFile) != UNZ_OK) { free(read_buffer); unzClose(zipFile); error = "CoreUnzip: unzOpenCurrentFile Failed!"; CoreSetError(error); return false; } outputStream.open(targetPath, std::ios::trunc | std::ios::binary); if (!outputStream.is_open()) { free(read_buffer); unzCloseCurrentFile(zipFile); unzClose(zipFile); error = "CoreUnzip: failed to open file!"; error += targetPath.string(); CoreSetError(error); return false; } do { bytes_read = unzReadCurrentFile(zipFile, read_buffer, UNZIP_READ_SIZE); if (bytes_read < 0) { free(read_buffer); unzCloseCurrentFile(zipFile); unzClose(zipFile); error = "CoreUnzip: unzReadCurrentFile Failed!"; CoreSetError(error); return false; } else { // write data to file outputStream.write(read_buffer, bytes_read); } } while (bytes_read > 0); outputStream.close(); unzCloseCurrentFile(zipFile); } // break when we've iterated over all entries if ((i + 1) >= zipInfo.number_entry) { break; } // move to next file if (unzGoToNextFile(zipFile) != UNZ_OK) { free(read_buffer); unzClose(zipFile); error = "CoreUnzip: unzGoToNextFile Failed!"; CoreSetError(error); return false; } } unzClose(zipFile); free(read_buffer); return true; }