Skip to content

Commit 018602c

Browse files
committed
Resolve symlinks content
1 parent 866ffca commit 018602c

File tree

1 file changed

+85
-5
lines changed

1 file changed

+85
-5
lines changed

unpack.c

Lines changed: 85 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ ExtractedArchive* extract_archive(uint8_t* inputData, size_t inputSize ) {
4141
FileData* files = NULL;
4242
size_t files_count = 0;
4343
const char *error_message;
44+
bool hasSymLinks = false;
4445

4546
ExtractedArchive* result = (ExtractedArchive*)malloc(sizeof(ExtractedArchive));
4647
if (!result) {
@@ -57,13 +58,20 @@ ExtractedArchive* extract_archive(uint8_t* inputData, size_t inputSize ) {
5758
archive_read_support_format_all(archive);
5859

5960
if (archive_read_open_memory(archive, inputData, inputSize) != ARCHIVE_OK) {
60-
return error_handler(result,archive_error_string(archive), archive);
61+
return error_handler(result,archive_error_string(archive), archive);
6162
}
6263
files = malloc(sizeof(FileData) * files_struct_length);
6364

6465
while (archive_read_next_header(archive, &entry) == ARCHIVE_OK) {
6566
const char* filename = archive_entry_pathname(entry);
6667
size_t entrySize = archive_entry_size(entry);
68+
69+
// Ignore symbolic links for now
70+
if (archive_entry_filetype(entry) == AE_IFLNK) {
71+
hasSymLinks = true;
72+
continue;
73+
}
74+
6775
if (files_count + 1 > files_struct_length) {
6876
files_struct_length *= 2; // double the length
6977
FileData* oldfiles = files;
@@ -73,8 +81,9 @@ ExtractedArchive* extract_archive(uint8_t* inputData, size_t inputSize ) {
7381
result->files = oldfiles; // otherwise memory is lost, alternatively also everything can be freed.
7482
error_message = "Memory allocation error for file data.";
7583
return error_handler(result, error_message, archive);
76-
}
84+
}
7785
}
86+
7887
files[files_count].filename = strdup(filename);
7988
files[files_count].data = malloc(entrySize);
8089
files[files_count].data_size = entrySize;
@@ -105,6 +114,77 @@ ExtractedArchive* extract_archive(uint8_t* inputData, size_t inputSize ) {
105114
files_count++;
106115
}
107116

117+
// Resolve symlinks
118+
if (hasSymLinks) {
119+
// Rewind and reopen the archive to iterate over symlinks
120+
archive_read_free(archive);
121+
archive = archive_read_new();
122+
archive_read_support_filter_all(archive);
123+
archive_read_support_format_all(archive);
124+
125+
if (archive_read_open_memory(archive, inputData, inputSize) != ARCHIVE_OK) {
126+
return error_handler(result, archive_error_string(archive), archive);
127+
}
128+
129+
struct archive_entry *symlink_entry;
130+
while (archive_read_next_header(archive, &symlink_entry) == ARCHIVE_OK) {
131+
// Process only symlinks this time
132+
if (archive_entry_filetype(symlink_entry) != AE_IFLNK) {
133+
continue;
134+
}
135+
136+
const char *linkname = archive_entry_pathname(symlink_entry);
137+
const char *target = archive_entry_symlink(symlink_entry);
138+
139+
// Target not found
140+
if (!target) {
141+
continue;
142+
}
143+
144+
// Find the target file in the already populated files[]
145+
size_t target_index = (size_t)-1;
146+
for (size_t i = 0; i < files_count; i++) {
147+
if (strcmp(files[i].filename, target) == 0) {
148+
target_index = i;
149+
break;
150+
}
151+
}
152+
153+
// Target not found in the processed files
154+
if (target_index == (size_t)-1 || !files[target_index].data) {
155+
continue;
156+
}
157+
158+
// Add the symlink entry
159+
if (files_count + 1 > files_struct_length) {
160+
files_struct_length *= 2;
161+
FileData *oldfiles = files;
162+
files = realloc(files, sizeof(FileData) * files_struct_length);
163+
if (!files) {
164+
result->fileCount = files_count;
165+
result->files = oldfiles;
166+
error_message = "Memory allocation error for symlink data.";
167+
return error_handler(result, error_message, archive);
168+
}
169+
}
170+
171+
files[files_count].filename = strdup(linkname);
172+
files[files_count].data_size = files[target_index].data_size;
173+
files[files_count].data = malloc(files[target_index].data_size);
174+
if (!files[files_count].data) {
175+
free(files[files_count].filename);
176+
files[files_count].filename = NULL;
177+
result->fileCount = files_count;
178+
result->files = files;
179+
error_message = "Memory allocation error for symlink target data.";
180+
return error_handler(result, error_message, archive);
181+
}
182+
memcpy(files[files_count].data, files[target_index].data, files[target_index].data_size);
183+
184+
files_count++;
185+
}
186+
}
187+
108188
archive_read_free(archive);
109189
result->files = files;
110190
result->fileCount = files_count;
@@ -150,7 +230,7 @@ ExtractedArchive* decompression(uint8_t* inputData, size_t inputSize) {
150230

151231
const size_t buffsize = 64 * 1024;
152232
char buff[buffsize];
153-
size_t total_size = 0;
233+
size_t total_size = 0;
154234
const char *error_message;
155235

156236
FileData* files = malloc(sizeof(FileData) * (files_count + 1));
@@ -159,7 +239,7 @@ ExtractedArchive* decompression(uint8_t* inputData, size_t inputSize) {
159239
printf("Failed to allocate memory for files array\n");
160240
return NULL;
161241
}
162-
242+
163243
ExtractedArchive* result = (ExtractedArchive*)malloc(sizeof(ExtractedArchive));
164244
if (!result) {
165245
free(files);
@@ -259,4 +339,4 @@ void free_extracted_archive(ExtractedArchive* archive) {
259339
}
260340
free(archive->files);
261341
free(archive);
262-
}
342+
}

0 commit comments

Comments
 (0)