forked from janhq/cortex.cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patharchive_utils.h
More file actions
156 lines (134 loc) · 5.11 KB
/
archive_utils.h
File metadata and controls
156 lines (134 loc) · 5.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <archive.h>
#include <archive_entry.h>
#include <minizip/unzip.h>
#include <trantor/utils/Logger.h>
#include <filesystem>
#include <fstream>
#include <iostream>
#include "logging_utils.h"
namespace archive_utils {
inline bool UnzipFile(const std::string& input_zip_path,
const std::string& destination_path);
inline bool UntarFile(const std::string& input_tar_path,
const std::string& destination_path,
bool ignore_parent_dir = false);
inline bool ExtractArchive(const std::string& input_path,
const std::string& destination_path,
bool ignore_parent_dir = false) {
if (input_path.find(".zip") != std::string::npos) {
return UnzipFile(input_path, destination_path);
} else if (input_path.find(".tar") != std::string::npos ||
input_path.find(".tar.gz") != std::string::npos) {
return UntarFile(input_path, destination_path, ignore_parent_dir);
} else {
LOG_ERROR << "Unsupported file type: " << input_path << "\n";
return false;
}
}
inline bool UnzipFile(const std::string& input_zip_path,
const std::string& destination_path) {
unzFile zip_file = unzOpen(input_zip_path.c_str());
if (!zip_file) {
LOG_ERROR << "Failed to open zip file: " << input_zip_path << "\n";
return false;
}
std::filesystem::create_directories(destination_path);
if (unzGoToFirstFile(zip_file) != UNZ_OK) {
LOG_ERROR << "Error opening first file in zip" << "\n";
unzClose(zip_file);
return false;
}
do {
unz_file_info file_info;
char file_name[256];
if (unzGetCurrentFileInfo(zip_file, &file_info, file_name,
sizeof(file_name), nullptr, 0, nullptr,
0) != UNZ_OK) {
LOG_ERROR << "Failed to get file info" << "\n";
unzClose(zip_file);
return false;
}
std::string full_path = destination_path + "/" + file_name;
if (file_name[strlen(file_name) - 1] == '/') {
std::filesystem::create_directories(full_path);
} else {
std::filesystem::create_directories(
std::filesystem::path(full_path).parent_path());
if (unzOpenCurrentFile(zip_file) != UNZ_OK) {
LOG_ERROR << "Failed to open file in zip: " << file_name << "\n";
unzClose(zip_file);
return false;
}
std::ofstream outFile(full_path, std::ios::binary);
if (!outFile.is_open()) {
LOG_ERROR << "Failed to create file: " << full_path << "\n";
unzCloseCurrentFile(zip_file);
unzClose(zip_file);
return false;
}
char buffer[8192];
int bytes_read;
while ((bytes_read =
unzReadCurrentFile(zip_file, buffer, sizeof(buffer))) > 0) {
outFile.write(buffer, bytes_read);
}
outFile.close();
unzCloseCurrentFile(zip_file);
}
} while (unzGoToNextFile(zip_file) == UNZ_OK);
unzClose(zip_file);
LOG_INFO << "Extracted successfully " << input_zip_path << " to "
<< destination_path << "\n";
return true;
}
inline bool UntarFile(const std::string& input_tar_path,
const std::string& destination_path,
bool ignore_parent_dir) {
struct archive* tar_archive = archive_read_new();
archive_read_support_format_tar(tar_archive);
archive_read_support_filter_gzip(tar_archive);
if (archive_read_open_filename(tar_archive, input_tar_path.c_str(), 10240) !=
ARCHIVE_OK) {
LOG_ERROR << "Failed to open tar file: " << input_tar_path << "\n";
archive_read_free(tar_archive);
return false;
}
std::filesystem::create_directories(destination_path);
struct archive_entry* entry;
while (archive_read_next_header(tar_archive, &entry) == ARCHIVE_OK) {
const char* current_file = archive_entry_pathname(entry);
auto file_in_tar_path =
std::filesystem::path(destination_path) / current_file;
auto file_name = std::filesystem::path(file_in_tar_path).filename();
auto output_path = std::filesystem::path(destination_path) / file_name;
std::string full_path = destination_path + "/" + current_file;
if (archive_entry_filetype(entry) == AE_IFDIR) {
if (!ignore_parent_dir) {
std::filesystem::create_directories(full_path);
}
} else {
auto final_output_path =
ignore_parent_dir ? output_path.string() : full_path;
std::ofstream out_file(final_output_path, std::ios::binary);
if (!out_file.is_open()) {
LOG_ERROR << "Failed to create file: " << full_path << "\n";
archive_read_free(tar_archive);
return false;
}
const void* buff;
size_t size;
la_int64_t offset;
while (archive_read_data_block(tar_archive, &buff, &size, &offset) ==
ARCHIVE_OK) {
out_file.write(static_cast<const char*>(buff), size);
}
out_file.close();
}
archive_entry_clear(entry);
}
archive_read_free(tar_archive);
CTL_INF("Extracted successfully " << input_tar_path << " to "
<< destination_path << "\n");
return true;
}
} // namespace archive_utils