new: implement check and update functions

This commit is contained in:
ngn
2024-07-11 07:31:36 +03:00
parent f886bc08e4
commit 839bcb47bf
20 changed files with 456 additions and 52 deletions

65
src/ctx/check.c Normal file
View File

@ -0,0 +1,65 @@
#include "../../include/error.h"
#include "../../include/util.h"
#include "../../include/ctx.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
bool lm_ctx_check(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_check_callback_t callback, void *data){
if(NULL == ctx || NULL == pkg){
lm_error_set(LM_ERR_ArgNULL);
return false;
}
if(NULL == ctx->root){
lm_error_set(LM_ERR_CtxRootNULL);
return false;
}
if(!lm_ctx_database_init(ctx))
return false; // error set by function
size_t rootlen = strlen(ctx->root), current = 0, total = 0;
char *path = NULL, *hash = NULL, *fhash = NULL;
bool keep = false, ret = false;
total = lm_database_files_count(ctx->db, pkg);
while(lm_database_files_next(ctx->db, pkg, &path, &hash, &keep)){
char fp[rootlen+strlen(path)+10];
join(fp, ctx->root, path);
current++;
if(NULL != callback)
if(!callback(ctx, pkg, fp, current, total, data))
goto end;
if(!exists(fp)){
pdebug(__func__, "skipping %s because file does not exists", fp);
continue;
}
if((fhash = get_md5(fp)) == NULL){
char *suberr = lm_strerror_dup();
pdebug(__func__, "failed to get hash of %s: %s", fp, suberr);
lm_error_set(LM_ERR_FileHashFail, fp, suberr);
free(suberr);
goto end;
}
if(!eq(fhash, hash)){
lm_error_set(LM_ERR_FileHashNoMatch, fp);
goto end;
}
free(fhash);
fhash = NULL;
}
ret = true;
end:
lm_database_files_next_free(ctx->db, pkg, &path, &hash, &keep);
free(fhash);
return ret;
}

View File

@ -39,8 +39,8 @@ bool lm_ctx_database_find(lm_ctx_t *ctx, lm_pkg_t *pkg, char *name, char *versio
return lm_database_package_find(ctx->db, pkg, name, version);
}
bool lm_ctx_database_foreach(lm_ctx_t *ctx, lm_ctx_database_callback_t callback, void *data){
if(NULL == ctx || NULL == callback){
bool lm_ctx_database_next(lm_ctx_t *ctx, lm_pkg_t *pkg){
if(NULL == ctx || NULL == pkg){
lm_error_set(LM_ERR_ArgNULL);
return false;
}
@ -48,12 +48,18 @@ bool lm_ctx_database_foreach(lm_ctx_t *ctx, lm_ctx_database_callback_t callback,
if(!lm_ctx_database_init(ctx))
return false; // error set by function
lm_pkg_t pkg;
return lm_database_package_next(ctx->db, pkg);
}
while(lm_database_package_next(ctx->db, &pkg)){
if(!callback(ctx, &pkg, data))
break;
bool lm_ctx_database_next_free(lm_ctx_t *ctx, lm_pkg_t *pkg){
if(NULL == ctx || NULL == pkg){
lm_error_set(LM_ERR_ArgNULL);
return false;
}
if(!lm_ctx_database_init(ctx))
return false; // error set by function
lm_database_package_next_free(ctx->db, pkg);
return true;
}

View File

@ -170,7 +170,7 @@ bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_install_callback_t call
return false;
}
if(lm_ctx_database_is_installed(ctx, pkg, true)){
if(lm_ctx_database_is_installed(ctx, pkg, false)){
lm_error_set(LM_ERR_PkgAlreadyInstalled);
return false;
}

View File

@ -94,6 +94,7 @@ bool lm_ctx_remove(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_remove_callback_t callba
ret = true;
end:
lm_database_package_next_free(ctx->db, &cur);
lm_database_files_next_free(ctx->db, pkg, &path, &hash, &in_keep);
return ret;
}

View File

@ -8,54 +8,117 @@
#include <stdlib.h>
#include <string.h>
lm_ctx_update_list_t *lm_ctx_update(lm_ctx_t *ctx){
lm_ctx_update_list_t *list = malloc(sizeof(lm_ctx_update_list_t));
list->packages = NULL;
list->index = 0;
list->count = 0;
struct __lm_ctx_update_cb_data {
lm_ctx_update_callback_t callback;
lm_ctx_update_state_t state;
void *data;
};
if(!lm_ctx_database_init(ctx))
bool __lm_ctx_update_callback(lm_ctx_t *ctx, lm_pkg_t *pkg, char *file, size_t current, size_t total, void *data){
struct __lm_ctx_update_cb_data *cbdata = data;
if(NULL == cbdata->callback)
return true;
return cbdata->callback(ctx, pkg, cbdata->state, file, current, total, cbdata->data);
}
lm_ctx_update_list_t *lm_ctx_update_list(lm_ctx_t *ctx){
if(NULL == ctx){
lm_error_set(LM_ERR_ArgNULL);
return NULL;
lm_pkg_t *pkg = malloc(sizeof(lm_pkg_t));
while(lm_database_package_next(ctx->db, pkg)){
if(NULL == list->packages)
list->packages = malloc(sizeof(lm_pkg_t*));
else
list->packages = realloc(list->packages, (list->count+1)*sizeof(lm_pkg_t*));
list->packages[list->count++] = pkg;
pkg = malloc(sizeof(lm_pkg_t));
}
lm_ctx_update_list_t *list = malloc(sizeof(lm_ctx_update_list_t));
lm_pkg_t cur, *new = NULL;
bzero(list, sizeof(lm_ctx_update_list_t));
lm_package_init(&cur);
while(lm_ctx_database_next(ctx, &cur)){
if((new = lm_ctx_pool_find(ctx, cur.name, NULL)) == NULL)
continue;
if(eq(new->version, cur.version))
continue;
if(NULL == list->packages)
list->packages = malloc(sizeof(lm_pkg_t));
else
list->packages = realloc(list->packages, (list->count+1)*sizeof(lm_pkg_t));
lm_package_copy(&list->packages[list->count++], &cur);
}
lm_ctx_database_next_free(ctx, &cur);
return list;
}
lm_pkg_t *lm_ctx_update_next(lm_ctx_update_list_t *list){
lm_pkg_t *lm_ctx_update_list_next(lm_ctx_update_list_t *list){
if(NULL == list){
lm_error_set(LM_ERR_ArgNULL);
return NULL;
}
if(list->index >= list->count-1){
list->index = 0;
if(NULL == list->packages)
return NULL;
if(NULL == list->cur)
list->cur = &list->packages[0];
for(int i = 0; i < list->count-1; i++){
if(list->cur != &list->packages[i])
continue;
list->cur = &list->packages[i+1];
return list->cur;
}
return list->packages[list->index++];
list->cur = NULL;
return list->cur;
}
void lm_ctx_update_free(lm_ctx_update_list_t *list){
void lm_ctx_update_list_free(lm_ctx_update_list_t *list){
if(NULL == list){
lm_error_set(LM_ERR_ArgNULL);
return;
}
for(int i = 0; i < list->count; i++){
lm_package_free(list->packages[i]);
free(list->packages[i]);
if(NULL != list->packages){
for(int i = 0; i < list->count; i++)
lm_package_free(&list->packages[i]);
free(list->packages);
}
free(list);
}
bool lm_ctx_update(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_update_callback_t callback, void *data){
if(NULL == ctx || NULL == pkg){
lm_error_set(LM_ERR_ArgNULL);
return false;
}
struct __lm_ctx_update_cb_data cbdata = {
.state = UPDATE_REMOVE,
.callback = callback,
.data = data,
};
lm_pkg_t *new = NULL;
if((new = lm_ctx_pool_find(ctx, pkg->name, NULL)) == NULL){
lm_error_set(LM_ERR_PkgNotFound);
return false;
}
if(eq(new->version, pkg->version)){
lm_error_set(LM_ERR_PkgUpToDate);
return false;
}
if(!lm_ctx_remove(ctx, pkg, __lm_ctx_update_callback, &cbdata))
return false; // error set by function
if(!lm_ctx_install(ctx, new, __lm_ctx_update_callback, &cbdata))
return false; // error set by function
return true;
}

View File

@ -227,6 +227,7 @@ bool lm_database_files_next(lm_database_t *db, lm_pkg_t *pkg, char **path, char
free(*hash);
*path = NULL;
*hash = NULL;
*keep = false;
}
if(sqlite3_step(db->files_st) != SQLITE_ROW){

View File

@ -156,6 +156,8 @@ bool lm_database_package_next(lm_database_t *db, lm_pkg_t *pkg){
lm_error_set(LM_ERR_DbSqlPrepareFail);
return false;
}
lm_package_init(pkg);
if(sqlite3_step(db->packages_st) != SQLITE_ROW){
sqlite3_finalize(db->packages_st);
@ -163,8 +165,6 @@ bool lm_database_package_next(lm_database_t *db, lm_pkg_t *pkg){
return false;
}
lm_package_init(pkg);
pkg->name = strdup((char*)sqlite3_column_text(db->packages_st, PACKAGES_COLUMN_NAME-1));
pkg->desc = strdup((char*)sqlite3_column_text(db->packages_st, PACKAGES_COLUMN_DESC-1));
pkg->version = strdup((char*)sqlite3_column_text(db->packages_st, PACKAGES_COLUMN_VERSION-1));

View File

@ -150,6 +150,11 @@ void lm_error_set(lm_error_t code, ...) {
{.code = LM_ERR_InstallStatusFail, .desc = _("install script returned a bad status code") },
{.code = LM_ERR_InstallScriptFail, .desc = _("failed to run the package install script: %s") },
{.code = LM_ERR_PkgBreaks, .desc = _("removing package breaks %s") },
{.code = LM_ERR_PkgUpToDate, .desc = _("package is already up-to-date") },
{.code = LM_ERR_HashOpenFail, .desc = _("failed to open file for hashing") },
{.code = LM_ERR_HashDigestFail, .desc = _("failed create digest for hashing") },
{.code = LM_ERR_FileHashFail, .desc = _("failed to get hash of %s: %s") },
{.code = LM_ERR_FileHashNoMatch, .desc = _("file hash does not match for %s") },
};
char *fmt = NULL;

View File

@ -5,6 +5,7 @@
#include "../../include/util.h"
#include <errno.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
@ -48,12 +49,39 @@ bool lm_package_remove_download(lm_pkg_t *pkg){
}
bool lm_package_is_same(lm_pkg_t *one, lm_pkg_t *two){
if(NULL == one || NULL == two){
lm_error_set(LM_ERR_ArgNULL);
return false;
}
return eq(one->version, two->version) &&
eq(one->name, two->name) &&
eq(one->desc, two->desc) &&
one->size == two->size;
}
bool lm_package_copy(lm_pkg_t *dst, lm_pkg_t *src){
lm_package_init(dst);
dst->name = strdup(src->name);
dst->version = strdup(src->version);
dst->desc = strdup(src->desc);
dst->size = src->size;
dst->pool = src->pool;
if(NULL != src->keeps){
for(int i = 0; src->keeps[i] != NULL; i++)
lm_package_keep_add(dst, src->keeps[i]);
}
if(NULL != src->depends){
for(int i = 0; src->depends[i] != NULL; i++)
lm_package_depend_add(dst, src->depends[i]);
}
return lm_package_path_copy(dst, src);
}
void lm_package_free(lm_pkg_t *pkg){
lm_package_data_free(pkg);
bzero(pkg, sizeof(lm_pkg_t));

View File

@ -1,4 +1,5 @@
#include "../../include/package.h"
#include "../../include/error.h"
#include "../../include/types.h"
#include "../../include/util.h"
@ -38,6 +39,17 @@ bool lm_package_path_is_empty(lm_pkg_t *pkg){
NULL == pkg->paths.archive;
}
bool lm_package_path_copy(lm_pkg_t *dst, lm_pkg_t *src){
if(NULL == dst || NULL == src){
lm_error_set(LM_ERR_ArgNULL);
return false;
}
dst->paths.archive = strdup(src->paths.archive);
dst->paths.signature = strdup(src->paths.signature);
return true;
}
void lm_package_path_free(lm_pkg_t *pkg){
free(pkg->paths.signature);
free(pkg->paths.archive);

View File

@ -6,6 +6,7 @@
#include <arpa/inet.h>
#include <errno.h>
#include <linux/limits.h>
#include <openssl/evp.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@ -435,3 +436,40 @@ end:
return ret;
}
char *get_md5(char *path) {
const EVP_MD *alg = NULL;
EVP_MD_CTX *ctx = NULL;
FILE *file = NULL;
char *sum = NULL, buffer[255];
unsigned char digest[16];
unsigned int digest_len;
size_t read = 0;
alg = EVP_md5();
bzero(buffer, sizeof(buffer));
bzero(digest, sizeof(digest));
if ((file = fopen(path, "r")) == NULL) {
lm_error_set(LM_ERR_HashOpenFail);
return NULL;
}
if (EVP_DigestInit_ex(ctx, alg, NULL) <= 0) {
lm_error_set(LM_ERR_HashDigestFail);
return NULL;
}
while ((read = fread(buffer, sizeof(buffer), 1, file)) > 0)
EVP_DigestUpdate(ctx, buffer, read);
EVP_DigestFinal(ctx, digest, &digest_len);
EVP_MD_CTX_free(ctx);
sum = malloc((digest_len * 2) + 1);
for (int i = 0; i < sizeof(digest); i++)
sprintf(&sum[i * 2], "%02x", (unsigned int)digest[i]);
return sum;
}