Files
wazero/internal/gojs/process.go
Crypt Keeper 8464474e21 gojs: adds support for uid and gid (#1245)
This adds `gojs.WithOSUser` which passes through current user IDs so
that GOOS=js compiled wasm can read them. This also adds support for
reading back the uid and gid on files. In summary, this passes
`os.TestChown` except on windows where it will not work due to lack of
support.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-03-16 11:07:27 +08:00

104 lines
3.3 KiB
Go

package gojs
import (
"context"
"path"
"syscall"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/internal/gojs/custom"
"github.com/tetratelabs/wazero/internal/gojs/goos"
"github.com/tetratelabs/wazero/internal/gojs/util"
)
// processState are the mutable fields of the current process.
type processState struct {
cwd string
umask uint32
}
func newJsProcess(uid, gid, euid int, groups []int, proc *processState) *jsVal {
uidRef := toFloatRef(float64(uid))
gidRef := toFloatRef(float64(gid))
euidRef := toFloatRef(float64(euid))
groupSlice := make([]interface{}, 0, len(groups))
for _, group := range groups {
groupSlice = append(groupSlice, toFloatRef(float64(group)))
}
// jsProcess = js.Global().Get("process") // fs_js.go init
return newJsVal(goos.RefJsProcess, custom.NameProcess).
addProperties(map[string]interface{}{
"pid": float64(1), // Get("pid").Int() in syscall_js.go for syscall.Getpid
"ppid": goos.RefValueZero, // Get("ppid").Int() in syscall_js.go for syscall.Getppid
}).
addFunction(custom.NameProcessCwd, &processCwd{proc: proc}). // syscall.Cwd in fs_js.go
addFunction(custom.NameProcessChdir, &processChdir{proc: proc}). // syscall.Chdir in fs_js.go
addFunction(custom.NameProcessGetuid, getId(uidRef)). // syscall.Getuid in syscall_js.go
addFunction(custom.NameProcessGetgid, getId(gidRef)). // syscall.Getgid in syscall_js.go
addFunction(custom.NameProcessGeteuid, getId(euidRef)). // syscall.Geteuid in syscall_js.go
addFunction(custom.NameProcessGetgroups, returnSlice(groupSlice)). // syscall.Getgroups in syscall_js.go
addFunction(custom.NameProcessUmask, &processUmask{proc: proc}) // syscall.Umask in syscall_js.go
}
// processCwd implements jsFn for fs.Open syscall.Getcwd in fs_js.go
type processCwd struct {
proc *processState
}
func (p *processCwd) invoke(_ context.Context, _ api.Module, _ ...interface{}) (interface{}, error) {
return p.proc.cwd, nil
}
// processChdir implements jsFn for fs.Open syscall.Chdir in fs_js.go
type processChdir struct {
proc *processState
}
func (p *processChdir) invoke(_ context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
oldWd := p.proc.cwd
newWd := util.ResolvePath(oldWd, args[0].(string))
newWd = path.Clean(newWd)
if newWd == oldWd { // handle .
return nil, nil
}
if s, err := syscallStat(mod, newWd); err != nil {
return nil, err
} else if !s.isDir {
return nil, syscall.ENOTDIR
} else {
p.proc.cwd = newWd
return nil, nil
}
}
// processUmask implements jsFn for fs.Open syscall.Umask in fs_js.go
type processUmask struct {
proc *processState
}
func (p *processUmask) invoke(_ context.Context, _ api.Module, args ...interface{}) (interface{}, error) {
newUmask := goos.ValueToUint32(args[0])
oldUmask := p.proc.umask
p.proc.umask = newUmask
return oldUmask, nil
}
// getId implements jsFn for syscall.Getuid, syscall.Getgid and syscall.Geteuid in syscall_js.go
type getId goos.Ref
func (i getId) invoke(_ context.Context, _ api.Module, _ ...interface{}) (interface{}, error) {
return goos.Ref(i), nil
}
// returnSlice implements jsFn for syscall.Getgroups in syscall_js.go
type returnSlice []interface{}
func (s returnSlice) invoke(context.Context, api.Module, ...interface{}) (interface{}, error) {
return &objectArray{slice: s}, nil
}