From: Stephen Seo Date: Mon, 27 Jan 2025 10:20:58 +0000 (+0900) Subject: Impl --prefix extract for file fmt version 3 X-Git-Tag: 1.12^2~10 X-Git-Url: https://git.seodisparate.com/stephenseo/annotated.html?a=commitdiff_plain;h=34500fa445c84bd43749ba94ee69e2d661fc88be;p=SimpleArchiver Impl --prefix extract for file fmt version 3 TODO: Testing, cleanup, regression fixes. --- diff --git a/src/archiver.c b/src/archiver.c index 9e729bd..ff5da86 100644 --- a/src/archiver.c +++ b/src/archiver.c @@ -8246,6 +8246,10 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, return SDAS_SIGINT; } + const size_t prefix_length = state && state->parsed->prefix + ? strlen(state->parsed->prefix) + : 0; + // Link count. if (fread(buf, 1, 4, in_f) != 4) { return SDAS_INVALID_FILE; @@ -8279,21 +8283,25 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, uint_fast8_t skip_due_to_map = 0; uint_fast8_t skip_due_to_invalid = is_invalid ? 1 : 0; - if (fread(buf, 1, 2, in_f) != 2) { + if (fread(&u16, 2, 1, in_f) != 1) { return SDAS_INVALID_FILE; } - memcpy(&u16, buf, 2); simple_archiver_helper_16_bit_be(&u16); - __attribute__(( - cleanup(simple_archiver_helper_cleanup_c_string))) char *link_name = - malloc(u16 + 1); + const size_t link_name_length = u16; + + __attribute__((cleanup(simple_archiver_helper_cleanup_c_string))) + char *link_name = malloc(link_name_length + 1); - int ret = read_buf_full_from_fd( - in_f, (char *)buf, SIMPLE_ARCHIVER_BUFFER_SIZE, u16 + 1, link_name); + int ret = read_buf_full_from_fd(in_f, + (char *)buf, + SIMPLE_ARCHIVER_BUFFER_SIZE, + link_name_length + 1, + link_name); if (ret != SDAS_SUCCESS) { return ret; } + link_name[link_name_length] = 0; if (!do_extract) { fprintf(stderr, " Link name: %s\n", link_name); @@ -8311,6 +8319,15 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, #endif } + __attribute__((cleanup(simple_archiver_helper_cleanup_c_string))) + char *link_name_prefixed = NULL; + if (state && state->parsed->prefix) { + link_name_prefixed = malloc(prefix_length + link_name_length + 1); + memcpy(link_name_prefixed, state->parsed->prefix, prefix_length); + memcpy(link_name_prefixed + prefix_length, link_name, link_name_length + 1); + link_name_prefixed[prefix_length + link_name_length] = 0; + } + if (simple_archiver_validate_file_path(link_name)) { fprintf(stderr, " WARNING: Invalid link name \"%s\"!\n", link_name); skip_due_to_invalid = 1; @@ -8323,28 +8340,42 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, fprintf(stderr, " Skipping not specified in args...\n"); } - if (fread(buf, 1, 2, in_f) != 2) { + if (fread(&u16, 2, 1, in_f) != 1) { return SDAS_INVALID_FILE; } - memcpy(&u16, buf, 2); simple_archiver_helper_16_bit_be(&u16); + __attribute__((cleanup(simple_archiver_helper_cleanup_c_string))) + char *abs_path_prefixed = NULL; + __attribute__((cleanup(simple_archiver_helper_cleanup_c_string))) char *parsed_abs_path = NULL; if (u16 != 0) { - parsed_abs_path = malloc(u16 + 1); + const size_t path_length = u16; + parsed_abs_path = malloc(path_length + 1); ret = read_buf_full_from_fd(in_f, (char *)buf, SIMPLE_ARCHIVER_BUFFER_SIZE, - u16 + 1, + path_length + 1, parsed_abs_path); if (ret != SDAS_SUCCESS) { return ret; } - parsed_abs_path[u16] = 0; + parsed_abs_path[path_length] = 0; if (!do_extract) { fprintf(stderr, " Abs path: %s\n", parsed_abs_path); } + + if (state && state->parsed->prefix) { + abs_path_prefixed = + simple_archiver_helper_insert_prefix_in_link_path( + state->parsed->prefix, link_name, parsed_abs_path); + if (!abs_path_prefixed) { + fprintf(stderr, + "ERROR: Failed to insert prefix to absolute path!\n"); + return SDAS_INTERNAL_ERROR; + } + } } else if (!do_extract) { fprintf(stderr, " No Absolute path.\n"); } @@ -8354,22 +8385,38 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, } memcpy(&u16, buf, 2); simple_archiver_helper_16_bit_be(&u16); + + __attribute__((cleanup(simple_archiver_helper_cleanup_c_string))) + char *rel_path_prefixed = NULL; + __attribute__((cleanup(simple_archiver_helper_cleanup_c_string))) char *parsed_rel_path = NULL; if (u16 != 0) { - parsed_rel_path = malloc(u16 + 1); + const size_t path_length = u16; + parsed_rel_path = malloc(path_length + 1); ret = read_buf_full_from_fd(in_f, (char *)buf, SIMPLE_ARCHIVER_BUFFER_SIZE, - u16 + 1, + path_length + 1, parsed_rel_path); if (ret != SDAS_SUCCESS) { return ret; } - parsed_rel_path[u16] = 0; + parsed_rel_path[path_length] = 0; if (!do_extract) { fprintf(stderr, " Rel path: %s\n", parsed_rel_path); } + + if (state && state->parsed->prefix) { + rel_path_prefixed = + simple_archiver_helper_insert_prefix_in_link_path( + state->parsed->prefix, link_name, parsed_rel_path); + if (!rel_path_prefixed) { + fprintf(stderr, + "ERROR: Failed to insert prefix to relative path!\n"); + return SDAS_INTERNAL_ERROR; + } + } } else if (!do_extract) { fprintf(stderr, " No Relative path.\n"); } @@ -8543,7 +8590,7 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \ SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX simple_archiver_helper_make_dirs_perms( - link_name, + link_name_prefixed ? link_name_prefixed : link_name, (state->parsed->flags & 0x2000) ? simple_archiver_internal_permissions_to_mode_t( state->parsed->dir_permissions) @@ -8552,7 +8599,9 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, (state->parsed->flags & 0x800) ? state->parsed->gid : current_gid); int_fast8_t link_create_retry = 0; V3_SYMLINK_CREATE_RETRY_0: - ret = symlink(parsed_abs_path, link_name); + ret = symlink( + abs_path_prefixed ? abs_path_prefixed : parsed_abs_path, + link_name_prefixed ? link_name_prefixed : link_name); if (ret == -1) { if (link_create_retry) { fprintf( @@ -8571,14 +8620,17 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, " NOTICE: Symlink already exists and " "\"--overwrite-extract\" specified, attempting to " "overwrite...\n"); - unlink(link_name); + unlink(link_name_prefixed ? link_name_prefixed : link_name); link_create_retry = 1; goto V3_SYMLINK_CREATE_RETRY_0; } } return SDAS_FAILED_TO_EXTRACT_SYMLINK; } - ret = fchmodat(AT_FDCWD, link_name, permissions, AT_SYMLINK_NOFOLLOW); + ret = fchmodat(AT_FDCWD, + link_name_prefixed ? link_name_prefixed : link_name, + permissions, + AT_SYMLINK_NOFOLLOW); if (ret == -1) { if (errno == EOPNOTSUPP) { fprintf(stderr, @@ -8591,7 +8643,10 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, } } link_extracted = 1; - fprintf(stderr, " %s -> %s\n", link_name, parsed_abs_path); + fprintf(stderr, + " %s -> %s\n", + link_name_prefixed ? link_name_prefixed : link_name, + abs_path_prefixed ? abs_path_prefixed : parsed_abs_path); V3_SYMLINK_CREATE_AFTER_0: link_create_retry = 1; #endif @@ -8601,7 +8656,7 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \ SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX simple_archiver_helper_make_dirs_perms( - link_name, + link_name_prefixed ? link_name_prefixed : link_name, (state->parsed->flags & 0x2000) ? simple_archiver_internal_permissions_to_mode_t( state->parsed->dir_permissions) @@ -8610,7 +8665,9 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, (state->parsed->flags & 0x800) ? state->parsed->gid : current_gid); int_fast8_t link_create_retry = 0; V3_SYMLINK_CREATE_RETRY_1: - ret = symlink(parsed_rel_path, link_name); + ret = symlink( + rel_path_prefixed ? rel_path_prefixed : parsed_rel_path, + link_name_prefixed ? link_name_prefixed : link_name); if (ret == -1) { if (link_create_retry) { fprintf( @@ -8629,14 +8686,17 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, " NOTICE: Symlink already exists and " "\"--overwrite-extract\" specified, attempting to " "overwrite...\n"); - unlink(link_name); + unlink(link_name_prefixed ? link_name_prefixed : link_name); link_create_retry = 1; goto V3_SYMLINK_CREATE_RETRY_1; } } return SDAS_FAILED_TO_EXTRACT_SYMLINK; } - ret = fchmodat(AT_FDCWD, link_name, permissions, AT_SYMLINK_NOFOLLOW); + ret = fchmodat(AT_FDCWD, + link_name_prefixed ? link_name_prefixed : link_name, + permissions, + AT_SYMLINK_NOFOLLOW); if (ret == -1) { if (errno == EOPNOTSUPP) { fprintf(stderr, @@ -8650,7 +8710,10 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, } link_extracted = 1; - fprintf(stderr, " %s -> %s\n", link_name, parsed_rel_path); + fprintf(stderr, + " %s -> %s\n", + link_name_prefixed ? link_name_prefixed : link_name, + rel_path_prefixed ? rel_path_prefixed : parsed_rel_path); V3_SYMLINK_CREATE_AFTER_1: link_create_retry = 1; #endif @@ -8727,7 +8790,7 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, } ret = fchownat( AT_FDCWD, - link_name, + link_name_prefixed ? link_name_prefixed : link_name, state->parsed->flags & 0x400 ? state->parsed->uid : picked_uid, state->parsed->flags & 0x800 ? state->parsed->gid : picked_gid, AT_SYMLINK_NOFOLLOW); @@ -9146,10 +9209,23 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, file_count, file_info->filename); + const size_t filename_length = strlen(file_info->filename); + + __attribute__((cleanup(simple_archiver_helper_cleanup_c_string))) + char *filename_prefixed = NULL; + if (state && state->parsed->prefix) { + filename_prefixed = malloc(prefix_length + filename_length + 1); + memcpy(filename_prefixed, state->parsed->prefix, prefix_length); + memcpy(filename_prefixed + prefix_length, + file_info->filename, + filename_length + 1); + filename_prefixed[prefix_length + filename_length] = 0; + } + uint_fast8_t skip_due_to_map = 0; if (working_files_map && simple_archiver_hash_map_get( working_files_map, file_info->filename, - strlen(file_info->filename) + 1) == NULL) { + filename_length + 1) == NULL) { skip_due_to_map = 1; fprintf(stderr, " Skipping not specified in args...\n"); } else if ((file_info->other_flags & 1) != 0) { @@ -9175,7 +9251,9 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, if ((state->parsed->flags & 8) == 0) { // Check if file already exists. __attribute__((cleanup(simple_archiver_helper_cleanup_FILE))) - FILE *temp_fd = fopen(file_info->filename, "r"); + FILE *temp_fd = fopen( + filename_prefixed ? filename_prefixed : file_info->filename, + "r"); if (temp_fd) { fprintf(stderr, " WARNING: File already exists and " @@ -9193,7 +9271,7 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, } simple_archiver_helper_make_dirs_perms( - file_info->filename, + filename_prefixed ? filename_prefixed : file_info->filename, (state->parsed->flags & 0x2000) ? simple_archiver_internal_permissions_to_mode_t( state->parsed->dir_permissions) @@ -9201,24 +9279,37 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, (state->parsed->flags & 0x400) ? state->parsed->uid : file_info->uid, (state->parsed->flags & 0x800) ? state->parsed->gid : file_info->gid); int ret = read_decomp_to_out_file( - file_info->filename, pipe_outof_read, (char *)buf, - SIMPLE_ARCHIVER_BUFFER_SIZE, file_info->file_size, - &pipe_into_write, &chunk_remaining, in_f, hold_buf, &has_hold); + filename_prefixed ? filename_prefixed : file_info->filename, + pipe_outof_read, + (char *)buf, + SIMPLE_ARCHIVER_BUFFER_SIZE, + file_info->file_size, + &pipe_into_write, + &chunk_remaining, + in_f, + hold_buf, + &has_hold); if (ret != SDAS_SUCCESS) { return ret; } #if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \ SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \ SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX - if (chmod(file_info->filename, permissions) == -1) { + if (chmod(filename_prefixed ? filename_prefixed : file_info->filename, + permissions) + == -1) { return SDAS_INTERNAL_ERROR; } else if (geteuid() == 0 && - chown(file_info->filename, + chown(filename_prefixed + ? filename_prefixed + : file_info->filename, file_info->uid, file_info->gid) != 0) { fprintf(stderr, " ERROR Failed to set UID/GID of file \"%s\"!\n", - file_info->filename); + filename_prefixed + ? filename_prefixed + : file_info->filename); return SDAS_INTERNAL_ERROR; } #endif @@ -9294,10 +9385,23 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, return SDAS_INTERNAL_ERROR; } + const size_t filename_length = strlen(file_info->filename); + + __attribute__((cleanup(simple_archiver_helper_cleanup_c_string))) + char *filename_prefixed = NULL; + if (state && state->parsed->prefix) { + filename_prefixed = malloc(prefix_length + filename_length + 1); + memcpy(filename_prefixed, state->parsed->prefix, prefix_length); + memcpy(filename_prefixed + prefix_length, + file_info->filename, + filename_length + 1); + filename_prefixed[prefix_length + filename_length] = 0; + } + uint_fast8_t skip_due_to_map = 0; if (working_files_map && simple_archiver_hash_map_get( working_files_map, file_info->filename, - strlen(file_info->filename) + 1) == NULL) { + filename_length + 1) == NULL) { skip_due_to_map = 1; fprintf(stderr, " Skipping not specified in args...\n"); } else if (file_info->other_flags & 1) { @@ -9325,7 +9429,10 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, if ((state->parsed->flags & 8) == 0) { // Check if file already exists. __attribute__((cleanup(simple_archiver_helper_cleanup_FILE))) - FILE *temp_fd = fopen(file_info->filename, "r"); + FILE *temp_fd = fopen(filename_prefixed + ? filename_prefixed + : file_info->filename, + "r"); if (temp_fd) { fprintf(stderr, " WARNING: File already exists and " @@ -9340,7 +9447,7 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, } } simple_archiver_helper_make_dirs_perms( - file_info->filename, + filename_prefixed ? filename_prefixed : file_info->filename, (state->parsed->flags & 0x2000) ? simple_archiver_internal_permissions_to_mode_t( state->parsed->dir_permissions) @@ -9348,7 +9455,10 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, (state->parsed->flags & 0x400) ? state->parsed->uid : file_info->uid, (state->parsed->flags & 0x800) ? state->parsed->gid : file_info->gid); __attribute__((cleanup(simple_archiver_helper_cleanup_FILE))) - FILE *out_fd = fopen(file_info->filename, "wb"); + FILE *out_fd = fopen(filename_prefixed + ? filename_prefixed + : file_info->filename, + "wb"); int ret = read_fd_to_out_fd(in_f, out_fd, (char *)buf, SIMPLE_ARCHIVER_BUFFER_SIZE, file_info->file_size); @@ -9359,18 +9469,24 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, #if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \ SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \ SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX - if (chmod(file_info->filename, permissions) == -1) { - fprintf(stderr, - "ERROR Failed to set permissions of file \"%s\"!\n", - file_info->filename); + if (chmod(filename_prefixed ? filename_prefixed : file_info->filename, + permissions) + == -1) { + fprintf( + stderr, + "ERROR Failed to set permissions of file \"%s\"!\n", + filename_prefixed ? filename_prefixed : file_info->filename); return SDAS_INTERNAL_ERROR; } else if (geteuid() == 0 && - chown(file_info->filename, + chown(filename_prefixed + ? filename_prefixed + : file_info->filename, file_info->uid, file_info->gid) != 0) { - fprintf(stderr, - " ERROR Failed to set UID/GID of file \"%s\"!\n", - file_info->filename); + fprintf( + stderr, + " ERROR Failed to set UID/GID of file \"%s\"!\n", + filename_prefixed ? filename_prefixed : file_info->filename); return SDAS_INTERNAL_ERROR; } #endif @@ -9663,6 +9779,11 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, int_fast8_t do_extract, "/", simple_archiver_helper_datastructure_cleanup_nop); } + if (state && state->parsed->prefix) { + simple_archiver_list_add(string_parts, + strdup(state->parsed->prefix), + NULL); + } simple_archiver_list_add(string_parts, strdup((char *)buf), NULL); simple_archiver_list_add( string_parts,