Impl. setup for de/compression
All checks were successful
Run Unit Tests / build-and-run-unit-tests (push) Successful in 4s
All checks were successful
Run Unit Tests / build-and-run-unit-tests (push) Successful in 4s
Some setup code in preparation of doing the actual file compression when creating an archive.
This commit is contained in:
parent
0299129ea6
commit
ea845f2552
5 changed files with 159 additions and 0 deletions
|
@ -22,6 +22,14 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
||||
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
||||
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
||||
#include <fcntl.h>
|
||||
#include <spawn.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
typedef struct SDArchiverInternalToWrite {
|
||||
|
@ -465,3 +473,41 @@ int simple_archiver_print_archive_info(FILE *in_f) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int simple_archiver_de_compress(int pipe_fd_in, int pipe_fd_out,
|
||||
const char *cmd) {
|
||||
posix_spawn_file_actions_t file_actions;
|
||||
memset(&file_actions, 0, sizeof(file_actions));
|
||||
if (posix_spawn_file_actions_init(&file_actions) != 0) {
|
||||
close(pipe_fd_in);
|
||||
close(pipe_fd_out);
|
||||
return 1;
|
||||
} else if (posix_spawn_file_actions_adddup2(&file_actions, pipe_fd_in, 0) !=
|
||||
0) {
|
||||
posix_spawn_file_actions_destroy(&file_actions);
|
||||
close(pipe_fd_in);
|
||||
close(pipe_fd_out);
|
||||
return 2;
|
||||
} else if (posix_spawn_file_actions_adddup2(&file_actions, pipe_fd_out, 1) !=
|
||||
0) {
|
||||
posix_spawn_file_actions_destroy(&file_actions);
|
||||
close(pipe_fd_in);
|
||||
close(pipe_fd_out);
|
||||
return 3;
|
||||
}
|
||||
|
||||
__attribute__((cleanup(
|
||||
simple_archiver_helper_cmd_string_argv_free_ptr))) char **cmd_argv =
|
||||
simple_archiver_helper_cmd_string_to_argv(cmd);
|
||||
|
||||
pid_t spawned_pid;
|
||||
if (posix_spawnp(&spawned_pid, cmd_argv[0], &file_actions, NULL, cmd_argv,
|
||||
NULL) != 0) {
|
||||
posix_spawn_file_actions_destroy(&file_actions);
|
||||
return 4;
|
||||
}
|
||||
|
||||
posix_spawn_file_actions_destroy(&file_actions);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -55,4 +55,8 @@ int simple_archiver_write_all(FILE *out_f, SDArchiverState *state,
|
|||
/// Returns zero on success.
|
||||
int simple_archiver_print_archive_info(FILE *in_f);
|
||||
|
||||
/// Returns zero on success.
|
||||
int simple_archiver_de_compress(int pipe_fd_in, int pipe_fd_out,
|
||||
const char *cmd);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
|
||||
#include "helpers.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int simple_archiver_helper_is_big_endian(void) {
|
||||
union {
|
||||
uint32_t i;
|
||||
|
@ -54,3 +58,73 @@ void simple_archiver_helper_64_bit_be(uint64_t *value) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
char **simple_archiver_helper_cmd_string_to_argv(const char *cmd) {
|
||||
unsigned int capacity = 16;
|
||||
unsigned int idx = 0;
|
||||
// Size of every pointer is the same, so using size of (void*) should be ok.
|
||||
char **args = malloc(sizeof(void *) * capacity);
|
||||
memset(args, 0, sizeof(void *) * capacity);
|
||||
|
||||
unsigned int word_capacity = 16;
|
||||
unsigned int word_idx = 0;
|
||||
char *word = malloc(word_capacity);
|
||||
memset(word, 0, word_capacity);
|
||||
for (const char *c = cmd; *c != 0; ++c) {
|
||||
if (isspace(*c)) {
|
||||
if (word_idx > 0) {
|
||||
if (idx >= capacity) {
|
||||
capacity *= 2;
|
||||
args = realloc(args, sizeof(void *) * capacity);
|
||||
}
|
||||
args[idx] = malloc(word_idx + 1);
|
||||
memcpy(args[idx], word, word_idx);
|
||||
args[idx][word_idx] = 0;
|
||||
++idx;
|
||||
word_idx = 0;
|
||||
}
|
||||
} else {
|
||||
if (word_idx >= word_capacity) {
|
||||
word_capacity *= 2;
|
||||
word = realloc(word, word_capacity);
|
||||
}
|
||||
word[word_idx++] = *c;
|
||||
}
|
||||
}
|
||||
if (word_idx > 0) {
|
||||
if (idx >= capacity) {
|
||||
capacity *= 2;
|
||||
args = realloc(args, sizeof(void *) * capacity);
|
||||
}
|
||||
args[idx] = malloc(word_idx + 1);
|
||||
memcpy(args[idx], word, word_idx);
|
||||
args[idx][word_idx] = 0;
|
||||
++idx;
|
||||
word_idx = 0;
|
||||
}
|
||||
|
||||
free(word);
|
||||
|
||||
if (idx >= capacity) {
|
||||
args = realloc(args, sizeof(void *) * (capacity + 1));
|
||||
args[capacity] = NULL;
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
void simple_archiver_helper_cmd_string_argv_free(char **argv_strs) {
|
||||
if (argv_strs) {
|
||||
for (char **iter = argv_strs; *iter != 0; ++iter) {
|
||||
free(*iter);
|
||||
}
|
||||
free(argv_strs);
|
||||
}
|
||||
}
|
||||
|
||||
void simple_archiver_helper_cmd_string_argv_free_ptr(char ***argv_strs) {
|
||||
if (argv_strs) {
|
||||
simple_archiver_helper_cmd_string_argv_free(*argv_strs);
|
||||
*argv_strs = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,4 +35,12 @@ void simple_archiver_helper_32_bit_be(uint32_t *value);
|
|||
/// Swaps value from/to big-endian. Nop on big-endian systems.
|
||||
void simple_archiver_helper_64_bit_be(uint64_t *value);
|
||||
|
||||
/// Returns a array of c-strings on success, NULL on error.
|
||||
/// The returned array must be free'd with
|
||||
/// simple_archiver_helper_cmd_string_argv_free(...).
|
||||
char **simple_archiver_helper_cmd_string_to_argv(const char *cmd);
|
||||
|
||||
void simple_archiver_helper_cmd_string_argv_free(char **argv_strs);
|
||||
void simple_archiver_helper_cmd_string_argv_free_ptr(char ***argv_strs);
|
||||
|
||||
#endif
|
||||
|
|
27
src/test.c
27
src/test.c
|
@ -44,6 +44,15 @@ static int checks_passed = 0;
|
|||
++checks_passed; \
|
||||
} \
|
||||
} while (0);
|
||||
#define CHECK_STREQ(a, b) \
|
||||
do { \
|
||||
++checks_checked; \
|
||||
if (strcmp((a), (b)) == 0) { \
|
||||
++checks_passed; \
|
||||
} else { \
|
||||
printf("CHECK_STREQ at line %u failed: %s != %s\n", __LINE__, #a, #b); \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
int main(void) {
|
||||
// Test parser.
|
||||
|
@ -170,6 +179,24 @@ int main(void) {
|
|||
}
|
||||
}
|
||||
|
||||
// Test helpers cmd string to argv.
|
||||
do {
|
||||
const char *cmd = "zstd --compress --ultra\n -20 derp_file";
|
||||
char **result_argv = simple_archiver_helper_cmd_string_to_argv(cmd);
|
||||
CHECK_TRUE(result_argv);
|
||||
if (!result_argv) {
|
||||
break;
|
||||
}
|
||||
CHECK_STREQ("zstd", result_argv[0]);
|
||||
CHECK_STREQ("--compress", result_argv[1]);
|
||||
CHECK_STREQ("--ultra", result_argv[2]);
|
||||
CHECK_STREQ("-20", result_argv[3]);
|
||||
CHECK_STREQ("derp_file", result_argv[4]);
|
||||
CHECK_TRUE(result_argv[5] == NULL);
|
||||
|
||||
simple_archiver_helper_cmd_string_argv_free(result_argv);
|
||||
} while (0);
|
||||
|
||||
printf("Checks checked: %u\n", checks_checked);
|
||||
printf("Checks passed: %u\n", checks_passed);
|
||||
return checks_passed == checks_checked ? 0 : 1;
|
||||
|
|
Loading…
Reference in a new issue