Skip to content

Commit fd03ded

Browse files
committed
Symlink support
1 parent 866ffca commit fd03ded

File tree

3 files changed

+45
-18
lines changed

3 files changed

+45
-18
lines changed

src/index.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,16 @@ export const initUntarJS = async (locateWasm?: (file: string) => string): Promis
7474
* FilesPtr is a pointer that refers to an instance of the FileData in unpack.c
7575
typedef struct {
7676
char* filename;
77+
char* symlink;
7778
uint8_t* data;
7879
size_t data_size;
7980
} FileData;
8081
8182
and its fields are laid out in memory sequentially too so each field take 4 bytes:
8283
83-
4 bytes 4 bytes 4 bytes
84-
---------------|---------------|---------------
85-
filename data data_size
84+
4 bytes 4 bytes 4 bytes 4 bytes
85+
---------------|---------------|---------------|---------------
86+
filename symlink data data_size
8687
8788
`filesPtr + i * 12` calculates the memory address of the i-th FileData element in the array
8889
where `12` is the size of each FileData structure in memory in bytes: 4 + 4 + 4
@@ -91,16 +92,23 @@ export const initUntarJS = async (locateWasm?: (file: string) => string): Promis
9192
for (let i = 0; i < fileCount; i++) {
9293
const fileDataPtr = filesPtr + i * 12;
9394
const filenamePtr = wasmModule.getValue(fileDataPtr, 'i32');
94-
const dataSize = wasmModule.getValue(fileDataPtr + 8, 'i32');
95-
const dataPtr = wasmModule.getValue(fileDataPtr + 4, 'i32');
95+
const symlinkPtr = wasmModule.getValue(fileDataPtr + 4, 'i32');
96+
const dataPtr = wasmModule.getValue(fileDataPtr + 8, 'i32');
97+
const dataSize = wasmModule.getValue(fileDataPtr + 12, 'i32');
9698
const filename = wasmModule.UTF8ToString(filenamePtr);
97-
const fileData = new Uint8Array(
98-
wasmModule.HEAPU8.buffer,
99-
dataPtr,
100-
dataSize
101-
);
102-
const fileDataCopy = fileData.slice(0);
103-
files[filename] = fileDataCopy;
99+
const symlink = wasmModule.UTF8ToString(symlinkPtr);
100+
101+
if (symlink) {
102+
files[filename] = symlink;
103+
} else {
104+
const fileData = new Uint8Array(
105+
wasmModule.HEAPU8.buffer,
106+
dataPtr,
107+
dataSize
108+
);
109+
const fileDataCopy = fileData.slice(0);
110+
files[filename] = fileDataCopy;
111+
}
104112
}
105113

106114
wasmModule._free(inputPtr);

src/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
export type FilesData = { [filename: string]: Uint8Array };
1+
export type Symlink = string;
2+
3+
export type FilesData = { [filename: string]: Uint8Array | Symlink };
24

35
export interface IUnpackJSAPI {
46
extractData: (data: Uint8Array, decompressionOnly?: boolean) => Promise<FilesData>;

unpack.c

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

99
typedef struct {
1010
char* filename;
11+
char* symlink;
1112
uint8_t* data;
1213
size_t data_size;
1314
} FileData;
@@ -57,13 +58,27 @@ 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+
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+
78+
continue;
79+
}
80+
81+
6782
if (files_count + 1 > files_struct_length) {
6883
files_struct_length *= 2; // double the length
6984
FileData* oldfiles = files;
@@ -73,9 +88,10 @@ ExtractedArchive* extract_archive(uint8_t* inputData, size_t inputSize ) {
7388
result->files = oldfiles; // otherwise memory is lost, alternatively also everything can be freed.
7489
error_message = "Memory allocation error for file data.";
7590
return error_handler(result, error_message, archive);
76-
}
91+
}
7792
}
7893
files[files_count].filename = strdup(filename);
94+
files[files_count].symlink = strdup("");
7995
files[files_count].data = malloc(entrySize);
8096
files[files_count].data_size = entrySize;
8197

@@ -150,7 +166,7 @@ ExtractedArchive* decompression(uint8_t* inputData, size_t inputSize) {
150166

151167
const size_t buffsize = 64 * 1024;
152168
char buff[buffsize];
153-
size_t total_size = 0;
169+
size_t total_size = 0;
154170
const char *error_message;
155171

156172
FileData* files = malloc(sizeof(FileData) * (files_count + 1));
@@ -159,7 +175,7 @@ ExtractedArchive* decompression(uint8_t* inputData, size_t inputSize) {
159175
printf("Failed to allocate memory for files array\n");
160176
return NULL;
161177
}
162-
178+
163179
ExtractedArchive* result = (ExtractedArchive*)malloc(sizeof(ExtractedArchive));
164180
if (!result) {
165181
free(files);
@@ -194,6 +210,7 @@ ExtractedArchive* decompression(uint8_t* inputData, size_t inputSize) {
194210
if (!filename) filename = "decompression";
195211

196212
files[files_count].filename = strdup(filename);
213+
files[files_count].symlink = strdup("");
197214
files[files_count].data = NULL;
198215
files[files_count].data_size = 0;
199216

@@ -259,4 +276,4 @@ void free_extracted_archive(ExtractedArchive* archive) {
259276
}
260277
free(archive->files);
261278
free(archive);
262-
}
279+
}

0 commit comments

Comments
 (0)