}
}
-int internal_write_dir_entries(void *data, void *ud) {
+int internal_write_dir_entries_v2_v3(void *data, void *ud) {
const char *dir = data;
void **ptrs = ud;
FILE *out_f = ptrs[0];
fprintf(stderr, " %s\n", dir);
- unsigned long dir_name_length = strlen(dir);
- if (dir_name_length > 0xFFFF) {
+ const size_t prefix_length = state->parsed->prefix
+ ? strlen(state->parsed->prefix)
+ : 0;
+
+ const size_t dir_name_length = strlen(dir);
+ size_t total_name_length = dir_name_length + prefix_length;
+ if (total_name_length >= 0xFFFF) {
fprintf(stderr, "ERROR: Dirname \"%s\" is too long!\n", dir);
return 1;
}
- uint16_t u16 = (uint16_t)dir_name_length;
+ uint16_t u16 = (uint16_t)total_name_length;
simple_archiver_helper_16_bit_be(&u16);
if (fwrite(&u16, 2, 1, out_f) != 1) {
return 1;
}
- if (fwrite(dir, 1, dir_name_length + 1, out_f) != dir_name_length + 1) {
+ if (state->parsed->prefix) {
+ if (fwrite(state->parsed->prefix, 1, prefix_length, out_f)
+ != prefix_length) {
+ fprintf(stderr,
+ "ERROR: Failed to write prefix part of dirname \"%s\"!\n",
+ dir);
+ return 1;
+ } else if (fwrite(dir, 1, dir_name_length + 1, out_f)
+ != dir_name_length + 1) {
+ fprintf(stderr,
+ "ERROR: Failed to write (after prefix) dirname for \"%s\"!\n",
+ dir);
+ return 1;
+ }
+ } else if (fwrite(dir, 1, dir_name_length + 1, out_f)
+ != dir_name_length + 1) {
fprintf(stderr, "ERROR: Failed to write dirname for \"%s\"!\n", dir);
return 1;
}
return SDAS_FAILED_TO_WRITE;
}
+ const size_t prefix_length = state->parsed->prefix
+ ? strlen(state->parsed->prefix)
+ : 0;
+
char buf[SIMPLE_ARCHIVER_BUFFER_SIZE];
uint16_t u16 = 2;
return SDAS_FAILED_TO_WRITE;
}
- size_t len = strlen(node->data);
+ const size_t link_length = strlen(node->data);
+ size_t len = link_length;
+ if (state->parsed->prefix) {
+ len += prefix_length;
+ }
if (len >= 0xFFFF) {
fprintf(stderr, "ERROR: Link name is too long!\n");
return SDAS_INVALID_PARSED_STATE;
return SDAS_FAILED_TO_WRITE;
}
simple_archiver_helper_16_bit_be(&u16);
- if (fwrite(node->data, 1, u16 + 1, out_f) != (size_t)u16 + 1) {
+ if (state->parsed->prefix) {
+ size_t fwrite_ret = fwrite(state->parsed->prefix,
+ 1,
+ prefix_length,
+ out_f);
+ fwrite_ret += fwrite(node->data, 1, link_length + 1, out_f);
+ if (fwrite_ret != (size_t)u16 + 1) {
+ return SDAS_FAILED_TO_WRITE;
+ }
+ } else if (fwrite(node->data, 1, u16 + 1, out_f) != (size_t)u16 + 1) {
return SDAS_FAILED_TO_WRITE;
}
if (abs_path && (state->parsed->flags & 0x20) == 0 && !is_invalid) {
- len = strlen(abs_path);
- if (len >= 0xFFFF) {
- fprintf(stderr,
- "ERROR: Symlink destination absolute path is too long!\n");
- return SDAS_INVALID_PARSED_STATE;
- }
+ if (state->parsed->prefix) {
+ __attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
+ char *abs_path_prefixed =
+ simple_archiver_helper_insert_prefix_in_link_path(
+ state->parsed->prefix, node->data, abs_path);
+ if (!abs_path_prefixed) {
+ fprintf(stderr,
+ "ERROR: Failed to add prefix to abs symlink!\n");
+ return SDAS_INTERNAL_ERROR;
+ }
+ const size_t abs_path_pref_length = strlen(abs_path_prefixed);
+ if (abs_path_pref_length >= 0xFFFF) {
+ fprintf(stderr,
+ "ERROR: Symlink destination absolute path with prefix is "
+ "too long!\n");
+ return SDAS_INVALID_PARSED_STATE;
+ }
- u16 = (uint16_t)len;
- simple_archiver_helper_16_bit_be(&u16);
- if (fwrite(&u16, 2, 1, out_f) != 1) {
- return SDAS_FAILED_TO_WRITE;
- }
- simple_archiver_helper_16_bit_be(&u16);
- if (fwrite(abs_path, 1, u16 + 1, out_f) != (size_t)u16 + 1) {
- return SDAS_FAILED_TO_WRITE;
+ u16 = (uint16_t)abs_path_pref_length;
+ simple_archiver_helper_16_bit_be(&u16);
+ if (fwrite(&u16, 2, 1, out_f) != 1) {
+ return SDAS_FAILED_TO_WRITE;
+ }
+ simple_archiver_helper_16_bit_be(&u16);
+ if (fwrite(abs_path_prefixed, 1, u16 + 1, out_f) != (size_t)u16 + 1) {
+ return SDAS_FAILED_TO_WRITE;
+ }
+ } else {
+ const size_t abs_path_length = strlen(abs_path);
+ if (abs_path_length >= 0xFFFF) {
+ fprintf(stderr,
+ "ERROR: Symlink destination absolute path is too long!\n");
+ return SDAS_INVALID_PARSED_STATE;
+ }
+
+ u16 = (uint16_t)abs_path_length;
+ simple_archiver_helper_16_bit_be(&u16);
+ if (fwrite(&u16, 2, 1, out_f) != 1) {
+ return SDAS_FAILED_TO_WRITE;
+ }
+ simple_archiver_helper_16_bit_be(&u16);
+ if (fwrite(abs_path, 1, u16 + 1, out_f) != (size_t)u16 + 1) {
+ return SDAS_FAILED_TO_WRITE;
+ }
}
} else {
u16 = 0;
}
if (rel_path && !is_invalid) {
- len = strlen(rel_path);
- if (len >= 0xFFFF) {
- fprintf(stderr,
- "ERROR: Symlink destination relative path is too long!\n");
- return SDAS_INVALID_PARSED_STATE;
- }
+ if (state->parsed->prefix) {
+ __attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
+ char *rel_path_prefixed =
+ simple_archiver_helper_insert_prefix_in_link_path(
+ state->parsed->prefix, node->data, rel_path);
+ if (!rel_path_prefixed) {
+ fprintf(stderr,
+ "ERROR: Failed to add prefix to relative symlink!\n");
+ return SDAS_INTERNAL_ERROR;
+ }
+ const size_t rel_path_pref_length = strlen(rel_path_prefixed);
+ if (rel_path_pref_length >= 0xFFFF) {
+ fprintf(stderr,
+ "ERROR: Symlink destination relative path with prefix is "
+ "too long!\n");
+ return SDAS_INVALID_PARSED_STATE;
+ }
- u16 = (uint16_t)len;
- simple_archiver_helper_16_bit_be(&u16);
- if (fwrite(&u16, 2, 1, out_f) != 1) {
- return SDAS_FAILED_TO_WRITE;
- }
- simple_archiver_helper_16_bit_be(&u16);
- if (fwrite(rel_path, 1, u16 + 1, out_f) != (size_t)u16 + 1) {
- return SDAS_FAILED_TO_WRITE;
+ u16 = (uint16_t)rel_path_pref_length;
+ simple_archiver_helper_16_bit_be(&u16);
+ if (fwrite(&u16, 2, 1, out_f) != 1) {
+ return SDAS_FAILED_TO_WRITE;
+ }
+ simple_archiver_helper_16_bit_be(&u16);
+ if (fwrite(rel_path_prefixed, 1, u16 + 1, out_f) != (size_t)u16 + 1) {
+ return SDAS_FAILED_TO_WRITE;
+ }
+ } else {
+ len = strlen(rel_path);
+ if (len >= 0xFFFF) {
+ fprintf(stderr,
+ "ERROR: Symlink destination relative path is too long!\n");
+ return SDAS_INVALID_PARSED_STATE;
+ }
+
+ u16 = (uint16_t)len;
+ simple_archiver_helper_16_bit_be(&u16);
+ if (fwrite(&u16, 2, 1, out_f) != 1) {
+ return SDAS_FAILED_TO_WRITE;
+ }
+ simple_archiver_helper_16_bit_be(&u16);
+ if (fwrite(rel_path, 1, u16 + 1, out_f) != (size_t)u16 + 1) {
+ return SDAS_FAILED_TO_WRITE;
+ }
}
} else {
u16 = 0;
if (non_c_chunk_size) {
*non_c_chunk_size += file_info_struct->file_size;
}
- size_t len = strlen(file_info_struct->filename);
- if (len >= 0xFFFF) {
- fprintf(stderr, "ERROR: Filename is too large!\n");
- return SDAS_INVALID_FILE;
- }
- u16 = (uint16_t)len;
- simple_archiver_helper_16_bit_be(&u16);
- if (fwrite(&u16, 2, 1, out_f) != 1) {
- return SDAS_FAILED_TO_WRITE;
+ const size_t filename_len = strlen(file_info_struct->filename);
+ if (state->parsed->prefix) {
+ const size_t total_length = filename_len + prefix_length;
+ if (total_length >= 0xFFFF) {
+ fprintf(stderr, "ERROR: Filename with prefix is too large!\n");
+ return SDAS_INVALID_FILE;
+ }
+ u16 = (uint16_t)total_length;
+ simple_archiver_helper_16_bit_be(&u16);
+ if (fwrite(&u16, 2, 1, out_f) != 1) {
+ return SDAS_FAILED_TO_WRITE;
+ }
+ simple_archiver_helper_16_bit_be(&u16);
+ if (fwrite(state->parsed->prefix, 1, prefix_length, out_f)
+ != prefix_length) {
+ return SDAS_FAILED_TO_WRITE;
+ } else if (fwrite(file_info_struct->filename,
+ 1,
+ filename_len + 1,
+ out_f)
+ != filename_len + 1) {
+ return SDAS_FAILED_TO_WRITE;
+ }
+ } else {
+ if (filename_len >= 0xFFFF) {
+ fprintf(stderr, "ERROR: Filename is too large!\n");
+ return SDAS_INVALID_FILE;
+ }
+ u16 = (uint16_t)filename_len;
+ simple_archiver_helper_16_bit_be(&u16);
+ if (fwrite(&u16, 2, 1, out_f) != 1) {
+ return SDAS_FAILED_TO_WRITE;
+ }
+ simple_archiver_helper_16_bit_be(&u16);
+ if (fwrite(file_info_struct->filename, 1, u16 + 1, out_f) !=
+ (size_t)u16 + 1) {
+ return SDAS_FAILED_TO_WRITE;
+ }
}
- simple_archiver_helper_16_bit_be(&u16);
- if (fwrite(file_info_struct->filename, 1, u16 + 1, out_f) !=
- (size_t)u16 + 1) {
- return SDAS_FAILED_TO_WRITE;
- } else if (fwrite(file_info_struct->bit_flags, 1, 4, out_f) != 4) {
+
+ if (fwrite(file_info_struct->bit_flags, 1, 4, out_f) != 4) {
return SDAS_FAILED_TO_WRITE;
}
// UID and GID.
void_ptrs[1] = state;
if (simple_archiver_list_get(dirs_list,
- internal_write_dir_entries,
+ internal_write_dir_entries_v2_v3,
void_ptrs)) {
free(void_ptrs);
return SDAS_INTERNAL_ERROR;
void_ptrs[1] = state;
if (simple_archiver_list_get(dirs_list,
- internal_write_dir_entries,
+ internal_write_dir_entries_v2_v3,
void_ptrs)) {
free(void_ptrs);
return SDAS_INTERNAL_ERROR;