| 33 | using namespace CppLogging; |
| 34 | |
| 35 | Path UnzipFile(const Path& path) |
| 36 | { |
| 37 | // Open a zip archive |
| 38 | unzFile unzf; |
| 39 | #if defined(_WIN32) || defined(_WIN64) |
| 40 | zlib_filefunc64_def ffunc; |
| 41 | fill_win32_filefunc64W(&ffunc); |
| 42 | unzf = unzOpen2_64(path.wstring().c_str(), &ffunc); |
| 43 | #else |
| 44 | unzf = unzOpen64(path.string().c_str()); |
| 45 | #endif |
| 46 | if (unzf == nullptr) |
| 47 | throwex FileSystemException("Cannot open a zip archive!").Attach(path); |
| 48 | |
| 49 | // Smart resource cleaner pattern |
| 50 | auto unzip = resource(unzf, [](unzFile handle) { unzClose(handle); }); |
| 51 | |
| 52 | File destination(path + ".tmp"); |
| 53 | |
| 54 | // Open the destination file for writing |
| 55 | destination.Create(false, true); |
| 56 | |
| 57 | // Get info about the zip archive |
| 58 | unz_global_info global_info; |
| 59 | int result = unzGetGlobalInfo(unzf, &global_info); |
| 60 | if (result != UNZ_OK) |
| 61 | throwex FileSystemException("Cannot read a zip archive global info!").Attach(path); |
| 62 | |
| 63 | // Loop to extract all files from the zip archive |
| 64 | uLong i; |
| 65 | for (i = 0; i < global_info.number_entry; ++i) |
| 66 | { |
| 67 | unz_file_info file_info; |
| 68 | char filename[1024]; |
| 69 | |
| 70 | // Get info about the current file in the zip archive |
| 71 | result = unzGetCurrentFileInfo(unzf, &file_info, filename, (unsigned)countof(filename), NULL, 0, NULL, 0); |
| 72 | if (result != UNZ_OK) |
| 73 | throwex FileSystemException("Cannot read a zip archive file info!").Attach(path); |
| 74 | |
| 75 | // Check if this entry is a file |
| 76 | const size_t filename_length = strlen(filename); |
| 77 | if (filename[filename_length - 1] != '/') |
| 78 | { |
| 79 | // Open the current file in the zip archive |
| 80 | result = unzOpenCurrentFile(unzf); |
| 81 | if (result != UNZ_OK) |
| 82 | throwex FileSystemException("Cannot open a current file in the zip archive!").Attach(path); |
| 83 | |
| 84 | // Smart resource cleaner pattern |
| 85 | auto unzip_file = resource(unzf, [](unzFile handle) { unzCloseCurrentFile(handle); }); |
| 86 | |
| 87 | // Read data from the current file in the zip archive |
| 88 | do |
| 89 | { |
| 90 | uint8_t buffer[16384]; |
| 91 | result = unzReadCurrentFile(unzf, buffer, (unsigned)countof(buffer)); |
| 92 | if (result > 0) |
no test coverage detected