All checks were successful
Test / Create distribution (push) Successful in 1m0s
Test / Sandbox (push) Successful in 2m50s
Test / Hakurei (push) Successful in 4m23s
Test / ShareFS (push) Successful in 4m21s
Test / Hpkg (push) Successful in 4m48s
Test / Sandbox (race detector) (push) Successful in 5m26s
Test / Hakurei (race detector) (push) Successful in 6m20s
Test / Flake checks (push) Successful in 1m53s
This is significantly cleaner and runs somewhat faster. Signed-off-by: Ophestra <cat@gensokyo.uk>
375 lines
9.0 KiB
Go
375 lines
9.0 KiB
Go
package rosa
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"runtime"
|
|
"slices"
|
|
"strings"
|
|
"time"
|
|
|
|
"hakurei.app/container/fhs"
|
|
"hakurei.app/internal/pkg"
|
|
)
|
|
|
|
// busyboxBin is a busybox binary distribution installed under bin/busybox.
|
|
type busyboxBin struct {
|
|
// Underlying busybox binary.
|
|
bin pkg.FileArtifact
|
|
}
|
|
|
|
// Kind returns the hardcoded [pkg.Kind] value.
|
|
func (a busyboxBin) Kind() pkg.Kind { return kindBusyboxBin }
|
|
|
|
// Params is a noop.
|
|
func (a busyboxBin) Params(*pkg.IContext) {}
|
|
|
|
// IsExclusive returns false: Cure performs a trivial filesystem write.
|
|
func (busyboxBin) IsExclusive() bool { return false }
|
|
|
|
// Dependencies returns the underlying busybox [pkg.File].
|
|
func (a busyboxBin) Dependencies() []pkg.Artifact {
|
|
return []pkg.Artifact{a.bin}
|
|
}
|
|
|
|
// String returns the reporting name of the underlying file prefixed with expand.
|
|
func (a busyboxBin) String() string {
|
|
return "expand-" + a.bin.(fmt.Stringer).String()
|
|
}
|
|
|
|
// Cure installs the underlying busybox [pkg.File] to bin/busybox.
|
|
func (a busyboxBin) Cure(t *pkg.TContext) (err error) {
|
|
var r io.ReadCloser
|
|
if r, err = t.Open(a.bin); err != nil {
|
|
return
|
|
}
|
|
defer func() {
|
|
closeErr := r.Close()
|
|
if err == nil {
|
|
err = closeErr
|
|
}
|
|
}()
|
|
|
|
binDir := t.GetWorkDir().Append("bin")
|
|
if err = os.MkdirAll(binDir.String(), 0700); err != nil {
|
|
return
|
|
}
|
|
|
|
var w *os.File
|
|
if w, err = os.OpenFile(
|
|
binDir.Append("busybox").String(),
|
|
os.O_WRONLY|os.O_CREATE|os.O_EXCL,
|
|
0500,
|
|
); err != nil {
|
|
return
|
|
}
|
|
defer func() {
|
|
closeErr := w.Close()
|
|
if err == nil {
|
|
err = closeErr
|
|
}
|
|
}()
|
|
|
|
_, err = io.Copy(w, r)
|
|
return
|
|
}
|
|
|
|
// newBusyboxBin returns a [pkg.Artifact] containing a busybox installation from
|
|
// the https://busybox.net/downloads/binaries/ binary release.
|
|
func newBusyboxBin() pkg.Artifact {
|
|
var version, url, checksum string
|
|
switch runtime.GOARCH {
|
|
case "amd64":
|
|
version = "1.35.0"
|
|
url = "https://busybox.net/downloads/binaries/" +
|
|
version + "-" + linuxArch() + "-linux-musl/busybox"
|
|
checksum = "L7OBIsPu9enNHn7FqpBT1kOg_mCLNmetSeNMA3i4Y60Z5jTgnlX3qX3zcQtLx5AB"
|
|
case "arm64":
|
|
version = "1.31.0"
|
|
url = "https://busybox.net/downloads/binaries/" +
|
|
version + "-defconfig-multiarch-musl/busybox-armv8l"
|
|
checksum = "npJjBO7iwhjW6Kx2aXeSxf8kXhVgTCDChOZTTsI8ZfFfa3tbsklxRiidZQdrVERg"
|
|
|
|
default:
|
|
panic("unsupported target " + runtime.GOARCH)
|
|
}
|
|
|
|
return pkg.NewExec(
|
|
"busybox-bin-"+version, nil, pkg.ExecTimeoutMax, false,
|
|
fhs.AbsRoot, []string{
|
|
"PATH=/system/bin",
|
|
},
|
|
AbsSystem.Append("bin", "busybox"),
|
|
[]string{"hush", "-c", "" +
|
|
"busybox mkdir -p /work/system/bin/ && " +
|
|
"busybox cp /system/bin/busybox /work/system/bin/ && " +
|
|
"busybox --install -s /work/system/bin/"},
|
|
pkg.Path(AbsSystem, true, busyboxBin{pkg.NewHTTPGet(
|
|
&http.Client{Transport: &http.Transport{
|
|
// busybox website is really slow to respond
|
|
TLSHandshakeTimeout: 2 * time.Minute,
|
|
}}, url,
|
|
mustDecode(checksum),
|
|
)}),
|
|
)
|
|
}
|
|
|
|
func (t Toolchain) newBusybox() pkg.Artifact {
|
|
const (
|
|
version = "1.37.0"
|
|
checksum = "Ial94Tnt7esJ_YEeb0AxunVL6MGYFyOw7Rtu2o87CXCi1TLrc6rlznVsN1rZk7it"
|
|
)
|
|
|
|
var env []string
|
|
if t == toolchainStage3 {
|
|
env = append(env,
|
|
"EXTRA_LDFLAGS=-Wl,--dynamic-linker=/system/bin/linker")
|
|
}
|
|
|
|
return t.New("busybox-"+version, false, stage3Concat(t, []pkg.Artifact{},
|
|
t.Load(Make),
|
|
t.Load(KernelHeaders),
|
|
), nil, slices.Concat([]string{
|
|
"ROSA_BUSYBOX_ENABLE=" + strings.Join([]string{
|
|
"STATIC",
|
|
"PIE",
|
|
}, " "),
|
|
"ROSA_BUSYBOX_DISABLE=" + strings.Join([]string{
|
|
"SHA1_HWACCEL",
|
|
|
|
"FEATURE_IPV6",
|
|
"FEATURE_PREFER_IPV4_ADDRESS",
|
|
"FEATURE_HWIB",
|
|
"ARP",
|
|
"ARPING",
|
|
"BRCTL",
|
|
"FEATURE_BRCTL_FANCY",
|
|
"FEATURE_BRCTL_SHOW",
|
|
"DNSD",
|
|
"ETHER_WAKE",
|
|
"FTPD",
|
|
"FEATURE_FTPD_WRITE",
|
|
"FEATURE_FTPD_ACCEPT_BROKEN_LIST",
|
|
"FEATURE_FTPD_AUTHENTICATION",
|
|
"FTPGET",
|
|
"FTPPUT",
|
|
"FEATURE_FTPGETPUT_LONG_OPTIONS",
|
|
"HOSTNAME",
|
|
"DNSDOMAINNAME",
|
|
"HTTPD",
|
|
"FEATURE_HTTPD_PORT_DEFAULT",
|
|
"FEATURE_HTTPD_RANGES",
|
|
"FEATURE_HTTPD_SETUID",
|
|
"FEATURE_HTTPD_BASIC_AUTH",
|
|
"FEATURE_HTTPD_AUTH_MD5",
|
|
"FEATURE_HTTPD_CGI",
|
|
"FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR",
|
|
"FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV",
|
|
"FEATURE_HTTPD_ENCODE_URL_STR",
|
|
"FEATURE_HTTPD_ERROR_PAGES",
|
|
"FEATURE_HTTPD_PROXY",
|
|
"FEATURE_HTTPD_GZIP",
|
|
"FEATURE_HTTPD_ETAG",
|
|
"FEATURE_HTTPD_LAST_MODIFIED",
|
|
"FEATURE_HTTPD_DATE",
|
|
"FEATURE_HTTPD_ACL_IP",
|
|
"IFCONFIG",
|
|
"FEATURE_IFCONFIG_STATUS",
|
|
"FEATURE_IFCONFIG_SLIP",
|
|
"FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ",
|
|
"FEATURE_IFCONFIG_HW",
|
|
"FEATURE_IFCONFIG_BROADCAST_PLUS",
|
|
"IFENSLAVE",
|
|
"IFPLUGD",
|
|
"IFUP",
|
|
"IFDOWN",
|
|
"IFUPDOWN_IFSTATE_PATH",
|
|
"FEATURE_IFUPDOWN_IP",
|
|
"FEATURE_IFUPDOWN_IPV4",
|
|
"FEATURE_IFUPDOWN_IPV6",
|
|
"FEATURE_IFUPDOWN_MAPPING",
|
|
"INETD",
|
|
"FEATURE_INETD_SUPPORT_BUILTIN_ECHO",
|
|
"FEATURE_INETD_SUPPORT_BUILTIN_DISCARD",
|
|
"FEATURE_INETD_SUPPORT_BUILTIN_TIME",
|
|
"FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME",
|
|
"FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN",
|
|
"IP",
|
|
"IPADDR",
|
|
"IPLINK",
|
|
"IPROUTE",
|
|
"IPTUNNEL",
|
|
"IPRULE",
|
|
"IPNEIGH",
|
|
"FEATURE_IP_ADDRESS",
|
|
"FEATURE_IP_LINK",
|
|
"FEATURE_IP_LINK_CAN",
|
|
"FEATURE_IP_ROUTE",
|
|
"FEATURE_IP_ROUTE_DIR",
|
|
"FEATURE_IP_TUNNEL",
|
|
"FEATURE_IP_RULE",
|
|
"FEATURE_IP_NEIGH",
|
|
"IPCALC",
|
|
"FEATURE_IPCALC_LONG_OPTIONS",
|
|
"FEATURE_IPCALC_FANCY",
|
|
"FAKEIDENTD",
|
|
"NAMEIF",
|
|
"FEATURE_NAMEIF_EXTENDED",
|
|
"NBDCLIENT",
|
|
"NC",
|
|
"NC_SERVER",
|
|
"NC_EXTRA",
|
|
"NC_110_COMPAT",
|
|
"NETSTAT",
|
|
"FEATURE_NETSTAT_WIDE",
|
|
"FEATURE_NETSTAT_PRG",
|
|
"NSLOOKUP",
|
|
"FEATURE_NSLOOKUP_BIG",
|
|
"FEATURE_NSLOOKUP_LONG_OPTIONS",
|
|
"NTPD",
|
|
"FEATURE_NTPD_SERVER",
|
|
"FEATURE_NTPD_CONF",
|
|
"FEATURE_NTP_AUTH",
|
|
"PING",
|
|
"PING6",
|
|
"FEATURE_FANCY_PING",
|
|
"PSCAN",
|
|
"ROUTE",
|
|
"SLATTACH",
|
|
"SSL_CLIENT",
|
|
"TC",
|
|
"FEATURE_TC_INGRESS",
|
|
"TCPSVD",
|
|
"UDPSVD",
|
|
"TELNET",
|
|
"FEATURE_TELNET_TTYPE",
|
|
"FEATURE_TELNET_AUTOLOGIN",
|
|
"FEATURE_TELNET_WIDTH",
|
|
"TELNETD",
|
|
"FEATURE_TELNETD_STANDALONE",
|
|
"FEATURE_TELNETD_PORT_DEFAULT",
|
|
"FEATURE_TELNETD_INETD_WAIT",
|
|
"TFTP",
|
|
"FEATURE_TFTP_PROGRESS_BAR",
|
|
"FEATURE_TFTP_HPA_COMPAT",
|
|
"TFTPD",
|
|
"FEATURE_TFTP_GET",
|
|
"FEATURE_TFTP_PUT",
|
|
"FEATURE_TFTP_BLOCKSIZE",
|
|
"TLS",
|
|
"TRACEROUTE",
|
|
"TRACEROUTE6",
|
|
"FEATURE_TRACEROUTE_VERBOSE",
|
|
"FEATURE_TRACEROUTE_USE_ICMP",
|
|
"TUNCTL",
|
|
"FEATURE_TUNCTL_UG",
|
|
"VCONFIG",
|
|
"WGET",
|
|
"FEATURE_WGET_LONG_OPTIONS",
|
|
"FEATURE_WGET_STATUSBAR",
|
|
"FEATURE_WGET_FTP",
|
|
"FEATURE_WGET_AUTHENTICATION",
|
|
"FEATURE_WGET_TIMEOUT",
|
|
"FEATURE_WGET_HTTPS",
|
|
"FEATURE_WGET_OPENSSL",
|
|
"WHOIS",
|
|
"ZCIP",
|
|
"UDHCPD",
|
|
"FEATURE_UDHCPD_BOOTP",
|
|
"FEATURE_UDHCPD_WRITE_LEASES_EARLY",
|
|
"DHCPD_LEASES_FILE",
|
|
"DUMPLEASES",
|
|
"DHCPRELAY",
|
|
"UDHCPC",
|
|
"FEATURE_UDHCPC_ARPING",
|
|
"FEATURE_UDHCPC_SANITIZEOPT",
|
|
"UDHCPC_DEFAULT_SCRIPT",
|
|
"UDHCPC6_DEFAULT_SCRIPT",
|
|
"UDHCPC6",
|
|
"FEATURE_UDHCPC6_RFC3646",
|
|
"FEATURE_UDHCPC6_RFC4704",
|
|
"FEATURE_UDHCPC6_RFC4833",
|
|
"FEATURE_UDHCPC6_RFC5970",
|
|
}, " "),
|
|
}, env), `
|
|
config_enable() {
|
|
for ent in "$@"; do
|
|
sed "s/^# CONFIG_${ent}.*/CONFIG_${ent}=y/" -i .config
|
|
shift
|
|
done
|
|
}
|
|
|
|
config_disable() {
|
|
for ent in "$@"; do
|
|
sed "s/^CONFIG_${ent}=y/# CONFIG_${ent} is not set/" -i .config
|
|
shift
|
|
done
|
|
}
|
|
|
|
cat > /bin/gcc << EOF
|
|
exec clang \
|
|
-Qunused-arguments \
|
|
-Wno-ignored-optimization-argument \
|
|
${LDFLAGS} \
|
|
\$@
|
|
EOF
|
|
chmod +x /bin/gcc
|
|
|
|
cd "$(mktemp -d)"
|
|
make \
|
|
KBUILD_SRC=/usr/src/busybox \
|
|
-f /usr/src/busybox/Makefile \
|
|
defconfig
|
|
|
|
config_enable $ROSA_BUSYBOX_ENABLE
|
|
config_disable $ROSA_BUSYBOX_DISABLE
|
|
mkdir -p /system/bin
|
|
ln -s ../../usr/lib/libc.so /system/bin/linker || true
|
|
ln -s ../system/bin/pwd /bin/pwd || true
|
|
make \
|
|
CFLAGS_busybox="${LDFLAGS} ${EXTRA_LDFLAGS}" \
|
|
"-j$(nproc)"
|
|
|
|
mkdir -p /system/bin/ /work/bin/
|
|
cp busybox /system/bin/
|
|
|
|
mkdir -pv /work/system/bin/
|
|
busybox --install -s /work/system/bin/
|
|
cp -v busybox /work/system/bin/
|
|
ln -vs ../system/bin/hush /work/bin/sh
|
|
mkdir -vp /work/usr/bin/
|
|
ln -vs ../../system/bin/busybox /work/usr/bin/env
|
|
`, pkg.Path(AbsUsrSrc.Append("busybox"), true, t.NewPatchedSource(
|
|
"busybox", version, pkg.NewHTTPGetTar(
|
|
&http.Client{Transport: &http.Transport{
|
|
// busybox website is really slow to respond
|
|
TLSHandshakeTimeout: 2 * time.Minute,
|
|
}},
|
|
"https://busybox.net/downloads/busybox-"+version+".tar.bz2",
|
|
mustDecode(checksum),
|
|
pkg.TarBzip2,
|
|
), true, [2]string{"awk-fix-literal-backslash", `diff --git a/editors/awk.c b/editors/awk.c
|
|
index 64e752f4b..40f5ba7f7 100644
|
|
--- a/editors/awk.c
|
|
+++ b/editors/awk.c
|
|
@@ -2636,8 +2636,13 @@ static int awk_sub(node *rn, const char *repl, int nm, var *src, var *dest /*,in
|
|
resbuf = qrealloc(resbuf, residx + replen + n, &resbufsize);
|
|
memcpy(resbuf + residx, sp + pmatch[j].rm_so - start_ofs, n);
|
|
residx += n;
|
|
- } else
|
|
+ } else {
|
|
+/* '\\' and '&' following a backslash keep its original meaning, any other
|
|
+ * occurrence of a '\\' should be treated as literal */
|
|
+ if (bslash && c != '\\' && c != '&')
|
|
+ resbuf[residx++] = '\\';
|
|
resbuf[residx++] = c;
|
|
+ }
|
|
bslash = 0;
|
|
}
|
|
}`},
|
|
)))
|
|
}
|
|
func init() { artifactsF[Busybox] = Toolchain.newBusybox }
|