Compare commits
5 Commits
699c19e972
...
d42067df7c
| Author | SHA1 | Date | |
|---|---|---|---|
|
d42067df7c
|
|||
|
b9459a80c7
|
|||
|
f8189d1488
|
|||
|
5063b774c1
|
|||
|
766dd89ffa
|
@@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
@@ -227,8 +226,11 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
|
|||||||
} else {
|
} else {
|
||||||
if f, err := os.Open(flagDBusConfigSession); err != nil {
|
if f, err := os.Open(flagDBusConfigSession); err != nil {
|
||||||
log.Fatal(err.Error())
|
log.Fatal(err.Error())
|
||||||
} else if err = json.NewDecoder(f).Decode(&config.SessionBus); err != nil {
|
} else {
|
||||||
log.Fatalf("cannot load session bus proxy config from %q: %s", flagDBusConfigSession, err)
|
decodeJSON(log.Fatal, "load session bus proxy config", f, &config.SessionBus)
|
||||||
|
if err = f.Close(); err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,8 +238,11 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
|
|||||||
if flagDBusConfigSystem != "nil" {
|
if flagDBusConfigSystem != "nil" {
|
||||||
if f, err := os.Open(flagDBusConfigSystem); err != nil {
|
if f, err := os.Open(flagDBusConfigSystem); err != nil {
|
||||||
log.Fatal(err.Error())
|
log.Fatal(err.Error())
|
||||||
} else if err = json.NewDecoder(f).Decode(&config.SystemBus); err != nil {
|
} else {
|
||||||
log.Fatalf("cannot load system bus proxy config from %q: %s", flagDBusConfigSystem, err)
|
decodeJSON(log.Fatal, "load system bus proxy config", f, &config.SystemBus)
|
||||||
|
if err = f.Close(); err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +328,7 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
|
|||||||
|
|
||||||
c.Command("version", "Display version information", func(args []string) error { fmt.Println(internal.Version()); return errSuccess })
|
c.Command("version", "Display version information", func(args []string) error { fmt.Println(internal.Version()); return errSuccess })
|
||||||
c.Command("license", "Show full license text", func(args []string) error { fmt.Println(license); return errSuccess })
|
c.Command("license", "Show full license text", func(args []string) error { fmt.Println(license); return errSuccess })
|
||||||
c.Command("template", "Produce a config template", func(args []string) error { printJSON(os.Stdout, false, hst.Template()); return errSuccess })
|
c.Command("template", "Produce a config template", func(args []string) error { encodeJSON(log.Fatal, os.Stdout, false, hst.Template()); return errSuccess })
|
||||||
c.Command("help", "Show this help message", func([]string) error { c.PrintHelp(); return errSuccess })
|
c.Command("help", "Show this help message", func([]string) error { c.PrintHelp(); return errSuccess })
|
||||||
|
|
||||||
return c
|
return c
|
||||||
|
|||||||
60
cmd/hakurei/json.go
Normal file
60
cmd/hakurei/json.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// decodeJSON decodes json from r and stores it in v. A non-nil error results in a call to fatal.
|
||||||
|
func decodeJSON(fatal func(v ...any), op string, r io.Reader, v any) {
|
||||||
|
err := json.NewDecoder(r).Decode(v)
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
syntaxError *json.SyntaxError
|
||||||
|
unmarshalTypeError *json.UnmarshalTypeError
|
||||||
|
|
||||||
|
msg string
|
||||||
|
)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case errors.As(err, &syntaxError) && syntaxError != nil:
|
||||||
|
msg = syntaxError.Error() +
|
||||||
|
" at byte " + strconv.FormatInt(syntaxError.Offset, 10)
|
||||||
|
|
||||||
|
case errors.As(err, &unmarshalTypeError) && unmarshalTypeError != nil:
|
||||||
|
msg = "inappropriate " + unmarshalTypeError.Value +
|
||||||
|
" at byte " + strconv.FormatInt(unmarshalTypeError.Offset, 10)
|
||||||
|
|
||||||
|
default:
|
||||||
|
// InvalidUnmarshalError: incorrect usage, does not need to be handled
|
||||||
|
// io.ErrUnexpectedEOF: no additional error information available
|
||||||
|
msg = err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
fatal("cannot " + op + ": " + msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodeJSON encodes v to output. A non-nil error results in a call to fatal.
|
||||||
|
func encodeJSON(fatal func(v ...any), output io.Writer, short bool, v any) {
|
||||||
|
encoder := json.NewEncoder(output)
|
||||||
|
if !short {
|
||||||
|
encoder.SetIndent("", " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := encoder.Encode(v); err != nil {
|
||||||
|
var marshalerError *json.MarshalerError
|
||||||
|
if errors.As(err, &marshalerError) && marshalerError != nil {
|
||||||
|
// this likely indicates an implementation error in hst
|
||||||
|
fatal("cannot encode json for " + marshalerError.Type.String() + ": " + marshalerError.Err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnsupportedTypeError, UnsupportedValueError: incorrect usage, does not need to be handled
|
||||||
|
fatal("cannot write json: " + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
107
cmd/hakurei/json_test.go
Normal file
107
cmd/hakurei/json_test.go
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
package main_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"hakurei.app/container/stub"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname decodeJSON hakurei.app/cmd/hakurei.decodeJSON
|
||||||
|
func decodeJSON(fatal func(v ...any), op string, r io.Reader, v any)
|
||||||
|
|
||||||
|
func TestDecodeJSON(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
t reflect.Type
|
||||||
|
data string
|
||||||
|
want any
|
||||||
|
msg string
|
||||||
|
}{
|
||||||
|
{"success", reflect.TypeFor[uintptr](), "3735928559\n", uintptr(0xdeadbeef), ""},
|
||||||
|
|
||||||
|
{"syntax", reflect.TypeFor[*int](), "\x00", nil,
|
||||||
|
`cannot load sample: invalid character '\x00' looking for beginning of value at byte 1`},
|
||||||
|
{"type", reflect.TypeFor[uintptr](), "-1", nil,
|
||||||
|
`cannot load sample: inappropriate number -1 at byte 2`},
|
||||||
|
{"default", reflect.TypeFor[*int](), "{", nil,
|
||||||
|
"cannot load sample: unexpected EOF"},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var (
|
||||||
|
gotP = reflect.New(tc.t)
|
||||||
|
gotMsg *string
|
||||||
|
)
|
||||||
|
decodeJSON(func(v ...any) {
|
||||||
|
if gotMsg != nil {
|
||||||
|
t.Fatal("fatal called twice")
|
||||||
|
}
|
||||||
|
msg := v[0].(string)
|
||||||
|
gotMsg = &msg
|
||||||
|
}, "load sample", strings.NewReader(tc.data), gotP.Interface())
|
||||||
|
if tc.msg != "" {
|
||||||
|
if gotMsg == nil {
|
||||||
|
t.Errorf("decodeJSON: success, want fatal %q", tc.msg)
|
||||||
|
} else if *gotMsg != tc.msg {
|
||||||
|
t.Errorf("decodeJSON: fatal = %q, want %q", *gotMsg, tc.msg)
|
||||||
|
}
|
||||||
|
} else if gotMsg != nil {
|
||||||
|
t.Errorf("decodeJSON: fatal = %q", *gotMsg)
|
||||||
|
} else if !reflect.DeepEqual(gotP.Elem().Interface(), tc.want) {
|
||||||
|
t.Errorf("decodeJSON: %#v, want %#v", gotP.Elem().Interface(), tc.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname encodeJSON hakurei.app/cmd/hakurei.encodeJSON
|
||||||
|
func encodeJSON(fatal func(v ...any), output io.Writer, short bool, v any)
|
||||||
|
|
||||||
|
func TestEncodeJSON(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
v any
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"marshaler", errorJSONMarshaler{},
|
||||||
|
`cannot encode json for main_test.errorJSONMarshaler: unique error 3735928559 injected by the test suite`},
|
||||||
|
{"default", func() {},
|
||||||
|
`cannot write json: json: unsupported type: func()`},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var called bool
|
||||||
|
encodeJSON(func(v ...any) {
|
||||||
|
if called {
|
||||||
|
t.Fatal("fatal called twice")
|
||||||
|
}
|
||||||
|
called = true
|
||||||
|
|
||||||
|
if v[0].(string) != tc.want {
|
||||||
|
t.Errorf("encodeJSON: fatal = %q, want %q", v[0].(string), tc.want)
|
||||||
|
}
|
||||||
|
}, nil, false, tc.v)
|
||||||
|
|
||||||
|
if !called {
|
||||||
|
t.Errorf("encodeJSON: success, want fatal %q", tc.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// errorJSONMarshaler implements json.Marshaler.
|
||||||
|
type errorJSONMarshaler struct{}
|
||||||
|
|
||||||
|
func (errorJSONMarshaler) MarshalJSON() ([]byte, error) { return nil, stub.UniqueError(0xdeadbeef) }
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
@@ -42,10 +41,7 @@ func tryPath(msg message.Msg, name string) (config *hst.Config) {
|
|||||||
r = os.Stdin
|
r = os.Stdin
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.NewDecoder(r).Decode(&config); err != nil {
|
decodeJSON(log.Fatal, "load configuration", r, &config)
|
||||||
log.Fatalf("cannot load configuration: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
@@ -12,23 +11,26 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/internal"
|
||||||
"hakurei.app/internal/app"
|
"hakurei.app/internal/app"
|
||||||
"hakurei.app/internal/app/state"
|
"hakurei.app/internal/app/state"
|
||||||
"hakurei.app/message"
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// printShowSystem populates and writes a representation of [hst.Info] to output.
|
||||||
func printShowSystem(output io.Writer, short, flagJSON bool) {
|
func printShowSystem(output io.Writer, short, flagJSON bool) {
|
||||||
t := newPrinter(output)
|
t := newPrinter(output)
|
||||||
defer t.MustFlush()
|
defer t.MustFlush()
|
||||||
|
|
||||||
info := &hst.Info{User: new(app.Hsu).MustID(nil)}
|
info := &hst.Info{Version: internal.Version(), User: new(app.Hsu).MustID(nil)}
|
||||||
app.CopyPaths().Copy(&info.Paths, info.User)
|
app.CopyPaths().Copy(&info.Paths, info.User)
|
||||||
|
|
||||||
if flagJSON {
|
if flagJSON {
|
||||||
printJSON(output, short, info)
|
encodeJSON(log.Fatal, output, short, info)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.Printf("Version:\t%s\n", info.Version)
|
||||||
t.Printf("User:\t%d\n", info.User)
|
t.Printf("User:\t%d\n", info.User)
|
||||||
t.Printf("TempDir:\t%s\n", info.TempDir)
|
t.Printf("TempDir:\t%s\n", info.TempDir)
|
||||||
t.Printf("SharePath:\t%s\n", info.SharePath)
|
t.Printf("SharePath:\t%s\n", info.SharePath)
|
||||||
@@ -36,6 +38,7 @@ func printShowSystem(output io.Writer, short, flagJSON bool) {
|
|||||||
t.Printf("RunDirPath:\t%s\n", info.RunDirPath)
|
t.Printf("RunDirPath:\t%s\n", info.RunDirPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// printShowInstance writes a representation of [state.State] or [hst.Config] to output.
|
||||||
func printShowInstance(
|
func printShowInstance(
|
||||||
output io.Writer, now time.Time,
|
output io.Writer, now time.Time,
|
||||||
instance *state.State, config *hst.Config,
|
instance *state.State, config *hst.Config,
|
||||||
@@ -44,9 +47,9 @@ func printShowInstance(
|
|||||||
|
|
||||||
if flagJSON {
|
if flagJSON {
|
||||||
if instance != nil {
|
if instance != nil {
|
||||||
printJSON(output, short, instance)
|
encodeJSON(log.Fatal, output, short, instance)
|
||||||
} else {
|
} else {
|
||||||
printJSON(output, short, config)
|
encodeJSON(log.Fatal, output, short, config)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -168,6 +171,7 @@ func printShowInstance(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// printPs writes a representation of active instances to output.
|
||||||
func printPs(output io.Writer, now time.Time, s state.Store, short, flagJSON bool) {
|
func printPs(output io.Writer, now time.Time, s state.Store, short, flagJSON bool) {
|
||||||
var entries state.Entries
|
var entries state.Entries
|
||||||
if e, err := state.Join(s); err != nil {
|
if e, err := state.Join(s); err != nil {
|
||||||
@@ -184,7 +188,7 @@ func printPs(output io.Writer, now time.Time, s state.Store, short, flagJSON boo
|
|||||||
for id, instance := range entries {
|
for id, instance := range entries {
|
||||||
es[id.String()] = instance
|
es[id.String()] = instance
|
||||||
}
|
}
|
||||||
printJSON(output, short, es)
|
encodeJSON(log.Fatal, output, short, es)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +217,7 @@ func printPs(output io.Writer, now time.Time, s state.Store, short, flagJSON boo
|
|||||||
for i, e := range exp {
|
for i, e := range exp {
|
||||||
v[i] = e.s
|
v[i] = e.s
|
||||||
}
|
}
|
||||||
printJSON(output, short, v)
|
encodeJSON(log.Fatal, output, short, v)
|
||||||
} else {
|
} else {
|
||||||
for _, e := range exp {
|
for _, e := range exp {
|
||||||
mustPrintln(output, e.s[:8])
|
mustPrintln(output, e.s[:8])
|
||||||
@@ -247,40 +251,39 @@ func printPs(output io.Writer, now time.Time, s state.Store, short, flagJSON boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// expandedStateEntry stores [state.State] alongside a string representation of its [state.ID].
|
||||||
type expandedStateEntry struct {
|
type expandedStateEntry struct {
|
||||||
s string
|
s string
|
||||||
*state.State
|
*state.State
|
||||||
}
|
}
|
||||||
|
|
||||||
func printJSON(output io.Writer, short bool, v any) {
|
// newPrinter returns a configured, wrapped [tabwriter.Writer].
|
||||||
encoder := json.NewEncoder(output)
|
|
||||||
if !short {
|
|
||||||
encoder.SetIndent("", " ")
|
|
||||||
}
|
|
||||||
if err := encoder.Encode(v); err != nil {
|
|
||||||
log.Fatalf("cannot serialise: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newPrinter(output io.Writer) *tp { return &tp{tabwriter.NewWriter(output, 0, 1, 4, ' ', 0)} }
|
func newPrinter(output io.Writer) *tp { return &tp{tabwriter.NewWriter(output, 0, 1, 4, ' ', 0)} }
|
||||||
|
|
||||||
|
// tp wraps [tabwriter.Writer] to provide additional formatting methods.
|
||||||
type tp struct{ *tabwriter.Writer }
|
type tp struct{ *tabwriter.Writer }
|
||||||
|
|
||||||
|
// Printf calls [fmt.Fprintf] on the underlying [tabwriter.Writer].
|
||||||
func (p *tp) Printf(format string, a ...any) {
|
func (p *tp) Printf(format string, a ...any) {
|
||||||
if _, err := fmt.Fprintf(p, format, a...); err != nil {
|
if _, err := fmt.Fprintf(p, format, a...); err != nil {
|
||||||
log.Fatalf("cannot write to tabwriter: %v", err)
|
log.Fatalf("cannot write to tabwriter: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Println calls [fmt.Fprintln] on the underlying [tabwriter.Writer].
|
||||||
func (p *tp) Println(a ...any) {
|
func (p *tp) Println(a ...any) {
|
||||||
if _, err := fmt.Fprintln(p, a...); err != nil {
|
if _, err := fmt.Fprintln(p, a...); err != nil {
|
||||||
log.Fatalf("cannot write to tabwriter: %v", err)
|
log.Fatalf("cannot write to tabwriter: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MustFlush calls the Flush method of [tabwriter.Writer] and calls [log.Fatalf] on a non-nil error.
|
||||||
func (p *tp) MustFlush() {
|
func (p *tp) MustFlush() {
|
||||||
if err := p.Writer.Flush(); err != nil {
|
if err := p.Writer.Flush(); err != nil {
|
||||||
log.Fatalf("cannot flush tabwriter: %v", err)
|
log.Fatalf("cannot flush tabwriter: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustPrint(output io.Writer, a ...any) {
|
func mustPrint(output io.Writer, a ...any) {
|
||||||
if _, err := fmt.Fprint(output, a...); err != nil {
|
if _, err := fmt.Fprint(output, a...); err != nil {
|
||||||
log.Fatalf("cannot print: %v", err)
|
log.Fatalf("cannot print: %v", err)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
"hakurei.app/message"
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
var hakureiPath = internal.MustHakureiPath()
|
var hakureiPathVal = internal.MustHakureiPath().String()
|
||||||
|
|
||||||
func mustRunApp(ctx context.Context, msg message.Msg, config *hst.Config, beforeFail func()) {
|
func mustRunApp(ctx context.Context, msg message.Msg, config *hst.Config, beforeFail func()) {
|
||||||
var (
|
var (
|
||||||
@@ -27,9 +27,9 @@ func mustRunApp(ctx context.Context, msg message.Msg, config *hst.Config, before
|
|||||||
log.Fatalf("cannot pipe: %v", err)
|
log.Fatalf("cannot pipe: %v", err)
|
||||||
} else {
|
} else {
|
||||||
if msg.IsVerbose() {
|
if msg.IsVerbose() {
|
||||||
cmd = exec.CommandContext(ctx, hakureiPath.String(), "-v", "app", "3")
|
cmd = exec.CommandContext(ctx, hakureiPathVal, "-v", "app", "3")
|
||||||
} else {
|
} else {
|
||||||
cmd = exec.CommandContext(ctx, hakureiPath.String(), "app", "3")
|
cmd = exec.CommandContext(ctx, hakureiPathVal, "app", "3")
|
||||||
}
|
}
|
||||||
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
||||||
cmd.ExtraFiles = []*os.File{r}
|
cmd.ExtraFiles = []*os.File{r}
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ const (
|
|||||||
identityMax = 9999
|
identityMax = 9999
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// hakureiPath is the absolute path to Hakurei.
|
||||||
|
//
|
||||||
|
// This is set by the linker.
|
||||||
|
var hakureiPath string
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
log.SetPrefix("hsu: ")
|
log.SetPrefix("hsu: ")
|
||||||
@@ -43,13 +48,18 @@ func main() {
|
|||||||
log.Fatal("this program must not be started by root")
|
log.Fatal("this program must not be started by root")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !path.IsAbs(hakureiPath) {
|
||||||
|
log.Fatal("this program is compiled incorrectly")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var toolPath string
|
var toolPath string
|
||||||
pexe := path.Join("/proc", strconv.Itoa(os.Getppid()), "exe")
|
pexe := path.Join("/proc", strconv.Itoa(os.Getppid()), "exe")
|
||||||
if p, err := os.Readlink(pexe); err != nil {
|
if p, err := os.Readlink(pexe); err != nil {
|
||||||
log.Fatalf("cannot read parent executable path: %v", err)
|
log.Fatalf("cannot read parent executable path: %v", err)
|
||||||
} else if strings.HasSuffix(p, " (deleted)") {
|
} else if strings.HasSuffix(p, " (deleted)") {
|
||||||
log.Fatal("hakurei executable has been deleted")
|
log.Fatal("hakurei executable has been deleted")
|
||||||
} else if p != mustCheckPath(hmain) {
|
} else if p != hakureiPath {
|
||||||
log.Fatal("this program must be started by hakurei")
|
log.Fatal("this program must be started by hakurei")
|
||||||
} else {
|
} else {
|
||||||
toolPath = p
|
toolPath = p
|
||||||
|
|||||||
@@ -19,5 +19,5 @@ buildGoModule {
|
|||||||
ldflags = lib.attrsets.foldlAttrs (
|
ldflags = lib.attrsets.foldlAttrs (
|
||||||
ldflags: name: value:
|
ldflags: name: value:
|
||||||
ldflags ++ [ "-X main.${name}=${value}" ]
|
ldflags ++ [ "-X main.${name}=${value}" ]
|
||||||
) [ "-s -w" ] { hmain = "${hakurei}/libexec/hakurei"; };
|
) [ "-s -w" ] { hakureiPath = "${hakurei}/libexec/hakurei"; };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"path"
|
|
||||||
)
|
|
||||||
|
|
||||||
const compPoison = "INVALIDINVALIDINVALIDINVALIDINVALID"
|
|
||||||
|
|
||||||
var (
|
|
||||||
hmain = compPoison
|
|
||||||
)
|
|
||||||
|
|
||||||
func mustCheckPath(p string) string {
|
|
||||||
if p != compPoison && p != "" && path.IsAbs(p) {
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
log.Fatal("this program is compiled incorrectly")
|
|
||||||
return compPoison
|
|
||||||
}
|
|
||||||
@@ -1029,8 +1029,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, stub.UniqueError(37)),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, stub.UniqueError(37)),
|
||||||
call("fatalf", stub.ExpectArgs{"cannot open intermediate root: %v", []any{stub.UniqueError(37)}}, nil, nil),
|
call("fatalf", stub.ExpectArgs{"cannot open intermediate root: %v", []any{stub.UniqueError(37)}}, nil, nil),
|
||||||
},
|
},
|
||||||
}, nil},
|
}, nil},
|
||||||
@@ -1088,8 +1088,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, stub.UniqueError(35)),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, stub.UniqueError(35)),
|
||||||
call("fatalf", stub.ExpectArgs{"cannot enter sysroot: %v", []any{stub.UniqueError(35)}}, nil, nil),
|
call("fatalf", stub.ExpectArgs{"cannot enter sysroot: %v", []any{stub.UniqueError(35)}}, nil, nil),
|
||||||
},
|
},
|
||||||
@@ -1148,8 +1148,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, stub.UniqueError(33)),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, stub.UniqueError(33)),
|
||||||
call("fatalf", stub.ExpectArgs{"cannot pivot into sysroot: %v", []any{stub.UniqueError(33)}}, nil, nil),
|
call("fatalf", stub.ExpectArgs{"cannot pivot into sysroot: %v", []any{stub.UniqueError(33)}}, nil, nil),
|
||||||
@@ -1209,8 +1209,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, stub.UniqueError(31)),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, stub.UniqueError(31)),
|
||||||
@@ -1271,8 +1271,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -1334,8 +1334,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -1398,8 +1398,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -1463,8 +1463,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -1529,8 +1529,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -1603,8 +1603,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -1710,8 +1710,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -1818,8 +1818,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -1927,8 +1927,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -2041,8 +2041,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -2143,8 +2143,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -2236,8 +2236,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -2331,8 +2331,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -2433,8 +2433,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -2572,8 +2572,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall"
|
. "syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetPtracer allows processes to ptrace(2) the calling process.
|
// SetPtracer allows processes to ptrace(2) the calling process.
|
||||||
func SetPtracer(pid uintptr) error {
|
func SetPtracer(pid uintptr) error {
|
||||||
_, _, errno := syscall.Syscall(syscall.SYS_PRCTL, syscall.PR_SET_PTRACER, pid, 0)
|
_, _, errno := Syscall(SYS_PRCTL, PR_SET_PTRACER, pid, 0)
|
||||||
if errno == 0 {
|
if errno == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,7 @@ const (
|
|||||||
// SetDumpable sets the "dumpable" attribute of the calling process.
|
// SetDumpable sets the "dumpable" attribute of the calling process.
|
||||||
func SetDumpable(dumpable uintptr) error {
|
func SetDumpable(dumpable uintptr) error {
|
||||||
// linux/sched/coredump.h
|
// linux/sched/coredump.h
|
||||||
if _, _, errno := syscall.Syscall(syscall.SYS_PRCTL, syscall.PR_SET_DUMPABLE, dumpable, 0); errno != 0 {
|
if _, _, errno := Syscall(SYS_PRCTL, PR_SET_DUMPABLE, dumpable, 0); errno != 0 {
|
||||||
return errno
|
return errno
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ func SetDumpable(dumpable uintptr) error {
|
|||||||
|
|
||||||
// SetNoNewPrivs sets the calling thread's no_new_privs attribute.
|
// SetNoNewPrivs sets the calling thread's no_new_privs attribute.
|
||||||
func SetNoNewPrivs() error {
|
func SetNoNewPrivs() error {
|
||||||
_, _, errno := syscall.Syscall(syscall.SYS_PRCTL, PR_SET_NO_NEW_PRIVS, 1, 0)
|
_, _, errno := Syscall(SYS_PRCTL, PR_SET_NO_NEW_PRIVS, 1, 0)
|
||||||
if errno == 0 {
|
if errno == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -41,10 +41,10 @@ func SetNoNewPrivs() error {
|
|||||||
// Isatty tests whether a file descriptor refers to a terminal.
|
// Isatty tests whether a file descriptor refers to a terminal.
|
||||||
func Isatty(fd int) bool {
|
func Isatty(fd int) bool {
|
||||||
var buf [8]byte
|
var buf [8]byte
|
||||||
r, _, _ := syscall.Syscall(
|
r, _, _ := Syscall(
|
||||||
syscall.SYS_IOCTL,
|
SYS_IOCTL,
|
||||||
uintptr(fd),
|
uintptr(fd),
|
||||||
syscall.TIOCGWINSZ,
|
TIOCGWINSZ,
|
||||||
uintptr(unsafe.Pointer(&buf[0])),
|
uintptr(unsafe.Pointer(&buf[0])),
|
||||||
)
|
)
|
||||||
return r == 0
|
return r == 0
|
||||||
@@ -60,7 +60,7 @@ func Isatty(fd int) bool {
|
|||||||
func IgnoringEINTR(fn func() error) error {
|
func IgnoringEINTR(fn func() error) error {
|
||||||
for {
|
for {
|
||||||
err := fn()
|
err := fn()
|
||||||
if err != syscall.EINTR {
|
if err != EINTR {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
dist/release.sh
vendored
8
dist/release.sh
vendored
@@ -10,10 +10,10 @@ cp -rv "dist/comp" "${out}"
|
|||||||
|
|
||||||
go generate ./...
|
go generate ./...
|
||||||
go build -trimpath -v -o "${out}/bin/" -ldflags "-s -w -buildid= -extldflags '-static'
|
go build -trimpath -v -o "${out}/bin/" -ldflags "-s -w -buildid= -extldflags '-static'
|
||||||
-X hakurei.app/internal.version=${VERSION}
|
-X hakurei.app/internal.buildVersion=${VERSION}
|
||||||
-X hakurei.app/internal.hmain=/usr/bin/hakurei
|
-X hakurei.app/internal.hakureiPath=/usr/bin/hakurei
|
||||||
-X hakurei.app/internal.hsu=/usr/bin/hsu
|
-X hakurei.app/internal.hsuPath=/usr/bin/hsu
|
||||||
-X main.hmain=/usr/bin/hakurei" ./...
|
-X main.hakureiPath=/usr/bin/hakurei" ./...
|
||||||
|
|
||||||
rm -f "./${out}.tar.gz" && tar -C dist -czf "${out}.tar.gz" "${pname}"
|
rm -f "./${out}.tar.gz" && tar -C dist -czf "${out}.tar.gz" "${pname}"
|
||||||
rm -rf "./${out}"
|
rm -rf "./${out}"
|
||||||
|
|||||||
@@ -52,7 +52,10 @@ type Paths struct {
|
|||||||
RunDirPath *check.Absolute `json:"run_dir_path"`
|
RunDirPath *check.Absolute `json:"run_dir_path"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Info holds basic system information collected from the implementation.
|
||||||
type Info struct {
|
type Info struct {
|
||||||
|
// Version is a hardcoded version string.
|
||||||
|
Version string `json:"version"`
|
||||||
// User is the userid according to hsu.
|
// User is the userid according to hsu.
|
||||||
User int `json:"user"`
|
User int `json:"user"`
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
package internal
|
|
||||||
|
|
||||||
const compPoison = "INVALIDINVALIDINVALIDINVALIDINVALID"
|
|
||||||
|
|
||||||
var (
|
|
||||||
version = compPoison
|
|
||||||
)
|
|
||||||
|
|
||||||
// checkComp validates string value set at compile time.
|
|
||||||
func checkComp(s string) (string, bool) { return s, s != compPoison && s != "" }
|
|
||||||
|
|
||||||
func Version() string {
|
|
||||||
if v, ok := checkComp(version); ok {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
return "impure"
|
|
||||||
}
|
|
||||||
@@ -6,20 +6,20 @@ import (
|
|||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// Absolute paths to the Hakurei installation.
|
||||||
hmain = compPoison
|
//
|
||||||
hsu = compPoison
|
// These are set by the linker.
|
||||||
)
|
var hakureiPath, hsuPath string
|
||||||
|
|
||||||
// MustHakureiPath returns the absolute path to hakurei, configured at compile time.
|
// MustHakureiPath returns the [check.Absolute] path to hakurei.
|
||||||
func MustHakureiPath() *check.Absolute { return mustCheckPath(log.Fatal, "hakurei", hmain) }
|
func MustHakureiPath() *check.Absolute { return mustCheckPath(log.Fatal, "hakurei", hakureiPath) }
|
||||||
|
|
||||||
// MustHsuPath returns the absolute path to hakurei, configured at compile time.
|
// MustHsuPath returns the [check.Absolute] to hsu.
|
||||||
func MustHsuPath() *check.Absolute { return mustCheckPath(log.Fatal, "hsu", hsu) }
|
func MustHsuPath() *check.Absolute { return mustCheckPath(log.Fatal, "hsu", hsuPath) }
|
||||||
|
|
||||||
// mustCheckPath checks a pathname against compPoison, then [container.NewAbs], calling fatal if either step fails.
|
// mustCheckPath checks a pathname to not be zero, then [check.NewAbs], calling fatal if either step fails.
|
||||||
func mustCheckPath(fatal func(v ...any), name, pathname string) *check.Absolute {
|
func mustCheckPath(fatal func(v ...any), name, pathname string) *check.Absolute {
|
||||||
if pathname != compPoison && pathname != "" {
|
if pathname != "" {
|
||||||
if a, err := check.NewAbs(pathname); err != nil {
|
if a, err := check.NewAbs(pathname); err != nil {
|
||||||
fatal(err.Error())
|
fatal(err.Error())
|
||||||
return nil // unreachable
|
return nil // unreachable
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ func TestMustCheckPath(t *testing.T) {
|
|||||||
pathname string
|
pathname string
|
||||||
wantFatal string
|
wantFatal string
|
||||||
}{
|
}{
|
||||||
{"poison", compPoison, "invalid test path, this program is compiled incorrectly"},
|
|
||||||
{"zero", "", "invalid test path, this program is compiled incorrectly"},
|
{"zero", "", "invalid test path, this program is compiled incorrectly"},
|
||||||
{"not absolute", "\x00", `path "\x00" is not absolute`},
|
{"not absolute", "\x00", `path "\x00" is not absolute`},
|
||||||
{"success", "/proc/nonexistent", ""},
|
{"success", "/proc/nonexistent", ""},
|
||||||
|
|||||||
19
internal/version.go
Normal file
19
internal/version.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
// FallbackVersion is returned when a version string was not set by the linker.
|
||||||
|
const FallbackVersion = "dirty"
|
||||||
|
|
||||||
|
// buildVersion is the Hakurei tree's version string at build time.
|
||||||
|
//
|
||||||
|
// This is set by the linker.
|
||||||
|
var buildVersion string
|
||||||
|
|
||||||
|
// Version returns the Hakurei tree's version string.
|
||||||
|
// It is either the value of the constant [FallbackVersion] or,
|
||||||
|
// when possible, a release tag like "v1.0.0".
|
||||||
|
func Version() string {
|
||||||
|
if buildVersion != "" {
|
||||||
|
return buildVersion
|
||||||
|
}
|
||||||
|
return FallbackVersion
|
||||||
|
}
|
||||||
@@ -75,9 +75,9 @@ buildGoModule rec {
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
version = "v${version}";
|
buildVersion = "v${version}";
|
||||||
hmain = "${placeholder "out"}/libexec/hakurei";
|
hakureiPath = "${placeholder "out"}/libexec/hakurei";
|
||||||
hsu = "/run/wrappers/bin/hsu";
|
hsuPath = "/run/wrappers/bin/hsu";
|
||||||
};
|
};
|
||||||
|
|
||||||
# nix build environment does not allow acls
|
# nix build environment does not allow acls
|
||||||
|
|||||||
Reference in New Issue
Block a user