diff --git a/Makefile b/Makefile index 4c33ebc..9d4ad8b 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,7 @@ include config.mk -COLOR_GREEN=\033[0;32m -COLOR_BLUE=\033[0;34m -COLOR_RESET=\033[0m - all: - @echo "Run 'make test' for the test binary, or 'make lib' to generate a static library." + @echo "No make option specified." @echo "Run 'make help' for a full list of options." help: @@ -26,15 +22,13 @@ lib: $(AR) -rc build/lib/libglacier.a build/lib/libglacier.o install: - @echo "$(COLOR_BLUE)[i]$(COLOR_RESET) Installing static library to $(PREFIX)/lib..." - install lib/libglacier.a $(PREFIX)/lib + install build/lib/libglacier.a $(PREFIX)/lib install include/config.h $(PREFIX)/include/glacier install include/data.h $(PREFIX)/include/glacier install include/log.h $(PREFIX)/include/glacier install include/pkgops.h $(PREFIX)/include/glacier install include/runtime.h $(PREFIX)/include/glacier install include/security.h $(PREFIX)/include/glacier - @echo "$(COLOR_GREEN)[*]$(COLOR_RESET) Finished installing static library to $(PREFIX)/lib." clean: rm -rf build diff --git a/VERSION b/VERSION index 08fd861..d8cfec1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.0.3-rc +0.1.0-rc diff --git a/settings.h b/settings.h new file mode 100644 index 0000000..5de7fab --- /dev/null +++ b/settings.h @@ -0,0 +1,27 @@ +/* + * config.h - Various compile-time settings for libglacier + * + * This file is part of Glacier. + * + * Glacier is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * Glacier is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Glacier. If + * not, see . + */ + +#ifndef CONFIG_H_ +#define CONFIG_H_ + +/* LG_VERBOSE - whether to use verbose logging for library events or not + * + * 0 is false, 1 is true + */ +#define LG_VERBOSE 0 + +#endif diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..2752e8a --- /dev/null +++ b/src/config.c @@ -0,0 +1,103 @@ +/* + * config.c - Configuration parsing functions + * + * This file is part of libglacier. + * + * Liblacier is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * Libglacier is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Libglacier. If + * not, see . + */ + +/* ALL FUNCTIONS IN THIS FILE DEFINED IN: config.h */ + +/* + * init_config + * + * DESCRIPTION: Initialize libconfig. + * PARAMETERS: None. + * + */ + +int +init_config(void) +{ + config_init(&cfg); + + if (! config_read_file(&cfg, runtime_files[0])) { + fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), + config_error_line(&cfg), config_error_text(&cfg)); + config_destroy(&cfg); + return(EXIT_FAILURE); + } + + if (LG_VERBOSE == 1) { + infolog("Initialized libconfig"); + } + + return 0; +} + +/* + * die_config + * + * DESCRIPTION: Kill libconfig. + * PARAMETERS: None. + * + */ + +int +die_config(void) +{ + config_destroy(&cfg); + + if (LG_VERBOSE == 1) { + infolog("Destroyed libconfig"); + } + + return(EXIT_SUCCESS); +} + +/* + * load_all_from_config + * + * DESCRIPTION: Loads all settings from the Glacier config file. + * PARAMETERS: None. + * + */ + +int +load_all_from_config(void) +{ + /* this is probably really ugly but it works */ + if (! config_lookup_bool(&cfg, "GLACIER_DO_INT_CHECK", &GLACIER_DO_INT_CHECK)) { return 1; } + if (! config_lookup_bool(&cfg, "GLACIER_VERBOSE", &GLACIER_VERBOSE)) { return 1; } + + return 0; +} + +/* + * load_all_from_profile + * + * DESCRIPTION: Loads all settings from the Glacier system profile. + * PARAMETERS: None. + * + */ + +int +load_all_from_profile(void) +{ + if (! config_lookup_string(&cfg, "GLACIER_REPO", &GLACIER_REPO)) { return 1; } + if (! config_lookup_string(&cfg, "GLACIER_ARCH", &GLACIER_ARCH)) { return 1; } + if (! config_lookup_string(&cfg, "GLACIER_TARGET", &GLACIER_TARGET)) { return 1; } + if (! config_lookup_string(&cfg, "GLACIER_SYSTEM_PROFILE", &GLACIER_SYSTEM_PROFILE)) { return 1; } + + return 0; +} + diff --git a/src/data.h b/src/data.h new file mode 100644 index 0000000..1a4e655 --- /dev/null +++ b/src/data.h @@ -0,0 +1,20 @@ +/* + * data.c - Data structure functions + * + * This file is part of libglacier. + * + * Liblacier is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * Libglacier is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Libglacier. If + * not, see . + */ + +/* ALL FUNCTIONS IN THIS FILE DEFINED IN: config.h */ + + diff --git a/src/libglacier.c b/src/libglacier.c new file mode 100644 index 0000000..1493f7d --- /dev/null +++ b/src/libglacier.c @@ -0,0 +1,680 @@ +/* + * libglacier.c - Backend C library for Glacier + * + * This file is part of Glacier. + * + * Glacier is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * Glacier is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Glacier. If + * not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "include/globals.h" + +#define BUFFER_SIZE 1024 +#define MAX_CHILDREN 64 +#define MAX_SIZE 256 + +/* + * Global Variables + * + * Descriptions are given as comments after the variable declaration. + * DEFINED IN: globals.h + * + */ + +config_t cfg; /* Context for libconfig */ +config_setting_t *setting; /* Pointer for setting */ +const char str; /* Unsure what this does, will possibly remove later */ + +int GLACIER_ALLOW_SERVICES; /* Declaration of GLACIER_ALLOW_SERVICES as given in glacier.cfg */ +char GLACIER_ALLOWED_LICENSES; /* Declaration of GLACIER_ALLOWED_LICENSES as given in glacier.cfg */ +int GLACIER_DO_INT_CHECK; /* Declaration of GLACIER_DO_INT_CHECK as given in glacier.cfg */ +int GLACIER_VERBOSE; /* Declaration of GLACIER_VERBOSE as given in glacier.cfg */ + +const char *GLACIER_REPO; /* Declaration of GLACIER_REPO as defined in profile.cfg */ +const char *GLACIER_ARCH; /* Declaration of GLACIER_ARCH as defined in profile.cfg */ +const char *GLACIER_TARGET; /* Declaration of GLACIER_TARGET as defined in profile.cfg */ +const char *GLACIER_LOCALDB; /* Declaration of GLACIER_LOCALDB as defined in profile.cfg */ +const char *GLACIER_SYSTEM_PROFILE; /* Declaration of GLACIER_SYSTEM_PROFILE as defined in profile.cfg */ + +/* Required runtime files */ +const char *runtime_files[] = { + "/etc/glacier.cfg", + "/etc/glacier/call-hooks", + "/etc/make.conf" + }; + +FILE *expected_hash; /* File pointer for expected hash */ +FILE *pkg; /* File pointer for package hash */ + +/* + * END GLOBAL VARIABLES + */ + +/* + * node + * + * DESCRIPTION: Definition of node type. + * DEFINED IN: data.h + * + */ + +struct node { + char *data; + struct node *children[MAX_CHILDREN]; + int numChildren; +}; + +/* + * infolog + * + * DESCRIPTION: Output a stylized info message. + * PARAMETERS: char MSG[] + * DEFINED IN: log.h + * + */ + +void +infolog(char MSG[]) +{ + if (MSG == NULL) { + return; + } + + printf(COL_BLUE "[i]" COL_RESET " %s\n", MSG); + return; +} + +/* + * warnlog + * + * DESCRIPTION: Output a stylized warning message. + * Parameters: char MSG[] + * DEFINED IN: log.h + * + */ + +void +warnlog(char MSG[]) +{ + if (MSG == NULL) { + return; + } + + printf(COL_YELLOW "[!]" COL_RESET " %s\n", MSG); + return; +} + +/* + * errlog + * + * DESCRIPTION: Output a stylized error message. + * PARAMETERS: char MSG[] + * DEFINED IN: log.h + * + */ + +void +errlog(char MSG[]) +{ + if (MSG == NULL) { + return; + } + + fprintf(stderr, COL_RED "[x]" COL_RESET " %s\n", MSG); + return; +} + +/* + * successlog + * + * DESCRIPTION: Output a stylized success message. + * PARAMETERS: char MSG[] + * DEFINED IN: log.h + * + */ + +void +successlog(char MSG[]) +{ + if (MSG == NULL) { + return; + } + + printf(COL_GREEN "[*]" COL_RESET " %s\n", MSG); + return; +} + +/* + * runtime_exists + * + * DESCRIPTION: Check if necesary runtime files exist. + * PARAMETERS: None. + * DEFINED IN: runtime.h + * + */ + +int +runtime_exists(void) +{ + int f; + + for (f = 0; f < sizeof(runtime_files); f++) { + if (access(runtime_files[f], F_OK) == 0) { + continue; + } else { + /* might keep this message, might not, idk */ + /* errlog("Runtime files are missing, cannot continue with operation."); + printf(COL_RED "[x]" COL_RESET " The following files are missing:\n"); + printf(COL_RED "[x]" COL_RESET " \t%s\n", runtime_files[f]); */ + return 0; + } + } + return 1; +} + +/* + * is_process_root + * + * DESCRIPTION: Check if process is running as root. + * PARAMETERS: char MSG[] + * DEFINED IN: runtime.h + * + */ + +int +is_process_root(void) +{ + if (getuid() != 0) { + return 0; /* process is not running as root */ + } + else { + return 1; /* process is running as root */ + } +} + +/* + * init_config + * + * DESCRIPTION: Initialize libconfig. + * PARAMETERS: None. + * DEFINED IN: config.h + * + */ + +int +init_config(void) +{ + config_init(&cfg); + + if (! config_read_file(&cfg, runtime_files[0])) { + fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), + config_error_line(&cfg), config_error_text(&cfg)); + config_destroy(&cfg); + return(EXIT_FAILURE); + } + + if (LG_VERBOSE == 1) { + infolog("Initialized libconfig"); + } + + return 0; +} + +/* + * die_config + * + * DESCRIPTION: Kill libconfig. + * PARAMETERS: None. + * DEFINED IN: config.h + * + */ + +int +die_config(void) +{ + config_destroy(&cfg); + + if (LG_VERBOSE == 1) { + infolog("Destroyed libconfig"); + } + + return(EXIT_SUCCESS); +} + +/* + * load_all_from_config + * + * DESCRIPTION: Loads all settings from the Glacier config file. + * PARAMETERS: None. + * DEFINED IN: config.h + * + */ + +int +load_all_from_config(void) +{ + /* this is probably really ugly but it works */ + if (! config_lookup_bool(&cfg, "GLACIER_DO_INT_CHECK", &GLACIER_DO_INT_CHECK)) { return 1; } + if (! config_lookup_bool(&cfg, "GLACIER_VERBOSE", &GLACIER_VERBOSE)) { return 1; } + + return 0; +} + +/* + * load_all_from_profile + * + * DESCRIPTION: Loads all settings from the Glacier system profile. + * PARAMETERS: None. + * DEFINED IN: config.h + * + */ + +int +load_all_from_profile(void) +{ + if (! config_lookup_string(&cfg, "GLACIER_REPO", &GLACIER_REPO)) { return 1; } + if (! config_lookup_string(&cfg, "GLACIER_ARCH", &GLACIER_ARCH)) { return 1; } + if (! config_lookup_string(&cfg, "GLACIER_TARGET", &GLACIER_TARGET)) { return 1; } + if (! config_lookup_string(&cfg, "GLACIER_SYSTEM_PROFILE", &GLACIER_SYSTEM_PROFILE)) { return 1; } + + return 0; +} + +/* + * load_setting_from_config + * + * DESCRIPTION: Load a specified setting from the Glacier config file. + * PARAMETERS: char SETTING[] + * DEFINED IN: config.h + * + */ + +/* int +load_setting_from_config(char SETTING[]) +{} */ + +/* +* create_node +* +* DESCRIPTION: Create a dependency tree node. +* PARAMETERS: char *data +* DEFINED IN: data.h +* +*/ + +struct node +*create_node(char *data) +{ + struct node *newNode = (struct node*)malloc(sizeof(struct node)); + newNode->data = strdup(data); + newNode->numChildren = 0; + return newNode; +} + +/* + * add_child + * + * DESCRIPTION: Add a child node to a parent node. + * PARAMETERS: struct node *parent, struct node *child + * DEFINED IN: data.h + * + */ + +void +add_child(struct node *parent, struct node *child) +{ + if (parent->numChildren < MAX_CHILDREN) { + parent->children[parent->numChildren++] = child; + } else { + if (LG_VERBOSE == 1) { errlog("Maximum number of children exceeded"); } + exit(1); + } +} + +/* +* print_tree +* +* DESCRIPTION: Print a dependency tree. +* PARAMETERS: struct node *root, int level +* DEFINED IN: data.h +* +*/ + +void +print_tree(struct node *root, int level) +{ + if (root == NULL) { + return; + } + + for (int i = 0; i < level; i++) { + printf(" "); + } + + printf("%s\n", root->data); + + for (int i = 0; i < root->numChildren; i++) { + print_tree(root->children[i], level + 1); + } +} + +/* + * queue + * + * DESCRIPTION: Definition of queue type. + * DEFINED IN: data.h + * + */ + +typedef struct { + int items[MAX_SIZE]; + int front; + int rear; +} queue; + +/* +* init_queue +* +* DESCRIPTION: Initialize a queue. +* PARAMETERS: queue *q +* DEFINED IN: data.h +* +*/ + +void +init_queue(queue *q) +{ + q -> front = -1; + q -> rear = 0; +} + +/* +* queue_is_empty +* +* DESCRIPTION: Check if queue is empty. +* PARAMETERS: struct node *root, int level +* DEFINED IN: data.h +* +*/ + +bool queue_is_empty(queue *q) { return (q -> front == q -> rear -1); } + +/* +* queue_is_full +* +* DESCRIPTION: Check if queue is full. +* PARAMETERS: queue *q +* DEFINED IN: data.h +* +*/ + +bool queue_is_full(queue *q) { return (q -> rear == MAX_SIZE); } + +/* +* enqueue +* +* DESCRIPTION: Enqueue an element at the back of the queue. +* PARAMETERS: queue *q, int value +* DEFINED IN: data.h +* +*/ + +void +enqueue (queue *q, int value) +{ + if (queue_is_full(q)) { + printf("Queue is full\n"); + return; + } + + q -> items[q -> rear] = value; + q -> rear++; +} + +/* +* dequeue +* +* DESCRIPTION: Dequeue the element at the front of the queue. +* PARAMETERS: queue *q, int value +* DEFINED IN: data.h +* +*/ + +void +dequeue(queue *q) +{ + if (queue_is_empty(q)) { + printf("Queue is empty\n"); + return; + } + + q -> front++; +} + +/* +* peek +* +* DESCRIPTION: View the element at the front of the queue. +* PARAMETERS: struct node *root, int level +* DEFINED IN: data.h +* +*/ + +int +peek(queue *q) +{ + if (queue_is_empty(q)) { + printf("Queue is empty\n"); + return -1; + } + + return q -> items[q -> front + 1]; +} + +/* +* print_queue +* +* DESCRIPTION: Print the queue. +* PARAMETERS: queue *q +* DEFINED IN: data.h +* +*/ + +void +print_queue(queue *q) +{ + if (queue_is_empty(q)) { + printf("Queue is empty\n"); + return; + } + + printf("Current Queue: "); + + for (int i = q -> front + 1; i < q -> rear; i++) { + printf("%d ", q -> items[i]); + } + printf("\n"); +} + +/* + * mkworkspace + * + * DESCRIPTION: Creates a new Glacier workspace in /tmp. + * PARAMETERS: None. + * DEFINED IN: pkgops.h + * + */ + +int +mkworkspace(void) +{ + DIR* workspace = opendir("/tmp/glacier-workspace"); + if (workspace) { + /* infolog("Not creating new workspace, valid workspace already exists."); */ + return 0; + } else if (ENOENT == errno) { + /* infolog("Creating new Glacier workspace..."); */ + mkdir("/tmp/glacier-workspace", 0777); + return 1; + } else { + if (LG_VERBOSE == 1) { + errlog("in mkworkspace()"); + errlog("mkdir() failed to run"); + } + return -1; + } +} + +/* + * prepare_pkg + * + * DESCRIPTION: Copies a package archive from the localdb to the workspace, and unpacks it. + * PARAMETERS: char PACKAGE[] + * DEFINED IN: pkgops.h + * + */ + +int +prepare_pkg(char PACKAGE[]) +{ + if (PACKAGE == NULL) { + printf(COL_RED "[x] " COL_RESET "Package '%s' does not exist in the local database.\n", PACKAGE); + errlog("Ensure your local database is up to date and try again."); + errlog("This can be done by running 'glacier-update-pkgdb' as root."); + return 1; + } else { + char PKG_NEW[512]; + strcat(PKG_NEW, "/tmp/glacier-workspace/"); + strcat(PKG_NEW, PACKAGE); + strcat(PKG_NEW, ".tar"); + FILE *pkg_old, *pkg_new; + char filename[100], contents; + + pkg_old = fopen(PACKAGE, "r"); + pkg_new = fopen(PKG_NEW, "a+"); + + contents = fgetc(pkg_old); + + while (contents != EOF) { + fputc(contents, pkg_new); + contents = fgetc(pkg_old); + } + + fclose(pkg_old); + fclose(pkg_new); + char *tar_args[] = { + "/bin/tar", /* This should be changed to /glacier/bin/tar later on */ + "-xvf", + PKG_NEW, + NULL, + }; + + execvp( + "/bin/tar", /* Above comment applies here */ + tar_args + ); + if (errno != 0) { + printf(COL_RED "[x] " COL_RESET "Error while unpacking archive for package %s.\n", PACKAGE); + return errno; + } + remove(PKG_NEW); + char pkg_dir[512]; + strcat(pkg_dir, "/tmp/glacier-workspace/"); + strcat(pkg_dir, PACKAGE); + chdir(pkg_dir); + } +} + +/* + * run_make_task + * + * DESCRIPTION: Runs a make task in current working directory + * PARAMETERS: char TASK[] + * DEFINED IN: pkgops.h + * + */ + +int +run_make_task(char TASK[]) +{ + char *build_args[] = { + "/bin/make", /* This should be changed to /glacier/bin/make later on */ + TASK, + NULL + }; + + execvp( + "/bin/make", /* Above comment applies here */ + build_args + ); + if (errno != 0) { + errlog("An error occurred while running the make task."); + return errno; + } +} + +/* + * compare_file_hash + * + * DESCRIPTION: Compare two file hashes + * PARAMETERS: char ORIG_HASH[], char FILE[] + * DEFINED IN: security.h + * + */ + +/* +int +compare_file_hash(char ORIG_HASH[], char FILE[]) +{ + FILE *pkg; + + pkg = fopen(FILE, "rb"); + if (pkg == NULL) { + return -1; + } + + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256_CTX sha256; + + SHA256_Init(&sha256); + + const int hashBufferSize = 1024; + unsigned char hashBuffer[hashBufferSize]; + int bytesRead; + + while ((byesRead = fread(hashBuffer, 1, hashBufferSize, pkg)) != 0) { + SHA256_Update(&sha256, hashBuffer, bytesRead); + } + + SHA256_Final(hash, &sha256); + fclose(pkg); + + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + printf("%02x", hash[i]); + } +} +*/