|
|
|
@ -759,32 +759,49 @@ int write_files_fn(void *data, void *ud) {
|
|
|
|
|
// Get absolute path.
|
|
|
|
|
__attribute__((cleanup(
|
|
|
|
|
simple_archiver_helper_cleanup_malloced))) void *abs_path = NULL;
|
|
|
|
|
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
|
|
|
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
|
|
|
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
|
|
|
|
abs_path = realpath(file_info->filename, NULL);
|
|
|
|
|
#endif
|
|
|
|
|
__attribute__((cleanup(
|
|
|
|
|
simple_archiver_helper_cleanup_malloced))) void *rel_path = NULL;
|
|
|
|
|
if (abs_path) {
|
|
|
|
|
// Get relative path.
|
|
|
|
|
// First get absolute path of link.
|
|
|
|
|
__attribute__((cleanup(
|
|
|
|
|
simple_archiver_helper_cleanup_malloced))) void *link_abs_path =
|
|
|
|
|
simple_archiver_file_abs_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);
|
|
|
|
|
|
|
|
|
|
rel_path =
|
|
|
|
|
simple_archiver_filenames_to_relative_path(link_abs_path, abs_path);
|
|
|
|
|
if ((state->parsed->flags & 0x100) != 0) {
|
|
|
|
|
// Preserve symlink target.
|
|
|
|
|
char *path_buf = malloc(1024);
|
|
|
|
|
ssize_t ret = readlink(file_info->filename, path_buf, 1023);
|
|
|
|
|
if (ret == -1) {
|
|
|
|
|
fprintf(stderr, "WARNING: Failed to get symlink's target!\n");
|
|
|
|
|
free(path_buf);
|
|
|
|
|
((uint8_t *)temp_to_write->buf)[1] |= 0x8;
|
|
|
|
|
} else {
|
|
|
|
|
path_buf[ret] = 0;
|
|
|
|
|
if (path_buf[0] == '/') {
|
|
|
|
|
abs_path = path_buf;
|
|
|
|
|
((uint8_t *)temp_to_write->buf)[1] |= 0x4;
|
|
|
|
|
} else {
|
|
|
|
|
rel_path = path_buf;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
abs_path = realpath(file_info->filename, NULL);
|
|
|
|
|
if (abs_path) {
|
|
|
|
|
// Get relative path.
|
|
|
|
|
// First get absolute path of link.
|
|
|
|
|
__attribute__((cleanup(
|
|
|
|
|
simple_archiver_helper_cleanup_malloced))) void *link_abs_path =
|
|
|
|
|
simple_archiver_file_abs_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);
|
|
|
|
|
|
|
|
|
|
rel_path = simple_archiver_filenames_to_relative_path(link_abs_path,
|
|
|
|
|
abs_path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if absolute path refers to one of the filenames.
|
|
|
|
|
if (abs_path && (state->parsed->flags & 0x20) == 0 &&
|
|
|
|
|
(state->parsed->flags & 0x100) == 0 &&
|
|
|
|
|
!simple_archiver_hash_map_get(state->map, abs_path,
|
|
|
|
|
strlen(abs_path) + 1)) {
|
|
|
|
|
// Is not a filename being archived.
|
|
|
|
@ -804,6 +821,43 @@ int write_files_fn(void *data, void *ud) {
|
|
|
|
|
file_info->filename);
|
|
|
|
|
((uint8_t *)temp_to_write->buf)[1] |= 0x8;
|
|
|
|
|
}
|
|
|
|
|
} else if ((state->parsed->flags & 0x100) != 0 &&
|
|
|
|
|
(state->parsed->flags & 0x80) == 0 &&
|
|
|
|
|
(((uint8_t *)temp_to_write->buf)[1] & 0x8) == 0) {
|
|
|
|
|
__attribute__((cleanup(
|
|
|
|
|
simple_archiver_helper_cleanup_c_string))) char *resolved_path = NULL;
|
|
|
|
|
if (abs_path || rel_path) {
|
|
|
|
|
resolved_path = realpath(file_info->filename, NULL);
|
|
|
|
|
if (!resolved_path) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: Symlink \"%s\" is invalid, will not be stored! "
|
|
|
|
|
"(Use \"--no-safe-links\" to disable this behavior)\n",
|
|
|
|
|
file_info->filename);
|
|
|
|
|
((uint8_t *)temp_to_write->buf)[1] |= 0x8;
|
|
|
|
|
} else if (!simple_archiver_hash_map_get(state->map, resolved_path,
|
|
|
|
|
strlen(resolved_path) + 1)) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: Symlink \"%s\" points to outside archive contents, "
|
|
|
|
|
"will not be stored! (Use \"--no-safe-links\" to disable "
|
|
|
|
|
"this behavior)\n",
|
|
|
|
|
file_info->filename);
|
|
|
|
|
((uint8_t *)temp_to_write->buf)[1] |= 0x8;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: Unable to get target path from symlink \"%s\"!\n",
|
|
|
|
|
file_info->filename);
|
|
|
|
|
((uint8_t *)temp_to_write->buf)[1] |= 0x8;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!abs_path && !rel_path) {
|
|
|
|
|
// No valid paths, set as invalid.
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: Could not get valid abs/rel path for symlink \"%s\" "
|
|
|
|
|
"(invalid symlink)!\n",
|
|
|
|
|
file_info->filename);
|
|
|
|
|
((uint8_t *)temp_to_write->buf)[1] |= 0x8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Store the 4 byte bit-flags for file.
|
|
|
|
@ -822,8 +876,10 @@ int write_files_fn(void *data, void *ud) {
|
|
|
|
|
|
|
|
|
|
// Store the absolute and relative paths.
|
|
|
|
|
if (!abs_path) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: Failed to get absolute path of link destination!\n");
|
|
|
|
|
if ((state->parsed->flags & 0x100) == 0) {
|
|
|
|
|
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;
|
|
|
|
@ -896,9 +952,17 @@ int write_files_fn(void *data, void *ud) {
|
|
|
|
|
// Write all previously set data.
|
|
|
|
|
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);
|
|
|
|
|
if (abs_path) {
|
|
|
|
|
fprintf(stderr, " abs path: %s\n", (char *)abs_path);
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr, " abs path is NOT set\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (rel_path) {
|
|
|
|
|
fprintf(stderr, " rel path: %s\n", (char *)rel_path);
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr, " rel path is NOT set\n");
|
|
|
|
|
}
|
|
|
|
|
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_free(&to_write);
|
|
|
|
|
}
|
|
|
|
@ -974,10 +1038,15 @@ int filenames_to_abs_map_fn(void *data, void *ud) {
|
|
|
|
|
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,
|
|
|
|
|
simple_archiver_helper_datastructure_cleanup_nop, NULL);
|
|
|
|
|
if (!simple_archiver_hash_map_get(abs_filenames, fullpath_dirname_copy,
|
|
|
|
|
strlen(fullpath_dirname_copy) + 1)) {
|
|
|
|
|
simple_archiver_hash_map_insert(
|
|
|
|
|
abs_filenames, fullpath_dirname_copy, fullpath_dirname_copy,
|
|
|
|
|
strlen(fullpath_dirname_copy) + 1,
|
|
|
|
|
simple_archiver_helper_datastructure_cleanup_nop, NULL);
|
|
|
|
|
} else {
|
|
|
|
|
free(fullpath_dirname_copy);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
prev = fullpath_dirname;
|
|
|
|
|
}
|
|
|
|
@ -1680,6 +1749,29 @@ int files_to_chunk_count(void *data, void *ud) {
|
|
|
|
|
|
|
|
|
|
int greater_fn(int64_t a, int64_t b) { return a > b; }
|
|
|
|
|
|
|
|
|
|
void simple_archiver_internal_paths_to_files_map(SDArchiverHashMap *files_map,
|
|
|
|
|
const char *filename) {
|
|
|
|
|
simple_archiver_hash_map_insert(
|
|
|
|
|
files_map, (void *)1, strdup((const char *)filename),
|
|
|
|
|
strlen((const char *)filename) + 1,
|
|
|
|
|
simple_archiver_helper_datastructure_cleanup_nop, NULL);
|
|
|
|
|
__attribute__((
|
|
|
|
|
cleanup(simple_archiver_helper_cleanup_c_string))) char *filename_copy =
|
|
|
|
|
strdup(filename);
|
|
|
|
|
char *filename_dirname = dirname(filename_copy);
|
|
|
|
|
|
|
|
|
|
while (strcmp(filename_dirname, ".") != 0) {
|
|
|
|
|
if (!simple_archiver_hash_map_get(files_map, filename_dirname,
|
|
|
|
|
strlen(filename_dirname) + 1)) {
|
|
|
|
|
simple_archiver_hash_map_insert(
|
|
|
|
|
files_map, (void *)1, strdup(filename_dirname),
|
|
|
|
|
strlen(filename_dirname) + 1,
|
|
|
|
|
simple_archiver_helper_datastructure_cleanup_nop, NULL);
|
|
|
|
|
}
|
|
|
|
|
filename_dirname = dirname(filename_dirname);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *simple_archiver_error_to_string(enum SDArchiverStateReturns error) {
|
|
|
|
|
switch (error) {
|
|
|
|
|
case SDAS_SUCCESS:
|
|
|
|
@ -2059,30 +2151,51 @@ int simple_archiver_write_v1(FILE *out_f, SDArchiverState *state,
|
|
|
|
|
node = node->next;
|
|
|
|
|
++u32;
|
|
|
|
|
memset(buf, 0, 2);
|
|
|
|
|
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
|
|
|
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
|
|
|
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
|
|
|
|
// Check if symlink points to thing to be stored into archive.
|
|
|
|
|
__attribute__((
|
|
|
|
|
cleanup(simple_archiver_helper_cleanup_malloced))) void *abs_path =
|
|
|
|
|
realpath(node->data, NULL);
|
|
|
|
|
__attribute__((cleanup(
|
|
|
|
|
simple_archiver_helper_cleanup_malloced))) void *rel_path = NULL;
|
|
|
|
|
if (abs_path) {
|
|
|
|
|
__attribute__((cleanup(
|
|
|
|
|
simple_archiver_helper_cleanup_malloced))) void *link_abs_path =
|
|
|
|
|
simple_archiver_file_abs_path(node->data);
|
|
|
|
|
if (!link_abs_path) {
|
|
|
|
|
fprintf(stderr, "WARNING: Failed to get absolute path to link!\n");
|
|
|
|
|
} else {
|
|
|
|
|
rel_path = simple_archiver_filenames_to_relative_path(link_abs_path,
|
|
|
|
|
abs_path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint_fast8_t is_invalid = 0;
|
|
|
|
|
|
|
|
|
|
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
|
|
|
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
|
|
|
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
|
|
|
|
__attribute__((cleanup(
|
|
|
|
|
simple_archiver_helper_cleanup_malloced))) void *abs_path = NULL;
|
|
|
|
|
__attribute__((cleanup(
|
|
|
|
|
simple_archiver_helper_cleanup_malloced))) void *rel_path = NULL;
|
|
|
|
|
if ((state->parsed->flags & 0x100) != 0) {
|
|
|
|
|
// Preserve symlink target.
|
|
|
|
|
char *path_buf = malloc(1024);
|
|
|
|
|
ssize_t ret = readlink(node->data, path_buf, 1023);
|
|
|
|
|
if (ret == -1) {
|
|
|
|
|
fprintf(stderr, "WARNING: Failed to get symlink's target!\n");
|
|
|
|
|
free(path_buf);
|
|
|
|
|
is_invalid = 1;
|
|
|
|
|
} else {
|
|
|
|
|
path_buf[ret] = 0;
|
|
|
|
|
if (path_buf[0] == '/') {
|
|
|
|
|
abs_path = path_buf;
|
|
|
|
|
buf[0] |= 1;
|
|
|
|
|
} else {
|
|
|
|
|
rel_path = path_buf;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
abs_path = realpath(node->data, NULL);
|
|
|
|
|
// Check if symlink points to thing to be stored into archive.
|
|
|
|
|
if (abs_path) {
|
|
|
|
|
__attribute__((cleanup(
|
|
|
|
|
simple_archiver_helper_cleanup_malloced))) void *link_abs_path =
|
|
|
|
|
simple_archiver_file_abs_path(node->data);
|
|
|
|
|
if (!link_abs_path) {
|
|
|
|
|
fprintf(stderr, "WARNING: Failed to get absolute path to link!\n");
|
|
|
|
|
} else {
|
|
|
|
|
rel_path = simple_archiver_filenames_to_relative_path(link_abs_path,
|
|
|
|
|
abs_path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (abs_path && (state->parsed->flags & 0x20) == 0 &&
|
|
|
|
|
(state->parsed->flags & 0x100) == 0 &&
|
|
|
|
|
!simple_archiver_hash_map_get(abs_filenames, abs_path,
|
|
|
|
|
strlen(abs_path) + 1)) {
|
|
|
|
|
// Is not a filename being archived.
|
|
|
|
@ -2098,6 +2211,36 @@ int simple_archiver_write_v1(FILE *out_f, SDArchiverState *state,
|
|
|
|
|
// Safe links disabled, set preference to absolute path.
|
|
|
|
|
buf[0] |= 1;
|
|
|
|
|
}
|
|
|
|
|
} else if ((state->parsed->flags & 0x100) != 0 &&
|
|
|
|
|
(state->parsed->flags & 0x80) == 0 && !is_invalid) {
|
|
|
|
|
__attribute__((cleanup(
|
|
|
|
|
simple_archiver_helper_cleanup_c_string))) char *target_realpath =
|
|
|
|
|
realpath(node->data, NULL);
|
|
|
|
|
if (!target_realpath) {
|
|
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
|
|
|
|
"WARNING: \"%s\" is an invalid symlink and \"--no-safe-links\" "
|
|
|
|
|
"not specified, will skip this symlink!\n",
|
|
|
|
|
(const char *)node->data);
|
|
|
|
|
is_invalid = 1;
|
|
|
|
|
} else if (!simple_archiver_hash_map_get(abs_filenames, target_realpath,
|
|
|
|
|
strlen(target_realpath) + 1)) {
|
|
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
|
|
|
|
"WARNING: \"%s\" points to outside of archived files and "
|
|
|
|
|
"\"--no-safe-links\" not specified, will skip this symlink!\n",
|
|
|
|
|
(const char *)node->data);
|
|
|
|
|
is_invalid = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!abs_path && !rel_path) {
|
|
|
|
|
// No valid paths, mark as invalid.
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: \"%s\" is an invalid symlink, will not store rel/abs "
|
|
|
|
|
"link paths!\n",
|
|
|
|
|
(const char *)node->data);
|
|
|
|
|
is_invalid = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get symlink stats for permissions.
|
|
|
|
@ -2842,6 +2985,18 @@ int simple_archiver_parse_archive_version_0(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
// fprintf(stderr, "\"%s\" put in map\n", key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__attribute__((cleanup(simple_archiver_list_free)))
|
|
|
|
|
SDArchiverLinkedList *links_list =
|
|
|
|
|
state && state->parsed && state->parsed->flags & 0x80
|
|
|
|
|
? NULL
|
|
|
|
|
: simple_archiver_list_init();
|
|
|
|
|
__attribute__((cleanup(simple_archiver_hash_map_free)))
|
|
|
|
|
SDArchiverHashMap *files_map =
|
|
|
|
|
state && state->parsed && state->parsed->flags & 0x80
|
|
|
|
|
? NULL
|
|
|
|
|
: simple_archiver_hash_map_init();
|
|
|
|
|
|
|
|
|
|
for (uint32_t idx = 0; idx < size; ++idx) {
|
|
|
|
|
if (is_sig_int_occurred) {
|
|
|
|
|
return SDAS_SIGINT;
|
|
|
|
@ -2972,6 +3127,10 @@ int simple_archiver_parse_archive_version_0(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
cleanup_overwrite_filename_delete_simple(&to_overwrite_dest);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (files_map && !skip && out_f_name) {
|
|
|
|
|
simple_archiver_internal_paths_to_files_map(files_map, out_f_name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
|
|
|
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
|
|
|
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
|
|
|
@ -3450,19 +3609,19 @@ int simple_archiver_parse_archive_version_0(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
if (ret == -1) {
|
|
|
|
|
if (retry_symlink) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: Failed to create symlink after removing "
|
|
|
|
|
" WARNING: Failed to create symlink after removing "
|
|
|
|
|
"existing symlink!\n");
|
|
|
|
|
goto V0_SYMLINK_CREATE_AFTER_0;
|
|
|
|
|
} else if (errno == EEXIST) {
|
|
|
|
|
if ((state->parsed->flags & 8) == 0) {
|
|
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
|
|
|
|
"WARNING: Symlink already exists and "
|
|
|
|
|
" WARNING: Symlink already exists and "
|
|
|
|
|
"\"--overwrite-extract\" is not specified, skipping!\n");
|
|
|
|
|
goto V0_SYMLINK_CREATE_AFTER_0;
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"NOTICE: Symlink already exists and "
|
|
|
|
|
" NOTICE: Symlink already exists and "
|
|
|
|
|
"\"--overwrite-extract\" specified, attempting to "
|
|
|
|
|
"overwrite...\n");
|
|
|
|
|
unlink(out_f_name);
|
|
|
|
@ -3473,17 +3632,21 @@ int simple_archiver_parse_archive_version_0(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
return SDAS_FAILED_TO_EXTRACT_SYMLINK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (links_list) {
|
|
|
|
|
simple_archiver_list_add(links_list, strdup(out_f_name), NULL);
|
|
|
|
|
}
|
|
|
|
|
ret = fchmodat(AT_FDCWD, out_f_name, permissions,
|
|
|
|
|
AT_SYMLINK_NOFOLLOW);
|
|
|
|
|
if (ret == -1) {
|
|
|
|
|
if (errno == EOPNOTSUPP) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"NOTICE: Setting permissions of symlink is not "
|
|
|
|
|
" NOTICE: Setting permissions of symlink is not "
|
|
|
|
|
"supported by FS/OS!\n");
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: Failed to set permissions of symlink (%d)!\n",
|
|
|
|
|
errno);
|
|
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
|
|
|
|
" WARNING: Failed to set permissions of symlink (%d)!\n",
|
|
|
|
|
errno);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
V0_SYMLINK_CREATE_AFTER_0:
|
|
|
|
@ -3500,19 +3663,19 @@ int simple_archiver_parse_archive_version_0(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
if (ret == -1) {
|
|
|
|
|
if (retry_symlink) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: Failed to create symlink after removing "
|
|
|
|
|
" WARNING: Failed to create symlink after removing "
|
|
|
|
|
"existing symlink!\n");
|
|
|
|
|
goto V0_SYMLINK_CREATE_AFTER_1;
|
|
|
|
|
} else if (errno == EEXIST) {
|
|
|
|
|
if ((state->parsed->flags & 8) == 0) {
|
|
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
|
|
|
|
"WARNING: Symlink already exists and "
|
|
|
|
|
" WARNING: Symlink already exists and "
|
|
|
|
|
"\"--overwrite-extract\" is not specified, skipping!\n");
|
|
|
|
|
goto V0_SYMLINK_CREATE_AFTER_1;
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"NOTICE: Symlink already exists and "
|
|
|
|
|
" NOTICE: Symlink already exists and "
|
|
|
|
|
"\"--overwrite-extract\" specified, attempting to "
|
|
|
|
|
"overwrite...\n");
|
|
|
|
|
unlink(out_f_name);
|
|
|
|
@ -3523,17 +3686,21 @@ int simple_archiver_parse_archive_version_0(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
return SDAS_FAILED_TO_EXTRACT_SYMLINK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (links_list) {
|
|
|
|
|
simple_archiver_list_add(links_list, strdup(out_f_name), NULL);
|
|
|
|
|
}
|
|
|
|
|
ret = fchmodat(AT_FDCWD, out_f_name, permissions,
|
|
|
|
|
AT_SYMLINK_NOFOLLOW);
|
|
|
|
|
if (ret == -1) {
|
|
|
|
|
if (errno == EOPNOTSUPP) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"NOTICE: Setting permissions of symlink is not "
|
|
|
|
|
" NOTICE: Setting permissions of symlink is not "
|
|
|
|
|
"supported by FS/OS!\n");
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: Failed to set permissions of symlink (%d)!\n",
|
|
|
|
|
errno);
|
|
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
|
|
|
|
" WARNING: Failed to set permissions of symlink (%d)!\n",
|
|
|
|
|
errno);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
V0_SYMLINK_CREATE_AFTER_1:
|
|
|
|
@ -3548,16 +3715,20 @@ int simple_archiver_parse_archive_version_0(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
if (ret == -1) {
|
|
|
|
|
return SDAS_FAILED_TO_EXTRACT_SYMLINK;
|
|
|
|
|
}
|
|
|
|
|
if (links_list) {
|
|
|
|
|
simple_archiver_list_add(links_list, strdup(out_f_name), NULL);
|
|
|
|
|
}
|
|
|
|
|
ret =
|
|
|
|
|
fchmodat(AT_FDCWD, out_f_name, permissions, AT_SYMLINK_NOFOLLOW);
|
|
|
|
|
if (ret == -1) {
|
|
|
|
|
if (errno == EOPNOTSUPP) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"NOTICE: Setting permissions of symlink is not supported "
|
|
|
|
|
"by FS/OS!\n");
|
|
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
|
|
|
|
" NOTICE: Setting permissions of symlink is not supported "
|
|
|
|
|
"by FS/OS!\n");
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: Failed to set permissions of symlink (%d)!\n",
|
|
|
|
|
" WARNING: Failed to set permissions of symlink (%d)!\n",
|
|
|
|
|
errno);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -3570,16 +3741,20 @@ int simple_archiver_parse_archive_version_0(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
if (ret == -1) {
|
|
|
|
|
return SDAS_FAILED_TO_EXTRACT_SYMLINK;
|
|
|
|
|
}
|
|
|
|
|
if (links_list) {
|
|
|
|
|
simple_archiver_list_add(links_list, strdup(out_f_name), NULL);
|
|
|
|
|
}
|
|
|
|
|
ret =
|
|
|
|
|
fchmodat(AT_FDCWD, out_f_name, permissions, AT_SYMLINK_NOFOLLOW);
|
|
|
|
|
if (ret == -1) {
|
|
|
|
|
if (errno == EOPNOTSUPP) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"NOTICE: Setting permissions of symlink is not supported "
|
|
|
|
|
"by FS/OS!\n");
|
|
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
|
|
|
|
" NOTICE: Setting permissions of symlink is not supported "
|
|
|
|
|
"by FS/OS!\n");
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: Failed to set permissions of symlink (%d)!\n",
|
|
|
|
|
" WARNING: Failed to set permissions of symlink (%d)!\n",
|
|
|
|
|
errno);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -3587,12 +3762,16 @@ int simple_archiver_parse_archive_version_0(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
|
|
|
|
"WARNING: Symlink entry in archive has no paths to link to!\n");
|
|
|
|
|
" WARNING: Symlink entry in archive has no paths to link to!\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (do_extract && links_list && files_map) {
|
|
|
|
|
simple_archiver_safe_links_enforce(links_list, files_map);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_sig_int_occurred) {
|
|
|
|
|
return SDAS_SIGINT;
|
|
|
|
|
}
|
|
|
|
@ -3637,6 +3816,21 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__attribute__((cleanup(simple_archiver_list_free)))
|
|
|
|
|
SDArchiverLinkedList *links_list =
|
|
|
|
|
state && state->parsed && state->parsed->flags & 0x80
|
|
|
|
|
? NULL
|
|
|
|
|
: simple_archiver_list_init();
|
|
|
|
|
__attribute__((cleanup(simple_archiver_hash_map_free)))
|
|
|
|
|
SDArchiverHashMap *files_map =
|
|
|
|
|
state && state->parsed && state->parsed->flags & 0x80
|
|
|
|
|
? NULL
|
|
|
|
|
: simple_archiver_hash_map_init();
|
|
|
|
|
|
|
|
|
|
__attribute__((
|
|
|
|
|
cleanup(simple_archiver_helper_cleanup_c_string))) char *cwd_realpath =
|
|
|
|
|
realpath(".", NULL);
|
|
|
|
|
|
|
|
|
|
const int_fast8_t is_compressed = (buf[0] & 1) ? 1 : 0;
|
|
|
|
|
|
|
|
|
|
__attribute__((cleanup(
|
|
|
|
@ -3704,9 +3898,7 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
const uint_fast8_t is_invalid = (buf[1] & 4) ? 1 : 0;
|
|
|
|
|
|
|
|
|
|
if (is_invalid) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
" WARNING: This symlink entry was marked invalid (not a safe "
|
|
|
|
|
"link)!\n");
|
|
|
|
|
fprintf(stderr, " WARNING: This symlink entry was marked invalid!\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
|
|
|
@ -3789,21 +3981,22 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
ret = symlink(path, link_name);
|
|
|
|
|
if (ret == -1) {
|
|
|
|
|
if (link_create_retry) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: Failed to create symlink after removing existing "
|
|
|
|
|
"symlink!\n");
|
|
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
|
|
|
|
" WARNING: Failed to create symlink after removing existing "
|
|
|
|
|
"symlink!\n");
|
|
|
|
|
goto V1_SYMLINK_CREATE_AFTER_0;
|
|
|
|
|
} else if (errno == EEXIST) {
|
|
|
|
|
if ((state->parsed->flags & 8) == 0) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: Symlink already exists and "
|
|
|
|
|
" WARNING: Symlink already exists and "
|
|
|
|
|
"\"--overwrite-extract\" is not specified, skipping!\n");
|
|
|
|
|
goto V1_SYMLINK_CREATE_AFTER_0;
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
|
|
|
|
"NOTICE: Symlink already exists and \"--overwrite-extract\" "
|
|
|
|
|
"specified, attempting to overwrite...\n");
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
" NOTICE: Symlink already exists and "
|
|
|
|
|
"\"--overwrite-extract\" specified, attempting to "
|
|
|
|
|
"overwrite...\n");
|
|
|
|
|
unlink(link_name);
|
|
|
|
|
link_create_retry = 1;
|
|
|
|
|
goto V1_SYMLINK_CREATE_RETRY_0;
|
|
|
|
@ -3815,11 +4008,11 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
if (ret == -1) {
|
|
|
|
|
if (errno == EOPNOTSUPP) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"NOTICE: Setting permissions of symlink is not supported "
|
|
|
|
|
" NOTICE: Setting permissions of symlink is not supported "
|
|
|
|
|
"by FS/OS!\n");
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: Failed to set permissions of symlink (%d)!\n",
|
|
|
|
|
" WARNING: Failed to set permissions of symlink (%d)!\n",
|
|
|
|
|
errno);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -3828,7 +4021,7 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
V1_SYMLINK_CREATE_AFTER_0:
|
|
|
|
|
link_create_retry = 1;
|
|
|
|
|
#endif
|
|
|
|
|
} else {
|
|
|
|
|
} else if (!do_extract) {
|
|
|
|
|
fprintf(stderr, " Abs path: %s\n", path);
|
|
|
|
|
}
|
|
|
|
|
} else if (!do_extract) {
|
|
|
|
@ -3861,21 +4054,22 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
ret = symlink(path, link_name);
|
|
|
|
|
if (ret == -1) {
|
|
|
|
|
if (link_create_retry) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: Failed to create symlink after removing existing "
|
|
|
|
|
"symlink!\n");
|
|
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
|
|
|
|
" WARNING: Failed to create symlink after removing existing "
|
|
|
|
|
"symlink!\n");
|
|
|
|
|
goto V1_SYMLINK_CREATE_AFTER_1;
|
|
|
|
|
} else if (errno == EEXIST) {
|
|
|
|
|
if ((state->parsed->flags & 8) == 0) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: Symlink already exists and "
|
|
|
|
|
" WARNING: Symlink already exists and "
|
|
|
|
|
"\"--overwrite-extract\" is not specified, skipping!\n");
|
|
|
|
|
goto V1_SYMLINK_CREATE_AFTER_1;
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
|
|
|
|
"NOTICE: Symlink already exists and \"--overwrite-extract\" "
|
|
|
|
|
"specified, attempting to overwrite...\n");
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
" NOTICE: Symlink already exists and "
|
|
|
|
|
"\"--overwrite-extract\" specified, attempting to "
|
|
|
|
|
"overwrite...\n");
|
|
|
|
|
unlink(link_name);
|
|
|
|
|
link_create_retry = 1;
|
|
|
|
|
goto V1_SYMLINK_CREATE_RETRY_1;
|
|
|
|
@ -3887,11 +4081,11 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
if (ret == -1) {
|
|
|
|
|
if (errno == EOPNOTSUPP) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"NOTICE: Setting permissions of symlink is not supported "
|
|
|
|
|
" NOTICE: Setting permissions of symlink is not supported "
|
|
|
|
|
"by FS/OS!\n");
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"WARNING: Failed to set permissions of symlink (%d)!\n",
|
|
|
|
|
" WARNING: Failed to set permissions of symlink (%d)!\n",
|
|
|
|
|
errno);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -3900,7 +4094,7 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
V1_SYMLINK_CREATE_AFTER_1:
|
|
|
|
|
link_create_retry = 1;
|
|
|
|
|
#endif
|
|
|
|
|
} else {
|
|
|
|
|
} else if (!do_extract) {
|
|
|
|
|
fprintf(stderr, " Rel path: %s\n", path);
|
|
|
|
|
}
|
|
|
|
|
} else if (!do_extract) {
|
|
|
|
@ -3911,6 +4105,9 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
!skip_due_to_invalid) {
|
|
|
|
|
fprintf(stderr, " WARNING: Symlink \"%s\" was not created!\n",
|
|
|
|
|
link_name);
|
|
|
|
|
} else if (do_extract && link_extracted && !skip_due_to_map &&
|
|
|
|
|
!skip_due_to_invalid && links_list) {
|
|
|
|
|
simple_archiver_list_add(links_list, strdup(link_name), NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -4011,6 +4208,11 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
simple_archiver_helper_64_bit_be(&u64);
|
|
|
|
|
file_info->file_size = u64;
|
|
|
|
|
|
|
|
|
|
if (files_map) {
|
|
|
|
|
simple_archiver_internal_paths_to_files_map(files_map,
|
|
|
|
|
file_info->filename);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
simple_archiver_list_add(file_info_list, file_info,
|
|
|
|
|
free_internal_file_info);
|
|
|
|
|
file_info = NULL;
|
|
|
|
@ -4340,6 +4542,10 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (do_extract && links_list && files_map) {
|
|
|
|
|
simple_archiver_safe_links_enforce(links_list, files_map);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SDAS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -4523,3 +4729,69 @@ int simple_archiver_validate_file_path(const char *filepath) {
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void simple_archiver_safe_links_enforce(SDArchiverLinkedList *links_list,
|
|
|
|
|
SDArchiverHashMap *files_map) {
|
|
|
|
|
uint_fast8_t need_to_print_note = 1;
|
|
|
|
|
// safe-links: Check that every link maps to a file in the files_map.
|
|
|
|
|
__attribute__((
|
|
|
|
|
cleanup(simple_archiver_helper_cleanup_c_string))) char *path_to_cwd =
|
|
|
|
|
realpath(".", NULL);
|
|
|
|
|
|
|
|
|
|
// Ensure path_to_cwd ends with '/'.
|
|
|
|
|
uint32_t idx = 0;
|
|
|
|
|
while (path_to_cwd[idx] != 0) {
|
|
|
|
|
++idx;
|
|
|
|
|
}
|
|
|
|
|
if (path_to_cwd[idx - 1] != '/') {
|
|
|
|
|
char *temp = malloc(idx + 2);
|
|
|
|
|
memcpy(temp, path_to_cwd, idx);
|
|
|
|
|
temp[idx] = '/';
|
|
|
|
|
temp[idx + 1] = 0;
|
|
|
|
|
free(path_to_cwd);
|
|
|
|
|
path_to_cwd = temp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check every link to make sure it points to an existing file.
|
|
|
|
|
SDArchiverLLNode *links_node = links_list->head;
|
|
|
|
|
while (links_node->next != links_list->tail) {
|
|
|
|
|
links_node = links_node->next;
|
|
|
|
|
__attribute__((
|
|
|
|
|
cleanup(simple_archiver_helper_cleanup_c_string))) char *link_realpath =
|
|
|
|
|
realpath(links_node->data, NULL);
|
|
|
|
|
if (link_realpath) {
|
|
|
|
|
// Get local path.
|
|
|
|
|
__attribute__((cleanup(
|
|
|
|
|
simple_archiver_helper_cleanup_c_string))) char *link_localpath =
|
|
|
|
|
simple_archiver_filenames_to_relative_path(path_to_cwd,
|
|
|
|
|
link_realpath);
|
|
|
|
|
if (!simple_archiver_hash_map_get(files_map, link_localpath,
|
|
|
|
|
strlen(link_localpath) + 1)) {
|
|
|
|
|
// Invalid symlink.
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"Symlink \"%s\" is invalid (not pointing to archived file), "
|
|
|
|
|
"removing...\n",
|
|
|
|
|
(const char *)links_node->data);
|
|
|
|
|
unlink(links_node->data);
|
|
|
|
|
if (need_to_print_note) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"NOTE: Disable this behavior with \"--no-safe-links\" if "
|
|
|
|
|
"needed.\n");
|
|
|
|
|
need_to_print_note = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Invalid symlink.
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"Symlink \"%s\" is invalid (failed to resolve), removing...\n",
|
|
|
|
|
(const char *)links_node->data);
|
|
|
|
|
unlink(links_node->data);
|
|
|
|
|
if (need_to_print_note) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"NOTE: Disable this behavior with \"--no-safe-links\" if "
|
|
|
|
|
"needed.\n");
|
|
|
|
|
need_to_print_note = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|