Skip to content

Commit 5b74bfd

Browse files
committed
Handle symlinks take two
1 parent dcd976c commit 5b74bfd

File tree

2 files changed

+388
-327
lines changed

2 files changed

+388
-327
lines changed

unpack.c

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
typedef struct {
1010
char* filename;
11-
char* symlink;
1211
uint8_t* data;
1312
size_t data_size;
1413
} FileData;
@@ -42,6 +41,7 @@ ExtractedArchive* extract_archive(uint8_t* inputData, size_t inputSize ) {
4241
FileData* files = NULL;
4342
size_t files_count = 0;
4443
const char *error_message;
44+
bool hasSymLinks = false;
4545

4646
ExtractedArchive* result = (ExtractedArchive*)malloc(sizeof(ExtractedArchive));
4747
if (!result) {
@@ -66,19 +66,12 @@ ExtractedArchive* extract_archive(uint8_t* inputData, size_t inputSize ) {
6666
const char* filename = archive_entry_pathname(entry);
6767
size_t entrySize = archive_entry_size(entry);
6868

69+
// Ignore symbolic links for now
6970
if (archive_entry_filetype(entry) == AE_IFLNK) {
70-
// It's a symbolic link
71-
const char* target = archive_entry_symlink(entry);
72-
73-
files[files_count].filename = strdup(filename);
74-
files[files_count].symlink = strdup(target);
75-
76-
files_count++;
77-
71+
hasSymLinks = true;
7872
continue;
7973
}
8074

81-
8275
if (files_count + 1 > files_struct_length) {
8376
files_struct_length *= 2; // double the length
8477
FileData* oldfiles = files;
@@ -90,9 +83,8 @@ ExtractedArchive* extract_archive(uint8_t* inputData, size_t inputSize ) {
9083
return error_handler(result, error_message, archive);
9184
}
9285
}
86+
9387
files[files_count].filename = strdup(filename);
94-
free(files[files_count].symlink);
95-
files[files_count].symlink = NULL;
9688
files[files_count].data = malloc(entrySize);
9789
files[files_count].data_size = entrySize;
9890

@@ -122,6 +114,77 @@ ExtractedArchive* extract_archive(uint8_t* inputData, size_t inputSize ) {
122114
files_count++;
123115
}
124116

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+
125188
archive_read_free(archive);
126189
result->files = files;
127190
result->fileCount = files_count;
@@ -211,7 +274,6 @@ ExtractedArchive* decompression(uint8_t* inputData, size_t inputSize) {
211274
if (!filename) filename = "decompression";
212275

213276
files[files_count].filename = strdup(filename);
214-
files[files_count].symlink = strdup("");
215277
files[files_count].data = NULL;
216278
files[files_count].data_size = 0;
217279

@@ -273,7 +335,6 @@ void free_extracted_archive(ExtractedArchive* archive) {
273335
}
274336
for (size_t i = 0; i < archive->fileCount; i++) {
275337
free(archive->files[i].filename);
276-
free(archive->files[i].symlink);
277338
free(archive->files[i].data);
278339
}
279340
free(archive->files);

0 commit comments

Comments
 (0)