Add tix-upgrade(8).
This commit is contained in:
parent
560e81d008
commit
0965628801
6
Makefile
6
Makefile
|
@ -237,6 +237,8 @@ sysroot-system: sysroot-fsh sysroot-base-headers
|
||||||
echo /etc/sortix-release >> "$(SYSROOT)/tix/manifest/system"
|
echo /etc/sortix-release >> "$(SYSROOT)/tix/manifest/system"
|
||||||
ln -sf sortix-release "$(SYSROOT)/etc/os-release"
|
ln -sf sortix-release "$(SYSROOT)/etc/os-release"
|
||||||
echo /etc/os-release >> "$(SYSROOT)/tix/manifest/system"
|
echo /etc/os-release >> "$(SYSROOT)/tix/manifest/system"
|
||||||
|
find etc | sed -e 's,^,/,' >> "$(SYSROOT)/tix/manifest/system"
|
||||||
|
cp -RT etc "$(SYSROOT)/etc"
|
||||||
find share | sed -e 's,^,/,' >> "$(SYSROOT)/tix/manifest/system"
|
find share | sed -e 's,^,/,' >> "$(SYSROOT)/tix/manifest/system"
|
||||||
cp -RT share "$(SYSROOT)/share"
|
cp -RT share "$(SYSROOT)/share"
|
||||||
export SYSROOT="$(SYSROOT)" && \
|
export SYSROOT="$(SYSROOT)" && \
|
||||||
|
@ -274,6 +276,7 @@ else ifneq ($(SORTIX_INCLUDE_SOURCE),no)
|
||||||
cp Makefile -t "$(SYSROOT)/src"
|
cp Makefile -t "$(SYSROOT)/src"
|
||||||
cp README -t "$(SYSROOT)/src"
|
cp README -t "$(SYSROOT)/src"
|
||||||
cp -RT build-aux "$(SYSROOT)/src/build-aux"
|
cp -RT build-aux "$(SYSROOT)/src/build-aux"
|
||||||
|
cp -RT etc "$(SYSROOT)/src/etc"
|
||||||
cp -RT share "$(SYSROOT)/src/share"
|
cp -RT share "$(SYSROOT)/src/share"
|
||||||
(for D in $(MODULES); do (cp -R $$D -t "$(SYSROOT)/src" && $(MAKE) -C "$(SYSROOT)/src/$$D" clean) || exit $$?; done)
|
(for D in $(MODULES); do (cp -R $$D -t "$(SYSROOT)/src" && $(MAKE) -C "$(SYSROOT)/src/$$D" clean) || exit $$?; done)
|
||||||
endif
|
endif
|
||||||
|
@ -457,6 +460,9 @@ $(LIVE_INITRD): sysroot
|
||||||
echo "include /etc/default/passwd.d/*" >> $(LIVE_INITRD).d/etc/passwd
|
echo "include /etc/default/passwd.d/*" >> $(LIVE_INITRD).d/etc/passwd
|
||||||
echo "root::0:root" > $(LIVE_INITRD).d/etc/group
|
echo "root::0:root" > $(LIVE_INITRD).d/etc/group
|
||||||
echo "include /etc/default/group.d/*" >> $(LIVE_INITRD).d/etc/group
|
echo "include /etc/default/group.d/*" >> $(LIVE_INITRD).d/etc/group
|
||||||
|
(echo 'channel = $(CHANNEL)' && \
|
||||||
|
echo 'release_key = $(RELEASE_KEY)' && \
|
||||||
|
echo 'release_sig_url = $(RELEASE_SIG_URL)') > $(LIVE_INITRD).d/etc/upgrade.conf
|
||||||
mkdir -p $(LIVE_INITRD).d/home
|
mkdir -p $(LIVE_INITRD).d/home
|
||||||
mkdir -p $(LIVE_INITRD).d/root -m 700
|
mkdir -p $(LIVE_INITRD).d/root -m 700
|
||||||
cp -RT "$(SYSROOT)/etc/skel" $(LIVE_INITRD).d/root
|
cp -RT "$(SYSROOT)/etc/skel" $(LIVE_INITRD).d/root
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
set_minimal="cut dash e2fsprogs grep grub mdocml sed xargs"
|
set_minimal="cut dash e2fsprogs grep grub libssl mdocml sed signify tar wget xargs xorriso xz"
|
||||||
set_basic="$set_minimal binutils bison bzip2 diffutils ed flex gawk gcc git gzip libcurl libcurses libssl libstdc++ nano ntpd make patch pkg-config python ssh tar vim wget xz xorriso"
|
set_basic="$set_minimal binutils bison bzip2 diffutils ed flex gawk gcc git gzip libcurl libcurses libstdc++ nano ntpd make patch pkg-config python ssh vim"
|
||||||
sets="basic minimal"
|
sets="basic minimal"
|
||||||
|
|
|
@ -1,2 +1,6 @@
|
||||||
VERSION=1.1dev
|
VERSION=1.1dev
|
||||||
|
CHANNEL?=nightly
|
||||||
RELEASE?=$(VERSION)
|
RELEASE?=$(VERSION)
|
||||||
|
RELEASE_MASTER?=https://sortix.org/release
|
||||||
|
RELEASE_KEY=/etc/signify/sortix-$(VERSION).pub
|
||||||
|
RELEASE_SIG_URL?=$(RELEASE_MASTER)/$(CHANNEL)/$(HOST_MACHINE).sh.sig
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
untrusted comment: signify public key
|
||||||
|
RWQiTQbFzyZJVobf/pn53Jp3njhRB9DgwkMaNakCpDE9RaTABMjlbz9W
|
|
@ -0,0 +1,2 @@
|
||||||
|
untrusted comment: signify public key
|
||||||
|
RWQnkSm9lj1YIZYpt1Y3mHYzFsaky82gQF6CrW4lme9OoEYzSIl2ZsIC
|
|
@ -0,0 +1,2 @@
|
||||||
|
untrusted comment: signify public key
|
||||||
|
RWTGrBXmGvl2zUpCa47ui5EyPsnitKLjsCZ2YZphNY8F3b33t6QWYDs1
|
|
@ -0,0 +1,2 @@
|
||||||
|
untrusted comment: signify public key
|
||||||
|
RWRTbLQ+3+a9I5yche2BEVP03TRtumGO4Vgq1AQ/5bRj8JAJ1R0+vpxE
|
|
@ -22,6 +22,10 @@ as part of
|
||||||
.Xr installation 7
|
.Xr installation 7
|
||||||
to match what was installed.
|
to match what was installed.
|
||||||
.Pp
|
.Pp
|
||||||
|
The file also controls the actions of
|
||||||
|
.Xr tix 8
|
||||||
|
when upgrading releases and installing ports.
|
||||||
|
.Pp
|
||||||
Developers may wish to customize what happens to
|
Developers may wish to customize what happens to
|
||||||
.Pa /src
|
.Pa /src
|
||||||
on a system upgrade.
|
on a system upgrade.
|
||||||
|
@ -45,7 +49,32 @@ Lines are supposed to contain assignments to variables.
|
||||||
An assignment is the name of the variable, whitespace, an equal character,
|
An assignment is the name of the variable, whitespace, an equal character,
|
||||||
whitespace, the value, whitespace, and then the end of the line.
|
whitespace, the value, whitespace, and then the end of the line.
|
||||||
.Bl -tag -width "12345678"
|
.Bl -tag -width "12345678"
|
||||||
.It Sy grub Ns "=" Ns Oo Sy no "|" yes Oc (default Sy no ) .
|
.It Sy channel Ns "=" Ns Ar channel
|
||||||
|
If the current release has an upgrade path named
|
||||||
|
.Ar channel
|
||||||
|
to a new release,
|
||||||
|
then system upgrades will upgrade to that new release.
|
||||||
|
If no such release path exists or if this variable is not set, upgrades will
|
||||||
|
continue to upgrade to the current release series.
|
||||||
|
Depending on the current release, the offically supported values are
|
||||||
|
.Sy stable
|
||||||
|
for stable releases and
|
||||||
|
.Sy nightly
|
||||||
|
for development releases.
|
||||||
|
Downgrading releases is not supported. For instance, if the current system is
|
||||||
|
a development release, specifying
|
||||||
|
.Sy stable
|
||||||
|
will not downgrade the system to the previous stable release, as no such upgrade
|
||||||
|
path exists.
|
||||||
|
Instead upgrades will upgrade to the next stable release when it becomes
|
||||||
|
available.
|
||||||
|
.It Sy force_mirror Ns "=" Ns Oo Sy no "|" yes Oc (default Sy no )
|
||||||
|
Use the preferred mirror set with
|
||||||
|
.Sy mirror
|
||||||
|
even if the file specified by
|
||||||
|
.Sy release_sig_url
|
||||||
|
does not list it.
|
||||||
|
.It Sy grub Ns "=" Ns Oo Sy no "|" yes Oc (default Sy no )
|
||||||
States GRUB is used as the bootloader.
|
States GRUB is used as the bootloader.
|
||||||
If either the
|
If either the
|
||||||
.Sy system
|
.Sy system
|
||||||
|
@ -57,7 +86,18 @@ then the bootloader is reinstalled
|
||||||
.Xr ( grub-install 8 )
|
.Xr ( grub-install 8 )
|
||||||
and updated
|
and updated
|
||||||
.Xr ( update-grub 8 ) .
|
.Xr ( update-grub 8 ) .
|
||||||
.It Sy newsrc Ns "=" Ns Oo Sy no "|" yes Oc (default Sy no ) .
|
.It Sy mirror Ns "=" Ns Ar mirror
|
||||||
|
Download releases and ports from this preferred
|
||||||
|
.Ar mirror ,
|
||||||
|
a URL to the top level directory of a mirror.
|
||||||
|
The mirror is only used if the file specified by
|
||||||
|
.Sy release_sig_url
|
||||||
|
lists this mirror, unless
|
||||||
|
.Sy force_mirror
|
||||||
|
is set to
|
||||||
|
.Sy yes .
|
||||||
|
If no mirror is set, a default mirror is used.
|
||||||
|
.It Sy newsrc Ns "=" Ns Oo Sy no "|" yes Oc (default Sy no )
|
||||||
Place the new source code in
|
Place the new source code in
|
||||||
.Pa /newsrc
|
.Pa /newsrc
|
||||||
and move any existing
|
and move any existing
|
||||||
|
@ -69,17 +109,39 @@ This preserves the current
|
||||||
directory.
|
directory.
|
||||||
This takes precedence over and disables the behavior described under
|
This takes precedence over and disables the behavior described under
|
||||||
.Sy src .
|
.Sy src .
|
||||||
.It Sy ports Ns "=" Ns Oo Sy no "|" yes Oc (default Sy yes ) .
|
.It Sy ports Ns "=" Ns Oo Sy no "|" yes Oc (default Sy yes )
|
||||||
Install the new ports.
|
Install the new ports.
|
||||||
Ports that don't exist anymore will be removed.
|
Ports that don't exist anymore will be removed.
|
||||||
.It Sy src Ns "=" Ns Oo Sy no "|" yes Oc (default Sy no ) .
|
.It Sy release_key Ns "=" Ns Ar release_key
|
||||||
|
Verify the file specified by
|
||||||
|
.Sy release_sig_url
|
||||||
|
with the
|
||||||
|
.Xr signify 1
|
||||||
|
public key file at the path
|
||||||
|
.Ar release_key .
|
||||||
|
This variable is updated during system upgrades and there is no need to change
|
||||||
|
this variable manually.
|
||||||
|
.It Sy release_sig_url Ns "=" Ns Ar release_sig_url
|
||||||
|
Download the meta-information about the current release from the URL
|
||||||
|
.Ar release_sig_url .
|
||||||
|
This file is verified with the
|
||||||
|
.Xr signify 1
|
||||||
|
public key in the
|
||||||
|
.Sy release_key
|
||||||
|
variable.
|
||||||
|
The file describes the current release, provides checksums of all the published
|
||||||
|
files, lists all the supported mirrors, provides instructions on how to upgrade
|
||||||
|
to this release, and lists all the supported upgrade paths to new releases.
|
||||||
|
This variable is updated during system upgrades and there is no need to change
|
||||||
|
this variable manually.
|
||||||
|
.It Sy src Ns "=" Ns Oo Sy no "|" yes Oc (default Sy no )
|
||||||
Place the new source code in
|
Place the new source code in
|
||||||
.Pa /src
|
.Pa /src
|
||||||
and move any existing
|
and move any existing
|
||||||
.Pa /src
|
.Pa /src
|
||||||
into
|
into
|
||||||
.Pa /oldsrc .
|
.Pa /oldsrc .
|
||||||
.It Sy system Ns "=" Ns Oo Sy no "|" yes Oc (default Sy yes ) .
|
.It Sy system Ns "=" Ns Oo Sy no "|" yes Oc (default Sy yes )
|
||||||
Install the new system.
|
Install the new system.
|
||||||
The upgrade hooks are run if needed as described in
|
The upgrade hooks are run if needed as described in
|
||||||
.Xr following-development 7 .
|
.Xr following-development 7 .
|
||||||
|
@ -96,6 +158,18 @@ then regenerate
|
||||||
The defaults will be used if
|
The defaults will be used if
|
||||||
.Pa /etc/upgrade.conf
|
.Pa /etc/upgrade.conf
|
||||||
is missing.
|
is missing.
|
||||||
|
If
|
||||||
|
.Sy release_key
|
||||||
|
or
|
||||||
|
.Sy release_sig_url
|
||||||
|
are absent,
|
||||||
|
.Xr tix 8
|
||||||
|
will not be able to upgrade the current system nor install ports.
|
||||||
|
If
|
||||||
|
.Sy channel
|
||||||
|
is absent,
|
||||||
|
.Xr tix 8
|
||||||
|
will not upgrade to new releases.
|
||||||
.Sh FILES
|
.Sh FILES
|
||||||
.Bl -tag -width "/etc/upgrade.conf" -compact
|
.Bl -tag -width "/etc/upgrade.conf" -compact
|
||||||
.It Pa /etc/upgrade.conf
|
.It Pa /etc/upgrade.conf
|
||||||
|
@ -103,11 +177,12 @@ Upgrade configuration.
|
||||||
.El
|
.El
|
||||||
.Sh EXAMPLES
|
.Sh EXAMPLES
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
system = yes
|
grub = yes
|
||||||
ports = yes
|
ports = yes
|
||||||
src = no
|
src = no
|
||||||
grub = yes
|
system = yes
|
||||||
.Ed
|
.Ed
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr upgrade 7 ,
|
.Xr upgrade 7 ,
|
||||||
.Xr sysupgrade 8
|
.Xr sysupgrade 8 ,
|
||||||
|
.Xr tix 8
|
||||||
|
|
|
@ -37,6 +37,10 @@ void conf_init(struct conf* conf)
|
||||||
|
|
||||||
void conf_free(struct conf* conf)
|
void conf_free(struct conf* conf)
|
||||||
{
|
{
|
||||||
|
free(conf->channel);
|
||||||
|
free(conf->mirror);
|
||||||
|
free(conf->release_key);
|
||||||
|
free(conf->release_sig_url);
|
||||||
conf_init(conf);
|
conf_init(conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,12 +64,43 @@ static bool conf_assign(struct conf* conf,
|
||||||
const char* path,
|
const char* path,
|
||||||
off_t line_number)
|
off_t line_number)
|
||||||
{
|
{
|
||||||
if ( !strcmp(name, "grub") )
|
char* new_value;
|
||||||
|
if ( !strcmp(name, "channel") )
|
||||||
|
{
|
||||||
|
if ( !(new_value = strdup(value)) )
|
||||||
|
return false;
|
||||||
|
free(conf->channel);
|
||||||
|
conf->channel = new_value;
|
||||||
|
}
|
||||||
|
else if ( !strcmp(name, "force_mirror") )
|
||||||
|
conf->force_mirror = conf_boolean(name, value, path, line_number);
|
||||||
|
else if ( !strcmp(name, "grub") )
|
||||||
conf->grub = conf_boolean(name, value, path, line_number);
|
conf->grub = conf_boolean(name, value, path, line_number);
|
||||||
|
else if ( !strcmp(name, "mirror") )
|
||||||
|
{
|
||||||
|
if ( !(new_value = strdup(value)) )
|
||||||
|
return false;
|
||||||
|
free(conf->mirror);
|
||||||
|
conf->mirror = new_value;
|
||||||
|
}
|
||||||
else if ( !strcmp(name, "newsrc") )
|
else if ( !strcmp(name, "newsrc") )
|
||||||
conf->newsrc = conf_boolean(name, value, path, line_number);
|
conf->newsrc = conf_boolean(name, value, path, line_number);
|
||||||
else if ( !strcmp(name, "ports") )
|
else if ( !strcmp(name, "ports") )
|
||||||
conf->ports = conf_boolean(name, value, path, line_number);
|
conf->ports = conf_boolean(name, value, path, line_number);
|
||||||
|
else if ( !strcmp(name, "release_key") )
|
||||||
|
{
|
||||||
|
if ( !(new_value = strdup(value)) )
|
||||||
|
return false;
|
||||||
|
free(conf->release_key);
|
||||||
|
conf->release_key = new_value;
|
||||||
|
}
|
||||||
|
else if ( !strcmp(name, "release_sig_url") )
|
||||||
|
{
|
||||||
|
if ( !(new_value = strdup(value)) )
|
||||||
|
return false;
|
||||||
|
free(conf->release_sig_url);
|
||||||
|
conf->release_sig_url = new_value;
|
||||||
|
}
|
||||||
else if ( !strcmp(name, "src") )
|
else if ( !strcmp(name, "src") )
|
||||||
conf->src = conf_boolean(name, value, path, line_number);
|
conf->src = conf_boolean(name, value, path, line_number);
|
||||||
else if ( !strcmp(name, "system") )
|
else if ( !strcmp(name, "system") )
|
||||||
|
|
|
@ -22,9 +22,14 @@
|
||||||
|
|
||||||
struct conf
|
struct conf
|
||||||
{
|
{
|
||||||
|
char* channel;
|
||||||
|
bool force_mirror;
|
||||||
bool grub;
|
bool grub;
|
||||||
|
char* mirror;
|
||||||
bool newsrc;
|
bool newsrc;
|
||||||
bool ports;
|
bool ports;
|
||||||
|
char* release_key;
|
||||||
|
char* release_sig_url;
|
||||||
bool src;
|
bool src;
|
||||||
bool system;
|
bool system;
|
||||||
};
|
};
|
||||||
|
|
|
@ -494,6 +494,21 @@ int main(void)
|
||||||
// TODO: You can leave this program by pressing ^C but it can leave your
|
// TODO: You can leave this program by pressing ^C but it can leave your
|
||||||
// system in an inconsistent state.
|
// system in an inconsistent state.
|
||||||
|
|
||||||
|
if ( conf.channel )
|
||||||
|
install_configurationf("upgrade.conf", "a", "channel = %s\n",
|
||||||
|
conf.channel);
|
||||||
|
if ( conf.force_mirror != false )
|
||||||
|
install_configurationf("upgrade.conf", "a", "force_mirror = %s\n",
|
||||||
|
conf.force_mirror ? "yes" : "no");
|
||||||
|
if ( conf.mirror )
|
||||||
|
install_configurationf("upgrade.conf", "a", "mirror = %s\n",
|
||||||
|
conf.mirror);
|
||||||
|
if ( conf.release_key )
|
||||||
|
install_configurationf("upgrade.conf", "a", "release_key = %s\n",
|
||||||
|
conf.release_key);
|
||||||
|
if ( conf.release_sig_url )
|
||||||
|
install_configurationf("upgrade.conf", "a", "release_sig_url = %s\n",
|
||||||
|
conf.release_sig_url);
|
||||||
install_configurationf("upgrade.conf", "a", "src = yes\n");
|
install_configurationf("upgrade.conf", "a", "src = yes\n");
|
||||||
|
|
||||||
// TODO: GUI support.
|
// TODO: GUI support.
|
||||||
|
|
|
@ -330,6 +330,10 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
if ( copy_files )
|
if ( copy_files )
|
||||||
{
|
{
|
||||||
|
// TODO: Update /etc/upgrade.conf with new release values.
|
||||||
|
// TODO: What about native upgrades using make sysmerge? Should those
|
||||||
|
// values be updated then? Should there be an option to control
|
||||||
|
// this behavior?
|
||||||
const char* target = "";
|
const char* target = "";
|
||||||
if ( wait )
|
if ( wait )
|
||||||
{
|
{
|
||||||
|
|
|
@ -868,6 +868,7 @@ int main(void)
|
||||||
}
|
}
|
||||||
if ( conf.system )
|
if ( conf.system )
|
||||||
upgrade_finalize(target_release, &new_release, "", ".");
|
upgrade_finalize(target_release, &new_release, "", ".");
|
||||||
|
// TODO: Update /etc/upgrade.conf with new release values.
|
||||||
if ( conf.system )
|
if ( conf.system )
|
||||||
{
|
{
|
||||||
printf(" - Creating initrd...\n");
|
printf(" - Creating initrd...\n");
|
||||||
|
|
|
@ -26,11 +26,14 @@ tix-vars \
|
||||||
|
|
||||||
PROGRAMS:=\
|
PROGRAMS:=\
|
||||||
$(BINARIES) \
|
$(BINARIES) \
|
||||||
|
tix-clean \
|
||||||
tix-eradicate-libtool-la \
|
tix-eradicate-libtool-la \
|
||||||
|
tix-fetch \
|
||||||
tix-iso-add \
|
tix-iso-add \
|
||||||
tix-iso-bootconfig \
|
tix-iso-bootconfig \
|
||||||
tix-iso-liveconfig \
|
tix-iso-liveconfig \
|
||||||
tix-port \
|
tix-port \
|
||||||
|
tix-upgrade \
|
||||||
|
|
||||||
MANPAGES8=\
|
MANPAGES8=\
|
||||||
tix-build.8 \
|
tix-build.8 \
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Copyright (c) 2017 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-clean
|
||||||
|
# Remove temporary tix files.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
collection=""
|
||||||
|
sysroot=""
|
||||||
|
|
||||||
|
dashdash=
|
||||||
|
previous_option=
|
||||||
|
for argument do
|
||||||
|
if test -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 ;;
|
||||||
|
-o) previous_option=output ;;
|
||||||
|
--collection=*) collection=$parameter ;;
|
||||||
|
--collection) previous_option=collection ;;
|
||||||
|
--sysroot=*) sysroot=$parameter ;;
|
||||||
|
--sysroot) previous_option=sysroot ;;
|
||||||
|
-*) echo "$0: unrecognized option $argument" >&2
|
||||||
|
exit 1 ;;
|
||||||
|
*)
|
||||||
|
if [ $operand = 1 ]; then
|
||||||
|
input="$argument"
|
||||||
|
operand=2
|
||||||
|
elif [ $operand = 2 ]; then
|
||||||
|
directory="$argument"
|
||||||
|
operand=3
|
||||||
|
else
|
||||||
|
echo "$0: unexpected extra operand $argument" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if test -n "$previous_option"; then
|
||||||
|
echo "$0: option '$argument' requires an argument" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf "$collection/var/cache/tix"
|
|
@ -0,0 +1,424 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Copyright (c) 2017, 2021 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-fetch
|
||||||
|
# Download operating system files.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
boot=false
|
||||||
|
collection=""
|
||||||
|
continue=""
|
||||||
|
execpatch=false
|
||||||
|
initrd=false
|
||||||
|
insecure_downgrade_to_http=false
|
||||||
|
insecure_no_check_certificate=false
|
||||||
|
input_release_file=
|
||||||
|
input_release_sig_file=
|
||||||
|
input_sha256sum=
|
||||||
|
normalize=false
|
||||||
|
output=""
|
||||||
|
outputdir=""
|
||||||
|
output_release_file= # TODO: A better term for this?
|
||||||
|
output_release_sig_file= # TODO: A better term for this?
|
||||||
|
output_sha256sum=
|
||||||
|
patch=false
|
||||||
|
port=false
|
||||||
|
porttix=false
|
||||||
|
release=false
|
||||||
|
sha256=false
|
||||||
|
sha256sum=false
|
||||||
|
source=false
|
||||||
|
source_full=false
|
||||||
|
srctix=false
|
||||||
|
sysroot=""
|
||||||
|
toolchain=false
|
||||||
|
url=false
|
||||||
|
url_master=false
|
||||||
|
url_master_release=false
|
||||||
|
url_mirror=false
|
||||||
|
url_mirror_release=false
|
||||||
|
url_release_sig=false
|
||||||
|
url_sha256sum=false
|
||||||
|
# TODO: Option to select this default:
|
||||||
|
# TODO: This hides errors. Fix wget so it has a quiet, but errors, mode.
|
||||||
|
wget_options="-q --show-progress"
|
||||||
|
|
||||||
|
# TODO: Ability to get source code easily for gcc/binutils/libstdc++.
|
||||||
|
|
||||||
|
dashdash=
|
||||||
|
previous_option=
|
||||||
|
for argument do
|
||||||
|
if test -n "$previous_option"; then
|
||||||
|
eval $previous_option=\$argument
|
||||||
|
previous_option=
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $argument in
|
||||||
|
*=?*) parameter=$(expr "X$argument" : '[^=]*=\(.*\)' || true) ;;
|
||||||
|
*=) parameter= ;;
|
||||||
|
*) parameter=yes ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case $dashdash$argument in
|
||||||
|
--) dashdash=yes ;;
|
||||||
|
-c) continue="-c" ;;
|
||||||
|
# TODO: Support -ofoo
|
||||||
|
-o) previous_option=output ;;
|
||||||
|
-O) previous_option=outputdir ;;
|
||||||
|
-q) wget_options="-q" ;;
|
||||||
|
-v) wget_options="-v" ;;
|
||||||
|
--boot) boot=true ;;
|
||||||
|
--collection=*) collection=$parameter ;;
|
||||||
|
--collection) previous_option=collection ;;
|
||||||
|
--continue) continue="--continue" ;;
|
||||||
|
--download-non-verbose) previous_option="-nv" ;;
|
||||||
|
--download-non-verbose) previous_option="-v" ;;
|
||||||
|
--download-quiet) previous_option="-q" ;;
|
||||||
|
--download-verbose) previous_option="-v" ;;
|
||||||
|
--execpatch) execpatch=true ;;
|
||||||
|
--initrd) initrd=true ;;
|
||||||
|
--input-release-file=*) input_release_file=$parameter ;;
|
||||||
|
--insecure-downgrade-to-http) insecure_downgrade_to_http=true ;;
|
||||||
|
--insecure-no-check-certificate) insecure_no_check_certificate=true ;;
|
||||||
|
--input-release-file) previous_option=input_release_file ;;
|
||||||
|
--input-release-sig-file=*) input_release_sig_file=$parameter ;;
|
||||||
|
--input-release-sig-file) previous_option=input_release_sig_file ;;
|
||||||
|
--input-sha256sum=*) input_sha256sum=$parameter ;;
|
||||||
|
--input-sha256sum) previous_option=input_sha256sum ;;
|
||||||
|
--normalize) normalize=true ;;
|
||||||
|
--nv) wget_options="-nv" ;;
|
||||||
|
--outputdir=*) outputdir=$parameter ;;
|
||||||
|
--outputdir) previous_option=outputdir ;;
|
||||||
|
--output=*) output=$parameter ;;
|
||||||
|
--output) previous_option=output ;;
|
||||||
|
--output-release-file=*) output_release_file=$parameter ;;
|
||||||
|
--output-release-file) previous_option=output_release_file ;;
|
||||||
|
--output-release-sig-file=*) output_release_sig_file=$parameter ;;
|
||||||
|
--output-release-sig-file) previous_option=output_release_sig_file ;;
|
||||||
|
--output-sha256sum=*) output_sha256sum=$parameter ;;
|
||||||
|
--output-sha256sum) previous_option=output_sha256sum ;;
|
||||||
|
--patch) patch=true ;;
|
||||||
|
--port) port=true ;;
|
||||||
|
--porttix) porttix=true ;;
|
||||||
|
--release) release=true ;;
|
||||||
|
--sha256) sha256=true ;;
|
||||||
|
--sha256sum) sha256sum=true ;;
|
||||||
|
--source-full) source_full=true ;;
|
||||||
|
--source) source=true ;;
|
||||||
|
--srctix) srctix=true ;;
|
||||||
|
--sysroot) previous_option=sysroot ;;
|
||||||
|
--sysroot=*) sysroot=$parameter ;;
|
||||||
|
--toolchain) toolchain=true ;;
|
||||||
|
--url) url=true ;;
|
||||||
|
--url-master) url_master=true ;;
|
||||||
|
--url-mirror) url_mirror=true ;;
|
||||||
|
--url-master-release) url_master_release=true ;;
|
||||||
|
--url-mirror-release) url_mirror_release=true ;;
|
||||||
|
--url-release-sig) url_release_sig=true ;;
|
||||||
|
--url-sha256sum) url_sha256sum=true ;;
|
||||||
|
--wget-options) previous_option=wget_options ;;
|
||||||
|
--wget-options=*) wget_options=$parameter ;;
|
||||||
|
-*) echo "$0: unrecognized option $argument" >&2
|
||||||
|
exit 1 ;;
|
||||||
|
*) break ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if test -n "$previous_option"; then
|
||||||
|
echo "$0: option '$argument' requires an argument" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# TODO: Mutually incompatible options.
|
||||||
|
|
||||||
|
conf() {
|
||||||
|
grep -E "^$1[[:space:]]*=" -- "$collection/etc/upgrade.conf" |
|
||||||
|
tail -n 1 |
|
||||||
|
sed -E 's/^[^=]*=[[:space:]]*(|.*[^[:space:]])[[:space:]]*/\1/'
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpdir=$(mktemp -dt tix-fetch-port.XXXXXX)
|
||||||
|
trap 'rm -rf -- "$tmpdir"' EXIT HUP INT QUIT TERM
|
||||||
|
|
||||||
|
RELEASE_KEY=$(conf release_key)
|
||||||
|
RELEASE_SIG_URL=$(conf release_sig_url)
|
||||||
|
PREFERRED_MIRROR=$(conf mirror)
|
||||||
|
FORCE_MIRROR=$(conf force_mirror)
|
||||||
|
USER_AGENT="$(uname -s)/$(uname -r) ($(uname -m); $(uname -v))"
|
||||||
|
|
||||||
|
if $insecure_no_check_certificate; then
|
||||||
|
echo "$0: warning: insecurely not checking https certificates" >&2
|
||||||
|
wget_options="$wget_options --no-check-certificate"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $insecure_downgrade_to_http; then
|
||||||
|
echo "$0: warning: insecurely downloading without https" >&2
|
||||||
|
RELEASE_SIG_URL="$(echo "$RELEASE_SIG_URL" | sed -E 's,^https:,http:,')"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $url_release_sig; then
|
||||||
|
printf "%s\n" "$RELEASE_SIG_URL"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# HACK: Provide more useful errors when wget is silent:
|
||||||
|
do_wget() {
|
||||||
|
(set +e
|
||||||
|
wget "$@"
|
||||||
|
status=$?
|
||||||
|
set -e
|
||||||
|
what=
|
||||||
|
case $status in
|
||||||
|
0) exit 0 ;;
|
||||||
|
1) what="Generic error" ;;
|
||||||
|
2) what="Parse error" ;;
|
||||||
|
3) what="File I/O error" ;;
|
||||||
|
4) what="Network I/O error" ;;
|
||||||
|
5) what="Transport Layer Security verification failure" ;;
|
||||||
|
6) what="Username/password failure" ;;
|
||||||
|
7) what="Protocol error" ;;
|
||||||
|
8) what="Error response" ;;
|
||||||
|
*) what="Exit code $status" ;;
|
||||||
|
esac
|
||||||
|
echo "$0: $what when running: wget $@" >&2
|
||||||
|
exit $status)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fetch signed release description.
|
||||||
|
if [ -z "$input_release_file" ]; then
|
||||||
|
if [ -z "$input_release_sig_file" ]; then
|
||||||
|
(cd "$tmpdir" &&
|
||||||
|
do_wget -U "$USER_AGENT" $wget_options -O release.sh.sig \
|
||||||
|
-- "$RELEASE_SIG_URL")
|
||||||
|
else
|
||||||
|
cp -T -- "$input_release_sig_file" "$tmpdir/release.sh.sig"
|
||||||
|
fi
|
||||||
|
signify -Vq -p "$RELEASE_KEY" -em "$tmpdir/release.sh"
|
||||||
|
else
|
||||||
|
cp -T -- "$input_release_file" "$tmpdir/release.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Store the signed release file if requested.
|
||||||
|
if [ -n "$output_release_sig_file" ]; then
|
||||||
|
cp -T -- "$tmpdir/release.sh.sig" "$output_release_sig_file"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Store the release file (without signature) if requested.
|
||||||
|
if [ -n "$output_release_file" ]; then
|
||||||
|
cp -T -- "$tmpdir/release.sh" "$output_release_file"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Load the release description.
|
||||||
|
# TODO: SECURITY: REMOTE CODE EXECUTION OF SIGNED REMOTE CODE.
|
||||||
|
# TODO: SECURITY: Protect against responding with older release.sh.
|
||||||
|
. "`realpath -- "$tmpdir/release.sh"`" # Avoid PATH search with absolute path.
|
||||||
|
|
||||||
|
if $url_master; then
|
||||||
|
printf "%s\n" "$MASTER"
|
||||||
|
exit
|
||||||
|
elif $url_master_release; then
|
||||||
|
printf "%s\n" "$MASTER/$RELEASE"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Default to the master mirror but switch to the preferred mirror if the release
|
||||||
|
# description knows about the mirror and believes it to be trustworthy.
|
||||||
|
MIRROR="$MASTER"
|
||||||
|
for POTENTIAL_MIRROR in $MIRRORS; do
|
||||||
|
if [ "$POTENTIAL_MIRROR" = "$PREFERRED_MIRROR" ]; then
|
||||||
|
MIRROR="$PREFERRED_MIRROR"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ -n "$PREFERRED_MIRROR" ] && [ "$MIRROR" != "$PREFERRED_MIRROR" ]; then
|
||||||
|
if [ "$FORCE_MIRROR" = yes ]; then
|
||||||
|
MIRROR="$PREFERRED_MIRROR"
|
||||||
|
else
|
||||||
|
echo "$0: warning: ignoring unsupported mirror $PREFERRED_MIRROR" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $insecure_downgrade_to_http; then
|
||||||
|
MIRROR="$(echo "$MIRROR" | sed -E 's,^https:,http:,')"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $url_mirror; then
|
||||||
|
printf "%s\n" "$MIRROR"
|
||||||
|
exit
|
||||||
|
elif $url_mirror_release; then
|
||||||
|
printf "%s\n" "$MIRROR/$RELEASE"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
RELEASE_URL="$MIRROR/$RELEASE"
|
||||||
|
|
||||||
|
# Fetch sha256sum file and check its SHA256 hash with the release description.
|
||||||
|
if $url_sha256sum; then
|
||||||
|
printf "%s\n" "$RELEASE_URL/$SHA256SUM_FILE"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
if [ -z "$input_sha256sum" ]; then
|
||||||
|
# TODO: If the mirror doesn't work, try the master.
|
||||||
|
(cd "$tmpdir" &&
|
||||||
|
do_wget -U "$USER_AGENT" $wget_options -O sha256sum \
|
||||||
|
-- "$RELEASE_URL/$SHA256SUM_FILE")
|
||||||
|
else
|
||||||
|
cp -T -- "$input_sha256sum" "$tmpdir/sha256sum"
|
||||||
|
fi
|
||||||
|
# TODO: Check if upstream release description changed, if so, start over.
|
||||||
|
echo "$SHA256SUM_SHA256SUM $tmpdir/sha256sum" | sha256sum -cq
|
||||||
|
|
||||||
|
# Store the sha256sum file if requested.
|
||||||
|
if [ -n "$output_sha256sum" ]; then
|
||||||
|
cp -T -- "$tmpdir/sha256sum" "$output_sha256sum"
|
||||||
|
fi
|
||||||
|
|
||||||
|
escape_extended_regex() {
|
||||||
|
printf "%s\n" "$1" | sed -E -e 's/[[$()*?\+.^{|}]/\\\0/g'
|
||||||
|
}
|
||||||
|
|
||||||
|
# TODO: Remove:
|
||||||
|
#escape_extended_regex_test_self() {
|
||||||
|
# printf "%s\n" "$1" | grep -E "^$(escape_extended_regex "$1")\$"
|
||||||
|
#}
|
||||||
|
|
||||||
|
request() {
|
||||||
|
REQUEST="$1"
|
||||||
|
REQUESTDIR="$2"
|
||||||
|
REQUESTFINAL="${3-$1}"
|
||||||
|
FULLREQUEST="$REQUESTDIR$REQUEST"
|
||||||
|
|
||||||
|
if $url; then
|
||||||
|
printf '%s\n' "$RELEASE_URL/$FULLREQUEST"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $sha256 || $sha256sum; then
|
||||||
|
set +e # Don't fail if grep exits 1 (no match).
|
||||||
|
# TODO: Should this be a checksum(1) feature to look up a hash?
|
||||||
|
grep -E "^[0-9a-fA-F]{64} $(escape_extended_regex "$FULLREQUEST")$" \
|
||||||
|
"$tmpdir/sha256sum" > "$tmpdir/match"
|
||||||
|
EXITCODE=$?
|
||||||
|
set -e
|
||||||
|
if [ 2 -le "$EXITCODE" ]; then (exit $EXITCODE); fi
|
||||||
|
if $sha256 && [ -s "$tmpdir/match" ]; then
|
||||||
|
grep -Eo '^[0-9a-fA-F]{64}' "$tmpdir/match"
|
||||||
|
fi
|
||||||
|
if $sha256sum && [ -s "$tmpdir/match" ]; then
|
||||||
|
cat "$tmpdir/match"
|
||||||
|
fi
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Decide the final location the file will end up.
|
||||||
|
if [ -n "$output" ]; then
|
||||||
|
FINAL="$output"
|
||||||
|
OUTPUTDIR=$(dirname -- "$output")
|
||||||
|
elif [ -n "$outputdir" ]; then
|
||||||
|
FINAL="$outputdir/$REQUESTFINAL"
|
||||||
|
OUTPUTDIR="$outputdir"
|
||||||
|
else
|
||||||
|
FINAL="$REQUESTFINAL"
|
||||||
|
OUTPUTDIR=.
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If a resumable download, store the file directly to the destination path.
|
||||||
|
# Otherwise download to a temporary directory and move only to the final
|
||||||
|
# location if the cryptographic check is passed.
|
||||||
|
if [ -n "$continue" ]; then
|
||||||
|
DOWNLOADDIR="$OUTPUTDIR"
|
||||||
|
OUTPUT="$FINAL"
|
||||||
|
else
|
||||||
|
DOWNLOADDIR="$tmpdir/download"
|
||||||
|
OUTPUT="$DOWNLOADDIR/$REQUEST"
|
||||||
|
mkdir -p -- "$DOWNLOADDIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fetch the file.
|
||||||
|
# TODO: If the mirror doesn't work, try the master.
|
||||||
|
(cd "$DOWNLOADDIR" &&
|
||||||
|
mkdir -p -- "$(dirname -- "$REQUEST")" &&
|
||||||
|
do_wget -U "$USER_AGENT" $wget_options $continue -O "$REQUEST" \
|
||||||
|
-- "$RELEASE_URL/$FULLREQUEST")
|
||||||
|
|
||||||
|
# Verify the cryptographic integrity of the fetched file.
|
||||||
|
ABSOLUTE_OUTPUT=$(realpath -- "$OUTPUT")
|
||||||
|
mkdir -p -- "$tmpdir/check"
|
||||||
|
(cd "$tmpdir/check" &&
|
||||||
|
mkdir -p -- "$(dirname -- "$FULLREQUEST")"
|
||||||
|
ln -s -- "$ABSOLUTE_OUTPUT" "$FULLREQUEST"
|
||||||
|
if ! sha256sum -q -C "$tmpdir/sha256sum" -- "$FULLREQUEST"; then
|
||||||
|
# Don't leave behind a file that didn't pass a cryptographic check.
|
||||||
|
if [ -n "$continue" ]; then
|
||||||
|
# TODO: Check if upstream release description changed, if so, start over.
|
||||||
|
echo "error: Deleting corrupted output file: $OUTPUT" 2>&1
|
||||||
|
rm -f -- "$OUTPUT"
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
fi)
|
||||||
|
rm -rf -- "$tmpdir/check"
|
||||||
|
|
||||||
|
# Move the file to the final destination if not already.
|
||||||
|
if [ -z "$continue" ]; then
|
||||||
|
if [ -z "$output" ]; then
|
||||||
|
(cd "$OUTPUTDIR" && mkdir -p -- "$(dirname -- "$REQUESTFINAL")")
|
||||||
|
fi
|
||||||
|
cp -T -- "$OUTPUT" "$FINAL"
|
||||||
|
rm -rf -- "$tmpdir/download"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if $release; then
|
||||||
|
request "$BUILD_FILE" "" "$(basename -- "$BUILD_FILE")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# TODO: --source, --source-full
|
||||||
|
# TODO: --binutils, --gcc, --libstdc++
|
||||||
|
|
||||||
|
# Fetch each of the specified signed files from the mirror.
|
||||||
|
for REQUEST; do
|
||||||
|
# If --port then fetch the port by the requested name.
|
||||||
|
if $port; then
|
||||||
|
REQUEST="$REQUEST.tix.tar.xz"
|
||||||
|
REQUESTDIR="repository/$MACHINE-sortix/"
|
||||||
|
elif $boot; then
|
||||||
|
REQUEST="$REQUEST"
|
||||||
|
REQUESTDIR="$MACHINE/boot/"
|
||||||
|
elif $initrd; then
|
||||||
|
REQUEST="$REQUEST.initrd.xz"
|
||||||
|
REQUESTDIR="$MACHINE/boot/"
|
||||||
|
elif $patch; then
|
||||||
|
REQUEST="$REQUEST.patch"
|
||||||
|
REQUESTDIR="patches/"
|
||||||
|
elif $normalize; then
|
||||||
|
REQUEST="$REQUEST.normalize"
|
||||||
|
REQUESTDIR="patches/"
|
||||||
|
elif $srctix; then
|
||||||
|
REQUEST="$REQUEST.srctix.tar.xz"
|
||||||
|
REQUESTDIR="srctix/"
|
||||||
|
elif $porttix; then
|
||||||
|
REQUEST="$REQUEST.porttix.tar.xz"
|
||||||
|
REQUESTDIR="porttix/"
|
||||||
|
elif $toolchain; then
|
||||||
|
REQUESTDIR="toolchain/"
|
||||||
|
else
|
||||||
|
REQUESTDIR=""
|
||||||
|
fi
|
||||||
|
request "$REQUEST" "$REQUESTDIR"
|
||||||
|
done
|
|
@ -0,0 +1,230 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Copyright (c) 2017, 2021 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-upgrade
|
||||||
|
# Upgrade operating system and ports.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cachedir=""
|
||||||
|
clean=false
|
||||||
|
collection=""
|
||||||
|
download_only=false
|
||||||
|
fetch_options=
|
||||||
|
ports_only=false
|
||||||
|
sysroot=""
|
||||||
|
upgrade_ports=false
|
||||||
|
upgrade_system=false
|
||||||
|
wait=""
|
||||||
|
|
||||||
|
dashdash=
|
||||||
|
previous_option=
|
||||||
|
for argument do
|
||||||
|
if test -n "$previous_option"; then
|
||||||
|
eval $previous_option=\$argument
|
||||||
|
previous_option=
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $argument in
|
||||||
|
*=?*) parameter=$(expr "X$argument" : '[^=]*=\(.*\)' || true) ;;
|
||||||
|
*=) parameter= ;;
|
||||||
|
*) parameter=yes ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case $dashdash$argument in
|
||||||
|
--) dashdash=yes ;;
|
||||||
|
-w) wait=-w ;;
|
||||||
|
--cachedir=*) cachedir=$parameter ;;
|
||||||
|
--cachedir) previous_option=cachedir ;;
|
||||||
|
--clean) clean=true ;;
|
||||||
|
--collection=*) collection=$parameter ;;
|
||||||
|
--collection) previous_option=collection ;;
|
||||||
|
--download-only) download_only=true ;;
|
||||||
|
--insecure-downgrade-to-http) fetch_options="$fetch_options $argument" ;;
|
||||||
|
--insecure-no-check-certificate) fetch_options="$fetch_options $argument" ;;
|
||||||
|
--ports) upgrade_ports=true ;;
|
||||||
|
--system) upgrade_system=true ;;
|
||||||
|
--sysroot) previous_option=sysroot ;;
|
||||||
|
--sysroot=*) sysroot=$parameter ;;
|
||||||
|
--wait) wait=--wait ;;
|
||||||
|
-*) echo "$0: unrecognized option $argument" >&2
|
||||||
|
exit 1 ;;
|
||||||
|
*) break ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if test -n "$previous_option"; then
|
||||||
|
echo "$0: option '$argument' requires an argument" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# TODO: Reject additional operands.
|
||||||
|
|
||||||
|
if [ -z "$collection" ]; then
|
||||||
|
collection="$sysroot"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$collection" ]; then
|
||||||
|
collection=$(cd "$collection" && pwd)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! $upgrade_ports && ! $upgrade_system; then
|
||||||
|
upgrade_ports=true
|
||||||
|
upgrade_system=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Update only ports if this isn't a whole system installation.
|
||||||
|
if [ ! -e "$collection/tix/manifest/system" ]; then
|
||||||
|
ports_only=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$cachedir" ]; then
|
||||||
|
cachedir="$collection/var/cache/tix"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $clean; then
|
||||||
|
echo "Removing cache directory: $cachedir"
|
||||||
|
rm -rf -- "$cachedir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p -- "$cachedir"
|
||||||
|
mkdir -p -- "$cachedir/new"
|
||||||
|
|
||||||
|
# Fetch latest release.sig.sh from the master and its matching sha256sum file.
|
||||||
|
tix-fetch $fetch_options \
|
||||||
|
--output-release-sig-file="$cachedir/new/release.sh.sig" \
|
||||||
|
--output-sha256sum="$cachedir/new/sha256sum"
|
||||||
|
|
||||||
|
# If release.sig.sh or sha256sum changed, clean the cache directory of downloads
|
||||||
|
# that were currently in progress as they might not have the right checksums.
|
||||||
|
# TODO: This requires diff(1) in the base system! Avoid that. Get a cmp(1)!
|
||||||
|
if ! diff -- "$cachedir/release.sh.sig" \
|
||||||
|
"$cachedir/new/release.sh.sig" 1>/dev/null 2>/dev/null ||
|
||||||
|
! diff -- "$cachedir/sha256sum" \
|
||||||
|
"$cachedir/new/sha256sum" 1>/dev/null 2>/dev/null; then
|
||||||
|
rm -rf -- "$cachedir/boot"
|
||||||
|
rm -rf -- "$cachedir/repository"
|
||||||
|
rm -rf -- "$cachedir/sysroot"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Store the new release.sig.sh and sha256sum files so we can resume the download
|
||||||
|
# if cancelled and these files still match.
|
||||||
|
mv -- "$cachedir/new/release.sh.sig" "$cachedir/release.sh.sig"
|
||||||
|
mv -- "$cachedir/new/sha256sum" "$cachedir/sha256sum"
|
||||||
|
rm -rf -- "$cachedir/new"
|
||||||
|
|
||||||
|
mkdir -p "$cachedir/boot"
|
||||||
|
mkdir -p "$cachedir/repository"
|
||||||
|
|
||||||
|
if $upgrade_system; then
|
||||||
|
# Fetch the base system initrds from the mirror.
|
||||||
|
# TODO: What about the system source code in /src?
|
||||||
|
# TODO: Get the overlay initrd if it exists.
|
||||||
|
tix-fetch $fetch_options \
|
||||||
|
--input-release-sig-file="$cachedir/release.sh.sig" \
|
||||||
|
--input-sha256sum="$cachedir/sha256sum" \
|
||||||
|
-c --initrd -O "$cachedir/boot" -- system
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $upgrade_ports; then
|
||||||
|
# Fetch each port from the mirror.
|
||||||
|
ports=$(LC_ALL=C sort -- "$collection/tix/installed.list")
|
||||||
|
# TODO: This fails if the port does not exist upstream.
|
||||||
|
mkdir -p "$cachedir/repository"
|
||||||
|
for port in $ports; do
|
||||||
|
# The port has a hash if if it exists upstream.
|
||||||
|
sha256=$(tix-fetch $fetch_options \
|
||||||
|
--input-release-sig-file="$cachedir/release.sh.sig" \
|
||||||
|
--input-sha256sum="$cachedir/sha256sum" \
|
||||||
|
--sha256 --port -- $port)
|
||||||
|
# If the port exists upstream, get the latest version.
|
||||||
|
if [ -n "$sha256" ]; then
|
||||||
|
tix-fetch $fetch_options \
|
||||||
|
--input-release-sig-file="$cachedir/release.sh.sig" \
|
||||||
|
--input-sha256sum="$cachedir/sha256sum" \
|
||||||
|
-c --port -O "$cachedir/repository" -- $port
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Stop if only downloading.
|
||||||
|
if $download_only; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf -- "$cachedir/sysroot"
|
||||||
|
mkdir -p -- "$cachedir/sysroot"
|
||||||
|
|
||||||
|
if $upgrade_system; then
|
||||||
|
# Extract the base system into the sysroot.
|
||||||
|
rm -rf -- "$cachedir/sysroot"
|
||||||
|
mkdir -p -- "$cachedir/sysroot"
|
||||||
|
for initrd in system overlay; do
|
||||||
|
initrd_path="$cachedir/boot/$initrd.initrd"
|
||||||
|
if [ -e "$initrd_path.xz" ]; then
|
||||||
|
echo "Extracting $initrd.initrd.xz..."
|
||||||
|
unxz -k "$initrd_path.xz"
|
||||||
|
initrdfs "$initrd_path" extract -C "$cachedir/sysroot" /
|
||||||
|
rm -f "$initrd_path.xz"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# TODO: These install all the ports in "$cachedir/repository" but the directory
|
||||||
|
# might not have been cleared, it could contain unverified ports.
|
||||||
|
if $upgrade_system; then
|
||||||
|
# Do a full system upgrade using the sysroot and the new ports.
|
||||||
|
# TODO: If sysmerge -w, such as on ABI upgrades, the e2fsprogs package is not
|
||||||
|
# installed in the system root and the new initrd might not contain a
|
||||||
|
# /sbin/fsck.ext2 and the system can become bricked if it needs a fsck
|
||||||
|
# on boot.
|
||||||
|
# TODO: There's no support here for doing a sysmerge on a given sysroot.
|
||||||
|
if $upgrade_ports; then
|
||||||
|
# TODO: Get the architecture from somewhere else than /etc/machine?
|
||||||
|
tix-collection "$cachedir/sysroot" create \
|
||||||
|
--platform="$(cat -- "$sysroot/etc/machine")-sortix" \
|
||||||
|
--prefix= --generation=2
|
||||||
|
tix-install --collection="$cachedir/sysroot" -- "$cachedir/repository/"*
|
||||||
|
full=--full
|
||||||
|
else
|
||||||
|
# TODO: Is this case supported?
|
||||||
|
full=
|
||||||
|
fi
|
||||||
|
sysmerge $full $wait "$cachedir/sysroot"
|
||||||
|
elif $upgrade_ports; then
|
||||||
|
# Upgrade to each of the new ports.
|
||||||
|
# TODO: tix-install --reinstall is unsupported due to lack of support for
|
||||||
|
# files moving between manifests or being deleted.
|
||||||
|
tix-install --reinstall -- "$cachedir/repository/"*
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf -- "$cachedir/boot"
|
||||||
|
rm -rf -- "$cachedir/repository"
|
||||||
|
rm -rf -- "$cachedir/sysroot"
|
||||||
|
|
||||||
|
#tmp=
|
||||||
|
#trap '[ -n "$tmp" ] && rm -rf "$tmp"' EXIT HUP INT QUIT TERM
|
||||||
|
#tmp=$(mktemp -dt upgrade.XXXXXX)
|
||||||
|
#mkdir -p "$tmp/tmp"
|
||||||
|
#export TMPDIR="$tmp/tmp"
|
||||||
|
#(cd "$tmp" && tix-fetch --release -o sortix.iso)
|
||||||
|
#mkdir -p "$tmp/sortix.iso.d"
|
||||||
|
#echo "Extracting sortix.iso..."
|
||||||
|
#xorriso -osirrox on -indev "$tmp/sortix.iso" -extract / "$tmp/sortix.iso.d" > /dev/null 2> /dev/null
|
||||||
|
#rm -f "$tmp/sortix.iso"
|
45
tix/tix.c
45
tix/tix.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2015, 2016 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2015, 2016, 2017 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -170,6 +170,8 @@ static void version(FILE* fp, const char* argv0)
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
const char* tmp = getenv_def("TMPDIR", "/tmp");
|
||||||
|
|
||||||
params_t params;
|
params_t params;
|
||||||
memset(¶ms, 0, sizeof(params));
|
memset(¶ms, 0, sizeof(params));
|
||||||
params.collection = NULL;
|
params.collection = NULL;
|
||||||
|
@ -245,7 +247,7 @@ int main(int argc, char* argv[])
|
||||||
errx(1, "error: no command specified.");
|
errx(1, "error: no command specified.");
|
||||||
|
|
||||||
const char* cmd = argv[1];
|
const char* cmd = argv[1];
|
||||||
if ( !strcmp(cmd, "install") )
|
if ( !strcmp(cmd, "old-install") )
|
||||||
{
|
{
|
||||||
if ( argc == 2 )
|
if ( argc == 2 )
|
||||||
errx(1, "expected list of packages to install after `install'");
|
errx(1, "expected list of packages to install after `install'");
|
||||||
|
@ -276,6 +278,45 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
else if ( !strcmp(cmd, "install") )
|
||||||
|
{
|
||||||
|
initialize_tmp(tmp, "tix-install");
|
||||||
|
if ( chdir(tmp_root) < 0 )
|
||||||
|
err(1, "%s", tmp_root);
|
||||||
|
|
||||||
|
if ( fork_and_wait_or_death() )
|
||||||
|
{
|
||||||
|
char** fetch_argv = malloc(sizeof(char*) * (5 + (argc-2) + 1));
|
||||||
|
fetch_argv[0] = (char*) "tix-fetch";
|
||||||
|
fetch_argv[1] = (char*) "--collection";
|
||||||
|
fetch_argv[2] = params.collection;
|
||||||
|
fetch_argv[3] = (char*) "--port";
|
||||||
|
fetch_argv[4] = (char*) "--";
|
||||||
|
int offset = 5;
|
||||||
|
for ( int i = 0; i < argc-2; i++ )
|
||||||
|
fetch_argv[offset + i] = argv[2 + i];
|
||||||
|
fetch_argv[offset + argc-2] = NULL;
|
||||||
|
execvp(fetch_argv[0], (char* const*) fetch_argv);
|
||||||
|
err(127, "`%s'", fetch_argv[0]);
|
||||||
|
}
|
||||||
|
for ( int i = 2; i < argc; i++ )
|
||||||
|
{
|
||||||
|
const char* pkg_name = argv[i];
|
||||||
|
char* pkg_path = print_string("%s%s", pkg_name, ".tix.tar.xz");
|
||||||
|
if ( fork_and_wait_or_death() )
|
||||||
|
{
|
||||||
|
const char* install_argv[] =
|
||||||
|
{
|
||||||
|
"tix-install",
|
||||||
|
"--collection", params.collection,
|
||||||
|
"--", pkg_path,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
execvp(install_argv[0], (char* const*) install_argv);
|
||||||
|
err(127, "`%s'", install_argv[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: unknown command: `%s'\n", argv0, cmd);
|
fprintf(stderr, "%s: unknown command: `%s'\n", argv0, cmd);
|
||||||
|
|
Loading…
Reference in New Issue