Skip to content

Commit

Permalink
Add libmpq__archive_dup
Browse files Browse the repository at this point in the history
This allows the user to duplicate an existing archive information,
e.g. for reading from multiple threads.
  • Loading branch information
glebm committed Nov 3, 2021
1 parent 130c082 commit f1a3d48
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
60 changes: 60 additions & 0 deletions libmpq/mpq.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,66 @@ int32_t libmpq__archive_open(mpq_archive_s **mpq_archive, const char *mpq_filena
return result;
}

/* duplicates an mpq archive. */
int32_t libmpq__archive_dup(mpq_archive_s *orig_archive, const char *mpq_filename, mpq_archive_s **mpq_archive) {
int32_t result = 0;

if ((*mpq_archive = calloc(1, sizeof(mpq_archive_s))) == NULL) {

/* archive struct could not be allocated */
return LIBMPQ_ERROR_MALLOC;
}

/* check if file exists and is readable */
if (((*mpq_archive)->fp = fopen_utf8(mpq_filename)) == NULL) {

/* file could not be opened. */
result = errno == ENOENT ? LIBMPQ_ERROR_EXIST : LIBMPQ_ERROR_OPEN;
goto error;
}

(*mpq_archive)->block_size = orig_archive->block_size;
(*mpq_archive)->archive_offset = orig_archive->archive_offset;
(*mpq_archive)->mpq_header = orig_archive->mpq_header;
(*mpq_archive)->mpq_header_ex = orig_archive->mpq_header_ex;
(*mpq_archive)->files = orig_archive->files;

const mpq_header_s *header = &(*mpq_archive)->mpq_header;

/* allocate memory for the block table, hash table, file and block table to file mapping. */
if (((*mpq_archive)->mpq_block = malloc(header->block_table_count * sizeof(mpq_block_s))) == NULL ||
((*mpq_archive)->mpq_block_ex = malloc(header->block_table_count * sizeof(mpq_block_ex_s))) == NULL ||
((*mpq_archive)->mpq_hash = malloc(header->hash_table_count * sizeof(mpq_hash_s))) == NULL ||
((*mpq_archive)->mpq_file = calloc(header->block_table_count, sizeof(mpq_file_s))) == NULL ||
((*mpq_archive)->mpq_map = malloc(header->block_table_count * sizeof(mpq_map_s))) == NULL) {

/* memory allocation problem. */
result = LIBMPQ_ERROR_MALLOC;
goto error;
}

memcpy((*mpq_archive)->mpq_block, orig_archive->mpq_block, header->block_table_count * sizeof(mpq_block_s));
memcpy((*mpq_archive)->mpq_block_ex, orig_archive->mpq_block_ex, header->block_table_count * sizeof(mpq_block_ex_s));
memcpy((*mpq_archive)->mpq_hash, orig_archive->mpq_hash, header->block_table_count * sizeof(mpq_hash_s));
memcpy((*mpq_archive)->mpq_map, orig_archive->mpq_map, header->block_table_count * sizeof(mpq_map_s));

return LIBMPQ_SUCCESS;
error:
if ((*mpq_archive)->fp)
fclose((*mpq_archive)->fp);

free((*mpq_archive)->mpq_map);
free((*mpq_archive)->mpq_file);
free((*mpq_archive)->mpq_hash);
free((*mpq_archive)->mpq_block);
free((*mpq_archive)->mpq_block_ex);
free(*mpq_archive);

*mpq_archive = NULL;

return result;
}

/* this function close the file descriptor, free the decryption buffer and the file list. */
int32_t libmpq__archive_close(mpq_archive_s *mpq_archive) {

Expand Down
1 change: 1 addition & 0 deletions libmpq/mpq.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ extern LIBMPQ_API const char *libmpq__strerror(int32_t return_code);
/* generic mpq archive information. */
extern LIBMPQ_API int32_t libmpq__archive_open(mpq_archive_s **mpq_archive, const char *mpq_filename, libmpq__off_t archive_offset);
extern LIBMPQ_API int32_t libmpq__archive_close(mpq_archive_s *mpq_archive);
extern LIBMPQ_API int32_t libmpq__archive_dup(mpq_archive_s *orig_archive, const char *mpq_filename, mpq_archive_s **mpq_archive);
extern LIBMPQ_API int32_t libmpq__archive_size_packed(mpq_archive_s *mpq_archive, libmpq__off_t *packed_size);
extern LIBMPQ_API int32_t libmpq__archive_size_unpacked(mpq_archive_s *mpq_archive, libmpq__off_t *unpacked_size);
extern LIBMPQ_API int32_t libmpq__archive_offset(mpq_archive_s *mpq_archive, libmpq__off_t *offset);
Expand Down

0 comments on commit f1a3d48

Please sign in to comment.