diff --git a/libropkg/include/ropkg/package.h b/libropkg/include/ropkg/package.h new file mode 100644 index 0000000..75db89b --- /dev/null +++ b/libropkg/include/ropkg/package.h @@ -0,0 +1,13 @@ +#ifndef ROPKG_PACKAGE_H_ +#define ROPKG_PACKAGE_H_ + +#include +#include +#include + +struct ropkg_reader; + +ROPKG_API b_result +ropkg_extract_metadata(struct ropkg_reader *reader, b_directory *dest); + +#endif diff --git a/libropkg/package.c b/libropkg/package.c new file mode 100644 index 0000000..a51a6a4 --- /dev/null +++ b/libropkg/package.c @@ -0,0 +1,132 @@ +#include "reader.h" + +#include +#include +#include + +static b_result extract_file( + struct ropkg_reader *pkg, + const char *path_cstr, + b_directory *dest) +{ + b_path *path = b_path_create_from_cstr(path_cstr); + if (!path) { + return ROPKG_RESULT_ERR(NO_MEMORY); + } + + b_path *dir_path = NULL; + b_path_get_directory(path, &dir_path); + if (!dir_path) { + b_path_release(path); + return ROPKG_RESULT_ERR(NO_MEMORY); + } + + b_result result = B_RESULT_SUCCESS; + if (b_path_length(dir_path) > 0) { + b_directory *parent_dir; + result = b_directory_open( + dest, + dir_path, + B_DIRECTORY_OPEN_CREATE_INTERMEDIATE, + &parent_dir); + b_directory_release(parent_dir); + } + + if (b_result_is_error(result)) { + goto end; + } + + b_file *dest_file = NULL; + result = b_file_open( + dest, + path, + B_FILE_WRITE_ONLY | B_FILE_CREATE | B_FILE_BINARY, + &dest_file); + if (b_result_is_error(result)) { + goto end; + } + + char data[] = "Hello"; + size_t nr_written = 0; + b_file_write(dest_file, 0, sizeof data, data, &nr_written); + b_file_release(dest_file); + +end: + b_path_release(path); + b_path_release(dir_path); + return result; +} + +static b_result extract_subpackage( + struct ropkg_reader *pkg, + const char *name, + b_directory *dest) +{ + b_directory *dest_subdir; + b_result result = b_directory_open( + dest, + B_RV_PATH(name), + B_DIRECTORY_OPEN_CREATE, + &dest_subdir); + if (b_result_is_error(result)) { + return result; + } + + b_cstream_begin_compressed_section(pkg->r_stream, NULL); + + struct ropkg_reader *subpkg = NULL; + enum ropkg_status status = ropkg_reader_open(pkg->r_stream, &subpkg); + if (status != ROPKG_SUCCESS) { + result = ROPKG_RESULT_STATUS(status); + goto end; + } + + while (!ropkg_reader_eof(subpkg)) { + const struct ropkg_file_info *file + = ropkg_reader_current_file(subpkg); + result = extract_file(subpkg, file->f_filename, dest_subdir); + if (b_result_is_error(result)) { + break; + } + + status = ropkg_reader_move_next(subpkg); + if (status != ROPKG_SUCCESS) { + result = ROPKG_RESULT_STATUS(status); + break; + } + } + +end: + b_cstream_end_compressed_section(pkg->r_stream, NULL, NULL); + return result; +} + +b_result ropkg_extract_metadata(struct ropkg_reader *pkg, b_directory *dest) +{ + b_result result = B_RESULT_SUCCESS; + + while (!ropkg_reader_eof(pkg)) { + const struct ropkg_file_info *file + = ropkg_reader_current_file(pkg); + + int section = -1; + + if (!strncmp(file->f_filename, "meta.tar", 8)) { + result = extract_subpackage(pkg, "meta", dest); + } else if (!strncmp(file->f_filename, "control.tar", 11)) { + result = extract_subpackage(pkg, "control", dest); + } + + if (b_result_is_error(result)) { + break; + } + + enum ropkg_status status = ropkg_reader_move_next(pkg); + if (status != ROPKG_SUCCESS) { + result = ROPKG_RESULT_STATUS(status); + break; + } + } + + return result; +}