Split "rel-path-from-abs-paths" into function

This commit is contained in:
Stephen Seo 2024-10-02 13:15:30 +09:00
parent 6376be2840
commit b09948d245
4 changed files with 73 additions and 40 deletions

View file

@ -83,6 +83,7 @@ add_executable(test_simplearchiver
src/test.c
src/parser.c
src/helpers.c
src/archiver.c
src/algorithms/linear_congruential_gen.c
src/data_structures/linked_list.c
src/data_structures/hash_map.c

View file

@ -767,46 +767,8 @@ int write_files_fn(void *data, void *ud) {
// 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.
size_t idx;
size_t 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_fast8_t 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);
rel_path =
simple_archiver_filenames_to_relative_path(link_abs_path, abs_path);
}
}
@ -3015,3 +2977,53 @@ int simple_archiver_de_compress(int pipe_fd_in[2], int pipe_fd_out[2],
return 1;
#endif
}
char *simple_archiver_filenames_to_relative_path(const char *from_abs,
const char *to_abs) {
if (!from_abs || !to_abs) {
return NULL;
}
// Get first non-common char and last slash before it.
uint_fast32_t idx;
uint_fast32_t last_slash;
for (idx = 0, last_slash = 0; idx < strlen(from_abs) && idx < strlen(to_abs);
++idx) {
if (((const char *)to_abs)[idx] != ((const char *)from_abs)[idx]) {
break;
} else if (((const char *)to_abs)[idx] == '/') {
last_slash = idx + 1;
}
}
// Get substrings of both paths.
char *link_substr = (char *)from_abs + last_slash;
char *dest_substr = (char *)to_abs + last_slash;
char *rel_path = malloc(strlen(dest_substr) + 1);
strncpy(rel_path, dest_substr, strlen(dest_substr) + 1);
// fprintf(stderr, "DEBUG: link_substr \"%s\", dest_substr \"%s\"\n",
// link_substr, dest_substr);
// Get the relative path finally.
int_fast8_t 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);
return rel_path;
}

View file

@ -88,4 +88,8 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
int simple_archiver_de_compress(int pipe_fd_in[2], int pipe_fd_out[2],
const char *cmd, void *pid_out);
/// If returns non-NULL, must be free'd.
char *simple_archiver_filenames_to_relative_path(const char *from_abs,
const char *to_abs);
#endif

View file

@ -23,6 +23,7 @@
#include <string.h>
// Local includes.
#include "archiver.h"
#include "helpers.h"
#include "parser_internal.h"
@ -241,6 +242,21 @@ int main(void) {
free(out);
}
// Test archiver.
{
__attribute__((
cleanup(simple_archiver_helper_cleanup_c_string))) char *rel_path =
simple_archiver_filenames_to_relative_path(
"/one/two/three/four/five", "/one/two/branch/other/path");
CHECK_STREQ(rel_path, "../../branch/other/path");
simple_archiver_helper_cleanup_c_string(&rel_path);
rel_path = simple_archiver_filenames_to_relative_path(
"/one/two/three/four/five", "/one/two/three/other/dir/");
CHECK_STREQ(rel_path, "../other/dir/");
simple_archiver_helper_cleanup_c_string(&rel_path);
}
printf("Checks checked: %u\n", checks_checked);
printf("Checks passed: %u\n", checks_passed);
return checks_passed == checks_checked ? 0 : 1;