diff --git a/internal/rosa/busybox.go b/internal/rosa/busybox.go index 3fe221b..25baee9 100644 --- a/internal/rosa/busybox.go +++ b/internal/rosa/busybox.go @@ -5,6 +5,8 @@ import ( "io" "net/http" "os" + "slices" + "strings" "time" "hakurei.app/container/fhs" @@ -97,3 +99,260 @@ func newBusyboxBin() pkg.Artifact { )}), ) } + +// NewBusybox returns a [pkg.Artifact] containing a dynamically linked busybox +// installation usable within the [Toolchain] it is compiled against. +func (t Toolchain) NewBusybox() pkg.Artifact { + const ( + version = "1.37.0" + checksum = "Ial94Tnt7esJ_YEeb0AxunVL6MGYFyOw7Rtu2o87CXCi1TLrc6rlznVsN1rZk7it" + ) + + extra := []pkg.Artifact{ + t.NewMake(), + t.NewKernelHeaders(), + } + var env []string + + if t == toolchainStage3 { + extra = nil + env = append(env, "EXTRA_LDFLAGS=-static") + } + + return t.New("busybox-"+version, extra, nil, slices.Concat([]string{ + "ROSA_BUSYBOX_ENABLE=" + strings.Join([]string{ + "STATIC", + "PIE", + }, " "), + "ROSA_BUSYBOX_DISABLE=" + strings.Join([]string{ + "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 \ + -Wno-ignored-optimization-argument \ + ${ROSA_CFLAGS} \ + ${LDFLAGS} \ + \$@ +EOF +chmod +x /bin/gcc + +cd /usr/src/busybox +chmod +w editors editors/awk.c +patch -p 1 < /usr/src/patches/awk-fix-literal-backslash.patch + +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 +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 +`, pkg.Path(AbsUsrSrc.Append("busybox"), true, 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, + )), pkg.Path( + AbsUsrSrc.Append("patches", "awk-fix-literal-backslash.patch"), false, + pkg.NewFile("awk-fix-literal-backslash.patch", []byte(`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; + } + }`)), + )) +}