libropkg: add functions for extracting metadata from package files
This commit is contained in:
132
libropkg/package.c
Normal file
132
libropkg/package.c
Normal file
@@ -0,0 +1,132 @@
|
||||
#include "reader.h"
|
||||
|
||||
#include <blue/core/error.h>
|
||||
#include <blue/io/directory.h>
|
||||
#include <ropkg/reader.h>
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user