Impl. "safe links" by default for v0
By default, links that point to outside of archive (or possibly doesn't point to anything) will be ignored. Use "--no-safe-links" to preserve such symlinks. Note this has only been implemented for v0 of the file format in this commit, and not yet v1.
This commit is contained in:
parent
7ee54bddf2
commit
cef3e4184a
4 changed files with 78 additions and 9 deletions
|
@ -57,6 +57,11 @@ Following the file-count bytes, the following bytes are added for each file:
|
||||||
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
|
3. The third bit is UNSET if relative links are preferred, and is SET
|
||||||
if absolute links are preferred.
|
if absolute links are preferred.
|
||||||
|
4. The fourth bit is set if this file/symlink-entry is invalid and must
|
||||||
|
be skipped. Ignore following bytes after these 4 bytes bit-flags in
|
||||||
|
this specification and skip to the next entry; if marked invalid,
|
||||||
|
the following specification bytes for this file/symlink entry must
|
||||||
|
not exist.
|
||||||
3. The third byte.
|
3. The third byte.
|
||||||
1. Currently unused.
|
1. Currently unused.
|
||||||
4. The fourth byte.
|
4. The fourth byte.
|
||||||
|
|
|
@ -114,6 +114,20 @@ void cleanup_temp_filename_delete(void ***ptrs_array) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cleanup_overwrite_filename_delete_simple(char **filename) {
|
||||||
|
if (filename && *filename) {
|
||||||
|
if ((*filename)[0] != 0) {
|
||||||
|
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
||||||
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
||||||
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
||||||
|
unlink(*filename);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
free(*filename);
|
||||||
|
*filename = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int write_files_fn(void *data, void *ud) {
|
int write_files_fn(void *data, void *ud) {
|
||||||
if (is_sig_int_occurred) {
|
if (is_sig_int_occurred) {
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -773,16 +787,39 @@ int write_files_fn(void *data, void *ud) {
|
||||||
if (abs_path && (state->parsed->flags & 0x20) == 0 &&
|
if (abs_path && (state->parsed->flags & 0x20) == 0 &&
|
||||||
!simple_archiver_hash_map_get(state->map, abs_path,
|
!simple_archiver_hash_map_get(state->map, abs_path,
|
||||||
strlen(abs_path) + 1)) {
|
strlen(abs_path) + 1)) {
|
||||||
// Is not a filename being archived, set preference to absolute path.
|
// Is not a filename being archived.
|
||||||
fprintf(stderr,
|
if ((state->parsed->flags & 0x80) != 0) {
|
||||||
"NOTICE: abs_path exists, \"--no-abs-symlink\" not specified, "
|
// No safe links, set preference to absolute path.
|
||||||
"and link refers to file NOT in archive; preferring abs_path.\n");
|
fprintf(
|
||||||
((uint8_t *)temp_to_write->buf)[1] |= 0x4;
|
stderr,
|
||||||
|
"NOTICE: abs_path exists, \"--no-abs-symlink\" not specified, "
|
||||||
|
"and link refers to file NOT in archive; preferring abs_path.\n");
|
||||||
|
((uint8_t *)temp_to_write->buf)[1] |= 0x4;
|
||||||
|
} else {
|
||||||
|
// Safe links, do not store symlink!
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the 4 byte bit-flags for file.
|
// 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);
|
||||||
|
|
||||||
|
if ((((uint8_t *)temp_to_write->buf)[1] & 0x8) != 0) {
|
||||||
|
// Skipped symlink.
|
||||||
|
simple_archiver_list_get(to_write, write_list_datas_fn, state->out_f);
|
||||||
|
simple_archiver_list_free(&to_write);
|
||||||
|
char format_str[64];
|
||||||
|
snprintf(format_str, 64, FILE_COUNTS_OUTPUT_FORMAT_STR_1, state->digits,
|
||||||
|
state->digits);
|
||||||
|
fprintf(stderr, format_str, ++(state->count), state->max);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Store the absolute and relative paths.
|
// Store the absolute and relative paths.
|
||||||
if (!abs_path) {
|
if (!abs_path) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
@ -2802,6 +2839,9 @@ int simple_archiver_parse_archive_version_0(FILE *in_f, int_fast8_t do_extract,
|
||||||
simple_archiver_helper_cleanup_malloced))) void *out_f_name = NULL;
|
simple_archiver_helper_cleanup_malloced))) void *out_f_name = NULL;
|
||||||
__attribute__((cleanup(simple_archiver_helper_cleanup_FILE))) FILE *out_f =
|
__attribute__((cleanup(simple_archiver_helper_cleanup_FILE))) FILE *out_f =
|
||||||
NULL;
|
NULL;
|
||||||
|
__attribute__((cleanup(
|
||||||
|
cleanup_overwrite_filename_delete_simple))) char *to_overwrite_dest =
|
||||||
|
NULL;
|
||||||
if (u16 < SIMPLE_ARCHIVER_BUFFER_SIZE) {
|
if (u16 < SIMPLE_ARCHIVER_BUFFER_SIZE) {
|
||||||
if (fread(buf, 1, u16 + 1, in_f) != (size_t)u16 + 1) {
|
if (fread(buf, 1, u16 + 1, in_f) != (size_t)u16 + 1) {
|
||||||
return SDAS_INVALID_FILE;
|
return SDAS_INVALID_FILE;
|
||||||
|
@ -2831,12 +2871,14 @@ int simple_archiver_parse_archive_version_0(FILE *in_f, int_fast8_t do_extract,
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
if (errno == ELOOP) {
|
if (errno == ELOOP) {
|
||||||
// Is an existing symbolic file.
|
// Is an existing symbolic file.
|
||||||
unlink((const char *)buf);
|
// Defer deletion to after "is invalid" check.
|
||||||
|
to_overwrite_dest = strdup((const char *)buf);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
close(fd);
|
close(fd);
|
||||||
// Is an existing file.
|
// Is an existing file.
|
||||||
unlink((const char *)buf);
|
// Defer deletion to after "is invalid" check.
|
||||||
|
to_overwrite_dest = strdup((const char *)buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!skip) {
|
if (!skip) {
|
||||||
|
@ -2878,12 +2920,14 @@ int simple_archiver_parse_archive_version_0(FILE *in_f, int_fast8_t do_extract,
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
if (errno == ELOOP) {
|
if (errno == ELOOP) {
|
||||||
// Is an existing symbolic file.
|
// Is an existing symbolic file.
|
||||||
unlink((const char *)uc_heap_buf);
|
// Defer deletion to after "is invalid" check.
|
||||||
|
to_overwrite_dest = strdup((const char *)uc_heap_buf);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
close(fd);
|
close(fd);
|
||||||
// Is an existing file.
|
// Is an existing file.
|
||||||
unlink((const char *)uc_heap_buf);
|
// Defer deletion to after "is invalid" check.
|
||||||
|
to_overwrite_dest = strdup((const char *)uc_heap_buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!skip) {
|
if (!skip) {
|
||||||
|
@ -2898,6 +2942,17 @@ int simple_archiver_parse_archive_version_0(FILE *in_f, int_fast8_t do_extract,
|
||||||
return SDAS_INVALID_FILE;
|
return SDAS_INVALID_FILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for "invalid entry" flag.
|
||||||
|
if ((buf[1] & 0x8) != 0) {
|
||||||
|
free(to_overwrite_dest);
|
||||||
|
to_overwrite_dest = NULL;
|
||||||
|
fprintf(stderr, " This file entry was marked invalid, skipping...\n");
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// Do deferred overwrite action: remove existing file/symlink.
|
||||||
|
cleanup_overwrite_filename_delete_simple(&to_overwrite_dest);
|
||||||
|
}
|
||||||
|
|
||||||
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
||||||
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
||||||
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
||||||
|
|
|
@ -168,6 +168,9 @@ void simple_archiver_print_usage(void) {
|
||||||
fprintf(stderr, "--overwrite-extract : allows overwriting when extracting\n");
|
fprintf(stderr, "--overwrite-extract : allows overwriting when extracting\n");
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"--no-abs-symlink : do not store absolute paths for symlinks\n");
|
"--no-abs-symlink : do not store absolute paths for symlinks\n");
|
||||||
|
fprintf(stderr,
|
||||||
|
"--no-safe-links : keep symlinks that link to outside archive "
|
||||||
|
"contents\n");
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"--temp-files-dir <dir> : where to store temporary files created "
|
"--temp-files-dir <dir> : where to store temporary files created "
|
||||||
"when compressing (defaults to current working directory)\n");
|
"when compressing (defaults to current working directory)\n");
|
||||||
|
@ -303,6 +306,11 @@ int simple_archiver_parse_args(int argc, const char **argv,
|
||||||
out->flags |= 0x8;
|
out->flags |= 0x8;
|
||||||
} else if (strcmp(argv[0], "--no-abs-symlink") == 0) {
|
} else if (strcmp(argv[0], "--no-abs-symlink") == 0) {
|
||||||
out->flags |= 0x20;
|
out->flags |= 0x20;
|
||||||
|
} else if (strcmp(argv[0], "--no-safe-links") == 0) {
|
||||||
|
out->flags |= 0x80;
|
||||||
|
fprintf(stderr,
|
||||||
|
"NOTICE: Disabling safe-links, symlinks that point to outside "
|
||||||
|
"archived files will be preserved!\n");
|
||||||
} else if (strcmp(argv[0], "--temp-files-dir") == 0) {
|
} else if (strcmp(argv[0], "--temp-files-dir") == 0) {
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
fprintf(stderr, "ERROR: --temp-files-dir is missing an argument!\n");
|
fprintf(stderr, "ERROR: --temp-files-dir is missing an argument!\n");
|
||||||
|
|
|
@ -36,6 +36,7 @@ typedef struct SDArchiverParsed {
|
||||||
/// 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.
|
/// 0b xx1x xxxx - Do not save absolute paths for symlinks.
|
||||||
/// 0b x1xx xxxx - Sort files by size before archiving.
|
/// 0b x1xx xxxx - Sort files by size before archiving.
|
||||||
|
/// 0b 1xxx xxxx - No safe links.
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
/// Null-terminated string.
|
/// Null-terminated string.
|
||||||
char *filename;
|
char *filename;
|
||||||
|
|
Loading…
Reference in a new issue