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

View File

@ -1,6 +1,6 @@
CC = gcc
all: ../dist/client_install ../dist/client_remove ../dist/server
all: ../dist/client_install ../dist/client_remove ../dist/client_update ../dist/client_check ../dist/client_list ../dist/server
../dist/client_install: client/install.c client/*.h ../dist/libmp.so
mkdir -pv ../dist
@ -10,6 +10,18 @@ all: ../dist/client_install ../dist/client_remove ../dist/server
mkdir -pv ../dist
$(CC) -L../dist $< -lmp -o $@
../dist/client_update: client/update.c client/*.h ../dist/libmp.so
mkdir -pv ../dist
$(CC) -L../dist $< -lmp -o $@
../dist/client_check: client/check.c client/*.h ../dist/libmp.so
mkdir -pv ../dist
$(CC) -L../dist $< -lmp -o $@
../dist/client_list: client/list.c client/*.h ../dist/libmp.so
mkdir -pv ../dist
$(CC) -L../dist $< -lmp -o $@
../dist/server: server/*.c ../dist/libmp.so
mkdir -pv ../dist
$(CC) -L../dist $< -lmp -o $@

45
examples/client/check.c Normal file
View File

@ -0,0 +1,45 @@
#include "../../include/all.h"
#include "./common.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
int ret = EXIT_FAILURE;
lm_pkg_t pkg;
lm_ctx_t ctx;
lm_package_init(&pkg);
if (argc != 2) {
printf("usage: %s <package name>\n", argv[0]);
return ret;
}
lm_ctx_init(&ctx);
if (!lm_ctx_set_data(&ctx, DATA_DIR)) {
printf("failed to set data dir: %s (%d)\n", lm_strerror(), lm_error());
goto end;
}
if (!lm_ctx_database_find(&ctx, &pkg, argv[1], NULL)) {
printf("failed to find package: %s (%d)\n", lm_strerror(), lm_error());
goto end;
}
printf("checking %s (%s)...\n", pkg.name, pkg.version);
if (!lm_ctx_check(&ctx, &pkg, NULL, NULL)) {
printf("failed to verify the package: %s (%d)\n", lm_strerror(), lm_error());
goto end;
}
ret = EXIT_SUCCESS;
end:
lm_package_free(&pkg);
lm_ctx_free(&ctx);
return ret;
}

28
examples/client/list.c Normal file
View File

@ -0,0 +1,28 @@
#include "../../include/all.h"
#include "./common.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
lm_ctx_t ctx;
lm_pkg_t pkg;
int ret = EXIT_FAILURE;
lm_ctx_init(&ctx);
if (!lm_ctx_set_data(&ctx, DATA_DIR)) {
printf("failed to set data dir: %s (%d)\n", lm_strerror(), lm_error());
goto end;
}
printf("listing installed packages:\n");
while (lm_ctx_database_next(&ctx, &pkg))
printf("%s (%s)\n", pkg.name, pkg.version);
end:
lm_ctx_database_next_free(&ctx, &pkg);
return ret;
}

60
examples/client/update.c Normal file
View File

@ -0,0 +1,60 @@
#include "../../include/all.h"
#include "./common.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
lm_ctx_update_list_t *list = NULL;
int ret = EXIT_FAILURE;
lm_pkg_t pkg, *cur = NULL;
lm_ctx_t ctx;
if (!mkdir_ifnot(ROOT_DIR)) {
printf("failed to create root dir: %s\n", ROOT_DIR);
return ret;
}
lm_ctx_init(&ctx);
if (!lm_ctx_set_data(&ctx, DATA_DIR)) {
printf("failed to set data dir: %s (%d)\n", lm_strerror(), lm_error());
goto end;
}
if (!lm_ctx_set_temp(&ctx, TEMP_DIR)) {
printf("failed to set temp dir: %s (%d)\n", lm_strerror(), lm_error());
goto end;
}
if (!lm_ctx_set_root(&ctx, ROOT_DIR)) {
printf("failed to set root dir: %s (%d)\n", lm_strerror(), lm_error());
goto end;
}
if ((list = lm_ctx_update_list(&ctx)) == NULL) {
printf("failed to get update list: %s (%d)", lm_strerror(), lm_error());
goto end;
}
if (list->count == 0) {
printf("all packages are up-to-date\n");
goto end;
}
while ((cur = lm_ctx_update_list_next(list)) != NULL) {
printf("updating %s (%s)...\n", cur->name, cur->version);
if (!lm_ctx_update(&ctx, cur, NULL, NULL)) {
printf("failed to update package: %s\n", lm_strerror());
goto end;
}
}
ret = EXIT_SUCCESS;
end:
lm_ctx_update_list_free(list);
lm_ctx_free(&ctx);
return ret;
}

View File

@ -21,9 +21,9 @@ typedef struct lm_ctx_resolve_list {
} lm_ctx_resolve_list_t;
typedef struct lm_ctx_update_list {
lm_pkg_t **packages;
size_t count;
size_t index;
lm_pkg_t *packages;
lm_pkg_t *cur;
size_t count;
} lm_ctx_update_list_t;
typedef enum lm_ctx_sync_state {
@ -35,6 +35,11 @@ typedef enum lm_ctx_sync_state {
SYNC_LIST_FAIL = 5,
} lm_ctx_sync_state_t;
typedef enum lm_ctx_update_state {
UPDATE_REMOVE = 0,
UPDATE_INSTALL = 1,
} lm_ctx_update_state_t;
/* ###################
## ctx callbacks ##
################### */
@ -43,6 +48,8 @@ typedef bool (*lm_ctx_download_callback_t)(
lm_ctx_t *ctx, lm_pkg_t *pkg, bool is_archive, size_t current, size_t total, void *data);
typedef bool (*lm_ctx_install_callback_t)(
lm_ctx_t *ctx, lm_pkg_t *pkg, char *file, size_t current, size_t total, void *data);
typedef bool (*lm_ctx_update_callback_t)(
lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_update_state_t state, char *file, size_t current, size_t total, void *data);
typedef bool (*lm_ctx_sync_callback_t)(
lm_ctx_t *ctx, lm_pool_t *pool, lm_ctx_sync_state_t state, size_t current, size_t total, void *data);
typedef bool (*lm_ctx_ping_callback_t)(lm_ctx_t *ctx, lm_pool_t *pool, bool status, void *data);
@ -66,9 +73,11 @@ lm_ctx_resolve_list_t *lm_ctx_resolve(
lm_pkg_t *lm_ctx_resolve_next(lm_ctx_resolve_list_t *list); // returns the next package in the list
void lm_ctx_resolve_free(lm_ctx_resolve_list_t *list); // frees the resolved list returned by lm_ctx_resolve
lm_ctx_update_list_t *lm_ctx_update(lm_ctx_t *ctx); // returns a list of packages to update
lm_pkg_t *lm_ctx_update_next(lm_ctx_update_list_t *list); // returns the next package in the list
void lm_ctx_update_free(lm_ctx_update_list_t *list); // frees the update list returned by lm_ctx_update
lm_ctx_update_list_t *lm_ctx_update_list(lm_ctx_t *ctx); // get a list of packages to update
lm_pkg_t *lm_ctx_update_list_next(lm_ctx_update_list_t *list); // get the next package in the update list
void lm_ctx_update_list_free(lm_ctx_update_list_t *list); // free the update list
bool lm_ctx_update(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_update_callback_t callback,
void *data); // returns a list of packages to update
bool lm_ctx_download(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_download_callback_t callback,
void *data); // downloads a single package
@ -98,5 +107,5 @@ lm_pool_t *lm_ctx_pool_by_url(lm_ctx_t *ctx, char *host, char *path); // find p
bool lm_ctx_database_init(lm_ctx_t *ctx); // init ctx database (if not already present)
bool lm_ctx_database_is_installed(lm_ctx_t *ctx, lm_pkg_t *pkg, bool check_version); // check if a package is installed
bool lm_ctx_database_find(lm_ctx_t *ctx, lm_pkg_t *pkg, char *name, char *version); // find a package by name
bool lm_ctx_database_foreach(
lm_ctx_t *ctx, lm_ctx_database_callback_t callback, void *data); // loop for each package in the database
bool lm_ctx_database_next(lm_ctx_t *ctx, lm_pkg_t *pkg); // load the next package into pkg pointer
bool lm_ctx_database_next_free(lm_ctx_t *ctx, lm_pkg_t *pkg); // free the used next pointers

View File

@ -133,6 +133,11 @@ typedef enum lm_error {
LM_ERR_InstallStatusFail = 125,
LM_ERR_InstallScriptFail = 126,
LM_ERR_PkgBreaks = 127,
LM_ERR_PkgUpToDate = 128,
LM_ERR_HashOpenFail = 129,
LM_ERR_HashDigestFail = 130,
LM_ERR_FileHashFail = 131,
LM_ERR_FileHashNoMatch = 132,
} lm_error_t;
typedef struct lm_error_desc {

View File

@ -12,6 +12,7 @@ lm_pkg_t *lm_package_new();
void lm_package_free(lm_pkg_t *pkg);
bool lm_package_verify(lm_pkg_t *pkg);
void lm_package_init(lm_pkg_t *pkg);
bool lm_package_copy(lm_pkg_t *dst, lm_pkg_t *src);
bool lm_package_data_load(lm_pkg_t *pkg, char *file);
void lm_package_data_free(lm_pkg_t *pkg);
@ -34,4 +35,5 @@ 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);
void lm_package_path_free(lm_pkg_t *pkg);
bool lm_package_path_copy(lm_pkg_t *dst, lm_pkg_t *src);
bool lm_package_is_same(lm_pkg_t *one, lm_pkg_t *two);

View File

@ -16,12 +16,13 @@ bool is_digit(char c);
bool copy_from_buffer(void *dst, void *buffer, size_t size, ssize_t *total, ssize_t *used);
bool copy_to_buffer(void *buffer, void *src, size_t size, ssize_t *total, ssize_t *used);
bool copy_file(char *dst, char *src);
bool can_write(char *path);
bool can_read(char *path);
bool is_file(char *path);
bool is_dir(char *path);
bool exists(char *path);
char *get_md5(char *path);
bool copy_file(char *dst, char *src);
bool can_write(char *path);
bool can_read(char *path);
bool is_file(char *path);
bool is_dir(char *path);
bool exists(char *path);
bool package_parse(char *package, char *name, char *version);
bool package_version_valid(char *name);

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-10 16:36+0300\n"
"POT-Creation-Date: 2024-07-11 07:30+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"
@ -559,3 +559,26 @@ msgstr ""
#, c-format
msgid "removing package breaks %s"
msgstr ""
#: src/error.c:153
#, fuzzy
msgid "package is already up-to-date"
msgstr "URL hostname is too large"
#: src/error.c:154
msgid "failed to open file for hashing"
msgstr ""
#: src/error.c:155
msgid "failed create digest for hashing"
msgstr ""
#: src/error.c:156
#, c-format
msgid "failed to get hash of %s: %s"
msgstr ""
#: src/error.c:157
#, c-format
msgid "file hash does not match for %s"
msgstr ""

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;
}