#include #include #include #include "libmbpk.h" #include "ini.h" #include #include #define MBPK_DB_DIR "/var/lib/mbpk" #define MBPK_REPO_DIR "/var/lib/mbpk-repo" #define MBPK_REPO_CONFIG "/etc/mbpk-repos.ini" #define MAX_REPOS 32 typedef struct { const char *name; const char *desc; const char *url; char **packages; } mbpk_repository; struct curl_memory { char* memory; size_t size; }; mbpk_repository *repos[MAX_REPOS]; int repo_count = 0; static char* strdup(const char *s) { size_t size = strlen(s) + 1; char* p = (char*)malloc(size); if (p) { memcpy(p, s, size); } return p; } static size_t curl_memory_write_calback(void *contents, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; struct curl_memory *mem = (struct curl_memory*)userp; char *ptr = realloc(mem->memory, mem->size + realsize + 1); if (!ptr) { return 0; } mem->memory = ptr; memcpy(&(mem->memory[mem->size]), contents, realsize); mem->size += realsize; mem->memory[mem->size] = 0; return realsize; } int mbpk_init(void) { CURLcode result; struct stat st; if (stat(MBPK_DB_DIR, &st) == -1) { if (mkdir(MBPK_DB_DIR, 0755) == -1) { return MBPK_DB_FAIL; } } if (stat(MBPK_REPO_DIR, &st) == -1) { if (mkdir(MBPK_REPO_DIR, 0755) == -1) { return MBPK_REPO_FAIL; } } result = curl_global_init(CURL_GLOBAL_ALL); if (result != CURLE_OK) { return MBPK_CURL_INIT_FAIL; } return MBPK_OK; } static int repo_conf_handler(void* user, const char* section, const char* name, const char* value) { if (!(strcmp(name, "url") == 0)) { return 0; /* unknown name, error */ } if (repo_count >= MAX_REPOS) { return 0; /* too many repos */ } repos[repo_count] = malloc(sizeof(mbpk_repository)); if (repos[repo_count] == NULL) { return 0; /* out of memory */ } repos[repo_count]->name = strdup(section); repos[repo_count]->desc = NULL; /* mbpk_update_repositories will fill this in later */ repos[repo_count]->url = strdup(value); repos[repo_count]->packages = NULL; /* mbpk_update_repositories will fill this in later */ if (repos[repo_count]->name == NULL || repos[repo_count]->url == NULL) { free((void*)repos[repo_count]->name); free((void*)repos[repo_count]->url); free(repos[repo_count]); repos[repo_count] = NULL; return 0; /* out of memory */ } repo_count++; return 1; } int mbpk_update_repositories(void) { /* Declarations */ struct stat st; int i; mbpk_repository *repo; CURL* curl; CURLcode result; char *repo_ini_url; char *repo_ini_path; char *repo_dir; size_t dir_len; struct curl_memory chunk; repo_count = 0; if (ini_parse(MBPK_REPO_CONFIG, repo_conf_handler, NULL) < 0) { return MBPK_REPO_FAIL; } for (i = 0; i < repo_count; i++) { repo = repos[i]; printf("[libmbpk debug] processing repo %s\n", repo->name); chunk.memory = malloc(1); if (!chunk.memory) { return MBPK_OUT_OF_MEMORY; } chunk.size = 0; curl = curl_easy_init(); if (curl) { repo_ini_url = malloc(strlen(repo->url) + strlen("/repo.ini") + 1); if (!repo_ini_url) { return MBPK_OUT_OF_MEMORY; } strcpy(repo_ini_url, repo->url); strcat(repo_ini_url, "/repo.ini"); printf("[libmbpk debug] URL: %s\n", repo_ini_url); printf("[libmbpk debug] repo url field: %s\n", repo->url); curl_easy_setopt(curl, CURLOPT_URL, repo_ini_url); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); /* follow redirects */ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_memory_write_calback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&chunk); result = curl_easy_perform(curl); curl_easy_cleanup(curl); free(repo_ini_url); if (result != CURLE_OK) { printf("[libmbpk debug] perform cURL failed\n"); free(chunk.memory); return MBPK_CURL_PERFORM_FAIL; } else { printf("[libmbpk debug] %lu bytes received\n", (unsigned long)chunk.size); printf("[libmbpk debug] Response:\n%s\n", chunk.memory); } } else { free(chunk.memory); return MBPK_CURL_INIT_FAIL; } dir_len = strlen(MBPK_REPO_DIR) + 1 + strlen(repo->name) + 1; repo_dir = malloc(dir_len); free(chunk.memory); } return MBPK_OK; } void mbpk_cleanup(void) { int i; for (i = 0; i < repo_count; i++) { if (repos[i]) { free((void*)repos[i]->name); free((void*)repos[i]->url); free((void*)repos[i]->desc); free((void*)repos[i]->packages); free((void*)repos[i]); repos[i] = NULL; } } repo_count = 0; curl_global_cleanup(); } const char* mbpk_strerr(int code) { const char* strerr; switch (code) { case MBPK_OK: strerr = "MBPK_OK (0)"; break; case MBPK_DB_FAIL: strerr = "MBPK_DB_FAIL (1)"; break; case MBPK_REPO_FAIL: strerr = "MBPK_REPO_FAIL (2)"; break; case MBPK_DL_FAIL: strerr = "MBPK_DL_FAIL (3)"; break; case MBPK_EXTRACT_FAIL: strerr = "MBPK_EXTRACT_FAIL (4)"; break; case MBPK_CURL_INIT_FAIL: strerr = "MBPK_CURL_INIT_FAIL (5)"; break; case MBPK_CURL_PERFORM_FAIL: strerr = "MBPK_CURL_PERFORM_FAIL (6)"; break; case MBPK_OUT_OF_MEMORY: strerr = "MBPK_OUT_OF_MEMORY (7)"; break; default: strerr = "MBPK_UNKNOWN_ERR"; break; } return strerr; }