new: implement check and update functions
This commit is contained in:
65
src/ctx/check.c
Normal file
65
src/ctx/check.c
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
115
src/ctx/update.c
115
src/ctx/update.c
@ -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;
|
||||
}
|
||||
|
@ -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){
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
38
src/util.c
38
src/util.c
@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user