diff --git a/compileopts/config.go b/compileopts/config.go index eca037503c..b026bb1358 100644 --- a/compileopts/config.go +++ b/compileopts/config.go @@ -84,6 +84,7 @@ func (c *Config) BuildTags() []string { tags = append(tags, []string{ "tinygo", // that's the compiler "purego", // to get various crypto packages to work + "osusergo", // to get osuser to work when go sources used "math_big_pure_go", // to get math/big to work "gc." + c.GC(), "scheduler." + c.Scheduler(), // used inside the runtime package "serial." + c.Serial()}...) // used inside the machine package diff --git a/loader/goroot.go b/loader/goroot.go index 8661bf67e0..3413d4ab23 100644 --- a/loader/goroot.go +++ b/loader/goroot.go @@ -45,7 +45,7 @@ func GetCachedGoroot(config *compileopts.Config) (string, error) { } // Find the overrides needed for the goroot. - overrides := pathsToOverride(config.GoMinorVersion, needsSyscallPackage(config.BuildTags())) + overrides := pathsToOverride(config) // Resolve the merge links within the goroot. merge, err := listGorootMergeLinks(goroot, tinygoroot, overrides) @@ -225,9 +225,22 @@ func needsSyscallPackage(buildTags []string) bool { return false } +func needsOsUserPackage(buildTags []string) bool { + for _, tag := range buildTags { + if tag == "baremetal" { + return true + } + } + return false +} + // The boolean indicates whether to merge the subdirs. True means merge, false // means use the TinyGo version. -func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool { +func pathsToOverride(config *compileopts.Config) map[string]bool { + + goMinor := config.GoMinorVersion + buildTags := config.BuildTags() + paths := map[string]bool{ "": true, "crypto/": true, @@ -247,7 +260,6 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool { "net/": true, "net/http/": false, "os/": true, - "os/user/": false, "reflect/": false, "runtime/": false, "sync/": true, @@ -260,9 +272,14 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool { paths["crypto/internal/boring/sig/"] = false } - if needsSyscallPackage { + if needsSyscallPackage(buildTags) { paths["syscall/"] = true // include syscall/js } + + if needsOsUserPackage(buildTags) { + paths["os/user/"] = true + } + return paths } diff --git a/loader/loader.go b/loader/loader.go index fe75e6c9b4..b2c6231886 100644 --- a/loader/loader.go +++ b/loader/loader.go @@ -279,7 +279,7 @@ func (p *Program) getOriginalPath(path string) string { originalPath = realgorootPath } maybeInTinyGoRoot := false - for prefix := range pathsToOverride(p.config.GoMinorVersion, needsSyscallPackage(p.config.BuildTags())) { + for prefix := range pathsToOverride(p.config) { if runtime.GOOS == "windows" { prefix = strings.ReplaceAll(prefix, "/", "\\") } diff --git a/src/os/user/unimplemented_user.go b/src/os/user/unimplemented_user.go new file mode 100644 index 0000000000..3290f021ce --- /dev/null +++ b/src/os/user/unimplemented_user.go @@ -0,0 +1,31 @@ +package user + +/* + os/user stubbed functions + +TODO: these should return unsupported / unimplemented errors + +*/ + +import ( + "errors" +) + +// Current returns the current user. +// +// The first call will cache the current user information. +// Subsequent calls will return the cached value and will not reflect +// changes to the current user. +func Current() (*User, error) { + return nil, errors.New("user: Current not implemented") +} + +// Lookup always returns an error. +func Lookup(username string) (*User, error) { + return nil, errors.New("user: Lookup not implemented") +} + +// LookupGroup always returns an error. +func LookupGroup(name string) (*Group, error) { + return nil, errors.New("user: LookupGroup not implemented") +} diff --git a/src/os/user/user.go b/src/os/user/user.go index ee63625f2b..a1109314c6 100644 --- a/src/os/user/user.go +++ b/src/os/user/user.go @@ -1,10 +1,18 @@ -// Copyright 2016 The Go Authors. All rights reserved. +// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +/* +Package user allows user account lookups by name or id. + +tinygo: Largely copied from go1.22.6 +This is merged to "cached GOROOT/src/os/user" for baremetal systems +*/ package user -import "errors" +import ( + "strconv" +) // User represents a user account. type User struct { @@ -31,20 +39,6 @@ type User struct { HomeDir string } -// Current returns the current user. -// -// The first call will cache the current user information. -// Subsequent calls will return the cached value and will not reflect -// changes to the current user. -func Current() (*User, error) { - return nil, errors.New("user: Current not implemented") -} - -// Lookup always returns an error. -func Lookup(username string) (*User, error) { - return nil, errors.New("user: Lookup not implemented") -} - // Group represents a grouping of users. // // On POSIX systems Gid contains a decimal number representing the group ID. @@ -53,7 +47,33 @@ type Group struct { Name string // group name } -// LookupGroup always returns an error. -func LookupGroup(name string) (*Group, error) { - return nil, errors.New("user: LookupGroup not implemented") +// UnknownUserIdError is returned by LookupId when a user cannot be found. +type UnknownUserIdError int + +func (e UnknownUserIdError) Error() string { + return "user: unknown userid " + strconv.Itoa(int(e)) +} + +// UnknownUserError is returned by Lookup when +// a user cannot be found. +type UnknownUserError string + +func (e UnknownUserError) Error() string { + return "user: unknown user " + string(e) +} + +// UnknownGroupIdError is returned by LookupGroupId when +// a group cannot be found. +type UnknownGroupIdError string + +func (e UnknownGroupIdError) Error() string { + return "group: unknown groupid " + string(e) +} + +// UnknownGroupError is returned by LookupGroup when +// a group cannot be found. +type UnknownGroupError string + +func (e UnknownGroupError) Error() string { + return "group: unknown group " + string(e) }