This commit is contained in:
kento2 2026-09-06 14:11:51 +02:00
parent 1112bf28c8
commit 7af09a8b2a
9 changed files with 217 additions and 66 deletions

21
README
View file

@ -1,18 +1,5 @@
depends: https://github.com/arp242/toml-c
most development currently happens in ./pkin.
# development is kinda stuck
cause c does not support
coroutines/concurrency/parallelism properly.
expected usage:
(1) pkg_add /path/to/source/code/with/template/file
(2) pkg_add name of source template in source repo
We need a template format that specifies compiletime
dependencies in addition to the standart rpm spec fields
such as name, description, build script, etc..
In the case of (2), it must also specify an URL to get the
source code from.
in the end it should produce an rpm package and install it
(with dnf). referenced packages(like in dependencies) should
use the name from fedoras package list.
If a source template depends on another package that only
exists as a source template, pkg_add must make sure to
compile that first.

View file

@ -1,2 +1 @@
lr 1.0 foo http://localhost:8081/example.binpkg.tar
asd 1.0 asd http://kentoj/index.html
lr 1.0 foo http://localhost:8081/example.binpkg.tar 95f7a5fbfe6e126c88543b1291e031719d67bc28df6f9753b0a6fd891056500a

View file

@ -9,6 +9,7 @@ project(
cc = meson.get_compiler('c')
deps = [
cc.find_library('libowfat'),
cc.find_library('libbearssl'),
]
add_project_arguments(

View file

@ -42,11 +42,9 @@ int extract(char *in, const char *out)
{
struct archive *reader = NULL, *writer = NULL;
struct archive_entry *ent;
stralloc path;
int ret = 0;
int r;
size_t l;
const char *oldpath;
char *newpath;
reader = archive_read_new();
archive_read_support_filter_all(reader);
@ -68,13 +66,15 @@ int extract(char *in, const char *out)
goto done;
}
oldpath = archive_entry_pathname(ent);
newpath = alloca(str_len(oldpath) + str_len(out) + 1);
l = str_copy(newpath, out);
l += str_copy(newpath + l, "/");
str_copy(newpath + l, oldpath);
msg(oldpath, " -> ", newpath);
archive_entry_set_pathname(ent, newpath);
if (!stralloc_copys(&path, out)
|| !stralloc_cats(&path, "/")
|| !stralloc_cats(&path, archive_entry_pathname(ent))
|| !stralloc_0(&path)
) {
carpsys("append to stralloc");
goto done;
}
archive_entry_set_pathname(ent, path.s);
if (archive_write_header(writer, ent) != 0) {
carp("failed to write header ", errstr(writer));
@ -100,6 +100,7 @@ done:
archive_write_close(writer);
archive_write_free(writer);
}
stralloc_free(&path);
return ret;
}

View file

@ -1,5 +1,6 @@
#include <libowfat/errmsg.h>
#include <libowfat/str.h>
#include <libowfat/stralloc.h>
#include <unistd.h>
#include "../pkin.h"
@ -11,44 +12,12 @@ static int find_package(char *name, pkin_pkgmeta *pkgmeta)
{
pkin_repo_iter iter;
pkin_repo_iter_init(&iter);
while (pkin_repo_iter_read(&iter, pkgmeta))
if (str_equal(pkgmeta->name, name))
return 1;
return 0;
}
static void run(int argc, char **argv)
{
int i;
pkin_pkgmeta pkgmeta;
pkin_queue fetchq, extractq;
stralloc archivename;
if (!pkin_queue_prepare(&fetchq)
|| !pkin_queue_prepare(&extractq)
) die(111, "failed to create queue");
for (i = 0; i < argc; i++) {
if (!find_package(argv[i], &pkgmeta))
die(100, "package '", argv[i], "' not found ");
stralloc_copys(&archivename, pkgmeta.name);
stralloc_cats(&archivename, ".archive");
stralloc_0(&archivename);
pkin_queue_fetch_add(&fetchq, pkgmeta.url, archivename.s);
pkin_queue_extract_add(&extractq, archivename.s, pkgmeta.name);
if (pkin_verbose)
msg("queueing fetch/extract: ", pkgmeta.url);
}
stralloc_free(&archivename);
msg("fetching binary packages");
if (!pkin_queue_fetch_start(&fetchq))
die(111, "failed fetching packages");
msg("extracting fetched packages");
if (!pkin_queue_extract_start(&extractq))
die(111, "failed extracting packages");
}
void command_fetch(int argc, char **argv)
{
int i;
@ -63,5 +32,5 @@ void command_fetch(int argc, char **argv)
argc -= i;
argv += i;
run(argc, argv);
//run(argc, argv);
}

View file

@ -8,8 +8,8 @@
#include <libowfat/stralloc.h>
#include <libowfat/array.h>
#include <libowfat/buffer.h>
#include <bearssl_hash.h>
#include <limits.h>
#include <jansson.h>
#define PKIN_PKGMETA_NAME_MAX 128
#define PKIN_PKGMETA_DESCR_MAX 256
@ -25,6 +25,7 @@ typedef struct {
char descr[PKIN_PKGMETA_DESCR_MAX];
char version[PKIN_PKGMETA_VERSION_MAX];
char url[PKIN_PKGMETA_URL_MAX]; /* url to download binary package from */
char sha256sum[br_sha256_SIZE];
} pkin_pkgmeta;
typedef struct {
@ -56,10 +57,14 @@ typedef struct {
} pkin_queue;
int pkin_queue_prepare(pkin_queue *queue);
#define pkin_queue_fetch_prepare(q) pkin_queue_prepare(q)
void pkin_queue_fetch_add(pkin_queue *fetchqueue, char *url, char *output);
int pkin_queue_fetch_start(pkin_queue *fetchqueue);
#define pkin_queue_extract_prepare(q) pkin_queue_prepare(q)
void pkin_queue_extract_add(pkin_queue *extractqueue, char *src, char *dest);
int pkin_queue_extract_start(pkin_queue *extractqueue);
int pkin_fetch_and_install(array *pkgmetas);
#endif

View file

@ -0,0 +1,170 @@
#include <asm-generic/errno-base.h>
#include <bearssl_hash.h>
#include <libowfat/array.h>
#include <libowfat/buffer.h>
#include <libowfat/byte.h>
#include <libowfat/errmsg.h>
#include <libowfat/str.h>
#include <libowfat/stralloc.h>
#include <libowfat/open.h>
#include <unistd.h>
#include "../pkin.h"
static int get_cache_path(stralloc *sa, pkin_pkgmeta *pkgmeta)
{
if (!stralloc_copys(sa, PATH_CACHE)
|| !stralloc_cats(sa, "/")
|| !stralloc_cats(sa, pkgmeta->name)
|| !stralloc_cats(sa, "-")
|| !stralloc_cats(sa, pkgmeta->version)
|| !stralloc_cats(sa, ".pkinpkg")
|| !stralloc_0(sa)
) return 0;
return 1;
}
static int verify_checksum(pkin_pkgmeta *pkgmeta, int fd)
{
br_sha256_context ctx;
char buf[8192];
int r;
for(;;) {
r = read(fd, buf, sizeof(buf));
if (r == 0) break;
if (r < 0) { close(fd); return 0; }
br_sha224_update(&ctx, buf, r);
}
char out[br_sha256_SIZE];
br_sha256_out(&ctx, out);
return byte_diff(out, br_sha256_SIZE, pkgmeta->sha256sum) == 0;
}
static int fetch_all(array *pkgmetas)
{
array pkgbindirs;
char pkgbindir[] = PATH_TMP"/pkin.XXXXX";
pkin_queue queue;
int success, i, len;
stralloc path;
pkin_pkgmeta *pkgmeta;
success = 0;
if (!pkin_queue_fetch_prepare(&queue)) {
carpsys("prepare queue");
goto fetch_out;
}
/* add all pkgmetas with no valid cache entry to fetch-queue */
len = array_length(pkgmetas, sizeof(pkin_pkgmeta));
for (i = 0; i < len; i++) {
pkgmeta = array_get(pkgmetas, sizeof(pkin_pkgmeta), i);
if (!get_cache_path(&path, pkgmeta)) {
carpsys("append to stralloc");
goto fetch_out;
}
}
/* actually fetch files */
if (!pkin_queue_fetch_start(&queue)) {
carpsys("failed to fetch some packages");
goto fetch_out;
}
/* verify checksums */
for (i = 0; i < len; i++) {
pkgmeta = array_get(pkgmetas, sizeof(pkin_pkgmeta), i);
if (!get_cache_path(&path, pkgmeta)) {
carpsys("append to stralloc");
goto fetch_out;
}
fd = open_read(path.s);
if (fd < 0) {
carpsys("open_read ", path.s, "(fetched from ", pkgmeta->url, ")");
goto fetch_out;
}
if (!verify_checksum(pkgmeta, fd)) {
carpsys("Checksum mismatch for ", path.s, " from ", pkgmeta->url);
goto fetch_out;
}
close(fd);
}
success = 1;
fetch_out:
stralloc_free(&path);
return success;
}
static int extract_all(array *pkgmetas)
{
pkin_queue queue;
int success, i, len;
stralloc path;
pkin_pkgmeta *pkgmeta;
success = 0;
if (!pkin_queue_extract_prepare(&queue)) {
carpsys("prepare queue");
goto extract_out;
}
char binpkgdir[] = "/tmp/pkin.XXXXX";
len = array_length(pkgmetas, sizeof(pkin_pkgmeta));
for (i = 0; i < len; i++) {
pkgmeta = array_get(pkgmetas, sizeof(pkin_pkgmeta), i);
if (!get_cache_path(&path, pkgmeta)) {
carpsys("append to stralloc");
goto extract_out;
}
pkin_queue_extract_add(&queue, path.s, );
}
if (!pkin_queue_extract_start(&queue)) {
carpsys("failed to fetch package");
goto extract_out;
}
success = 1;
extract_out:
stralloc_free(&path);
return success;
}
static int install(pkin_pkgmeta *pkgmeta, char *binkpgdir)
{
}
static void run(int argc, char **argv)
{
int i;
pkin_pkgmeta pkgmeta;
pkin_queue fetchq, extractq;
stralloc archive_part, archive;
if (!pkin_queue_fetch_prepare(&fetchq)
|| !pkin_queue_extract_prepare(&extractq)
) die(111, "failed to create queue");
for (i = 0; i < argc; i++) {
if (!find_package(argv[i], &pkgmeta))
die(100, "package '", argv[i], "' not found ");
if (!cache_part_path(&archive_part, &pkgmeta)
|| !cache_completed_path(&archive, &pkgmeta)
) diesys(111, "append to stralloc");
pkin_queue_fetch_add(&fetchq, pkgmeta.url, archive_part.s);
pkin_queue_extract_add(&extractq, archivename.s, pkgmeta.name);
if (pkin_verbose)
msg("queueing fetch/extract: ", pkgmeta.url);
}
stralloc_free(&archivename);
msg("fetching binary packages");
if (!pkin_queue_fetch_start(&fetchq))
die(111, "failed fetching packages");
msg("extracting fetched packages");
if (!pkin_queue_extract_start(&extractq))
die(111, "failed extracting packages");
}

View file

@ -21,7 +21,8 @@ int pkin_queue_fetch_start(pkin_queue *queue)
* to not flood the terminal. It will still always send the
* "Download Results"-report. */
cmd = (char *[]){"aria2c", "--console-log-level=warn",
"--enable-color=false", "--allow-overwrite=true", "-i", "-", NULL};
"--enable-color=false", "--allow-overwrite=true", "--input-file=-",
"--dir=/", NULL};
pid = pkin__spawn(cmd, queue->pipefd[0], 1, 2);
if (pid < 0) {
carp("failed spawning aria2c to fetch files");

View file

@ -1,3 +1,4 @@
#include <bearssl_hash.h>
#include <libowfat/array.h>
#include <libowfat/buffer.h>
#include <libowfat/errmsg.h>
@ -23,9 +24,17 @@ static int parse_field(char *line, char *field, size_t fieldmax)
return l;
}
static int hexval(char c) {
if (c>='0' && c<='9') return c-'0';
if (c>='a' && c<='f') return c-'a'+10;
if (c>='A' && c<='F') return c-'A'+10;
return -1;
}
static int parse_pkgmeta(char *line, pkin_pkgmeta *res)
{
size_t l;
size_t l, i;
int high, low;
l = parse_field(line, res->name, PKIN_PKGMETA_NAME_MAX);
if (l == 0) goto skip;
@ -41,10 +50,19 @@ static int parse_pkgmeta(char *line, pkin_pkgmeta *res)
l = parse_field(line, res->url, PKIN_PKGMETA_URL_MAX);
if (l == 0) goto skip;
line += l+1;
// TODO use bearssl length var
if (str_len(line) != 64) goto skip;
for (i = 0; i < 32; i++) {
high = hexval(line[i*2]);
low = hexval(line[i*2+1]);
if (high < 0 || low < 0) goto skip;
res->sha256sum[i] = (unsigned char)((high<<4)|low);
}
return 1;
skip:
carp("skipping malformed pkgmeta: '", line, "'");
return 0;
}