Compare commits
8 commits
4b730b4824
...
d8068a6f5f
Author | SHA1 | Date | |
---|---|---|---|
d8068a6f5f | |||
b28e384149 | |||
c6d2d50c0f | |||
2f4c0d3679 | |||
9d105bc3a5 | |||
b90b7ae64f | |||
e9c327a62f | |||
d939939723 |
5 changed files with 315 additions and 33 deletions
|
@ -55,6 +55,8 @@ Following the file-count bytes, the following bytes are added for each file:
|
||||||
2. The second byte.
|
2. The second byte.
|
||||||
1. The first bit is "other write permission".
|
1. The first bit is "other write permission".
|
||||||
2. The second bit is "other execute permission".
|
2. The second bit is "other execute permission".
|
||||||
|
3. The third bit is UNSET if relative links are preferred, and is SET
|
||||||
|
if absolute links are preferred.
|
||||||
3. The third byte.
|
3. The third byte.
|
||||||
1. Currently unused.
|
1. Currently unused.
|
||||||
4. The fourth byte.
|
4. The fourth byte.
|
||||||
|
|
317
src/archiver.c
317
src/archiver.c
|
@ -28,6 +28,8 @@
|
||||||
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <spawn.h>
|
#include <spawn.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -35,7 +37,6 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "data_structures/hash_map.h"
|
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
#define TEMP_FILENAME_CMP "simple_archiver_compressed_%u.tmp"
|
#define TEMP_FILENAME_CMP "simple_archiver_compressed_%u.tmp"
|
||||||
|
@ -102,6 +103,43 @@ void cleanup_temp_filename_delete(void ***ptrs_array) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *filename_to_absolute_path(const char *filename) {
|
||||||
|
__attribute__((cleanup(free_malloced_memory))) void *path =
|
||||||
|
malloc(strlen(filename) + 1);
|
||||||
|
strncpy(path, filename, strlen(filename) + 1);
|
||||||
|
|
||||||
|
char *path_dir = dirname(path);
|
||||||
|
if (!path_dir) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((cleanup(free_malloced_memory))) void *dir_realpath =
|
||||||
|
realpath(path_dir, NULL);
|
||||||
|
if (!dir_realpath) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recreate "path" since it may have been modified by dirname().
|
||||||
|
free_malloced_memory(&path);
|
||||||
|
path = malloc(strlen(filename) + 1);
|
||||||
|
strncpy(path, filename, strlen(filename) + 1);
|
||||||
|
|
||||||
|
char *filename_basename = basename(path);
|
||||||
|
if (!filename_basename) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get combined full path to file.
|
||||||
|
char *fullpath =
|
||||||
|
malloc(strlen(dir_realpath) + 1 + strlen(filename_basename) + 1);
|
||||||
|
strncpy(fullpath, dir_realpath, strlen(dir_realpath) + 1);
|
||||||
|
fullpath[strlen(dir_realpath)] = '/';
|
||||||
|
strncpy(fullpath + strlen(dir_realpath) + 1, filename_basename,
|
||||||
|
strlen(filename_basename) + 1);
|
||||||
|
|
||||||
|
return fullpath;
|
||||||
|
}
|
||||||
|
|
||||||
int write_files_fn(void *data, void *ud) {
|
int write_files_fn(void *data, void *ud) {
|
||||||
const SDArchiverFileInfo *file_info = data;
|
const SDArchiverFileInfo *file_info = data;
|
||||||
SDArchiverState *state = ud;
|
SDArchiverState *state = ud;
|
||||||
|
@ -666,33 +704,149 @@ int write_files_fn(void *data, void *ud) {
|
||||||
// Unsupported platform. Just set the permission bits for user.
|
// Unsupported platform. Just set the permission bits for user.
|
||||||
((unsigned char *)temp_to_write->buf)[0] |= 0xE;
|
((unsigned char *)temp_to_write->buf)[0] |= 0xE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Need to get abs_path for checking/setting a flag before storing flags.
|
||||||
|
// Get absolute path.
|
||||||
|
__attribute__((cleanup(free_malloced_memory))) void *abs_path =
|
||||||
|
realpath(file_info->filename, NULL);
|
||||||
|
__attribute__((cleanup(free_malloced_memory))) void *rel_path = NULL;
|
||||||
|
if (abs_path) {
|
||||||
|
// Get relative path.
|
||||||
|
// First get absolute path of link.
|
||||||
|
__attribute__((cleanup(free_malloced_memory))) void *link_abs_path =
|
||||||
|
filename_to_absolute_path(file_info->filename);
|
||||||
|
if (!link_abs_path) {
|
||||||
|
fprintf(stderr, "WARNING: Failed to get absolute path of link!\n");
|
||||||
|
} else {
|
||||||
|
// fprintf(stderr, "DEBUG: abs_path: %s\nDEBUG: link_abs_path: %s\n",
|
||||||
|
// (char*)abs_path, (char*)link_abs_path);
|
||||||
|
|
||||||
|
// Compare paths to get relative path.
|
||||||
|
// Get first non-common char.
|
||||||
|
unsigned int idx;
|
||||||
|
unsigned int last_slash;
|
||||||
|
for (idx = 0, last_slash = 0;
|
||||||
|
idx < strlen(abs_path) && idx < strlen(link_abs_path); ++idx) {
|
||||||
|
if (((const char *)abs_path)[idx] !=
|
||||||
|
((const char *)link_abs_path)[idx]) {
|
||||||
|
break;
|
||||||
|
} else if (((const char *)abs_path)[idx] == '/') {
|
||||||
|
last_slash = idx + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Get substrings of both paths.
|
||||||
|
char *link_substr = (char *)link_abs_path + last_slash;
|
||||||
|
char *dest_substr = (char *)abs_path + last_slash;
|
||||||
|
rel_path = malloc(strlen(dest_substr) + 1);
|
||||||
|
strncpy(rel_path, dest_substr, strlen(dest_substr) + 1);
|
||||||
|
// fprintf(stderr, "DEBUG: link_substr: %s\nDEBUG: dest_substr: %s\n",
|
||||||
|
// link_substr, dest_substr);
|
||||||
|
|
||||||
|
// Generate the relative path.
|
||||||
|
int has_slash = 0;
|
||||||
|
idx = 0;
|
||||||
|
do {
|
||||||
|
for (; link_substr[idx] != '/' && link_substr[idx] != 0; ++idx);
|
||||||
|
if (link_substr[idx] == 0) {
|
||||||
|
has_slash = 0;
|
||||||
|
} else {
|
||||||
|
has_slash = 1;
|
||||||
|
char *new_rel_path = malloc(strlen(rel_path) + 1 + 3);
|
||||||
|
new_rel_path[0] = '.';
|
||||||
|
new_rel_path[1] = '.';
|
||||||
|
new_rel_path[2] = '/';
|
||||||
|
strncpy(new_rel_path + 3, rel_path, strlen(rel_path) + 1);
|
||||||
|
free(rel_path);
|
||||||
|
rel_path = new_rel_path;
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
} while (has_slash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if absolute path refers to one of the filenames.
|
||||||
|
if (abs_path && (state->parsed->flags & 0x20) == 0 &&
|
||||||
|
!simple_archiver_hash_map_get(state->map, abs_path,
|
||||||
|
strlen(abs_path) + 1)) {
|
||||||
|
// Is not a filename being archived, set preference to absolute path.
|
||||||
|
fprintf(stderr,
|
||||||
|
"NOTICE: abs_path exists, \"--no-abs-symlink\" not specified, "
|
||||||
|
"and link refers to file NOT in archive; preferring abs_path.\n");
|
||||||
|
((unsigned char *)temp_to_write->buf)[1] |= 0x4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the 4 byte bit-flags for file.
|
||||||
simple_archiver_list_add(to_write, temp_to_write, free_internal_to_write);
|
simple_archiver_list_add(to_write, temp_to_write, free_internal_to_write);
|
||||||
|
|
||||||
|
// Store the absolute and relative paths.
|
||||||
|
if (!abs_path) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"WARNING: Failed to get absolute path of link destination!\n");
|
||||||
|
temp_to_write = malloc(sizeof(SDArchiverInternalToWrite));
|
||||||
|
temp_to_write->buf = malloc(2);
|
||||||
|
temp_to_write->size = 2;
|
||||||
|
memset(temp_to_write->buf, 0, 2);
|
||||||
|
simple_archiver_list_add(to_write, temp_to_write, free_internal_to_write);
|
||||||
|
} else if ((state->parsed->flags & 0x20) == 0) {
|
||||||
// Write absolute path length.
|
// Write absolute path length.
|
||||||
// TODO actually store absolute path.
|
u16 = strlen(abs_path);
|
||||||
// u16 = 0;
|
simple_archiver_helper_16_bit_be(&u16);
|
||||||
// No need to convert to big-endian since 0 is 0.
|
|
||||||
// simple_archiver_helper_16_bit_be(&u16);
|
|
||||||
|
|
||||||
temp_to_write = malloc(sizeof(SDArchiverInternalToWrite));
|
temp_to_write = malloc(sizeof(SDArchiverInternalToWrite));
|
||||||
temp_to_write->buf = malloc(2);
|
temp_to_write->buf = malloc(2);
|
||||||
temp_to_write->size = 2;
|
temp_to_write->size = 2;
|
||||||
((unsigned char *)temp_to_write->buf)[0] = 0;
|
memcpy(temp_to_write->buf, &u16, 2);
|
||||||
((unsigned char *)temp_to_write->buf)[1] = 0;
|
|
||||||
simple_archiver_list_add(to_write, temp_to_write, free_internal_to_write);
|
simple_archiver_list_add(to_write, temp_to_write, free_internal_to_write);
|
||||||
|
|
||||||
|
// Write absolute path.
|
||||||
|
simple_archiver_helper_16_bit_be(&u16);
|
||||||
|
temp_to_write = malloc(sizeof(SDArchiverInternalToWrite));
|
||||||
|
temp_to_write->buf = malloc(u16 + 1);
|
||||||
|
temp_to_write->size = u16 + 1;
|
||||||
|
strncpy(temp_to_write->buf, abs_path, u16 + 1);
|
||||||
|
simple_archiver_list_add(to_write, temp_to_write, free_internal_to_write);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,
|
||||||
|
"NOTICE: Not saving absolute path since \"--no-abs-symlink\" "
|
||||||
|
"was specified.\n");
|
||||||
|
temp_to_write = malloc(sizeof(SDArchiverInternalToWrite));
|
||||||
|
temp_to_write->buf = malloc(2);
|
||||||
|
temp_to_write->size = 2;
|
||||||
|
memset(temp_to_write->buf, 0, 2);
|
||||||
|
simple_archiver_list_add(to_write, temp_to_write, free_internal_to_write);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rel_path) {
|
||||||
// Write relative path length.
|
// Write relative path length.
|
||||||
// TODO actually store relative path.
|
u16 = strlen(rel_path);
|
||||||
|
simple_archiver_helper_16_bit_be(&u16);
|
||||||
temp_to_write = malloc(sizeof(SDArchiverInternalToWrite));
|
temp_to_write = malloc(sizeof(SDArchiverInternalToWrite));
|
||||||
temp_to_write->buf = malloc(2);
|
temp_to_write->buf = malloc(2);
|
||||||
temp_to_write->size = 2;
|
temp_to_write->size = 2;
|
||||||
((unsigned char *)temp_to_write->buf)[0] = 0;
|
memcpy(temp_to_write->buf, &u16, 2);
|
||||||
((unsigned char *)temp_to_write->buf)[1] = 0;
|
|
||||||
simple_archiver_list_add(to_write, temp_to_write, free_internal_to_write);
|
simple_archiver_list_add(to_write, temp_to_write, free_internal_to_write);
|
||||||
|
|
||||||
|
// Write relative path.
|
||||||
|
simple_archiver_helper_16_bit_be(&u16);
|
||||||
|
temp_to_write = malloc(sizeof(SDArchiverInternalToWrite));
|
||||||
|
temp_to_write->buf = malloc(u16 + 1);
|
||||||
|
temp_to_write->size = u16 + 1;
|
||||||
|
strncpy(temp_to_write->buf, rel_path, u16 + 1);
|
||||||
|
simple_archiver_list_add(to_write, temp_to_write, free_internal_to_write);
|
||||||
|
} else {
|
||||||
|
temp_to_write = malloc(sizeof(SDArchiverInternalToWrite));
|
||||||
|
temp_to_write->buf = malloc(2);
|
||||||
|
temp_to_write->size = 2;
|
||||||
|
memset(temp_to_write->buf, 0, 2);
|
||||||
|
simple_archiver_list_add(to_write, temp_to_write, free_internal_to_write);
|
||||||
|
}
|
||||||
|
|
||||||
// Write all previously set data.
|
// Write all previously set data.
|
||||||
fprintf(stderr, "Writing symlink info: %s\n", file_info->filename);
|
fprintf(stderr, "Writing symlink info: %s\n", file_info->filename);
|
||||||
|
if ((state->parsed->flags & 0x20) == 0) {
|
||||||
|
fprintf(stderr, " abs path: %s\n", (char *)abs_path);
|
||||||
|
}
|
||||||
|
fprintf(stderr, " rel path: %s\n", (char *)rel_path);
|
||||||
simple_archiver_list_get(to_write, write_list_datas_fn, state->out_f);
|
simple_archiver_list_get(to_write, write_list_datas_fn, state->out_f);
|
||||||
simple_archiver_list_free(&to_write);
|
simple_archiver_list_free(&to_write);
|
||||||
}
|
}
|
||||||
|
@ -704,6 +858,54 @@ int write_files_fn(void *data, void *ud) {
|
||||||
void cleanup_nop_fn(__attribute__((unused)) void *unused) {}
|
void cleanup_nop_fn(__attribute__((unused)) void *unused) {}
|
||||||
void cleanup_free_fn(void *data) { free(data); }
|
void cleanup_free_fn(void *data) { free(data); }
|
||||||
|
|
||||||
|
int filenames_to_abs_map_fn(void *data, void *ud) {
|
||||||
|
SDArchiverFileInfo *file_info = data;
|
||||||
|
SDArchiverHashMap **abs_filenames = ud;
|
||||||
|
|
||||||
|
// Get combined full path to file.
|
||||||
|
char *fullpath = filename_to_absolute_path(file_info->filename);
|
||||||
|
if (!fullpath) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
simple_archiver_hash_map_insert(abs_filenames, fullpath, fullpath,
|
||||||
|
strlen(fullpath) + 1, cleanup_nop_fn, NULL);
|
||||||
|
|
||||||
|
// Try putting all parent dirs up to current working directory.
|
||||||
|
// First get absolute path to current working directory.
|
||||||
|
__attribute__((cleanup(free_malloced_memory))) void *cwd_dirname =
|
||||||
|
realpath(".", NULL);
|
||||||
|
if (!cwd_dirname) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use copy of fullpath to avoid clobbering it.
|
||||||
|
__attribute__((cleanup(free_malloced_memory))) void *fullpath_copy =
|
||||||
|
malloc(strlen(fullpath) + 1);
|
||||||
|
strncpy(fullpath_copy, fullpath, strlen(fullpath) + 1);
|
||||||
|
|
||||||
|
// Get dirnames.
|
||||||
|
char *prev = fullpath_copy;
|
||||||
|
char *fullpath_dirname;
|
||||||
|
while (1) {
|
||||||
|
fullpath_dirname = dirname(prev);
|
||||||
|
if (!fullpath_dirname || strlen(fullpath_dirname) <= strlen(cwd_dirname)) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// Make and store copy of fullpath_dirname.
|
||||||
|
char *fullpath_dirname_copy = malloc(strlen(fullpath_dirname) + 1);
|
||||||
|
strncpy(fullpath_dirname_copy, fullpath_dirname,
|
||||||
|
strlen(fullpath_dirname) + 1);
|
||||||
|
simple_archiver_hash_map_insert(
|
||||||
|
abs_filenames, fullpath_dirname_copy, fullpath_dirname_copy,
|
||||||
|
strlen(fullpath_dirname_copy) + 1, cleanup_nop_fn, NULL);
|
||||||
|
}
|
||||||
|
prev = fullpath_dirname;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
char *simple_archiver_error_to_string(enum SDArchiverStateReturns error) {
|
char *simple_archiver_error_to_string(enum SDArchiverStateReturns error) {
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case SDAS_SUCCESS:
|
case SDAS_SUCCESS:
|
||||||
|
@ -722,6 +924,10 @@ char *simple_archiver_error_to_string(enum SDArchiverStateReturns error) {
|
||||||
return "Invalid file";
|
return "Invalid file";
|
||||||
case SDAS_INTERNAL_ERROR:
|
case SDAS_INTERNAL_ERROR:
|
||||||
return "Internal error";
|
return "Internal error";
|
||||||
|
case SDAS_FAILED_TO_CREATE_MAP:
|
||||||
|
return "Failed to create set of filenames (internal error)";
|
||||||
|
case SDAS_FAILED_TO_EXTRACT_SYMLINK:
|
||||||
|
return "Failed to extract symlink (internal error)";
|
||||||
default:
|
default:
|
||||||
return "Unknown error";
|
return "Unknown error";
|
||||||
}
|
}
|
||||||
|
@ -736,6 +942,7 @@ SDArchiverState *simple_archiver_init_state(const SDArchiverParsed *parsed) {
|
||||||
state->flags = 0;
|
state->flags = 0;
|
||||||
state->parsed = parsed;
|
state->parsed = parsed;
|
||||||
state->out_f = NULL;
|
state->out_f = NULL;
|
||||||
|
state->map = NULL;
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -749,6 +956,14 @@ void simple_archiver_free_state(SDArchiverState **state) {
|
||||||
|
|
||||||
int simple_archiver_write_all(FILE *out_f, SDArchiverState *state,
|
int simple_archiver_write_all(FILE *out_f, SDArchiverState *state,
|
||||||
const SDArchiverLinkedList *filenames) {
|
const SDArchiverLinkedList *filenames) {
|
||||||
|
// First create a "set" of absolute paths to given filenames.
|
||||||
|
__attribute__((cleanup(simple_archiver_hash_map_free)))
|
||||||
|
SDArchiverHashMap *abs_filenames = simple_archiver_hash_map_init();
|
||||||
|
if (simple_archiver_list_get(filenames, filenames_to_abs_map_fn,
|
||||||
|
&abs_filenames)) {
|
||||||
|
return SDAS_FAILED_TO_CREATE_MAP;
|
||||||
|
}
|
||||||
|
|
||||||
if (fwrite("SIMPLE_ARCHIVE_VER", 1, 18, out_f) != 18) {
|
if (fwrite("SIMPLE_ARCHIVE_VER", 1, 18, out_f) != 18) {
|
||||||
return SDAS_FAILED_TO_WRITE;
|
return SDAS_FAILED_TO_WRITE;
|
||||||
}
|
}
|
||||||
|
@ -832,6 +1047,7 @@ int simple_archiver_write_all(FILE *out_f, SDArchiverState *state,
|
||||||
state->count = 0;
|
state->count = 0;
|
||||||
state->max = filenames->count;
|
state->max = filenames->count;
|
||||||
state->out_f = out_f;
|
state->out_f = out_f;
|
||||||
|
state->map = abs_filenames;
|
||||||
fprintf(stderr, "Begin archiving...\n");
|
fprintf(stderr, "Begin archiving...\n");
|
||||||
fprintf(stderr, "[%10u/%10u]\n", state->count, state->max);
|
fprintf(stderr, "[%10u/%10u]\n", state->count, state->max);
|
||||||
if (simple_archiver_list_get(filenames, write_files_fn, state)) {
|
if (simple_archiver_list_get(filenames, write_files_fn, state)) {
|
||||||
|
@ -1399,6 +1615,14 @@ int simple_archiver_parse_archive_info(FILE *in_f, int do_extract,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Is a symbolic link.
|
// Is a symbolic link.
|
||||||
|
|
||||||
|
int abs_preferred = (buf[1] & 0x4) != 0 ? 1 : 0;
|
||||||
|
fprintf(stderr, " Absolute path is %s\n",
|
||||||
|
(abs_preferred ? "preferred" : "NOT preferred"));
|
||||||
|
|
||||||
|
__attribute__((cleanup(free_malloced_memory))) void *abs_path = NULL;
|
||||||
|
__attribute__((cleanup(free_malloced_memory))) void *rel_path = NULL;
|
||||||
|
|
||||||
if (fread(&u16, 2, 1, in_f) != 1) {
|
if (fread(&u16, 2, 1, in_f) != 1) {
|
||||||
return SDAS_INVALID_FILE;
|
return SDAS_INVALID_FILE;
|
||||||
}
|
}
|
||||||
|
@ -1411,15 +1635,15 @@ int simple_archiver_parse_archive_info(FILE *in_f, int do_extract,
|
||||||
}
|
}
|
||||||
buf[1023] = 0;
|
buf[1023] = 0;
|
||||||
fprintf(stderr, " Link absolute path: %s\n", buf);
|
fprintf(stderr, " Link absolute path: %s\n", buf);
|
||||||
|
abs_path = malloc((size_t)u16 + 1);
|
||||||
|
strncpy(abs_path, (char *)buf, (size_t)u16 + 1);
|
||||||
} else {
|
} else {
|
||||||
__attribute__((cleanup(free_malloced_memory))) void *heap_buf =
|
abs_path = malloc(u16 + 1);
|
||||||
malloc(u16 + 1);
|
if (fread(abs_path, 1, u16 + 1, in_f) != (size_t)u16 + 1) {
|
||||||
unsigned char *uc_heap_buf = heap_buf;
|
|
||||||
if (fread(uc_heap_buf, 1, u16 + 1, in_f) != (size_t)u16 + 1) {
|
|
||||||
return SDAS_INVALID_FILE;
|
return SDAS_INVALID_FILE;
|
||||||
}
|
}
|
||||||
uc_heap_buf[u16 - 1] = 0;
|
((char *)abs_path)[u16 - 1] = 0;
|
||||||
fprintf(stderr, " Link absolute path: %s\n", uc_heap_buf);
|
fprintf(stderr, " Link absolute path: %s\n", (char *)abs_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fread(&u16, 2, 1, in_f) != 1) {
|
if (fread(&u16, 2, 1, in_f) != 1) {
|
||||||
|
@ -1434,15 +1658,62 @@ int simple_archiver_parse_archive_info(FILE *in_f, int do_extract,
|
||||||
}
|
}
|
||||||
buf[1023] = 0;
|
buf[1023] = 0;
|
||||||
fprintf(stderr, " Link relative path: %s\n", buf);
|
fprintf(stderr, " Link relative path: %s\n", buf);
|
||||||
|
rel_path = malloc((size_t)u16 + 1);
|
||||||
|
strncpy(rel_path, (char *)buf, (size_t)u16 + 1);
|
||||||
} else {
|
} else {
|
||||||
__attribute__((cleanup(free_malloced_memory))) void *heap_buf =
|
rel_path = malloc(u16 + 1);
|
||||||
malloc(u16 + 1);
|
if (fread(rel_path, 1, u16 + 1, in_f) != (size_t)u16 + 1) {
|
||||||
unsigned char *uc_heap_buf = heap_buf;
|
|
||||||
if (fread(uc_heap_buf, 1, u16 + 1, in_f) != (size_t)u16 + 1) {
|
|
||||||
return SDAS_INVALID_FILE;
|
return SDAS_INVALID_FILE;
|
||||||
}
|
}
|
||||||
uc_heap_buf[u16 - 1] = 0;
|
((char *)rel_path)[u16 - 1] = 0;
|
||||||
fprintf(stderr, " Link relative path: %s\n", uc_heap_buf);
|
fprintf(stderr, " Link relative path: %s\n", (char *)rel_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_extract) {
|
||||||
|
simple_archiver_helper_make_dirs((const char *)out_f_name);
|
||||||
|
if (abs_path && rel_path) {
|
||||||
|
if (abs_preferred) {
|
||||||
|
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
||||||
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
||||||
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
||||||
|
int ret = symlink(abs_path, out_f_name);
|
||||||
|
if (ret == -1) {
|
||||||
|
return SDAS_FAILED_TO_EXTRACT_SYMLINK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
||||||
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
||||||
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
||||||
|
int ret = symlink(rel_path, out_f_name);
|
||||||
|
if (ret == -1) {
|
||||||
|
return SDAS_FAILED_TO_EXTRACT_SYMLINK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else if (abs_path) {
|
||||||
|
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
||||||
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
||||||
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
||||||
|
int ret = symlink(abs_path, out_f_name);
|
||||||
|
if (ret == -1) {
|
||||||
|
return SDAS_FAILED_TO_EXTRACT_SYMLINK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else if (rel_path) {
|
||||||
|
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
||||||
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
||||||
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
||||||
|
int ret = symlink(rel_path, out_f_name);
|
||||||
|
if (ret == -1) {
|
||||||
|
return SDAS_FAILED_TO_EXTRACT_SYMLINK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
fprintf(
|
||||||
|
stderr,
|
||||||
|
"WARNING: Symlink entry in archive has no paths to link to!\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "data_structures/hash_map.h"
|
||||||
#include "data_structures/linked_list.h"
|
#include "data_structures/linked_list.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
|
@ -30,6 +31,7 @@ typedef struct SDArchiverState {
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
const SDArchiverParsed *parsed;
|
const SDArchiverParsed *parsed;
|
||||||
FILE *out_f;
|
FILE *out_f;
|
||||||
|
SDArchiverHashMap *map;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
unsigned int max;
|
unsigned int max;
|
||||||
} SDArchiverState;
|
} SDArchiverState;
|
||||||
|
@ -42,7 +44,9 @@ enum SDArchiverStateReturns {
|
||||||
SDAS_NO_DECOMPRESSOR,
|
SDAS_NO_DECOMPRESSOR,
|
||||||
SDAS_INVALID_PARSED_STATE,
|
SDAS_INVALID_PARSED_STATE,
|
||||||
SDAS_INVALID_FILE,
|
SDAS_INVALID_FILE,
|
||||||
SDAS_INTERNAL_ERROR
|
SDAS_INTERNAL_ERROR,
|
||||||
|
SDAS_FAILED_TO_CREATE_MAP,
|
||||||
|
SDAS_FAILED_TO_EXTRACT_SYMLINK
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Returned pointer must not be freed.
|
/// Returned pointer must not be freed.
|
||||||
|
|
|
@ -151,6 +151,8 @@ void simple_archiver_print_usage(void) {
|
||||||
"file's stored decompressor\n");
|
"file's stored decompressor\n");
|
||||||
fprintf(stderr, "--overwrite-create : allows overwriting an archive file\n");
|
fprintf(stderr, "--overwrite-create : allows overwriting an archive file\n");
|
||||||
fprintf(stderr, "--overwrite-extract : allows overwriting when extracting\n");
|
fprintf(stderr, "--overwrite-extract : allows overwriting when extracting\n");
|
||||||
|
fprintf(stderr,
|
||||||
|
"--no-abs-symlink : do not store absolute paths for symlinks\n");
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"-- : specifies remaining arguments are files to archive/extract\n");
|
"-- : specifies remaining arguments are files to archive/extract\n");
|
||||||
fprintf(
|
fprintf(
|
||||||
|
@ -243,6 +245,8 @@ int simple_archiver_parse_args(int argc, const char **argv,
|
||||||
out->flags |= 0x4;
|
out->flags |= 0x4;
|
||||||
} else if (strcmp(argv[0], "--overwrite-extract") == 0) {
|
} else if (strcmp(argv[0], "--overwrite-extract") == 0) {
|
||||||
out->flags |= 0x8;
|
out->flags |= 0x8;
|
||||||
|
} else if (strcmp(argv[0], "--no-abs-symlink") == 0) {
|
||||||
|
out->flags |= 0x20;
|
||||||
} else if (argv[0][0] == '-' && argv[0][1] == '-' && argv[0][2] == 0) {
|
} else if (argv[0][0] == '-' && argv[0][1] == '-' && argv[0][2] == 0) {
|
||||||
is_remaining_args = 1;
|
is_remaining_args = 1;
|
||||||
} else if (argv[0][0] != '-') {
|
} else if (argv[0][0] != '-') {
|
||||||
|
|
|
@ -30,6 +30,7 @@ typedef struct SDArchiverParsed {
|
||||||
/// 0b xxxx x1xx - Allow create archive overwrite.
|
/// 0b xxxx x1xx - Allow create archive overwrite.
|
||||||
/// 0b xxxx 1xxx - Allow extract overwrite.
|
/// 0b xxxx 1xxx - Allow extract overwrite.
|
||||||
/// 0b xxx1 xxxx - Create archive to stdout or read archive from stdin.
|
/// 0b xxx1 xxxx - Create archive to stdout or read archive from stdin.
|
||||||
|
/// 0b xx1x xxxx - Do not save absolute paths for symlinks.
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
/// Null-terminated string.
|
/// Null-terminated string.
|
||||||
char *filename;
|
char *filename;
|
||||||
|
|
Loading…
Reference in a new issue