new: support for local package files

This commit is contained in:
ngn 2024-08-06 04:44:42 +03:00
parent 73a1f997e6
commit 1219501aaa
9 changed files with 210 additions and 50 deletions

View File

@ -124,3 +124,9 @@ bool lm_ctx_database_next(lm_ctx_t *ctx, lm_entry_t *entry); // load the n
bool lm_ctx_database_next_free(lm_ctx_t *ctx, lm_entry_t *entry); // free the used next pointers
char *lm_ctx_database_changes(
lm_ctx_t *ctx, lm_entry_t *entry); // get changes file path for a package, FREE THE RETURNED POINTER
/* #######################
## package fucntions ##
####################### */
bool lm_ctx_package_from(lm_ctx_t *ctx, lm_pkg_t *pkg, char *archive);
void lm_ctx_package_from_free(lm_pkg_t *pkg);

View File

@ -144,6 +144,7 @@ typedef enum lm_error {
LM_ERR_PoolListBadDir = 142,
LM_ERR_FileNotExist = 143,
LM_ERR_FileNotLink = 144,
LM_ERR_ArchiveSetFail = 145,
} lm_error_t;
typedef struct lm_error_desc {

View File

@ -8,6 +8,12 @@
#define PKG_DATA_DEPENDS "depends"
#define PKG_DATA_KEEPS "keeps"
#define DATA_FILE "DATA"
#define HASHES_FILE "HASHES"
#define CHANGES_FILE "CHANGES"
#define INSTALL_FILE "INSTALL"
#define FILES_ARCHIVE "files.tar.gz"
typedef struct lm_pkg_data {
char *name;
char *desc;
@ -17,6 +23,14 @@ typedef struct lm_pkg_data {
ssize_t size;
} lm_pkg_data_t;
typedef struct lm_pkg_files {
char *data_file;
char *hashes_file;
char *changes_file;
char *install_file;
char *files_archive;
} lm_pkg_files_t;
typedef struct lm_pkg {
struct lm_pkg_data data;
struct lm_pool *pool;
@ -51,3 +65,6 @@ void lm_package_data_keep_free(lm_pkg_data_t *data);
bool lm_package_path_set_signature(lm_pkg_t *pkg, char *signature_path);
bool lm_package_path_set_archive(lm_pkg_t *pkg, char *archive_path);
bool lm_package_path_is_empty(lm_pkg_t *pkg);
lm_pkg_files_t *lm_package_extract(lm_pkg_t *pkg, char *target);
void lm_package_extract_free(lm_pkg_files_t *files);

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-08-04 18:59+0300\n"
"POT-Creation-Date: 2024-08-06 04:34+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -613,3 +613,7 @@ msgstr ""
#, c-format
msgid "file is a symbolic link: %s"
msgstr ""
#: src/error.c:164
msgid "failed to set the package archive"
msgstr ""

View File

@ -210,7 +210,12 @@ end:
}
bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, bool run_install, lm_ctx_install_callback_t callback, void *data) {
if(NULL == ctx->temp || NULL == pkg){
if(NULL == ctx || NULL == pkg){
lm_error_set(LM_ERR_ArgNULL);
return false;
}
if(NULL == ctx->temp){
lm_error_set(LM_ERR_CtxTempNULL);
return false;
}
@ -238,58 +243,41 @@ bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, bool run_install, lm_ctx_insta
return false;
}
lm_ctx_temp_clear(ctx);
if(!extract_archive(ctx->temp, pkg->archive))
return false; // error set by function
size_t bufsize = strlen(ctx->temp) + 25;
char data_file[bufsize], changes_file[bufsize], hashes_file[bufsize];
char install_file[bufsize], files_archive[bufsize];
lm_pkg_t temp;
lm_package_init(&temp);
join(data_file, ctx->temp, "DATA");
join(hashes_file, ctx->temp, "HASHES");
join(changes_file, ctx->temp, "CHANGES");
join(install_file, ctx->temp, "INSTALL");
join(files_archive, ctx->temp, "files.tar.gz");
if(!exists(data_file, NULL) || !is_file(data_file) ||
!exists(hashes_file, NULL) || !is_file(hashes_file) ||
!exists(changes_file, NULL) || !is_file(changes_file) ||
!exists(install_file, NULL) || !is_file(install_file) ||
!exists(files_archive, NULL) || !is_file(files_archive)){
lm_error_set(LM_ERR_PkgBadArchive);
return false;
}
if(!lm_package_data_load(&temp.data, data_file))
return false; // error set by function
if(!lm_package_is_same(&temp, pkg)){
pdebug(__func__, "DATA file does not match with stored %s data", pkg->data.name);
lm_error_set(LM_ERR_PkgDataNotMatch);
return false;
}
if(!lm_database_changes_update(ctx->db, &pkg->data, changes_file)){
char *suberr = lm_strerror_dup();
pdebug(__func__, "failed to update changes file for %s: %s", pkg->data.name, suberr);
lm_error_set(LM_ERR_PkgChangesUpdateFail, suberr);
return false;
}
lm_pkg_files_t *files;
char *line = NULL, *hash = NULL, *file = NULL;
ssize_t line_len = 0, file_len = 0;
FILE *hashes = NULL;
bool ret = false;
lm_pkg_t temp;
if((hashes = fopen(hashes_file, "r")) == NULL){
lm_ctx_temp_clear(ctx);
lm_package_init(&temp);
if((files = lm_package_extract(pkg, ctx->temp)) == NULL){
pdebug(__func__, "failed to extract %s: %s", pkg->data.name, lm_strerror());
goto end;
}
if(!lm_package_data_load(&temp.data, files->data_file))
goto end; // error set by function
if(!lm_package_is_same(&temp, pkg)){
pdebug(__func__, "DATA file does not match with stored %s data", pkg->data.name);
lm_error_set(LM_ERR_PkgDataNotMatch);
goto end;
}
if(!lm_database_changes_update(ctx->db, &pkg->data, files->changes_file)){
char *suberr = lm_strerror_dup();
pdebug(__func__, "failed to update changes file for %s: %s", pkg->data.name, suberr);
lm_error_set(LM_ERR_PkgChangesUpdateFail, suberr);
goto end;
}
if((hashes = fopen(files->hashes_file, "r")) == NULL){
pdebug(__func__, "failed to open hash file for %s", pkg->data.name);
lm_error_set(LM_ERR_PkgHashesOpenFail);
return false;
goto end;
}
while((line_len = getline(&line, (size_t*)&line_len, hashes)) > 0){
@ -333,7 +321,7 @@ bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, bool run_install, lm_ctx_insta
line_len = 0;
}
if(!__lm_ctx_extract_files(ctx, pkg, files_archive, callback, data)){
if(!__lm_ctx_extract_files(ctx, pkg, files->files_archive, callback, data)){
char *suberr = lm_strerror_dup();
pdebug(__func__, "failed to extract the files archive for %s: %s", pkg->data.name, suberr);
lm_error_set(LM_ERR_PkgExtractFilesFail, suberr);
@ -349,7 +337,7 @@ bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, bool run_install, lm_ctx_insta
goto end;
}
if(run_install && !__lm_ctx_run_install(ctx->root, install_file)){
if(run_install && !__lm_ctx_run_install(ctx->root, files->install_file)){
char *suberr = lm_strerror_dup();
pdebug(__func__, "failed to run install script: %s", lm_strerror());
lm_error_set(LM_ERR_InstallRunFail, suberr);
@ -357,7 +345,7 @@ bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, bool run_install, lm_ctx_insta
goto end;
}
if(!run_install && !__lm_ctx_save_install(ctx, pkg, install_file)){
if(!run_install && !__lm_ctx_save_install(ctx, pkg, files->install_file)){
char *suberr = lm_strerror_dup();
pdebug(__func__, "failed to save install script: %s", lm_strerror());
lm_error_set(LM_ERR_InstallSaveFail, suberr);
@ -372,6 +360,9 @@ end:
if(NULL != hashes)
fclose(hashes);
lm_package_free(&temp);
lm_package_extract_free(files);
if(!ret){
lm_database_entry_del(ctx->db, &pkg->data);
lm_database_changes_del(ctx->db, &pkg->data);

66
src/ctx/package.c Normal file
View File

@ -0,0 +1,66 @@
#include "../../include/package.h"
#include "../../include/error.h"
#include "../../include/util.h"
#include "../../include/ctx.h"
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
bool lm_ctx_package_from(lm_ctx_t *ctx, lm_pkg_t *pkg, char *archive){
if(NULL == ctx || NULL == pkg || NULL == archive){
lm_error_set(LM_ERR_ArgNULL);
return false;
}
// we should init the package pointer as soon as possible
// so if the caller calls ..._from_free we can prevent
// memory corruption
lm_package_init(pkg);
if(NULL == ctx->temp) {
lm_error_set(LM_ERR_CtxTempNULL);
return false;
}
size_t archive_len = strlen(archive);
char signature[archive_len+7];
lm_pkg_files_t *files = NULL;
bool ret = false;
sprintf(signature, "%s.sig", archive);
if(!lm_package_path_set_archive(pkg, archive) || !lm_package_path_set_signature(pkg, signature)){
lm_error_set(LM_ERR_ArchiveSetFail);
return false;
}
if(!lm_ctx_temp_clear(ctx)){
pdebug(__func__, "failed to clear the temp directory: %s", lm_strerror());
return false; // error set by function
}
if((files = lm_package_extract(pkg, ctx->temp)) == NULL){
pdebug(__func__, "failed to extract the archive (%s): %s", archive, lm_strerror());
return false; // error set by function
}
if(!lm_package_data_load(&pkg->data, files->data_file)){
pdebug(__func__, "failed to load the package data: %s", lm_strerror());
goto end; // error set by function
}
ret = true;
end:
lm_package_extract_free(files);
return ret;
}
void lm_ctx_package_from_free(lm_pkg_t *pkg){
if(NULL == pkg){
lm_error_set(LM_ERR_ArgNULL);
return;
}
lm_package_free(pkg);
}

View File

@ -161,6 +161,7 @@ void lm_error_set(lm_error_t code, ...) {
{.code = LM_ERR_PoolListBadDir, .desc = _("specified list extraction directory is not accessible") },
{.code = LM_ERR_FileNotExist, .desc = _("file does not exist: %s") },
{.code = LM_ERR_FileNotLink, .desc = _("file is a symbolic link: %s") },
{.code = LM_ERR_ArchiveSetFail, .desc = _("failed to set the package archive") },
};
char *fmt = NULL;

71
src/package/extract.c Normal file
View File

@ -0,0 +1,71 @@
#include "../../include/package.h"
#include "../../include/error.h"
#include "../../include/util.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
bool __lm_package_extract_check(char *file){
if(!exists(file, NULL) || !is_file(file)){
lm_error_set(LM_ERR_PkgBadArchive);
return false;
}
return true;
}
lm_pkg_files_t *lm_package_extract(lm_pkg_t *pkg, char *target){
if(NULL == pkg || NULL == target){
lm_error_set(LM_ERR_ArgNULL);
return NULL;
}
if(lm_package_path_is_empty(pkg)){
lm_error_set(LM_ERR_PkgPathsEmpty);
return NULL;
}
if(!extract_archive(target, pkg->archive))
return NULL;
lm_pkg_files_t *files = malloc(sizeof(lm_pkg_files_t));
bool ret = false;
bzero(files, sizeof(lm_pkg_files_t));
files->data_file = join_alloc(target, "DATA");
files->hashes_file = join_alloc(target, "HASHES");
files->changes_file = join_alloc(target, "CHANGES");
files->install_file = join_alloc(target, "INSTALL");
files->files_archive = join_alloc(target, "files.tar.gz");
if(!__lm_package_extract_check(files->data_file) ||
!__lm_package_extract_check(files->hashes_file) ||
!__lm_package_extract_check(files->changes_file) ||
!__lm_package_extract_check(files->install_file) ||
!__lm_package_extract_check(files->files_archive)){
goto end;
}
ret = true;
end:
if(!ret){
lm_package_extract_free(files);
files = NULL;
}
return files;
}
void lm_package_extract_free(lm_pkg_files_t *files){
if(NULL == files)
return;
free(files->data_file);
free(files->hashes_file);
free(files->changes_file);
free(files->install_file);
free(files->files_archive);
bzero(files, sizeof(lm_pkg_files_t));
free(files);
}

View File

@ -7,6 +7,7 @@
#include <stdbool.h>
#include <dirent.h>
#include <libgen.h>
#include <stdlib.h>
#include <string.h>
bool lm_pool_list_load(lm_pool_t *pool, char *dir){
@ -144,6 +145,8 @@ void lm_pool_list_free(lm_pool_t *pool){
while(NULL != cur){
prev = cur;
cur = cur->next;
lm_package_free(prev);
free(prev);
}
}