Compare commits

..

29 Commits

Author SHA1 Message Date
Jonas 'Sortie' Termansen 58dcca3b5e Add kernel(7) --firmware option. 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen 3f4e1a4732 Add fatfs(8). 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen 718f69e576 Add mtools port. 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen db9e4f415c Add getty(8). 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen 30c6849616 Add terminal and interrupt support to com(4). 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen cbe2ba567b Add nyan(1). 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen c8c6f48037 Draft video-player. 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen ea89ece89c Work around pty deadlock. 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen 0b32b1fc93 Add cdrom mounting live environment. 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen 0969b54fb6 Revert "Parallelize driver initialization."
This reverts commit 0fef08bbc4.
2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen 6dad066eaf Parallelize driver initialization. 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen 2a1263c647 Speed up ata(4) 400 ns waits.
Waiting for any non-zero duration currently waits for at least one timer
cycle (10 ms), which is especially expensive during early boot.

The current workaround of simply reading the status 14 times seems really
suspicious although the osdev wiki documents it, but let's see how well it
works on real hardware, it's probably good enough.

Try to determine the initial selected drive to save one drive selection.
2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen 4a8d728fa6 Decrease PS/2 timeouts. 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen b5cab6ccbd Add uptime(1) -pr options. 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen 2447eeb18c Add iso9660 filesystem implementation. 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen 539dfe1833 Add kernel virtual address space usage debug information. 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen 1d48ebecf8 Revert "Update to bison-3.8.2."
This reverts commit b82fae810b42c5426d21c4dc153b32f086dd7fde.
2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen 05b709480b Update to bison-3.8.2. 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen edf9987b2c Debug TCP socket state listing. 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen 68b73fd2b3 Add kernel heap allocation tracing debug facility. 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen f0a635fd8c Trianglix 4. 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen cfa4d0cac1 Add tix-check(8). 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen f180e2ca98 Volatile release. 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen 86d12f43a6 Add tix-upgrade(8). 2023-12-25 19:48:59 +01:00
Jonas 'Sortie' Termansen ddc60e265a Add tix-repository(8).
Support renaming, splitting, and deleting ports via RENAMES.
2023-12-25 19:48:47 +01:00
Jonas 'Sortie' Termansen f0caedab74 Add signify port. 2023-12-25 19:48:25 +01:00
Jonas 'Sortie' Termansen c5beb7bf51 Add pty(1). 2023-12-25 19:48:25 +01:00
Jonas 'Sortie' Termansen 373cf6cd3a Add irc(1).
Co-authored-by: Juhani Krekelä <juhani@krekelä.fi>
2023-12-25 19:48:25 +01:00
Jonas 'Sortie' Termansen 26290f64ce Add getaddrinfo(1). 2023-12-25 19:48:25 +01:00
9 changed files with 158 additions and 556 deletions

View File

@ -22,7 +22,6 @@ editor \
ext \
fat \
games \
host \
hostname \
ifconfig \
init \
@ -686,6 +685,7 @@ release-repository: sysroot $(SYSTEM_INITRD) $(SORTIX_RELEASE_DIR)/$(RELEASE)/re
cp $(SORTIX_REPOSITORY_DIR)/$(HOST)/$$port.tix.tar.xz $(SORTIX_RELEASE_DIR)/$(RELEASE)/repository/$(HOST) && \
cp $(SORTIX_REPOSITORY_DIR)/$(HOST)/$$port.version $(SORTIX_RELEASE_DIR)/$(RELEASE)/repository/$(HOST); \
done
tix-repository --generation=3 $(SORTIX_RELEASE_DIR)/$(RELEASE)/repository/$(HOST)
.PHONY: release-scripts
release-scripts: \

1
host/.gitignore vendored
View File

@ -1 +0,0 @@
host

View File

@ -1,25 +0,0 @@
include ../build-aux/platform.mak
include ../build-aux/compiler.mak
include ../build-aux/version.mak
include ../build-aux/dirs.mak
OPTLEVEL?=$(DEFAULT_OPTLEVEL)
CFLAGS?=$(OPTLEVEL)
CFLAGS += -Wall -Wextra
BINARIES = host
all: $(BINARIES)
.PHONY: all install clean
install: all
mkdir -p $(DESTDIR)$(BINDIR)
install $(BINARIES) $(DESTDIR)$(BINDIR)
%: %.c
$(CC) -std=gnu11 $(CFLAGS) $(CPPFLAGS) $< -o $@
clean:
rm -f $(BINARIES)

View File

@ -1,511 +0,0 @@
/*
* Copyright (c) 2016 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* host.c
* Domain name system client.
*/
#include <sys/dnsconfig.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <endian.h>
#include <err.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DNS_SIZE 512
#define DNS_NAME_MAX 255
#define DNS_LABEL_MAX 64
struct dns_header
{
uint16_t id;
uint16_t flags;
uint16_t qdcount;
uint16_t ancount;
uint16_t nscount;
uint16_t arcount;
};
struct dns_question
{
uint16_t qtype;
uint16_t qclass;
};
struct dns_record
{
uint16_t type;
uint16_t class;
uint16_t ttl_high;
uint16_t ttl_low;
uint16_t rdlength;
};
#define DNS_HEADER_FLAGS_RCODE_MASK (0xF << 0)
#define DNS_HEADER_FLAGS_RCODE_NO (0 << 0)
#define DNS_HEADER_FLAGS_RCODE_FORMAT (1 << 0)
#define DNS_HEADER_FLAGS_RCODE_SERVER (2 << 0)
#define DNS_HEADER_FLAGS_RCODE_NAME (3 << 0)
#define DNS_HEADER_FLAGS_RCODE_NOT_IMPLEMENTED (4 << 0)
#define DNS_HEADER_FLAGS_RCODE_REFUSED (5 << 0)
#define DNS_HEADER_FLAGS_RA (1 << 7)
#define DNS_HEADER_FLAGS_RD (1 << 8)
#define DNS_HEADER_FLAGS_TC (1 << 9)
#define DNS_HEADER_FLAGS_AA (1 << 10)
#define DNS_HEADER_FLAGS_OPCODE_MASK (0xF << 11)
#define DNS_HEADER_FLAGS_OPCODE_QUERY (0 << 11)
#define DNS_HEADER_FLAGS_OPCODE_IQUERY (1 << 11)
#define DNS_HEADER_FLAGS_OPCODE_STATUS (2 << 11)
#define DNS_HEADER_FLAGS_QR (1 << 15)
#define DNS_TYPE_A 1
#define DNS_TYPE_NS 2
#define DNS_TYPE_MD 3
#define DNS_TYPE_MF 4
#define DNS_TYPE_CNAME 5
#define DNS_TYPE_SOA 6
#define DNS_TYPE_MB 7
#define DNS_TYPE_MG 8
#define DNS_TYPE_MR 9
#define DNS_TYPE_NULL 10
#define DNS_TYPE_WKS 11
#define DNS_TYPE_PTR 12
#define DNS_TYPE_HINFO 13
#define DNS_TYPE_MINFO 14
#define DNS_TYPE_MX 15
#define DNS_TYPE_TXT 16
#define DNS_TYPE_AAAA 28
#define DNS_QTYPE_AXFR 252
#define DNS_QTYPE_MAILB 253
#define DNS_QTYPE_MAILA 254
#define DNS_QTYPE_ANY 255
#define DNS_CLASS_IN 1
#define DNS_CLASS_CS 2
#define DNS_CLASS_CH 3
#define DNS_CLASS_HS 4
#define DNS_QCLASS_ANY 255
static size_t encode_dns_header(unsigned char* msg,
size_t offset,
const struct dns_header* hdrin)
{
struct dns_header hdr;
if ( DNS_SIZE - offset < sizeof(hdr) )
errx(1, "dns message too large");
hdr.id = htobe16(hdrin->id);
hdr.flags = htobe16(hdrin->flags);
hdr.qdcount = htobe16(hdrin->qdcount);
hdr.ancount = htobe16(hdrin->ancount);
hdr.nscount = htobe16(hdrin->nscount);
hdr.arcount = htobe16(hdrin->arcount);
memcpy(msg + offset, &hdr, sizeof(hdr));
return offset + sizeof(hdr);
}
static size_t encode_dns_byte(unsigned char* msg,
size_t offset,
unsigned char byte)
{
if ( DNS_SIZE - offset < 1 )
errx(1, "dns message too large");
msg[offset] = byte;
return offset + 1;
}
static size_t encode_dns_name(unsigned char* msg,
size_t offset,
const char* name)
{
size_t index = 0;
size_t namelen = 0;
if ( !name[0] )
errx(1, "'%s' is not a valid name (unexpected end of input)", name);
while ( name[index] )
{
if ( !strcmp(name + index, ".") )
break;
if ( name[index] == '.' )
errx(1, "'%s' is not a valid name (empty label)", name);
size_t length = strcspn(name + index, ".");
if ( DNS_LABEL_MAX <= length )
errx(1, "'%s' is not a valid name (label too long)", name);
if ( namelen++ == DNS_NAME_MAX )
errx(1, "'%s' is not a valid name (name is too long)", name);
offset = encode_dns_byte(msg, offset, length & 0xFF);
for ( size_t i = 0; i < length; i++ )
{
if ( namelen++ == DNS_NAME_MAX )
errx(1, "'%s' is not a valid name (name is too long)", name);
offset = encode_dns_byte(msg, offset, name[index + i]);
}
index += length;
if ( name[index] == '.' )
index++;
}
if ( namelen++ == DNS_NAME_MAX )
errx(1, "'%s' is not a valid name (name is too long)", name);
offset = encode_dns_byte(msg, offset, 0);
return offset;
}
static size_t encode_dns_question(unsigned char* msg,
size_t offset,
const char* name,
const struct dns_question* qsin)
{
offset = encode_dns_name(msg, offset, name);
struct dns_question qs;
if ( DNS_SIZE - offset < sizeof(qs) )
errx(1, "dns message too large");
qs.qtype = htobe16(qsin->qtype);
qs.qclass = htobe16(qsin->qclass);
memcpy(msg + offset, &qs, sizeof(qs));
return offset + sizeof(qs);
}
static size_t decode_dns_header(const unsigned char* msg,
size_t offset,
size_t msg_size,
struct dns_header* hdrout)
{
struct dns_header hdr;
if ( msg_size - offset < sizeof(hdr) )
errx(1, "dns message too small");
memcpy(&hdr, msg + offset, sizeof(hdr));
hdrout->id = be16toh(hdr.id);
hdrout->flags = be16toh(hdr.flags);
hdrout->qdcount = be16toh(hdr.qdcount);
hdrout->ancount = be16toh(hdr.ancount);
hdrout->nscount = be16toh(hdr.nscount);
hdrout->arcount = be16toh(hdr.arcount);
return offset + sizeof(hdr);
}
static size_t decode_dns_byte(const unsigned char* msg,
size_t offset,
size_t msg_size,
unsigned char* byte)
{
if ( msg_size <= offset || msg_size - offset < 1 )
errx(1, "dns message too small");
*byte = msg[offset];
return offset + 1;
}
static size_t decode_dns_name(const unsigned char* msg,
size_t offset,
size_t msg_size,
char* name)
{
bool real_offset_set = false;
size_t real_offset = 0;
size_t index = 0;
size_t namelen = 0;
uint8_t b;
while ( true )
{
if ( namelen++ == DNS_NAME_MAX )
errx(1, "name too long");
offset = decode_dns_byte(msg, offset, msg_size, &b);
if ( 0xC0 & b )
{
namelen--;
size_t ptr = (b & 0x3F) << 8;
offset = decode_dns_byte(msg, offset, msg_size, &b);
ptr |= b;
if ( !real_offset_set )
{
real_offset = offset;
real_offset_set = true;
}
offset = ptr;
continue;
}
size_t length = b;
if ( DNS_LABEL_MAX <= length )
errx(1, "label too long");
if ( !length )
break;
if ( index )
name[index++] = '.';
for ( size_t i = 0; i < length; i++ )
{
if ( namelen++ == DNS_NAME_MAX )
errx(1, "name too long");
offset = decode_dns_byte(msg, offset, msg_size, &b);
// TODO: Handle if b == '.'.
name[index++] = b;
}
}
name[index++] = '.';
name[index] = '\0';
if ( real_offset_set )
return real_offset;
return offset;
}
static size_t decode_dns_question(const unsigned char* msg,
size_t offset,
size_t msg_size,
char* name,
struct dns_question* qsout)
{
offset = decode_dns_name(msg, offset, msg_size, name);
struct dns_question qs;
if ( msg_size <= offset || msg_size - offset < sizeof(qs) )
errx(1, "dns message too small");
memcpy(&qs, msg + offset, sizeof(qs));
qsout->qtype = be16toh(qs.qtype);
qsout->qclass = be16toh(qs.qclass);
return offset + sizeof(qs);
}
static size_t decode_dns_record(const unsigned char* msg,
size_t offset,
size_t msg_size,
char* name,
struct dns_record* rrout)
{
offset = decode_dns_name(msg, offset, msg_size, name);
struct dns_record rr;
if ( msg_size <= offset || msg_size - offset < sizeof(rr) )
errx(1, "dns message too small");
memcpy(&rr, msg + offset, sizeof(rr));
rrout->type = be16toh(rr.type);
rrout->class = be16toh(rr.class);
rrout->ttl_high = be16toh(rr.ttl_high);
rrout->ttl_low = be16toh(rr.ttl_low);
rrout->rdlength = be16toh(rr.rdlength);
return offset + sizeof(rr);
}
static void compact_arguments(int* argc, char*** argv)
{
for ( int i = 0; i < *argc; i++ )
{
while ( i < *argc && !(*argv)[i] )
{
for ( int n = i; n < *argc; n++ )
(*argv)[n] = (*argv)[n+1];
(*argc)--;
}
}
}
int main(int argc, char* argv[])
{
int ipv = 4;
const char* argv0 = argv[0];
for ( int i = 1; i < argc; i++ )
{
const char* arg = argv[i];
if ( arg[0] != '-' || !arg[1] )
continue;
argv[i] = NULL;
if ( !strcmp(arg, "--") )
break;
if ( arg[1] != '-' )
{
char c;
while ( (c = *++arg) ) switch ( c )
{
case '4': ipv = 4; break;
case '6': ipv = 6; break;
default:
fprintf(stderr, "%s: unknown option -- '%c'\n", argv0, c);
exit(1);
}
}
else
{
fprintf(stderr, "%s: unknown option: %s\n", argv0, arg);
exit(1);
}
}
compact_arguments(&argc, &argv);
if ( argc < 2 )
errx(1, "No host given");
const char* host = argv[1];
char nsipstr[INET_ADDRSTRLEN];
const char* nameserver;
if ( argc < 3 )
{
struct dnsconfig dnscfg;
if ( getdnsconfig(&dnscfg) < 0 )
err(1, "dnsconfig");
bool found = false;
for ( size_t i = 0; !found && i < dnscfg.servers_count; i++ )
{
if ( dnscfg.servers[i].family != AF_INET )
continue;
inet_ntop(AF_INET, &dnscfg.servers[i].addr, nsipstr, sizeof(nsipstr));
found = true;
}
if ( !found )
errx(1, "No nameserver given and no default configured");
nameserver = nsipstr;
}
else
nameserver = argv[2];
int port = 4 <= argc ? atoi(argv[3]) : 53;
if ( 5 <= argc )
errx(1, "Unexpected extra operand");
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if ( fd < 0 )
err(1, "socket");
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htobe16(port);
if ( inet_pton(AF_INET, nameserver, &addr.sin_addr) < 1 )
errx(1, "invalid ip address: %s", nameserver);
if ( connect(fd, (const struct sockaddr*) &addr, sizeof(addr)) < 0 )
err(1, "connect");
unsigned char req[DNS_SIZE];
size_t req_size = 0;
struct dns_header hdr;
hdr.id = 0;
hdr.flags = DNS_HEADER_FLAGS_RD;
hdr.qdcount = 1;
hdr.ancount = 0;
hdr.nscount = 0;
hdr.arcount = 0;
req_size = encode_dns_header(req, req_size, &hdr);
struct dns_question qs;
qs.qtype = ipv == 4 ? DNS_TYPE_A : DNS_TYPE_AAAA;
qs.qclass = DNS_CLASS_IN;
req_size = encode_dns_question(req, req_size, host, &qs);
ssize_t amount = send(fd, req, req_size, 0);
if ( amount < 0 )
err(1, "send");
// TODO: Use recvfrom to get the server ip.
unsigned char resp[DNS_SIZE];
ssize_t resp_size = recv(fd, resp, sizeof(resp), 0);
if ( resp_size < 0 )
err(1, "recv");
// TODO: Verify the response came from the correct ip.
size_t offset = 0;
offset = decode_dns_header(resp, offset, resp_size, &hdr);
// TODO: Verify the response has the correct id.
#if 0
printf("id = %u\n", hdr.id);
printf("flags = 0x%X\n", hdr.flags);
printf("qdcount = %u\n", hdr.qdcount);
printf("ancount = %u\n", hdr.ancount);
printf("nscount = %u\n", hdr.nscount);
printf("arcount = %u\n", hdr.arcount);
#endif
uint16_t rcode = hdr.flags & DNS_HEADER_FLAGS_RCODE_MASK;
if ( rcode == DNS_HEADER_FLAGS_RCODE_FORMAT )
errx(1, "format error");
else if ( rcode == DNS_HEADER_FLAGS_RCODE_SERVER )
errx(1, "server error");
else if ( rcode == DNS_HEADER_FLAGS_RCODE_NAME )
errx(1, "no such name");
else if ( rcode == DNS_HEADER_FLAGS_RCODE_NOT_IMPLEMENTED )
errx(1, "not implemented error");
else if ( rcode == DNS_HEADER_FLAGS_RCODE_REFUSED )
errx(1, "refused");
else if ( rcode != DNS_HEADER_FLAGS_RCODE_NO )
errx(1, "unknown error (rcode=0x%X)", rcode);
if ( hdr.flags & DNS_HEADER_FLAGS_TC )
errx(1, "truncated");
// TODO: Check query bit.
for ( uint16_t i = 0; i < hdr.qdcount; i++ )
{
char name[DNS_NAME_MAX + 1];
offset = decode_dns_question(resp, offset, resp_size, name, &qs);
//printf("%s type=%u class=%u\n", name, qs.qtype, qs.qclass);
}
for ( uint16_t i = 0; i < hdr.ancount; i++ )
{
char name[DNS_NAME_MAX + 1];
struct dns_record rr;
offset = decode_dns_record(resp, offset, resp_size, name, &rr);
uint32_t ttl = (uint32_t) rr.ttl_high << 16 | rr.ttl_low;
printf("%s type=%u class=%u ttl=%u ", name, rr.type, rr.class, ttl);
if ( rr.class == DNS_CLASS_IN && rr.type == DNS_TYPE_A )
{
unsigned char ip[4];
for ( size_t i = 0; i < 4; i++ )
offset = decode_dns_byte(resp, offset, resp_size, &ip[i]);
printf("%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
}
else if ( rr.class == DNS_CLASS_IN && rr.type == DNS_TYPE_AAAA )
{
unsigned char ip[16];
for ( size_t i = 0; i < 16; i++ )
offset = decode_dns_byte(resp, offset, resp_size, &ip[i]);
for ( size_t i = 0; i < 16; i++ )
{
if ( i && !(i & 1) )
putchar(':');
printf("%02x", ip[i]);
}
}
else if ( rr.type == DNS_TYPE_CNAME )
{
char cname[DNS_NAME_MAX + 1];
offset = decode_dns_name(resp, offset, resp_size, cname);
printf("CNAME %s", cname);
}
else
{
printf("0x");
fflush(stdout);
for ( size_t i = 0; i < rr.rdlength; i++ )
{
unsigned char b;
offset = decode_dns_byte(resp, offset, resp_size, &b);
if ( isprint(b) && b != '\'' )
printf("'%c'", b);
else
printf("%02X", b);
fflush(stdout);
}
}
printf("\n");
}
return 0;
}

View File

@ -34,6 +34,7 @@ tix-iso-add \
tix-iso-bootconfig \
tix-iso-liveconfig \
tix-port \
tix-repository \
tix-upgrade \
MANPAGES8=\

View File

@ -811,6 +811,9 @@ static void TixInfo(struct metainfo* minfo)
// TODO: Shell escape the values if needed.
fwrite_variable(tixinfo_fp, "TIX_VERSION", "3");
fwrite_variable(tixinfo_fp, "NAME", minfo->package_name);
const char* edition = metainfo_get(minfo, "EDITION", "pkg.edition");
if ( edition )
fwrite_variable(tixinfo_fp, "EDITION", edition);
const char* version = metainfo_get(minfo, "VERSION", "VERSION");
if ( version )
fwrite_variable(tixinfo_fp, "VERSION", version);
@ -829,6 +832,9 @@ static void TixInfo(struct metainfo* minfo)
else
fwrite_variable(tixinfo_fp, "PREFIX", minfo->prefix);
}
const char* renames = metainfo_get(minfo, "RENAMES", "pkg.renames");
if ( renames )
fwrite_variable(tixinfo_fp, "RENAMES", renames);
}
// TODO: After releasing Sortix 1.1, remove generation 2 compatibility.
else

View File

@ -37,6 +37,7 @@ output_sha256sum=
patch=false
package=false
release=false
repository_metadata=false
sha256=false
sha256sum=false
source=false
@ -115,6 +116,7 @@ for argument do
--output-upgrade-file) previous_option=output_upgrade_file ;;
--package) package=true ;;
--patch) patch=true ;;
--repository-metadata) repository_metadata=true ;;
--sha256) sha256=true ;;
--sha256sum) sha256sum=true ;;
--source-full) source_full=true ;;
@ -426,6 +428,8 @@ for REQUEST; do
if $package; then
REQUEST="$REQUEST.tix.tar.xz"
REQUESTDIR="repository/$MACHINE-sortix/"
elif $repository_metadata; then
REQUESTDIR="repository/$MACHINE-sortix/"
elif $boot; then
REQUEST="$REQUEST"
REQUESTDIR="$MACHINE/boot/"

96
tix/tix-repository Executable file
View File

@ -0,0 +1,96 @@
#!/bin/sh
# Copyright (c) 2023 Jonas 'Sortie' Termansen.
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# tix-repository
# Generate repository metadata.
set -e
generation=3
unset repository
operand=1
dashdash=
previous_option=
for argument do
if [ -n "$previous_option" ]; then
eval $previous_option=\$argument
previous_option=
continue
fi
case $argument in
*=?*) parameter=$(expr "X$argument" : '[^=]*=\(.*\)' || true) ;;
*=) parameter= ;;
*) parameter=yes ;;
esac
case $dashdash$argument in
--) dashdash=yes ;;
--generation=*) generation=$parameter ;;
--generation) previous_option=generation ;;
-*) echo "$0: unrecognized option $argument" >&2
exit 1 ;;
*)
if [ $operand = 1 ]; then
repository="$argument"
operand=2
else
echo "$0: unexpected extra operand $argument" >&2
exit 1
fi
;;
esac
done
if [ -n "$previous_option" ]; then
echo "$0: option '$argument' requires an argument" >&2
exit 1
fi
if [ -z "$repository" ]; then
echo "$0: error: No repository was specified" >&2
exit 1
fi
if [ "$generation" != 3 ]; then
echo "$0: error: --generation=$generation is not supported by this version" >&2
exit 1
fi
cd "$repository"
ls |
grep -E '\.tix.tar.xz$' |
grep -Eo '^[^.]*' |
LC_ALL=C sort -o packages.list
true > renames.list
true > manifest.list
for package in $(cat packages.list); do
tar -xOf "$package.tix.tar.xz" "tix/tixinfo/$package" > "$package.info"
tar -xOf "$package.tix.tar.xz" "tix/manifest/$package" > "$package.manifest"
sha256sum "$package.tix.tar.xz" > "$package.tix.tar.xz.sha256sum"
tix-vars -d '' "$package.info" RENAMES | tr , '\n' | sed -E '/^$/d' >> renames.list
sed -E "s/$/:$package/" "$package.manifest" >> manifest.list
done
LC_ALL=C sort -t: -k1,1 manifest.list -o manifest.list
find -type f '!' -name 'sha256sum' '!' -name '*.sha256sum' -exec sha256sum '{}' '+' |
sed -E 's, \./, ,' |
LC_ALL=C sort -k 2 > sha256sum

View File

@ -90,6 +90,10 @@ conf() {
tix-vars -d "$2" - "$4"
}
escape_extended_regex_sed() {
printf "%s\n" "$1" | sed -E -e 's/[[$()*?\+.^{|}'"$2"']/\\\0/g'
}
collection=$(cd "$collection" && pwd)
if ! $upgrade_ports && ! $upgrade_system; then
@ -183,27 +187,55 @@ else
done
fi
# Fetch each binary package from the mirror.
# TODO: Handle new mandatory / recommended ports.
# TODO: Handle renamed ports.
# TODO: Tracking sets like minimal/basic/full.
# TODO: Tracking sets like minimal/basic/full with new mandatory or recommended ports.
mkdir -p -- "$cachedir/repository"
tix-fetch $fetch_options \
--collection="$collection" \
--input-release-file="$cachedir/release.sh" \
--input-sha256sum="$cachedir/sha256sum" \
--repository-metadata -O "$cachedir/repository" renames.list
# Follow RENAMES recursively to handle renames, splits, and deletions.
rename() {
# TODO: Need to escape at least +.
if grep -Eq "^$(escape_extended_regex_sed "$1"):" "$cachedir/repository/renames.list"; then
for new in $(grep -E "^$1:" "$cachedir/repository/renames.list" |
grep -Eo '[^:]*$'); do
rename "$new"
done
else
echo "$1" | grep -Eo '^[^@]*'
fi
}
# Determine the final package list after the renames.
packages=""
for package in $(LC_ALL=C ls -- "$collection/tix/tixinfo"); do
# The package exists upstream if it has a hash.
sha256=$(tix-fetch $fetch_options \
--collection="$collection" \
--input-release-file="$cachedir/release.sh" \
--input-sha256sum="$cachedir/sha256sum" \
--sha256 --package -- $package)
if [ -n "$sha256" ]; then
tix-fetch $fetch_options \
--collection="$collection" \
--input-release-file="$cachedir/release.sh" \
--input-sha256sum="$cachedir/sha256sum" \
-c --package -O "$cachedir/repository" -- $package
packages="$packages $package"
fi
edition=$(tix-vars -d 1 "$collection/tix/tixinfo/$package" EDITION)
packages="$packages $(rename "$package@$edition")"
done
# Sort and deduplicate the package list and check for existence.
packages=$(for package in $packages; do
# The package exists upstream if it has a hash.
if [ -n "$(tix-fetch $fetch_options \
--collection="$collection" \
--input-release-file="$cachedir/release.sh" \
--input-sha256sum="$cachedir/sha256sum" \
--sha256 --package -- $package)" ]; then
echo $package
fi
done | LC_ALL=C sort -u)
# Fetch each binary package from the mirror.
for package in $packages; do
tix-fetch $fetch_options \
--collection="$collection" \
--input-release-file="$cachedir/release.sh" \
--input-sha256sum="$cachedir/sha256sum" \
-c --package -O "$cachedir/repository" -- $package
done
# Stop if only downloading.