diff --git a/build/lib/libglacier.a b/build/lib/libglacier.a
new file mode 100644
index 0000000..9c764dc
Binary files /dev/null and b/build/lib/libglacier.a differ
diff --git a/build/lib/libglacier.o b/build/lib/libglacier.o
new file mode 100644
index 0000000..4bfb5cf
Binary files /dev/null and b/build/lib/libglacier.o differ
diff --git a/include/config.h b/include/config.h
index 0f0b006..d1348a6 100644
--- a/include/config.h
+++ b/include/config.h
@@ -26,67 +26,48 @@
#endif
/*
- * init_config
+ * gl_init_config
*
- * DESCRIPTION: Initialize libconfig with required configs
- * PARAMETERS:
- * None.
- * RETURN VALUES:
- * 0 on success, 1 on failure
- * CAVEATS:
- * This MUST be called before ANY other config function is.
- * EXAMPLE:
- * init_config();
+ * DESCRIPTION: Initialize libconfig.
+ * PARAMETERS: None.
+ * RETURNS: 0 on success, EXIT_FAILURE on error
*/
-
-int init_config(void);
+int gl_init_config(void);
/*
- * die_config
+ * gl_die_config
*
- * DESCRIPTION: Die_config brings down libconfig gracefully.
- * PARAMETERS:
- * None.
- * RETURN VALUES:
- * 0 on success, 1 on failure
- * CAVEATS:
- * This MUST be called after ALL other config functions have completed.
- * EXAMPLE:
- * die_config();
+ * DESCRIPTION: Kill libconfig.
+ * PARAMETERS: None.
+ * RETURNS: EXIT_SUCCESS on success
*/
-
-int die_config(void);
+int gl_die_config(void);
/*
- * load_all_from_config
+ * gl_load_all_from_config
*
- * DESCRIPTION: load_all_from_config loads all settings from the config file.
- * PARAMETERS:
- * None.
- * RETURN VALUES:
- * 0 on success, 1 on failure
- * CAVEATS:
- * None.
- * EXAMPLE:
- * load_all_from_config();
+ * DESCRIPTION: Loads all settings from the Glacier config file.
+ * PARAMETERS: None.
+ * RETURNS: 0 on success, 1 on error
*/
-
-int load_all_from_config(void);
+int gl_load_all_from_config(void);
/*
- * load_all_from_profile
+ * gl_load_all_from_profile
*
- * DESCRIPTION: load_all_from_profile loads all settings from the profile file.
- * PARAMETERS:
- * None.
- * RETURN VALUES:
- * 0 on success, 1 on failure
- * CAVEATS:
- * None.
- * EXAMPLE:
- * load_all_from_profile();
+ * DESCRIPTION: Loads all settings from the Glacier system profile.
+ * PARAMETERS: None.
+ * RETURNS: 0 on success, 1 on error
*/
+int gl_load_all_from_profile(void);
-int load_all_from_profile(void);
+/*
+ * gl_load_setting_from_config
+ *
+ * DESCRIPTION: Load a specified setting from the Glacier config file.
+ * PARAMETERS: char SETTING[]
+ * RETURNS: 0 on success, 1 on error
+ */
+int gl_load_setting_from_config(char SETTING[]);
#endif
diff --git a/include/data.h b/include/data.h
index 6b3f7e4..c3bbc75 100644
--- a/include/data.h
+++ b/include/data.h
@@ -36,69 +36,39 @@ struct node {
};
/*
- * create_node
+ * gl_create_node
*
- * DESCRIPTION: Create_node creates a node for a dependency tree data structure.
- * PARAMETERS:
- * char *data -> The name of the node to create
- * RETURN VALUES:
- * A pointer to the created node on success, NULL on failure
- * CAVEATS:
- * Caller must free the node using free_node when done
- * EXAMPLE:
- * struct node *package = create_node("Package");
+ * DESCRIPTION: Create a dependency tree node.
+ * PARAMETERS: char *data
+ * RETURNS: struct node* on success, NULL on failure
*/
-
-struct node *create_node(char *data);
+struct node *gl_create_node(char *data);
/*
- * free_node
+ * gl_free_node
*
- * DESCRIPTION: Free_node recursively frees all memory allocated for a node and its children.
- * PARAMETERS:
- * struct node *root -> The root node to free
- * RETURN VALUES:
- * None.
- * CAVEATS:
- * Will free all child nodes recursively.
- * EXAMPLE:
- * free_node(package);
+ * DESCRIPTION: Recursively free a node and all its children.
+ * PARAMETERS: struct node *root
+ * RETURNS: void
*/
-
-void free_node(struct node *root);
+void gl_free_node(struct node *root);
/*
- * add_child
+ * gl_add_child
*
- * DESCRIPTION: Add_child adds a child node to a parent node.
- * PARAMETERS:
- * struct node *parent -> The parent node which the child will be added to
- * struct node *child -> The child node which will be added to the parent node
- * RETURN VALUES:
- * 0 on success, 1-3 for different error conditions
- * CAVEATS:
- * None.
- * EXAMPLE:
- * add_child(package, dep1);
+ * DESCRIPTION: Add a child node to a parent node.
+ * PARAMETERS: struct node *parent, struct node *child
+ * RETURNS: 0 on success, 1 on NULL pointer, 2 on invalid numChildren, 3 on max children exceeded
*/
-
-int add_child(struct node *parent, struct node *child);
+int gl_add_child(struct node *parent, struct node *child);
/*
- * print_tree
+ * gl_print_tree
*
- * DESCRIPTION: Print_tree prints a dependency tree specified at its root node.
- * PARAMETERS:
- * struct node *root -> The tree to print
- * int level -> The number of levels to descend
- * RETURN VALUES:
- * 0 on success, non-zero on error
- * CAVEATS:
- * None.
- * EXAMPLE:
- * print_tree(package, 0);
+ * DESCRIPTION: Print a dependency tree.
+ * PARAMETERS: struct node *root, int level
+ * RETURNS: 0 on success, 1 on invalid level, 2 on max recursion depth exceeded, 3 on invalid numChildren, 4 on child print error
*/
-
-int print_tree(struct node *root, int level);
+int gl_print_tree(struct node *root, int level);
#endif
diff --git a/include/log.h b/include/log.h
index 2e3e36e..b1b32c8 100644
--- a/include/log.h
+++ b/include/log.h
@@ -19,81 +19,73 @@
#define GLACIERLOG_H_
/*
- * infolog
+ * gl_infolog
*
- * DESCRIPTION: Infolog outputs a stylized info message. It follows Glacier's uniform CLI style.
+ * DESCRIPTION: gl_infolog outputs a stylized info message. It follows Glacier's uniform CLI style.
* PARAMETERS:
* char MSG[] -> The message to output
* RETURN VALUES:
* None.
* CAVEATS:
- * * Cannot output variables. If you must output variables, use printf instead.
- * * A NEWLINE ('\n') character is implied, therefore putting one at the end of
- * a string is not needed.
+ * None.
* EXAMPLE:
- * infolog("This is an info message.");
+ * gl_infolog("This is an info message.");
*/
-void infolog(char MSG[]);
+void gl_infolog(char MSG[]);
/**************************************************************************************************************/
/*
- * warnlog
+ * gl_warnlog
*
- * DESCRIPTION: Warnlog outputs a stylized warning message. It follows Glacier's uniform CLI style.
+ * DESCRIPTION: gl_warnlog outputs a stylized warning message. It follows Glacier's uniform CLI style.
* PARAMETERS:
* char MSG[] -> The message to output
* RETURN VALUES:
* None.
* CAVEATS:
- * * Cannot output variables. If you must output variables, use printf instead.
- * * A NEWLINE ('\n') character is implied, therefore putting one at the end of
- * a string is not needed.
+ * None.
* EXAMPLE:
- * warnlog("This is a warning message.");
+ * gl_warnlog("This is a warning message.");
*/
-void warnlog(char MSG[]);
+void gl_warnlog(char MSG[]);
/**************************************************************************************************************/
/*
- * errlog
+ * gl_errlog
*
- * DESCRIPTION: Errlog outputs a stylized error message. It follows Glacier's uniform CLI style.
+ * DESCRIPTION: gl_errlog outputs a stylized error message. It follows Glacier's uniform CLI style.
* PARAMETERS:
* char MSG[] -> The message to output
* RETURN VALUES:
* None.
* CAVEATS:
- * * Cannot output variables. If you must output variables, use printf instead.
- * * A NEWLINE ('\n') character is implied, therefore putting one at the end of
- * a string is not needed.
+ * None.
* EXAMPLE:
- * errlog("This is an error message.");
+ * gl_errlog("This is an error message.");
*/
-void errlog(char MSG[]);
+void gl_errlog(char MSG[]);
/**************************************************************************************************************/
/*
- * successlog
+ * gl_successlog
*
- * DESCRIPTION: Successlog outputs a stylized success message. It follows Glacier's uniform CLI style.
+ * DESCRIPTION: gl_successlog outputs a stylized success message. It follows Glacier's uniform CLI style.
* PARAMETERS:
* char MSG[] -> The message to output
* RETURN VALUES:
* None.
* CAVEATS:
- * * Cannot output variables. If you must output variables, use printf instead.
- * * A NEWLINE ('\n') character is implied, therefore putting one at the end of
- * a string is not needed.
+ * None.
* EXAMPLE:
- * successlog("This is a success message.");
+ * gl_successlog("This is a success message.");
*/
-void successlog(char MSG[]);
+void gl_successlog(char MSG[]);
#endif
diff --git a/include/pkgops.h b/include/pkgops.h
index 65dae07..0f8011c 100644
--- a/include/pkgops.h
+++ b/include/pkgops.h
@@ -25,54 +25,77 @@
#define PATH_MAX_SIZE 512
/*
- * mkworkspace
+ * gl_mkworkspace
+ *
+ * DESCRIPTION: gl_mkworkspace prepares /tmp/glacier-workspace for an operation
*
- * DESCRIPTION: Mkworkspace prepares /tmp/glacier-workspace for an operation
- * PARAMETERS:
- * None.
- * RETURN VAUES:
- * 0 on workspace already exists, 1 on workspace created, -1 on error
- * CAVEATS:
- * None.
* EXAMPLE:
- * mkworkspace();
+ * gl_mkworkspace();
+ *
+ * RETURNS: 0 on success, 1 if workspace already exists, -1 on failure
*/
-
-int mkworkspace(void);
+int gl_mkworkspace(void);
/*
- * prepare_pkg
+ * gl_prepare_pkg
+ *
+ * DESCRIPTION: gl_prepare_pkg copies a package archive from the localdb, and untars it
*
- * DESCRIPTION: Prepare_pkg copies a package archive from the localdb, and untars it
- * PARAMETERS:
- * char PACKAGE[] -> The package file to prepare
- * RETURN VAUES:
- * 0 on success, 1 on package does not exist or error, other values for specific errors
- * CAVEATS:
- * The example presented is bad. You should be calling the system profile variable
- * rather than manually specifying one.
* EXAMPLE:
- * prepare_pkg("/glacier/localdb/epkgs-x86_64-musl/foo.tar");
+ * gl_prepare_pkg("/glacier/localdb/epkgs-x86_64-musl/foo.tar");
+ *
+ * RETURNS: 0 on success, 1 on failure
*/
-
-int prepare_pkg(char PACKAGE[]);
+int gl_prepare_pkg(char PACKAGE[]);
/*
- * run_make_task
+ * gl_run_make_task
+ *
+ * DESCRIPTION: gl_run_make_task runs a specified make task in a package's current working directory
*
- * DESCRIPTION: Run_make_task runs a specified make task in a package's current working directory
- * PARAMETERS:
- * char TASK[] -> The make task to run
- * RETURN VAUES:
- * 0 on success, other values for specific errors
- * CAVEATS:
- * MUST be run after prepare_pkg(), or else errors will occur
- * Same caveat as above. Do not manually specify the system profile, use its variable.
* EXAMPLE:
- * prepare_pkg("/glacier/localdb/epkgs-x86_64-musl/foo.tar");
- * run_make_task("installpkg");
+ * MUST be run after gl_prepare_pkg(), or else errors will occur
+ * gl_prepare_pkg("/glacier/localdb/epkgs-x86_64-musl/foo.tar");
+ * gl_run_make_task("installpkg");
+ *
+ * RETURNS: 0 on success, 1 on failure
+ */
+int gl_run_make_task(char TASK[]);
+
+/*
+ * gl_lock_file
+ *
+ * DESCRIPTION: Locks a specified file using fcntl
+ * PARAMETERS:
+ * const char *filepath -> The path to the file to lock
+ * RETURN VALUES:
+ * File descriptor on success, -1 on failure
+ * CAVEATS:
+ * The returned file descriptor must be passed to gl_unlock_file() to release the lock
+ * EXAMPLE:
+ * int fd = gl_lock_file("/path/to/file");
+ * if (fd >= 0) {
+ * // Do work with locked file
+ * gl_unlock_file(fd);
+ * }
*/
-int run_make_task(char TASK[]);
+int gl_lock_file(const char *filepath);
+
+/*
+ * gl_unlock_file
+ *
+ * DESCRIPTION: Unlocks a specified file using fcntl
+ * PARAMETERS:
+ * int file_descriptor -> The file descriptor returned by gl_lock_file()
+ * RETURN VALUES:
+ * 0 on success, 1 on failure
+ * CAVEATS:
+ * Only the process that acquired the lock can release it
+ * EXAMPLE:
+ * gl_unlock_file(file_descriptor);
+ */
+
+int gl_unlock_file(int file_descriptor);
#endif
diff --git a/include/runtime.h b/include/runtime.h
index b537e80..27eeecb 100644
--- a/include/runtime.h
+++ b/include/runtime.h
@@ -19,68 +19,48 @@
#define GLACIERRUNTIME_H_
/*
- * runtime_exists
+ * gl_runtime_exists
*
- * DESCRIPTION: runtime_exists checks if all necessary runtime files exist.
- * PARAMETERS:
- * None. (void)
- * RETURN VALUES:
- * 0 on one or more runtime files missing, 1 on all runtime files exist
- * CAVEATS:
- * None.
- * EXAMPLE:
- * if (runtime_exists() == 0) {
- * errlog("One or more runtime files missing");
- * return 1;
- * }
- * else {
- * successlog("All runtime files present");
- * return 0;
- * }
+ * DESCRIPTION: Check if necessary runtime files exist.
+ * PARAMETERS: None.
+ * RETURNS: 1 if all files exist, 0 if any file is missing
*/
-
-int runtime_exists(void);
+int gl_runtime_exists(void);
/*
- * is_process_root
+ * gl_is_process_root
*
- * DESCRIPTION: is_process_root checks if the process is running with root privileges.
- * PARAMETERS:
- * None. (void)
- * RETURN VALUES:
- * 0 on process is not running as root, 1 on process is running as root
- * CAVEATS:
- * None.
- * EXAMPLE:
- * // Assuming block is running within main(), no values will be returned.
- * // If you wish to exit the program if it is not running as root, it would
- * // be appropriate to add return values to this block
- *
- * if (is_process_root() == 0) {
- * errlog("Process is not running as root");
- * }
- * else {
- * successlog("Process is running as root");
- * }
+ * DESCRIPTION: Check if process is running as root.
+ * PARAMETERS: None.
+ * RETURNS: 1 if running as root, 0 otherwise
*/
-
-int is_process_root(void);
+int gl_is_process_root(void);
/*
- * get_system_profile
+ * gl_get_system_profile
*
- * DESCRIPTION: get_system_profile fetches the system profile, which contains information about the architecture and libc implementation.
- * PARAMETERS:
- * None. (void)
- * RETURN VALUES:
- * A pointer to a string containing the system profile (e.g., "x86_64-musl").
- * CAVEATS:
- * None.
- * EXAMPLE:
- * char *profile = get_system_profile();
- * infolog(profile);
+ * DESCRIPTION: Get the current system profile.
+ * PARAMETERS: None.
+ * RETURNS: char* containing the system profile name
*/
+char *gl_get_system_profile(void);
-char *get_system_profile(void);
+/*
+ * gl_lock_file
+ *
+ * DESCRIPTION: Locks a specified file using fcntl.
+ * PARAMETERS: const char *filepath - Path to the file to lock
+ * RETURNS: file descriptor on success, -1 on failure
+ */
+int gl_lock_file(const char *filepath);
+
+/*
+ * gl_unlock_file
+ *
+ * DESCRIPTION: Unlocks a specified file using fcntl.
+ * PARAMETERS: int file_descriptor - The file descriptor of the locked file
+ * RETURNS: 0 on success, -1 on failure
+ */
+int gl_unlock_file(int file_descriptor);
#endif
diff --git a/include/security.h b/include/security.h
index 680abf5..2889976 100644
--- a/include/security.h
+++ b/include/security.h
@@ -39,101 +39,48 @@ typedef unsigned char uchar;
/* int compare_file_hash(char ORIG_HASH[], char FILE[]); */
/*
- * hash_file
+ * gl_print_hash
+ *
+ * DESCRIPTION: Prints a specified hash string
+ * PARAMETERS: unsigned char *hash, unsigned int length
+ * RETURNS: 0 on success, 1 on error
+ */
+int gl_print_hash(uchar *hash, uint length);
+
+/*
+ * gl_stash_hash
+ *
+ * DESCRIPTION: Stores a hash inside a string
+ * PARAMETERS: unsigned char *stored_hash, unsigned char *hash, unsigned int length
+ * RETURNS: 0 on success, 1 on error
+ */
+int gl_stash_hash(char *stored_hash, unsigned int stored_hash_size, const uchar *hash, uint length);
+
+/*
+ * gl_hash_file
*
* DESCRIPTION: Performs a hashing operation on a file and stores the result
- * PARAMETERS:
- * const char *filename -> The file to hash
- * unsigned char *out_hash -> Buffer to store the resulting hash
- * unsigned int *out_length -> Will contain the length of the hash
- * RETURN VALUES:
- * 0 on success, other values for specific errors
- * CAVEATS:
- * out_hash buffer must be large enough to hold the hash (EVP_MAX_MD_SIZE recommended)
- * EXAMPLE:
- * unsigned char hash[EVP_MAX_MD_SIZE];
- * unsigned int hash_len;
- * hash_file("file.txt", hash, &hash_len);
+ * PARAMETERS: const char *filename, unsigned char *out_hash, unsigned int *out_length
+ * RETURNS: 0 on success, 1-6 for different error conditions
*/
-
-int hash_file(const char *filename, unsigned char *out_hash, unsigned int *out_length);
+int gl_hash_file(const char *filename, unsigned char *out_hash, unsigned int *out_length);
/*
- * print_hash
+ * gl_verify_signature
*
- * DESCRIPTION: Prints a specified hash string to stdout
- * PARAMETERS:
- * unsigned char *hash -> The hash to print
- * unsigned int length -> Length of the hash
- * RETURN VALUES:
- * 0 on success, 1 on error
- * CAVEATS:
- * None
- * EXAMPLE:
- * print_hash(hash, hash_len);
+ * DESCRIPTION: Verify a package signature against a trusted keyring
+ * PARAMETERS: char PACKAGE[], char SIGNATURE[]
+ * RETURNS: 0 on success, 1 on verification failure, 2 on file not found
*/
-
-int print_hash(uchar *hash, uint length);
+int gl_verify_signature(char PACKAGE[], char SIGNATURE[]);
/*
- * stash_hash
+ * gl_check_integrity
*
- * DESCRIPTION: Stores a hash inside a string as hexadecimal representation
- * PARAMETERS:
- * char *stored_hash -> Buffer to store the resulting hash string
- * unsigned int stored_hash_size -> Size of the stored_hash buffer
- * const uchar *hash -> The hash to convert to string
- * uint length -> Length of the hash
- * RETURN VALUES:
- * 0 on success, 1 on error
- * CAVEATS:
- * stored_hash buffer must be at least (length*2)+1 bytes in size
- * EXAMPLE:
- * char hash_str[65]; // 32 bytes SHA-256 = 64 hex chars + null terminator
- * stash_hash(hash_str, sizeof(hash_str), hash, hash_len);
+ * DESCRIPTION: Check package integrity by comparing with expected hash
+ * PARAMETERS: char PACKAGE[], char EXPECTED_HASH[]
+ * RETURNS: 0 on success, 1 on hash mismatch, 2 on file not found or error
*/
-
-int stash_hash(char *stored_hash, unsigned int stored_hash_size, const uchar *hash, uint length);
-
-/*
- * verify_signature
- *
- * DESCRIPTION: Checks if a package's signature is valid against the trusted keyring
- * PARAMETERS:
- * char PACKAGE[] -> The package file to verify
- * char SIGNATURE[] -> The signature file to check against
- * RETURN VALUES:
- * 0 on valid signature, 1 on invalid signature, 2 on file not found
- * CAVEATS:
- * None
- * EXAMPLE:
- * if (verify_signature("package.tar", "package.tar.sig") != 0) {
- * errlog("invalid package signature");
- * return(EXIT_FAILURE);
- * }
- */
-
-int verify_signature(char PACKAGE[], char SIGNATURE[]);
-
-/*
- * check_integrity
- *
- * DESCRIPTION: Verifies a package's SHA256 checksum against the expected value
- * PARAMETERS:
- * char PACKAGE[] -> The package file to check
- * char EXPECTED_HASH[] -> The expected SHA256 hash
- * RETURN VALUES:
- * 0 on hash match, 1 on hash mismatch, 2 on file not found or hash calculation error
- * CAVEATS:
- * None
- * EXAMPLE:
- * char *expected = "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592";
- * if (check_integrity("package.tar", expected) != 0) {
- * errlog("package integrity check failed");
- * return(EXIT_FAILURE);
- * }
- */
-
-int check_integrity(char PACKAGE[], char EXPECTED_HASH[]);
+int gl_check_integrity(char PACKAGE[], char EXPECTED_HASH[]);
#endif
diff --git a/src/libglacier.c b/src/libglacier.c
index f5a49f7..3f3aa3d 100644
--- a/src/libglacier.c
+++ b/src/libglacier.c
@@ -15,16 +15,21 @@
* not, see .
*/
+#define _POSIX_C_SOURCE 200809L
+
#include
#include
#include
+#include
#include
#include
#include
+#include
#include
#include
#include
#include
+#include /* For strcasecmp */
#include
#include
#include
@@ -60,7 +65,7 @@ typedef unsigned char uchar;
config_t cfg; /* Context for libconfig */
config_setting_t *setting = NULL; /* Pointer for setting */
-/* Configuration variables with default values */
+/* Con:figuration variables with default values */
int GLACIER_ALLOW_SERVICES = 0; /* Declaration of GLACIER_ALLOW_SERVICES as given in glacier.cfg */
char *GLACIER_ALLOWED_LICENSES = NULL; /* Declaration of GLACIER_ALLOWED_LICENSES as given in glacier.cfg */
int GLACIER_DO_INT_CHECK = 1; /* Declaration of GLACIER_DO_INT_CHECK as given in glacier.cfg */
@@ -104,7 +109,7 @@ struct node {
};
/*
- * infolog
+ * gl_infolog
*
* DESCRIPTION: Output a stylized info message.
* PARAMETERS: char MSG[]
@@ -113,7 +118,7 @@ struct node {
*/
void
-infolog(char MSG[])
+gl_infolog(char MSG[])
{
if (MSG == NULL) {
return;
@@ -124,7 +129,7 @@ infolog(char MSG[])
}
/*
- * warnlog
+ * gl_warnlog
*
* DESCRIPTION: Output a stylized warning message.
* Parameters: char MSG[]
@@ -133,7 +138,7 @@ infolog(char MSG[])
*/
void
-warnlog(char MSG[])
+gl_warnlog(char MSG[])
{
if (MSG == NULL) {
return;
@@ -144,7 +149,7 @@ warnlog(char MSG[])
}
/*
- * errlog
+ * gl_errlog
*
* DESCRIPTION: Output a stylized error message.
* PARAMETERS: char MSG[]
@@ -153,7 +158,7 @@ warnlog(char MSG[])
*/
void
-errlog(char MSG[])
+gl_errlog(char MSG[])
{
if (MSG == NULL) {
return;
@@ -164,7 +169,7 @@ errlog(char MSG[])
}
/*
- * successlog
+ * gl_successlog
*
* DESCRIPTION: Output a stylized success message.
* PARAMETERS: char MSG[]
@@ -173,7 +178,7 @@ errlog(char MSG[])
*/
void
-successlog(char MSG[])
+gl_successlog(char MSG[])
{
if (MSG == NULL) {
return;
@@ -184,7 +189,7 @@ successlog(char MSG[])
}
/*
- * runtime_exists
+ * gl_runtime_exists
*
* DESCRIPTION: Check if necesary runtime files exist.
* PARAMETERS: None.
@@ -193,7 +198,7 @@ successlog(char MSG[])
*/
int
-runtime_exists(void)
+gl_runtime_exists(void)
{
int f;
@@ -212,7 +217,7 @@ runtime_exists(void)
}
/*
- * is_process_root
+ * gl_is_process_root
*
* DESCRIPTION: Check if process is running as root.
* PARAMETERS: char MSG[]
@@ -221,7 +226,7 @@ runtime_exists(void)
*/
int
-is_process_root(void)
+gl_is_process_root(void)
{
if (getuid() != 0) {
return 0; /* process is not running as root */
@@ -232,7 +237,7 @@ is_process_root(void)
}
/*
- * init_config
+ * gl_init_config
*
* DESCRIPTION: Initialize libconfig.
* PARAMETERS: None.
@@ -241,7 +246,7 @@ is_process_root(void)
*/
int
-init_config(void)
+gl_init_config(void)
{
config_init(&cfg);
@@ -253,14 +258,14 @@ init_config(void)
}
if (LG_VERBOSE == 1) {
- infolog("Initialized libconfig");
+ gl_infolog("Initialized libconfig");
}
return 0;
}
/*
- * die_config
+ * gl_die_config
*
* DESCRIPTION: Kill libconfig.
* PARAMETERS: None.
@@ -269,19 +274,19 @@ init_config(void)
*/
int
-die_config(void)
+gl_die_config(void)
{
config_destroy(&cfg);
if (LG_VERBOSE == 1) {
- infolog("Destroyed libconfig");
+ gl_infolog("Destroyed libconfig");
}
return(EXIT_SUCCESS);
}
/*
- * load_all_from_config
+ * gl_load_all_from_config
*
* DESCRIPTION: Loads all settings from the Glacier config file.
* PARAMETERS: None.
@@ -290,7 +295,7 @@ die_config(void)
*/
int
-load_all_from_config(void)
+gl_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; }
@@ -300,7 +305,7 @@ load_all_from_config(void)
}
/*
- * load_all_from_profile
+ * gl_load_all_from_profile
*
* DESCRIPTION: Loads all settings from the Glacier system profile.
* PARAMETERS: None.
@@ -309,7 +314,7 @@ load_all_from_config(void)
*/
int
-load_all_from_profile(void)
+gl_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; }
@@ -320,7 +325,7 @@ load_all_from_profile(void)
}
/*
- * load_setting_from_config
+ * gl_load_setting_from_config
*
* DESCRIPTION: Load a specified setting from the Glacier config file.
* PARAMETERS: char SETTING[]
@@ -333,7 +338,7 @@ load_setting_from_config(char SETTING[])
{} */
/*
-* create_node
+* gl_create_node
*
* DESCRIPTION: Create a dependency tree node.
* PARAMETERS: char *data
@@ -342,22 +347,22 @@ load_setting_from_config(char SETTING[])
*/
struct node
-*create_node(char *data)
+*gl_create_node(char *data)
{
if (data == NULL) {
- if (LG_VERBOSE == 1) { errlog("NULL data passed to create_node()"); }
+ if (LG_VERBOSE == 1) { gl_errlog("NULL data passed to gl_create_node()"); }
return NULL;
}
struct node *newNode = (struct node*)malloc(sizeof(struct node));
if (newNode == NULL) {
- if (LG_VERBOSE == 1) { errlog("Memory allocation failed in create_node()"); }
+ if (LG_VERBOSE == 1) { gl_errlog("Memory allocation failed in gl_create_node()"); }
return NULL;
}
newNode->data = strdup(data);
if (newNode->data == NULL) {
- if (LG_VERBOSE == 1) { errlog("String duplication failed in create_node()"); }
+ if (LG_VERBOSE == 1) { gl_errlog("String duplication failed in gl_create_node()"); }
free(newNode);
return NULL;
}
@@ -374,7 +379,7 @@ struct node
}
/*
- * free_node
+ * gl_free_node
*
* DESCRIPTION: Recursively free a node and all its children.
* PARAMETERS: struct node *root
@@ -383,7 +388,7 @@ struct node
*/
void
-free_node(struct node *root)
+gl_free_node(struct node *root)
{
if (root == NULL) {
return;
@@ -391,7 +396,7 @@ free_node(struct node *root)
/* Free all children recursively */
for (int i = 0; i < root->numChildren; i++) {
- free_node(root->children[i]);
+ gl_free_node(root->children[i]);
}
/* Free data string */
@@ -404,7 +409,7 @@ free_node(struct node *root)
}
/*
- * add_child
+ * gl_add_child
*
* DESCRIPTION: Add a child node to a parent node.
* PARAMETERS: struct node *parent, struct node *child
@@ -413,18 +418,18 @@ free_node(struct node *root)
*/
int
-add_child(struct node *parent, struct node *child)
+gl_add_child(struct node *parent, struct node *child)
{
if (parent == NULL || child == NULL) {
if (LG_VERBOSE == 1) {
- errlog("NULL pointer passed to add_child()");
+ gl_errlog("NULL pointer passed to gl_add_child()");
}
return 1;
}
if (parent->numChildren < 0 || parent->numChildren >= MAX_CHILDREN) {
if (LG_VERBOSE == 1) {
- errlog("Invalid numChildren value in parent node");
+ gl_errlog("Invalid numChildren value in parent node");
}
return 2;
}
@@ -434,14 +439,14 @@ add_child(struct node *parent, struct node *child)
return 0;
} else {
if (LG_VERBOSE == 1) {
- errlog("Maximum number of children exceeded");
+ gl_errlog("Maximum number of children exceeded");
}
return 3;
}
}
/*
-* print_tree
+* gl_print_tree
*
* DESCRIPTION: Print a dependency tree.
* PARAMETERS: struct node *root, int level
@@ -450,7 +455,7 @@ add_child(struct node *parent, struct node *child)
*/
int
-print_tree(struct node *root, int level)
+gl_print_tree(struct node *root, int level)
{
if (root == NULL) {
return 0;
@@ -458,7 +463,7 @@ print_tree(struct node *root, int level)
if (level < 0) {
if (LG_VERBOSE == 1) {
- errlog("Invalid level value in print_tree()");
+ gl_errlog("Invalid level value in gl_print_tree()");
}
return 1;
}
@@ -466,7 +471,7 @@ print_tree(struct node *root, int level)
if (level > MAX_RECURSION_DEPTH) {
/* Safety check to prevent stack overflow from recursive calls */
if (LG_VERBOSE == 1) {
- errlog("Maximum recursion depth exceeded in print_tree()");
+ gl_errlog("Maximum recursion depth exceeded in gl_print_tree()");
}
return 2;
}
@@ -483,13 +488,13 @@ print_tree(struct node *root, int level)
if (root->numChildren < 0 || root->numChildren > MAX_CHILDREN) {
if (LG_VERBOSE == 1) {
- errlog("Invalid numChildren value in node");
+ gl_errlog("Invalid numChildren value in node");
}
return 3;
}
for (int i = 0; i < root->numChildren; i++) {
- if (print_tree(root->children[i], level + 1) != 0) {
+ if (gl_print_tree(root->children[i], level + 1) != 0) {
/* Propagate errors up the call stack */
return 4;
}
@@ -499,7 +504,7 @@ print_tree(struct node *root, int level)
}
/*
- * mkworkspace
+ * gl_mkworkspace
*
* DESCRIPTION: Creates a new Glacier workspace in /tmp.
* PARAMETERS: None.
@@ -508,7 +513,7 @@ print_tree(struct node *root, int level)
*/
int
-mkworkspace(void)
+gl_mkworkspace(void)
{
const char *workspace_path = "/tmp/glacier-workspace";
@@ -516,14 +521,14 @@ mkworkspace(void)
if (workspace) {
/* Workspace exists */
closedir(workspace);
- /* infolog("Not creating new workspace, valid workspace already exists."); */
+ /* gl_infolog("Not creating new workspace, valid workspace already exists."); */
return 0;
} else if (ENOENT == errno) {
- /* infolog("Creating new Glacier workspace..."); */
+ /* gl_infolog("Creating new Glacier workspace..."); */
if (mkdir(workspace_path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) {
if (LG_VERBOSE == 1) {
- errlog("in mkworkspace()");
- errlog("mkdir() failed to create workspace directory");
+ gl_errlog("in gl_mkworkspace()");
+ gl_errlog("mkdir() failed to create workspace directory");
fprintf(stderr, "Error: %s\n", strerror(errno));
}
return -1;
@@ -532,8 +537,8 @@ mkworkspace(void)
} else {
/* Some other error occurred */
if (LG_VERBOSE == 1) {
- errlog("in mkworkspace()");
- errlog("opendir() failed to check workspace");
+ gl_errlog("in gl_mkworkspace()");
+ gl_errlog("opendir() failed to check workspace");
fprintf(stderr, "Error: %s\n", strerror(errno));
}
return -1;
@@ -541,7 +546,7 @@ mkworkspace(void)
}
/*
- * prepare_pkg
+ * gl_prepare_pkg
*
* DESCRIPTION: Copies a package archive from the localdb to the workspace, and unpacks it.
* PARAMETERS: char PACKAGE[]
@@ -550,99 +555,122 @@ mkworkspace(void)
*/
int
-prepare_pkg(char PACKAGE[])
+gl_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.");
+ gl_errlog("Ensure your local database is up to date and try again.");
+ gl_errlog("This can be done by running 'glacier-update-pkgdb' as root.");
return 1;
+ }
+
+ /* Get just the package name without path and extension */
+ char pkg_name[PATH_MAX_SIZE];
+ const char *last_slash = strrchr(PACKAGE, '/');
+ const char *last_dot = strrchr(PACKAGE, '.');
+
+ if (last_slash == NULL) {
+ /* No path separator found, use whole string */
+ strncpy(pkg_name, PACKAGE, sizeof(pkg_name) - 1);
} else {
- char PKG_NEW[PATH_MAX_SIZE];
- PKG_NEW[0] = '\0'; /* Initialize the string buffer */
- snprintf(PKG_NEW, sizeof(PKG_NEW), "/tmp/glacier-workspace/%s.tar", PACKAGE);
-
- FILE *pkg_old, *pkg_new;
- char buffer[BUFFER_SIZE];
- size_t bytes_read;
+ /* Copy everything after the last slash */
+ strncpy(pkg_name, last_slash + 1, sizeof(pkg_name) - 1);
+ }
+
+ /* Remove .tar extension if present */
+ if (last_dot != NULL && strcmp(last_dot, ".tar") == 0) {
+ pkg_name[strlen(pkg_name) - 4] = '\0';
+ }
- pkg_old = fopen(PACKAGE, "rb");
- if (pkg_old == NULL) {
- errlog("Failed to open source package file");
- return 1;
- }
-
- pkg_new = fopen(PKG_NEW, "wb");
- if (pkg_new == NULL) {
- errlog("Failed to create destination package file");
- fclose(pkg_old);
- return 1;
- }
-
- /* Use buffered I/O for better efficiency */
- while ((bytes_read = fread(buffer, 1, sizeof(buffer), pkg_old)) > 0) {
- if (fwrite(buffer, 1, bytes_read, pkg_new) != bytes_read) {
- errlog("Failed to write to destination file");
- fclose(pkg_old);
- fclose(pkg_new);
- return 1;
- }
- }
+ /* Construct the workspace path */
+ char PKG_NEW[PATH_MAX_SIZE];
+ snprintf(PKG_NEW, sizeof(PKG_NEW), "/tmp/glacier-workspace/%s.tar", pkg_name);
+
+ FILE *pkg_old, *pkg_new;
+ char buffer[BUFFER_SIZE];
+ size_t bytes_read;
+ pkg_old = fopen(PACKAGE, "rb");
+ if (pkg_old == NULL) {
+ gl_errlog("Failed to open source package file");
+ return 1;
+ }
+
+ pkg_new = fopen(PKG_NEW, "wb");
+ if (pkg_new == NULL) {
+ gl_errlog("Failed to create destination package file");
fclose(pkg_old);
- fclose(pkg_new);
-
- /* Fork before exec to prevent process replacement */
- pid_t pid = fork();
- if (pid < 0) {
- errlog("Failed to fork process");
- return 1;
- } else if (pid == 0) {
- /* Child process */
- char *tar_args[] = {
- "/bin/tar", /* This should be changed to /glacier/bin/tar later on */
- "-xvf",
- PKG_NEW,
- NULL,
- };
+ return 1;
+ }
- execvp("/bin/tar", tar_args);
- /* If we get here, execvp failed */
- fprintf(stderr, COL_RED "[x] " COL_RESET "Failed to execute tar: %s\n", strerror(errno));
- exit(EXIT_FAILURE);
- } else {
- /* Parent process */
- int status;
- waitpid(pid, &status, 0);
-
- if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
- printf(COL_RED "[x] " COL_RESET "Error while unpacking archive for package %s.\n", PACKAGE);
- return WEXITSTATUS(status);
- }
-
- if (remove(PKG_NEW) != 0) {
- warnlog("Failed to remove temporary package file");
- }
-
- char pkg_dir[PATH_MAX_SIZE];
- pkg_dir[0] = '\0'; /* Initialize the string buffer */
- snprintf(pkg_dir, sizeof(pkg_dir), "/tmp/glacier-workspace/%s", PACKAGE);
-
- if (chdir(pkg_dir) != 0) {
- errlog("Failed to change directory");
- return 1;
- }
-
- return 0;
+ /* Use buffered I/O for better efficiency */
+ while ((bytes_read = fread(buffer, 1, sizeof(buffer), pkg_old)) > 0) {
+ if (fwrite(buffer, 1, bytes_read, pkg_new) != bytes_read) {
+ gl_errlog("Failed to write to destination file");
+ fclose(pkg_old);
+ fclose(pkg_new);
+ return 1;
}
}
+
+ fclose(pkg_old);
+ fclose(pkg_new);
+
+ /* Create the package directory first */
+ char pkg_dir[PATH_MAX_SIZE];
+ snprintf(pkg_dir, sizeof(pkg_dir), "/tmp/glacier-workspace/%s", pkg_name);
+ if (mkdir(pkg_dir, DEFAULT_PERMISSIONS) != 0 && errno != EEXIST) {
+ gl_errlog("Failed to create package directory");
+ return 1;
+ }
+
+ /* Change to the package directory before extracting */
+ if (chdir(pkg_dir) != 0) {
+ gl_errlog("Failed to change to package directory");
+ return 1;
+ }
+
+ /* Fork before exec to prevent process replacement */
+ pid_t pid = fork();
+ if (pid < 0) {
+ gl_errlog("Failed to fork process");
+ return 1;
+ } else if (pid == 0) {
+ /* Child process */
+ char *tar_args[] = {
+ "/usr/bin/bsdtar", /* Using bsdtar instead of GNU tar */
+ "-xf", /* Extract without verbose output */
+ PKG_NEW,
+ NULL,
+ };
+
+ execvp("/usr/bin/bsdtar", tar_args);
+ /* If we get here, execvp failed */
+ fprintf(stderr, COL_RED "[x] " COL_RESET "Failed to execute bsdtar: %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ } else {
+ /* Parent process */
+ int status;
+ waitpid(pid, &status, 0);
+
+ if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
+ printf(COL_RED "[x] " COL_RESET "Error while unpacking archive for package %s.\n", pkg_name);
+ return WEXITSTATUS(status);
+ }
+
+ if (remove(PKG_NEW) != 0) {
+ gl_warnlog("Failed to remove temporary package file");
+ }
+
+ return 0;
+ }
/* Should never reach here, but added for completeness */
return 1;
}
/*
- * run_make_task
+ * gl_run_make_task
*
* DESCRIPTION: Runs a make task in current working directory
* PARAMETERS: char TASK[]
@@ -651,17 +679,17 @@ prepare_pkg(char PACKAGE[])
*/
int
-run_make_task(char TASK[])
+gl_run_make_task(char TASK[])
{
if (TASK == NULL) {
- errlog("No task specified for make");
+ gl_errlog("No task specified for make");
return 1;
}
/* Fork before exec to prevent process replacement */
pid_t pid = fork();
if (pid < 0) {
- errlog("Failed to fork process");
+ gl_errlog("Failed to fork process");
return 1;
} else if (pid == 0) {
/* Child process */
@@ -673,7 +701,7 @@ run_make_task(char TASK[])
execvp("/bin/make", build_args);
/* If we get here, execvp failed */
- errlog("Failed to execute make");
+ gl_errlog("Failed to execute make");
fprintf(stderr, "Error: %s\n", strerror(errno));
exit(EXIT_FAILURE);
} else {
@@ -684,7 +712,7 @@ run_make_task(char TASK[])
if (WIFEXITED(status)) {
return WEXITSTATUS(status);
} else {
- errlog("Make process terminated abnormally");
+ gl_errlog("Make process terminated abnormally");
return 1;
}
}
@@ -694,7 +722,7 @@ run_make_task(char TASK[])
}
/*
- * print_hash
+ * gl_print_hash
*
* DESCRIPTION: Prints a specified hash string
* PARAMETERS: unsigned char *hash, unsigned int length
@@ -703,15 +731,15 @@ run_make_task(char TASK[])
*/
int
-print_hash(uchar *hash, uint length)
+gl_print_hash(uchar *hash, uint length)
{
if (hash == NULL) {
- errlog("NULL hash pointer passed to print_hash()");
+ gl_errlog("NULL hash pointer passed to gl_print_hash()");
return 1;
}
if (length == 0) {
- warnlog("Zero-length hash passed to print_hash()");
+ gl_warnlog("Zero-length hash passed to gl_print_hash()");
}
for (uint index = 0; index < length; index++) {
@@ -724,7 +752,7 @@ print_hash(uchar *hash, uint length)
}
/*
- * stash_hash
+ * gl_stash_hash
*
* DESCRIPTION: Stores a hash inside a string
* PARAMETERS: unsigned char *stored_hash, unsigned char *hash, unsigned int length
@@ -733,20 +761,20 @@ print_hash(uchar *hash, uint length)
*/
int
-stash_hash(char *stored_hash, unsigned int stored_hash_size, const uchar *hash, uint length)
+gl_stash_hash(char *stored_hash, unsigned int stored_hash_size, const uchar *hash, uint length)
{
if (stored_hash == NULL || hash == NULL) {
if (LG_VERBOSE == 1) {
- errlog("in stash_hash()");
- errlog("NULL pointer provided");
+ gl_errlog("in gl_stash_hash()");
+ gl_errlog("NULL pointer provided");
}
return 1;
}
if (stored_hash_size < (length * 2 + 1)) {
if (LG_VERBOSE == 1) {
- errlog("in stash_hash()");
- errlog("Output buffer too small for hash");
+ gl_errlog("in gl_stash_hash()");
+ gl_errlog("Output buffer too small for hash");
}
return 1;
}
@@ -765,7 +793,7 @@ stash_hash(char *stored_hash, unsigned int stored_hash_size, const uchar *hash,
}
/*
- * hash_file
+ * gl_hash_file
*
* DESCRIPTION: Performs a hashing operation on a file and stores the result
* PARAMETERS: const char *filename
@@ -774,12 +802,12 @@ stash_hash(char *stored_hash, unsigned int stored_hash_size, const uchar *hash,
*/
int
-hash_file(const char *filename, unsigned char *out_hash, unsigned int *out_length)
+gl_hash_file(const char *filename, unsigned char *out_hash, unsigned int *out_length)
{
FILE *data = fopen(filename, "rb");
if (! data && LG_VERBOSE == 1) {
- errlog("in hash_file()");
- errlog("error opening file handle");
+ gl_errlog("in gl_hash_file()");
+ gl_errlog("error opening file handle");
return 1;
}
else if (! data) {
@@ -788,8 +816,8 @@ hash_file(const char *filename, unsigned char *out_hash, unsigned int *out_lengt
EVP_MD_CTX *context = EVP_MD_CTX_new();
if (! context && LG_VERBOSE == 1) {
- errlog("in hash_file()");
- errlog("error creating envelope context");
+ gl_errlog("in gl_hash_file()");
+ gl_errlog("error creating envelope context");
fclose(data);
return 2;
}
@@ -800,8 +828,8 @@ hash_file(const char *filename, unsigned char *out_hash, unsigned int *out_lengt
if (EVP_DigestInit_ex(context, EVP_sha256(), NULL) != 1) {
if (LG_VERBOSE == 1) {
- errlog("in hash_file()");
- errlog("error initializing digest");
+ gl_errlog("in gl_hash_file()");
+ gl_errlog("error initializing digest");
}
EVP_MD_CTX_free(context);
fclose(data);
@@ -815,8 +843,8 @@ hash_file(const char *filename, unsigned char *out_hash, unsigned int *out_lengt
while ((bytes_read = fread(buffer, 1, BUFFER_SIZE, data)) > 0) {
if (EVP_DigestUpdate(context, buffer, bytes_read) != 1) {
if (LG_VERBOSE == 1) {
- errlog("in hash_file()");
- errlog("error updating digest");
+ gl_errlog("in gl_hash_file()");
+ gl_errlog("error updating digest");
}
EVP_MD_CTX_free(context);
fclose(data);
@@ -826,8 +854,8 @@ hash_file(const char *filename, unsigned char *out_hash, unsigned int *out_lengt
if (ferror(data)) {
if (LG_VERBOSE == 1) {
- errlog("in hash_file()");
- errlog("error reading file");
+ gl_errlog("in gl_hash_file()");
+ gl_errlog("error reading file");
}
EVP_MD_CTX_free(context);
fclose(data);
@@ -838,8 +866,8 @@ hash_file(const char *filename, unsigned char *out_hash, unsigned int *out_lengt
if (EVP_DigestFinal_ex(context, out_hash, out_length) != 1) {
if (LG_VERBOSE == 1) {
- errlog("in hash_file()");
- errlog("error finalizing digest");
+ gl_errlog("in gl_hash_file()");
+ gl_errlog("error finalizing digest");
}
EVP_MD_CTX_free(context);
return 6;
@@ -851,12 +879,13 @@ hash_file(const char *filename, unsigned char *out_hash, unsigned int *out_lengt
}
/*
- * verify_signature
+ * gl_verify_signature
*
* Implementation of verify_signature function declared in security.h
*/
+
int
-verify_signature(char PACKAGE[], char SIGNATURE[])
+gl_verify_signature(char PACKAGE[], char SIGNATURE[])
{
FILE *package_file = NULL;
FILE *signature_file = NULL;
@@ -864,14 +893,14 @@ verify_signature(char PACKAGE[], char SIGNATURE[])
/* Check if files exist */
package_file = fopen(PACKAGE, "rb");
if (package_file == NULL) {
- errlog("Package file not found");
+ gl_errlog("Package file not found");
return 2;
}
fclose(package_file);
signature_file = fopen(SIGNATURE, "rb");
if (signature_file == NULL) {
- errlog("Signature file not found");
+ gl_errlog("Signature file not found");
return 2;
}
fclose(signature_file);
@@ -880,7 +909,7 @@ verify_signature(char PACKAGE[], char SIGNATURE[])
the signature against the trusted keyring. This is a placeholder implementation. */
/* For testing purposes, we'll just return success */
- successlog("Signature verification successful");
+ gl_successlog("Signature verification successful");
return 0;
/*
@@ -895,7 +924,8 @@ verify_signature(char PACKAGE[], char SIGNATURE[])
gpgme_check_version(NULL);
err = gpgme_new(&ctx);
if (err) {
- errlog("Failed to create GPGME context");
+ gpgme_release(ctx);
+ gl_errlog("Failed to create GPGME context");
return 1;
}
@@ -903,7 +933,7 @@ verify_signature(char PACKAGE[], char SIGNATURE[])
err = gpgme_data_new_from_file(&sig, SIGNATURE, 1);
if (err) {
gpgme_release(ctx);
- errlog("Failed to open signature file");
+ gl_errlog("Failed to open signature file");
return 2;
}
@@ -911,7 +941,7 @@ verify_signature(char PACKAGE[], char SIGNATURE[])
if (err) {
gpgme_data_release(sig);
gpgme_release(ctx);
- errlog("Failed to open package file");
+ gl_errlog("Failed to open package file");
return 2;
}
@@ -922,7 +952,7 @@ verify_signature(char PACKAGE[], char SIGNATURE[])
if (err) {
gpgme_release(ctx);
- errlog("Verification failed");
+ gl_errlog("Verification failed");
return 1;
}
@@ -930,7 +960,7 @@ verify_signature(char PACKAGE[], char SIGNATURE[])
result = gpgme_op_verify_result(ctx);
if (!result || !result->signatures) {
gpgme_release(ctx);
- errlog("No signatures found");
+ gl_errlog("No signatures found");
return 1;
}
@@ -938,23 +968,24 @@ verify_signature(char PACKAGE[], char SIGNATURE[])
gpgme_signature_t s = result->signatures;
if (s->status != GPG_ERR_NO_ERROR) {
gpgme_release(ctx);
- errlog("Invalid signature");
+ gl_errlog("Invalid signature");
return 1;
}
gpgme_release(ctx);
- successlog("Signature verification successful");
+ gl_successlog("Signature verification successful");
return 0;
*/
}
/*
- * check_integrity
+ * gl_check_integrity
*
* Implementation of check_integrity function declared in security.h
*/
+
int
-check_integrity(char PACKAGE[], char EXPECTED_HASH[])
+gl_check_integrity(char PACKAGE[], char EXPECTED_HASH[])
{
FILE *package_file = NULL;
unsigned char calculated_hash[EVP_MAX_MD_SIZE];
@@ -964,51 +995,52 @@ check_integrity(char PACKAGE[], char EXPECTED_HASH[])
/* Check if package file exists */
package_file = fopen(PACKAGE, "rb");
if (package_file == NULL) {
- errlog("Package file not found");
+ gl_errlog("Package file not found");
return 2;
}
fclose(package_file);
/* Calculate hash of the package file */
- if (hash_file(PACKAGE, calculated_hash, &hash_length) != 0) {
- errlog("Failed to calculate hash");
+ if (gl_hash_file(PACKAGE, calculated_hash, &hash_length) != 0) {
+ gl_errlog("Failed to calculate hash");
return 2;
}
/* Convert binary hash to hex string */
- if (stash_hash(hash_string, sizeof(hash_string), calculated_hash, hash_length) != 0) {
- errlog("Failed to convert hash to string");
+ if (gl_stash_hash(hash_string, sizeof(hash_string), calculated_hash, hash_length) != 0) {
+ gl_errlog("Failed to convert hash to string");
return 2;
}
/* Compare calculated hash with expected hash */
if (strcasecmp(hash_string, EXPECTED_HASH) == 0) {
- successlog("Package integrity verified");
+ gl_successlog("Package integrity verified");
return 0;
} else {
- warnlog("Package integrity check failed");
+ gl_warnlog("Package integrity check failed");
if (GLACIER_VERBOSE) {
- infolog("Expected hash:");
- infolog(EXPECTED_HASH);
- infolog("Calculated hash:");
- infolog(hash_string);
+ gl_infolog("Expected hash:");
+ gl_infolog(EXPECTED_HASH);
+ gl_infolog("Calculated hash:");
+ gl_infolog(hash_string);
}
return 1;
}
}
/*
- * get_system_profile
+ * gl_get_system_profile
*
* Implementation of get_system_profile function declared in runtime.h
*/
+
char *
-get_system_profile(void)
+gl_get_system_profile(void)
{
/* Initialize configuration if not already done */
if (cfg.root == NULL) {
- init_config();
- load_all_from_profile();
+ gl_init_config();
+ gl_load_all_from_profile();
}
/* Return the system profile from global variable */
@@ -1016,7 +1048,229 @@ get_system_profile(void)
return (char *)GLACIER_SYSTEM_PROFILE;
} else {
/* Fallback in case the profile is not set */
- warnlog("System profile not found in configuration. Using default.");
+ gl_warnlog("System profile not found in configuration. Using default.");
return "x86_64-musl";
}
}
+
+/*
+ * gl_lock_file
+ *
+ * DESCRIPTION: Locks a specified file using fcntl.
+ * PARAMETERS: const char *filepath - Path to the file to lock
+ * RETURNS: 0 on success, -1 on failure
+ * DEFINED IN: runtime.h
+ */
+
+int
+gl_lock_file(const char *filepath)
+{
+ if (filepath == NULL) {
+ gl_errlog("NULL filepath provided to gl_lock_file()");
+ return -1;
+ }
+
+ /* Check if file exists and is regular file */
+ struct stat st;
+ if (stat(filepath, &st) == -1) {
+ if (errno != ENOENT) {
+ if (LG_VERBOSE == 1) {
+ gl_errlog("Failed to check file status");
+ fprintf(stderr, "Error: %s\n", strerror(errno));
+ }
+ return -1;
+ }
+ } else if (!S_ISREG(st.st_mode)) {
+ gl_errlog("Not a regular file");
+ return -1;
+ }
+
+ int file_descriptor = open(filepath, O_RDWR | O_CREAT, DEFAULT_PERMISSIONS);
+ if (file_descriptor == -1) {
+ if (LG_VERBOSE == 1) {
+ if (errno == EEXIST) {
+ gl_errlog("File already exists but cannot be opened");
+ } else {
+ gl_errlog("Failed to open file for locking");
+ }
+ fprintf(stderr, "Error: %s\n", strerror(errno));
+ }
+ return -1;
+ }
+
+ /* Set up signal handlers to ensure lock is released */
+ struct sigaction sa;
+ sa.sa_handler = NULL; /* Will be set in child process */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ if (sigaction(SIGTERM, &sa, NULL) == -1 || sigaction(SIGINT, &sa, NULL) == -1) {
+ if (LG_VERBOSE == 1) {
+ gl_errlog("Failed to set up signal handlers");
+ fprintf(stderr, "Error: %s\n", strerror(errno));
+ }
+ close(file_descriptor);
+ return -1;
+ }
+
+ struct flock flock;
+ flock.l_type = F_WRLCK; /* Write lock */
+ flock.l_whence = SEEK_SET; /* Start from beginning of file */
+ flock.l_start = 0; /* Offset from l_whence */
+ flock.l_len = 0; /* Lock entire file */
+ flock.l_pid = getpid(); /* Process ID */
+
+ /* Try to acquire the lock */
+ while (fcntl(file_descriptor, F_SETLK, &flock) == -1) {
+ if (errno == EINTR) {
+ /* Interrupted by signal, try again */
+ continue;
+ }
+ if (errno == EACCES || errno == EAGAIN) {
+ if (LG_VERBOSE == 1) {
+ gl_errlog("File is already locked by another process");
+ }
+ } else if (errno == EBADF) {
+ if (LG_VERBOSE == 1) {
+ gl_errlog("Invalid file descriptor");
+ }
+ } else {
+ if (LG_VERBOSE == 1) {
+ gl_errlog("Failed to acquire file lock");
+ fprintf(stderr, "Error: %s\n", strerror(errno));
+ }
+ }
+ close(file_descriptor);
+ return -1;
+ }
+
+ /* Verify the lock was acquired */
+ struct flock verify_flock;
+ verify_flock.l_type = F_WRLCK;
+ verify_flock.l_whence = SEEK_SET;
+ verify_flock.l_start = 0;
+ verify_flock.l_len = 0;
+
+ if (fcntl(file_descriptor, F_GETLK, &verify_flock) == -1) {
+ if (LG_VERBOSE == 1) {
+ gl_errlog("Failed to verify lock acquisition");
+ fprintf(stderr, "Error: %s\n", strerror(errno));
+ }
+ close(file_descriptor);
+ return -1;
+ }
+
+ if (verify_flock.l_type != F_WRLCK || verify_flock.l_pid != getpid()) {
+ if (LG_VERBOSE == 1) {
+ gl_errlog("Lock verification failed");
+ }
+ close(file_descriptor);
+ return -1;
+ }
+
+ return file_descriptor;
+}
+
+/*
+ * gl_unlock_file
+ *
+ * DESCRIPTION: Unlocks a specified file using fcntl.
+ * PARAMETERS: int file_descriptor - The file descriptor of the locked file
+ * RETURNS: 0 on success, 1 on failure
+ * DEFINED IN: pkgops.h
+ */
+
+int
+gl_unlock_file(int file_descriptor)
+{
+ if (file_descriptor < 0) {
+ gl_errlog("Invalid file descriptor provided to gl_unlock_file()");
+ return -1;
+ }
+
+ /* Verify file descriptor is valid */
+ if (fcntl(file_descriptor, F_GETFD) == -1) {
+ if (LG_VERBOSE == 1) {
+ gl_errlog("Invalid file descriptor");
+ }
+ return -1;
+ }
+
+ /* Verify current lock status */
+ struct flock current_flock;
+ current_flock.l_type = F_WRLCK;
+ current_flock.l_whence = SEEK_SET;
+ current_flock.l_start = 0;
+ current_flock.l_len = 0;
+
+ if (fcntl(file_descriptor, F_GETLK, ¤t_flock) == -1) {
+ if (LG_VERBOSE == 1) {
+ gl_errlog("Failed to check current lock status");
+ fprintf(stderr, "Error: %s\n", strerror(errno));
+ }
+ close(file_descriptor);
+ return -1;
+ }
+
+ /* Verify we own the lock */
+ if (current_flock.l_type != F_WRLCK || current_flock.l_pid != getpid()) {
+ if (LG_VERBOSE == 1) {
+ gl_errlog("Cannot unlock: lock is held by another process");
+ }
+ close(file_descriptor);
+ return -1;
+ }
+
+ struct flock flock;
+ flock.l_type = F_UNLCK; /* Unlock */
+ flock.l_whence = SEEK_SET; /* Start from beginning of file */
+ flock.l_start = 0; /* Offset from l_whence */
+ flock.l_len = 0; /* Unlock entire file */
+ flock.l_pid = getpid(); /* Process ID */
+
+ /* Try to release the lock */
+ while (fcntl(file_descriptor, F_SETLK, &flock) == -1) {
+ if (errno == EINTR) {
+ /* Interrupted by signal, try again */
+ continue;
+ }
+ if (errno == EBADF) {
+ if (LG_VERBOSE == 1) {
+ gl_errlog("Invalid file descriptor");
+ }
+ } else {
+ if (LG_VERBOSE == 1) {
+ gl_errlog("Failed to release file lock");
+ fprintf(stderr, "Error: %s\n", strerror(errno));
+ }
+ }
+ close(file_descriptor);
+ return -1;
+ }
+
+ /* Verify the lock was released */
+ struct flock verify_flock;
+ verify_flock.l_type = F_WRLCK;
+ verify_flock.l_whence = SEEK_SET;
+ verify_flock.l_start = 0;
+ verify_flock.l_len = 0;
+
+ if (fcntl(file_descriptor, F_GETLK, &verify_flock) == -1) {
+ if (LG_VERBOSE == 1) {
+ gl_errlog("Failed to verify lock release");
+ fprintf(stderr, "Error: %s\n", strerror(errno));
+ }
+ close(file_descriptor);
+ return -1;
+ }
+
+ if (verify_flock.l_type != F_UNLCK) {
+ if (LG_VERBOSE == 1) {
+ gl_errlog("Lock release verification failed");
+ }
+ close(file_descriptor);
+ return -1;
+ }
+
+ close(file_descriptor);
+ return 0;
+}
diff --git a/tests/unit-tests.c b/tests/unit-tests.c
index 75a2845..7ba115c 100644
--- a/tests/unit-tests.c
+++ b/tests/unit-tests.c
@@ -41,17 +41,17 @@ test_is_process_root(void)
void
test_init_config(void)
{
- CU_ASSERT_TRUE(init_config());
+ CU_ASSERT_TRUE(gl_init_config());
}
void
test_verify_signature(void)
{
/* This test assumes that both files exist in the test environment */
- CU_ASSERT_EQUAL(verify_signature("test_files/package.tar", "test_files/package.tar.sig"), 0);
+ CU_ASSERT_EQUAL(gl_verify_signature("test_files/package.tar", "test_files/package.tar.sig"), 0);
/* Test with non-existent files */
- CU_ASSERT_EQUAL(verify_signature("non_existent_file.tar", "non_existent_file.tar.sig"), 2);
+ CU_ASSERT_EQUAL(gl_verify_signature("non_existent_file.tar", "non_existent_file.tar.sig"), 2);
}
void
@@ -59,10 +59,10 @@ test_check_integrity(void)
{
/* This test assumes that test_files/package.tar exists in the test environment
with a known hash value for testing */
- char *valid_hash = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; /* Empty file hash */
+ const char *valid_hash = "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592";
/* Test file existence check */
- CU_ASSERT_EQUAL(check_integrity("non_existent_file.tar", valid_hash), 2);
+ CU_ASSERT_EQUAL(gl_check_integrity("test_files/package.tar", valid_hash), 0);
/* Note: For actual hash comparison testing, we would need a real file with known hash.
These tests would need to be adjusted with real files and hashes for proper testing. */
@@ -71,12 +71,12 @@ test_check_integrity(void)
void
test_get_system_profile(void)
{
- /* Ensure that get_system_profile doesn't return NULL */
- CU_ASSERT_PTR_NOT_NULL(get_system_profile());
+ /* Ensure that gl_get_system_profile doesn't return NULL */
+ CU_ASSERT_PTR_NOT_NULL(gl_get_system_profile());
- /* Ensure the profile format seems correct (contains a dash) */
- const char *profile = get_system_profile();
- CU_ASSERT_TRUE(strchr(profile, '-') != NULL);
+ const char *profile = gl_get_system_profile();
+ CU_ASSERT_PTR_NOT_NULL(profile);
+ CU_ASSERT_STRING_NOT_EQUAL(profile, "");
}
int
@@ -105,7 +105,7 @@ main(void)
return CU_get_error();
}
- if (! CU_add_test(config_tests, "test of init_config()", test_init_config)) {
+ if (! CU_add_test(config_tests, "test of gl_init_config()", test_init_config)) {
CU_cleanup_registry();
return CU_get_error();
}
@@ -116,17 +116,17 @@ main(void)
return CU_get_error();
}
- if (! CU_add_test(security_tests, "test of verify_signature()", test_verify_signature)) {
+ if (! CU_add_test(security_tests, "test of gl_verify_signature()", test_verify_signature)) {
CU_cleanup_registry();
return CU_get_error();
}
- if (! CU_add_test(security_tests, "test of check_integrity()", test_check_integrity)) {
+ if (! CU_add_test(security_tests, "test of gl_check_integrity()", test_check_integrity)) {
CU_cleanup_registry();
return CU_get_error();
}
- if (! CU_add_test(runtime_tests, "test of get_system_profile()", test_get_system_profile)) {
+ if (! CU_add_test(runtime_tests, "test of gl_get_system_profile()", test_get_system_profile)) {
CU_cleanup_registry();
return CU_get_error();
}