Compare commits

..

No commits in common. "d8068a6f5f8999dd274e25603a15df2f987af3b3" and "d939939723fbc653f593d707d68448c9f162b300" have entirely different histories.

5 changed files with 91 additions and 261 deletions

View file

@ -55,8 +55,6 @@ Following the file-count bytes, the following bytes are added for each file:
2. The second byte.
1. The first bit is "other write 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.
1. Currently unused.
4. The fourth byte.

View file

@ -37,6 +37,7 @@
#include <unistd.h>
#endif
#include "data_structures/hash_map.h"
#include "helpers.h"
#define TEMP_FILENAME_CMP "simple_archiver_compressed_%u.tmp"
@ -103,43 +104,6 @@ void cleanup_temp_filename_delete(void ***ptrs_array) {
#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) {
const SDArchiverFileInfo *file_info = data;
SDArchiverState *state = ud;
@ -704,90 +668,89 @@ int write_files_fn(void *data, void *ud) {
// Unsupported platform. Just set the permission bits for user.
((unsigned char *)temp_to_write->buf)[0] |= 0xE;
#endif
simple_archiver_list_add(to_write, temp_to_write, free_internal_to_write);
// 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);
// 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) {
}
// Get relative path.
__attribute__((cleanup(free_malloced_memory))) void *rel_path = NULL;
// First get absolute path of link.
// Get abs path to dirname of link.
unsigned int link_dir_path_len = strlen(file_info->filename) + 1;
__attribute__((cleanup(free_malloced_memory))) void *link_dir_path =
malloc(link_dir_path_len);
strncpy(link_dir_path, file_info->filename, link_dir_path_len);
char *link_dirname = dirname(link_dir_path);
__attribute__((cleanup(free_malloced_memory))) void *link_dir_abs_path =
realpath(link_dirname, NULL);
if (!link_dir_abs_path) {
fprintf(stderr,
"WARNING: Failed to get absolute path of link directory!\n");
} else {
// Get basename of link to append.
__attribute__((cleanup(free_malloced_memory))) void *link_filename =
malloc(strlen(file_info->filename) + 1);
strncpy(link_filename, file_info->filename,
strlen(file_info->filename) + 1);
char *link_basename = basename(link_filename);
// Set up full path to link.
unsigned int link_path_len = strlen(link_dir_abs_path);
__attribute__((cleanup(free_malloced_memory))) void *combined_path =
malloc(link_path_len + 1 + strlen(link_basename) + 1);
strncpy(combined_path, link_dir_abs_path, link_path_len + 1);
((char *)combined_path)[link_path_len] = '/';
strncpy((char *)combined_path + link_path_len + 1, link_basename,
strlen(link_basename) + 1);
// fprintf(stderr, "DEBUG: abs_path: %s\nDEBUG: combined_path: %s\n",
// (char*)abs_path, (char*)combined_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(combined_path); ++idx) {
if (((const char *)abs_path)[idx] !=
((const char *)combined_path)[idx]) {
break;
} else if (((const char *)abs_path)[idx] == '/') {
last_slash = idx + 1;
}
}
// Get substrings of both paths.
char *link_substr = (char *)combined_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);
}
if (abs_path) {
// Write absolute path length.
u16 = strlen(abs_path);
simple_archiver_helper_16_bit_be(&u16);
@ -806,9 +769,6 @@ int write_files_fn(void *data, void *ud) {
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;
@ -843,9 +803,7 @@ 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);
}
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_free(&to_write);
@ -858,54 +816,6 @@ int write_files_fn(void *data, void *ud) {
void cleanup_nop_fn(__attribute__((unused)) void *unused) {}
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) {
switch (error) {
case SDAS_SUCCESS:
@ -924,10 +834,6 @@ char *simple_archiver_error_to_string(enum SDArchiverStateReturns error) {
return "Invalid file";
case SDAS_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:
return "Unknown error";
}
@ -942,7 +848,6 @@ SDArchiverState *simple_archiver_init_state(const SDArchiverParsed *parsed) {
state->flags = 0;
state->parsed = parsed;
state->out_f = NULL;
state->map = NULL;
return state;
}
@ -956,14 +861,6 @@ void simple_archiver_free_state(SDArchiverState **state) {
int simple_archiver_write_all(FILE *out_f, SDArchiverState *state,
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) {
return SDAS_FAILED_TO_WRITE;
}
@ -1047,7 +944,6 @@ int simple_archiver_write_all(FILE *out_f, SDArchiverState *state,
state->count = 0;
state->max = filenames->count;
state->out_f = out_f;
state->map = abs_filenames;
fprintf(stderr, "Begin archiving...\n");
fprintf(stderr, "[%10u/%10u]\n", state->count, state->max);
if (simple_archiver_list_get(filenames, write_files_fn, state)) {
@ -1615,14 +1511,6 @@ int simple_archiver_parse_archive_info(FILE *in_f, int do_extract,
}
} else {
// 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) {
return SDAS_INVALID_FILE;
}
@ -1635,15 +1523,15 @@ int simple_archiver_parse_archive_info(FILE *in_f, int do_extract,
}
buf[1023] = 0;
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 {
abs_path = malloc(u16 + 1);
if (fread(abs_path, 1, u16 + 1, in_f) != (size_t)u16 + 1) {
__attribute__((cleanup(free_malloced_memory))) void *heap_buf =
malloc(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;
}
((char *)abs_path)[u16 - 1] = 0;
fprintf(stderr, " Link absolute path: %s\n", (char *)abs_path);
uc_heap_buf[u16 - 1] = 0;
fprintf(stderr, " Link absolute path: %s\n", uc_heap_buf);
}
if (fread(&u16, 2, 1, in_f) != 1) {
@ -1658,62 +1546,15 @@ int simple_archiver_parse_archive_info(FILE *in_f, int do_extract,
}
buf[1023] = 0;
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 {
rel_path = malloc(u16 + 1);
if (fread(rel_path, 1, u16 + 1, in_f) != (size_t)u16 + 1) {
__attribute__((cleanup(free_malloced_memory))) void *heap_buf =
malloc(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;
}
((char *)rel_path)[u16 - 1] = 0;
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");
}
uc_heap_buf[u16 - 1] = 0;
fprintf(stderr, " Link relative path: %s\n", uc_heap_buf);
}
}
}

View file

@ -21,7 +21,6 @@
#include <stdio.h>
#include "data_structures/hash_map.h"
#include "data_structures/linked_list.h"
#include "parser.h"
@ -31,7 +30,6 @@ typedef struct SDArchiverState {
unsigned int flags;
const SDArchiverParsed *parsed;
FILE *out_f;
SDArchiverHashMap *map;
unsigned int count;
unsigned int max;
} SDArchiverState;
@ -44,9 +42,7 @@ enum SDArchiverStateReturns {
SDAS_NO_DECOMPRESSOR,
SDAS_INVALID_PARSED_STATE,
SDAS_INVALID_FILE,
SDAS_INTERNAL_ERROR,
SDAS_FAILED_TO_CREATE_MAP,
SDAS_FAILED_TO_EXTRACT_SYMLINK
SDAS_INTERNAL_ERROR
};
/// Returned pointer must not be freed.

View file

@ -151,8 +151,6 @@ void simple_archiver_print_usage(void) {
"file's stored decompressor\n");
fprintf(stderr, "--overwrite-create : allows overwriting an archive file\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,
"-- : specifies remaining arguments are files to archive/extract\n");
fprintf(
@ -245,8 +243,6 @@ int simple_archiver_parse_args(int argc, const char **argv,
out->flags |= 0x4;
} else if (strcmp(argv[0], "--overwrite-extract") == 0) {
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) {
is_remaining_args = 1;
} else if (argv[0][0] != '-') {

View file

@ -30,7 +30,6 @@ typedef struct SDArchiverParsed {
/// 0b xxxx x1xx - Allow create archive overwrite.
/// 0b xxxx 1xxx - Allow extract overwrite.
/// 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;
/// Null-terminated string.
char *filename;