10/29 added basic package processing

This commit is contained in:
2025-10-29 09:01:29 -04:00
parent 21b3d18b5a
commit e591b71143
12 changed files with 903 additions and 9 deletions

4
pkg/README Normal file
View File

@@ -0,0 +1,4 @@
+ Glacier Packaging Format
Every Glacier package should contain the following files:
* pkg_meta.gpm (Glacier Package Manifest metadata file)

17
pkg/bar.gpm.cfg Normal file
View File

@@ -0,0 +1,17 @@
#
# bar
#
PKG_NAME = "bar";
PKG_VER = 1.0.0;
PKG_DESC = "example pkg";
PKG_MAINT = "liamwaldron@everestlinux.org";
PKG_COPYRIGHT = "GPL3";
PKG_DEPS = (
{ PKG_NAME = "foo"; PKG_VER = 1.1.1; };
);
PKG_CONFS = (
{};
);

10
pkg/pkg_meta.gpm Normal file
View File

@@ -0,0 +1,10 @@
#
# pkg_meta.gpm
#
PACKAGE_NAME = "pkg"
PACKAGE_VER = 1.0.0
PACKAGE_DESC = ""
PACKAGE_MAINT = ""
PACKAGE_LICENSE = "";
PACKAGE_ARCH = "";

17
src/common.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef COMMON_H_
#define COMMON_H_
#define _POSIX_C_SOURCE 200809L
#define _DEFAULT_SOURCE
#define _XOPEN_SOURCE 700
#include <sys/types.h>
typedef struct
{
char *path;
mode_t mode;
}
dir_t;
#endif

View File

@@ -21,3 +21,9 @@
[2025-09-22 23:24:51] [ERR] Failed to install package glibc
[2025-09-22 23:24:51] [INFO] Glacier started with PID 12345
[2025-09-22 23:24:51] [ERR] Failed to install package glibc
[2025-10-16 14:45:24] [INFO] Glacier started with PID 12345
[2025-10-16 14:45:24] [ERR] Failed to install package glibc
[2025-10-22 15:59:02] [INFO] Glacier started with PID 12345
[2025-10-22 15:59:02] [ERR] Failed to install package glibc
[2025-10-22 15:59:07] [INFO] Glacier started with PID 12345
[2025-10-22 15:59:07] [ERR] Failed to install package glibc

407
src/html/nord.css Normal file
View File

@@ -0,0 +1,407 @@
/* css/everest.css - stylesheet for everest-web */
/*
Copyright (C) 2023 Everest Linux.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".
*/
/* Sidebar menu */
.sidenav {
height: 100%;
width: 200px;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #2E3440;
overflow-x: hidden;
padding-top: 20px;
}
/* Menu links */
.sidenav a {
padding: 6px 8px 6px 16px;
text-decoration: none;
font-size: 20px;
color: #D8DEE9;
display: block;
}
.sidenav a:hover {
color: #88c0d0;
}
html {
background-color: #3B4252;
color: #ECEFF4;
}
.main {
margin-left: 200px;
padding: 0px 10px;
background-color: #3B4252;
}
.file {
font-family: monospace;
background-color: #2E3440;
border-left-style: solid;
border-left-color: #A3BE8C;
border-width: 4px;
border-radius: 2px;
padding: 4px;
width: 50%;
color: #ECEFF4;
}
.kernel {
font-family: monospace;
background-color: #2E3440;
border-left-style: solid;
border-left-color: #B48EAD;
border-width: 4px;
border-radius: 2px;
padding: 4px;
width: 50%;
color: #ECEFF4;
}
.note {
background-color: #88C0D0;
border-left-style: solid;
border-left-color: #88C0D0;
border-width: 4px;
border-radius: 2px;
padding: 4px;
width: 50%;
color: #2E3440;
}
.caution {
background-color: #EBCB8B;
border-left-style: solid;
border-left-color: #EBCB8B;
border-width: 4px;
border-radius: 2px;
padding: 4px;
width: 50%;
color: #2E3440;
}
.warning {
background-color: #BF616A;
border-left-style: solid;
border-left-color: #BF616A;
border-width: 4px;
border-radius: 2px;
padding: 4px;
width: 50%;
color: #D8DEE9;
}
.news {
background-color: #2E3440;
border-left-style: solid;
border-left-color: #88C0D0;
border-width: 4px;
border-radius: 2px;
padding: 4px;
width: 50%;
color: #ECEFF4;
}
table, td {
border: 2px solid;
border-color: #ECEFF4;
border-collapse: collapse;
padding: 4px;
background-color: #2E3440;
}
th {
border: 2px solid;
background-color: #88C0D0;
color: #2E3440;
border-color: #ECEFF4;
}
notehead {
background-color: #88C0D0;
border-left-style: solid;
border-left-color: #88C0D0;
border-width: 4px;
border-radius: 2px;
padding: 6px;
width: 50%;
color: #2E3440;
}
fhead {
background-color: #2E3440;
border-left-style: solid;
border-left-color: #A3BE8C;
border-width: 4px;
border-radius: 2px;
padding: 6px;
width: 50%;
color: #A3BE8C;
}
khead {
background-color: #2E3440;
border-left-style: solid;
border-left-color: #B48EAD;
border-width: 4px;
border-radius: 2px;
padding: 6px;
width: 50%;
color: #B48EAD;
}
cautionhead {
background-color: #EBCB8B;
border-left-style: solid;
border-left-color: #EBCB8B;
border-width: 4px;
border-radius: 2px;
padding: 6px;
width: 50%;
color: #2E3440;
}
warnhead {
background-color: #BF616A;
border-left-style: solid;
border-left-color: #BF616A;
border-width: 4px;
border-radius: 2px;
padding: 6px;
width: 50%;
color: #D8DEE9;
}
newshead {
background-color: #2E3440;
border-left-style: solid;
border-left-color: #88C0D0;
border-width: 4px;
border-radius: 2px;
padding: 4px;
width: 50%;
color: #88C0D0;
}
wikihead {
border-left-style: solid;
border-left-color: #D08770;
border-width: 4px;
border-radius: 2px;
padding: 6px;
color: #D08770;
}
bigcodehead {
background-color: #2E3440;
border-left-style: solid;
border-left-color: #ECEFF4;
border-width: 4px;
border-radius: 2px;
padding: 4px;
width: 50%;
color: #ECEFF4;
}
@media screen and (max-height: 450px) {
.sidenav {padding-top: 15px;}
.sidenav a{font-size: 18px;}
}
body {
font-family: sans-serif;
background-color: #3B4252;
color: #ECEFF4;
}
code {
font-family: monospace;
background-color: #2E3440;
border-left-style: solid;
border-left-width: 4px;
border-radius: 2px;
padding: 2px;
color: #ECEFF4;
}
.bigcode {
font-family: monospace;
background-color: #2E3440;
border-left-style: solid;
border-left-width: 4px;
border-radius: 2px;
padding: 6px;
border-color: #ECEFF4;
width: 50%;
}
cil {
font-family: monospace;
background-color: #2E3440;
padding: 2px;
}
cil-inv {
font-family: monospace;
background-color: #2E3440;
color: #ECEFF4;
padding: 2px;
}
wiki {
border-left-style: solid;
border-left-width: 4px;
border-radius: 2px;
padding: 6px;
border-color: #D08770;
}
/* file {
border-style: solid;
border-width: 4px;
border-radius: 2px;
padding: 2px;
border-color: black;
} */
h2 {
border-left-style: solid;
border-color: #88C0D0;
padding-left: 4px;
border-left-width: 6px;
border-radius: 5px;
color: #ECEFF4;
}
button {
font-size: 24px;
border-style: none;
border-left-style: solid;
border-width: 8px;
padding: 12px 28px;
border-color: #88C0D0;
border-radius: 5px;
background-color: #434C5E;
color: #ECEFF4;
}
button:hover {
background-color: #4C566A;
}
hr.dotted {
border-top: 3px dotted #bbb;
}
/* p {
color: #e6e6e6;
} */
/* strong {
color: #4a86e8ff;
} */
/* i {
color: #e6e6e6;
} */
footer {
text-align: center;
font-size: 10px;
padding: 20px;
}
#myInput {
width: 378px;
font-size: 16px;
padding: 10px;
border: 2px solid #88C0D0;
border-radius: 2px;
margin-bottom: 12px;
background-color: #434C5E;
color: #ECEFF4;
}
#myUL {
width: 400px;
list-style-type: none;
padding: 0;
margin: 0;
}
#myUL li a {
border-left-width: 2px;
border-left-style: solid;
border-left-color: #88C0D0;
margin-top: -1px;
background-color: #434C5E;
padding: 12px;
text-decoration: none;
font-size: 18px;
color: #ECEFF4;
display: block;
}
#myUL li a:hover:not(.header) {
background-color: #4C566A;
}
img {
padding: 8px;
}
/* */
body, html {
height: 100%;
}
/* The hero image */
.hero-image {
background-image: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url("../img/banner.jpg");
height: 55%;
background-position: 50% 30%;
background-repeat: no-repeat;
background-size: cover;
position: relative;
padding-top: 0px;
padding-right: 0px;
margin-right: -8px;
margin-top: -8px;
}
.hero-text {
text-align: center;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
}
hr {
color: #88c0d0;
width: 50%;
border-width: 4px;
border-radius: 5px;
margin-left: 0;
}
.tab {
display: inline-block;
margin-left: 80px;
}

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<title>Glacier Packaging Report</title>
<link type="text/css" rel="stylesheet" href="nord.css"/>
</head>
<body>
<h1>Packaging report: [DATE HERE]</h1>
<hr></hr>
<h2>Statistics</h2>
<p>Total transactions: [N_TRANSACTIONS]</p>
<p>Completed transactions: [N_COMP_TRANSACT]</p>
<p>Failed transactions: [N_FAIL_TRANSACT]</p>
<p>Writes performed to <code>/glacier/index</code>: [N_IND_WRITES]</p>
<hr></hr>
<h2>Systems</h2>
<p>Performed these changes on the following systems:</p>
<code>
<p>* localhost</p>
<p>* 192.168.30.0/24</p>
<p>&emsp;&emsp;* 192.168.30.1</p>
</code>
<hr></hr>
<h2>Insights</h2>
<!--PACKAGE INSIGHTS BEGIN HERE-->
<p><strong>foo</strong><p>
<p>1.0.0 ---&gt; 1.0.1</p>
<p>Files:</p>
<code>
<p>f&emsp;&emsp;/usr/glacier/index/lw/pkginfo/foo_current/foo.gpm (e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855)<p>
<p>f&emsp;&emsp;usr/glacier/index/lw/pkgdata/foo_current/bin/foo (e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855)<p>
<p>l&emsp;&emsp;/home/lw/.glacier/store/foo -&gt; /usr/glacier/index/lw/pkgdata/foo_current<p>
</code>
<hr>
<h2>Problems</h2>
</body>
</html>

View File

@@ -145,23 +145,43 @@ lg_gpkg_help(int argc, char *argv[])
(void)argc;
printf("%s: Manage the user package index\n", argv[0]);
printf("usage: %s [OPTIONS] PKG...\n", argv[0]);
printf("usage: %s [-hv] [-fux PKG]\n", argv[0]);
printf("\n");
printf("Options:\n"
"\t{-h}\tShow this message\n"
"\t{-v}\tShow the current version\n"
"\t{-f} PKG...\tMerge a package into the user index\n"
"\t{-u} PKG...\tUpgrade a merged package\n"
"\t{-x} PKG...\tRemove a merged package\n"
printf("{-h}\tShow this message\n"
"{-v}\tShow the current version\n"
"{-f} PKG...\tMerge a package into the user index\n"
"{-u} PKG...\tUpgrade a merged package\n"
"{-x} PKG...\tRemove a merged package\n"
"\n"
"This program is free software.\n"
"See the GNU GPL version 3 for details.\n"
);
);
}
void
lg_syspkg_help(int argc, char *argv[])
{
(void)argc;
printf("%s: Manage the system package index\n", argv[0]);
printf("usage: %s [-hv] [-fux PKG]\n", argv[0]);
printf("\n");
printf("{-h}\tShow this message\n"
"{-v}\tShow the current version\n"
"{-f} PKG...\tMerge a package into the user index\n"
"{-u} PKG...\tUpgrade a merged package\n"
"{-x} PKG...\tRemove a merged package\n"
"\n"
"This program is free software.\n"
"See the GNU GPL version 3 for details.\n"
);
}
int
main(void)
main(int argc, char *argv[])
{
lg_gpkg_help(argc, argv);
lg_syspkg_help(argc, argv);
lg_printf(LG_INFO, "info");
lg_printf(LG_WARN, "warning");
lg_printf(LG_ERR, "error");

374
src/pkg.c Normal file
View File

@@ -0,0 +1,374 @@
#define _POSIX_C_SOURCE 200809L
#define _XOPEN_SOURCE 700
#include <errno.h>
#include <libconfig.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "common.h"
/*
* semver_t
* DESCRIPTION: defines the struct for storing semantic versioning numbers
*/
typedef struct
{
int maj;
int min;
int pat;
char *tag;
}
semver_t;
/*
* dep_t
* DESCRIPTION: defines the struct for storing dependent packages
*/
typedef struct
{
char *dep_name;
semver_t dep_ver;
}
dep_t;
/*
* conf_t
* DESCRIPTION: defines the struct for storing conflicting packages
*/
typedef struct
{
char *conf_name;
semver_t conf_ver;
}
conf_t;
/*
* gl_pkg_t
* DESCRIPTION: defines the struct for storing packages in the gpkg format
*/
typedef struct
{
char *pkg_name;
semver_t pkg_ver;
char *pkg_desc;
char *pkg_maint;
char *pkg_copyright;
dep_t *pkg_dependencies;
conf_t *pkg_conflicts;
}
gl_pkg_t;
/* directory definitions */
static const dir_t gl_root = { "/glacier", 0750 };
static const dir_t gl_usr = { "/glacier/usr", 0700 };
static const dir_t gl_usr_index = { "/glacier/usr/index", 0700 };
static const dir_t gl_usr_store = { "/glacier/usr/store", 0700 };
static const dir_t gl_sys = { "/glacier/sys", 0700 };
static const dir_t gl_sys_index = { "/glacier/sys/index", 0700 };
static const dir_t gl_sys_store = { "/glacier/sys/store", 0700 };
/* null dependencies/conflicts for error throwing */
static dep_t null_dep = { "null", {-1, -1, -1, NULL} };
static conf_t null_conf = { "null", {-1, -1, -1, NULL} };
/*
* gl_pkgver
* DESCRIPTION: takes three integers and formats them as a semver_t struct
* PARAMETERS:
* ~ int major (the MAJOR number)
* ~ int minor (the MINOR number)
* ~ int patch (the PATCH number)
* RETURNS:
* ~ a pointer to a semver_t struct
*/
semver_t
gl_pkgver(int major, int minor, int patch)
{
semver_t pkgver = {major, minor, patch, NULL};
return pkgver;
}
semver_t
gl_parse_semver(const char *str)
{
semver_t v = {0, 0, 0, NULL};
if (!str) { return v; }
char buffer[64];
strncpy(buffer, str, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';
char *dash = strchr(buffer, '-');
if (dash) {
*dash = '\0';
dash++;
v.tag = strdup(dash);
}
sscanf(buffer, "%d.%d.%d", &v.maj, &v.min, &v.pat);
return v;
}
void
gl_free_semver(semver_T *v)
{
if (v && v->tag) { free (v->tag); };
}
gl_pkg_t empty = {
"null",
{-1, -1, -1, NULL},
"Null package for internal use. Returned upon an error.",
"null@null.null",
"null",
&null_dep,
&null_conf
};
int
gl_mkdir(dir_t *dir)
{
if (mkdir(dir -> path, dir -> mode) == 0) {
return 0;
}
if (errno == EEXIST) { return 0; }
perror("libglacier: mkdir");
return -1;
}
gl_pkg_t
*gl_spawn_pkg(char *name, semver_t *ver, char *desc, char *maint, char *copy, dep_t *dep, conf_t *conf)
{
gl_pkg_t *new_pkg = malloc(sizeof(gl_pkg_t));
if (!new_pkg) { return NULL; }
new_pkg -> pkg_name = name;
new_pkg -> pkg_ver = *ver;
new_pkg -> pkg_desc = desc;
new_pkg -> pkg_maint = maint;
new_pkg -> pkg_copyright = copy;
new_pkg -> pkg_dependencies = dep;
new_pkg -> pkg_conflicts = conf;
return new_pkg;
}
int
gl_gpm2pkg(const char *filename, gl_pkg_t *pkg)
{
config_t cfg;
config_setting_t *deps, *confs;
const char *tmp_str;
config_init(&cfg);
if (!config_read_file(&cfg, filename)) {
return ENOENT;
}
if (config_lookup_string(&cfg, "PKG_NAME", &tmp_str)) { pkg->pkg_name = strdup(tmp_str); }
if (config_lookup_string(&cfg, "PKG_DESC", &tmp_str)) { pkg->pkg_desc = strdup(tmp_str); }
if (config_lookup_string(&cfg, "PKG_MAINT", &tmp_str)) { pkg->pkg_maint = strdup(tmp_str); }
if (config_lookup_string(&cfg, "PKG_COPYRIGHT", &tmp_str)) { pkg->pkg_copyright = strup(tmp_str); }
if (config_lookup_string(&cfg, "PKG_VER", &tmp_str)) { pkg->pkg_ver = gl_parse_semver(tmp_str); }
deps = config_lookup(&cfg, "PKG_DEPS");
if (deps && config_setting_is_list(deps)) {
int count = config_setting_length(deps);
pkg->pkg_dependencies = calloc(count + 1, sizeof(dep_t));
for (int i = 0; i < count; i++) {
config_setting_t *d = config_setting_get_elem(deps, i);
const char *dep_name = NULL;
const char *dep_ver = NULL;
config_setting_lookup_string(d, "PKG_NAME", &dep_name);
config_setting_lookup_string(d, "PKG_VER", &dep_ver);
pkg->pkg_dependencies[i].dep_name = dep_name ? strdup(dep_name) : NULL;
pkg->pkg_dependencies[i].dep_ver = parse_semver(dep_ver);
}
}
confs = config_lookup(&cfg, "PKG_CONFS");
if (confs && config_setting_is_list(confs)) {
int count = config_setting_length(confs);
pkg->pkg_conflicts = calloc(count + 1, sizeof(conf_t));
for (int i = 0; i < count; i++) {
config_setting_t *c = config_setting_get_elem(confs, i);
const char *conf_name = NULL;
const char *conf_ver = NULL;
config_setting_lookup_string(c, "PKG_NAME", &conf_name);
config_setting_lookup_string(c, "PKG_VER", &conf_ver);
pkg->pkg_conflicts[i].conf_name = conf_name ? strdup(conf_name) : NULL;
pkg->pkg_conflicts[i].conf_ver = parse_semver(conf_ver);
}
}
config_destroy(&cfg);
return 0;
}
char
*gl_cat_dir(const dir_t *a, const dir_t *b)
{
size_t length = strlen(a->path) + strlen(b->path) + 2;
char *result = malloc(length);
if (!result) { return NULL; }
snprintf(result, length, "%s/%s", a->path, b-> path);
return result;
}
char
*gl_cat_dir_and_ver(const dir_t *base, const gl_pkg_t *pkg)
{
char version[32];
snprintf(version, sizeof(version), "%d.%d.%d",
pkg->pkg_ver.maj, pkg->pkg_ver.min, pkg->pkg_ver.pat);
size_t length = strlen(base->path) + strlen(pkg->pkg_name) + strlen(version) + 3;
char *result = malloc(length);
if (!result) { return NULL; }
snprintf(result, length, "%s/%s-%s", base->path, pkg->pkg_name, version);
return result;
}
dir_t
gl_return_dir(const dir_t *a, const dir_t *b, mode_t mode)
{
char *path = gl_cat_dir(a, b);
dir_t result = { path, mode };
return result;
}
dir_t
gl_return_dir_and_ver(const dir_t *base, gl_pkg_t *pkg, mode_t mode)
{
char *path = gl_cat_dir_and_ver(base, pkg);
dir_t result = { path, mode };
return result;
}
void
gl_free_path(char *path)
{
free(path);
}
void
gl_free_dir(dir_t *dir)
{
if (dir && dir->path) {
free(dir->path);
dir->path = NULL;
}
}
int
gl_prepare_pkgdir(gl_pkg_t *pkg, bool is_syspkg)
{
dir_t pkg_root = { pkg -> pkg_name, 0750 };
dir_t pkg_store_final;
dir_t pkg_index_final;
if (!is_syspkg) {
dir_t pkg_store_initial = gl_return_dir(&gl_usr_store, &pkg_root, 0750);
pkg_store_final = gl_return_dir_and_ver(&pkg_store_initial, pkg, 0750);
dir_t pkg_index_initial = gl_return_dir(&gl_usr_index, &pkg_root, 0750);
pkg_index_final = gl_return_dir_and_ver(&pkg_index_initial, pkg, 0750);
}
else if (is_syspkg) {
dir_t pkg_store_initial = gl_return_dir(&gl_sys_store, &pkg_root, 0750);
pkg_store_final = gl_return_dir_and_ver(&pkg_store_initial, pkg, 0750);
dir_t pkg_index_initial = gl_return_dir(&gl_sys_index, &pkg_root, 0750);
pkg_index_final = gl_return_dir_and_ver(&pkg_index_initial, pkg, 0750);
}
printf("%s\n%s\n", pkg_index_final.path, pkg_store_final.path);
gl_free_dir(&pkg_index_final);
gl_free_dir(&pkg_store_final);
return 0;
}
void
gl_show_pkg_props(const gl_pkg_t *pkg)
{
if (!pkg) {
printf("(null pkg)\n");
return;
}
printf("Package: %s\n", pkg->pkg_name);
printf("Version: %d.%d.%d\n", pkg->pkg_ver.maj, pkg->pkg_ver.min, pkg->pkg_ver.pat);
printf("Description: %s\n", pkg->pkg_desc);
printf("Maintainer: %s\n", pkg->pkg_maint);
printf("Copyright: %s\n", pkg->pkg_copyright);
if (pkg->pkg_dependencies) {
printf("Dependencies:\n");
dep_t *dep = pkg->pkg_dependencies;
printf("\t~ %s (%d.%d.%d)\n",
dep->dep_name,
dep->dep_ver.maj, dep->dep_ver.min, dep->dep_ver.pat);
}
else {
printf("Dependencies: (none)\n");
}
if (pkg->pkg_conflicts) {
printf("Conflicting packages:\n");
conf_t *conf = pkg->pkg_conflicts;
printf("\t~ %s (%d.%d.%d)\n",
conf->conf_name,
conf->conf_ver.maj, conf->conf_ver.min, conf->conf_ver.pat);
}
else {
printf("Conflicting packages: (none)\n");
}
}
int
main(void)
{
semver_t foo_v = gl_pkgver(1, 1, 1);
dep_t dep_empty = {"empty", foo_v};
conf_t conf_empty = {"empty", foo_v};
gl_pkg_t *foo = gl_spawn_pkg(
"foo",
&foo_v,
"example pkg",
"liamwaldron@everestlinux.org",
"GPL3",
&dep_empty,
&conf_empty
);
gl_show_pkg_props(foo);
gl_show_pkg_props(&empty);
if (gl_prepare_pkgdir(foo, false) == 0) {
printf("Package prepared\n");
return 0;
}
else {
return 1;
}
}

1
src/pkg.hpp Normal file
View File

@@ -0,0 +1 @@
#ifndef

BIN
src/x_log

Binary file not shown.

BIN
src/x_pkg Executable file

Binary file not shown.