gojs: stubs all remaining filesystem calls to ENOSYS (#1001)
This stubs all remaining syscalls for `GOARCH=wasm GOOS=js` to return ENOSYS, instead of panic'ing. This allows us to see the parameters it receives. For example: ``` ==> go.syscall/js.valueCall(fs.truncate(path=/tmp/_Go_TestTruncate135754730,length=0)) <== (err=function not implemented,ok=false) ``` Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
@@ -252,7 +252,7 @@ func TestRun(t *testing.T) {
|
||||
wazeroOpts: []string{"--hostlogging=filesystem", fmt.Sprintf("--mount=%s:/", filepath.Dir(bearPath))},
|
||||
wasmArgs: []string{"/bear.txt"},
|
||||
stdOut: "pooh\n",
|
||||
stdErr: fmt.Sprintf(`==> go.syscall/js.valueCall(fs.open(name=/bear.txt,flags=,perm=----------))
|
||||
stdErr: fmt.Sprintf(`==> go.syscall/js.valueCall(fs.open(path=/bear.txt,flags=,perm=----------))
|
||||
<== (err=<nil>,fd=4)
|
||||
==> go.syscall/js.valueCall(fs.fstat(fd=4))
|
||||
<== (err=<nil>,stat={isDir=false,mode=%[1]s,size=5,mtimeMs=%[2]d})
|
||||
|
||||
@@ -25,7 +25,7 @@ func newJsGlobal(rt http.RoundTripper) *jsVal {
|
||||
"fs": jsfs,
|
||||
"Date": jsDateConstructor,
|
||||
}).
|
||||
addFunction("fetch", &fetch{})
|
||||
addFunction("fetch", httpFetch{})
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -48,13 +48,13 @@ var (
|
||||
"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("cwd", &cwd{}). // syscall.Cwd in fs_js.go
|
||||
addFunction("chdir", &chdir{}). // syscall.Chdir in fs_js.go
|
||||
addFunction("getuid", &returnZero{}). // syscall.Getuid in syscall_js.go
|
||||
addFunction("getgid", &returnZero{}). // syscall.Getgid in syscall_js.go
|
||||
addFunction("geteuid", &returnZero{}). // syscall.Geteuid in syscall_js.go
|
||||
addFunction("getgroups", &returnSliceOfZero{}). // syscall.Getgroups in syscall_js.go
|
||||
addFunction("umask", &returnArg0{}) // syscall.Umask in syscall_js.go
|
||||
addFunction("cwd", processCwd{}). // syscall.Cwd in fs_js.go
|
||||
addFunction("chdir", processChdir{}). // syscall.Chdir in fs_js.go
|
||||
addFunction("getuid", returnZero{}). // syscall.Getuid in syscall_js.go
|
||||
addFunction("getgid", returnZero{}). // syscall.Getgid in syscall_js.go
|
||||
addFunction("geteuid", returnZero{}). // syscall.Geteuid in syscall_js.go
|
||||
addFunction("getgroups", returnSliceOfZero{}). // syscall.Getgroups in syscall_js.go
|
||||
addFunction("umask", returnArg0{}) // syscall.Umask in syscall_js.go
|
||||
|
||||
// uint8ArrayConstructor = js.Global().Get("Uint8Array")
|
||||
// // fs_js.go, rand_js.go, roundtrip_js.go init
|
||||
|
||||
@@ -16,12 +16,12 @@ import (
|
||||
//
|
||||
// This is defined as `Get("crypto")` in rand_js.go init
|
||||
var jsCrypto = newJsVal(goos.RefJsCrypto, "crypto").
|
||||
addFunction("getRandomValues", &getRandomValues{})
|
||||
addFunction("getRandomValues", cryptoGetRandomValues{})
|
||||
|
||||
type getRandomValues struct{}
|
||||
// cryptoGetRandomValues implements jsFn
|
||||
type cryptoGetRandomValues struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*getRandomValues) invoke(_ context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
func (cryptoGetRandomValues) invoke(_ context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
randSource := mod.(*wasm.CallContext).Sys.RandSource()
|
||||
|
||||
r := args[0].(*byteArray)
|
||||
|
||||
@@ -3,20 +3,31 @@ package custom
|
||||
const (
|
||||
NameCallback = "callback"
|
||||
|
||||
NameFs = "fs"
|
||||
NameFsOpen = "open"
|
||||
NameFsStat = "stat"
|
||||
NameFsFstat = "fstat"
|
||||
NameFsLstat = "lstat"
|
||||
NameFsClose = "close"
|
||||
NameFsWrite = "write"
|
||||
NameFsRead = "read"
|
||||
NameFsReaddir = "readdir"
|
||||
NameFsMkdir = "mkdir"
|
||||
NameFsRmdir = "rmdir"
|
||||
NameFsRename = "rename"
|
||||
NameFsUnlink = "unlink"
|
||||
NameFsUtimes = "utimes"
|
||||
NameFs = "fs"
|
||||
NameFsOpen = "open"
|
||||
NameFsStat = "stat"
|
||||
NameFsFstat = "fstat"
|
||||
NameFsLstat = "lstat"
|
||||
NameFsClose = "close"
|
||||
NameFsWrite = "write"
|
||||
NameFsRead = "read"
|
||||
NameFsReaddir = "readdir"
|
||||
NameFsMkdir = "mkdir"
|
||||
NameFsRmdir = "rmdir"
|
||||
NameFsRename = "rename"
|
||||
NameFsUnlink = "unlink"
|
||||
NameFsUtimes = "utimes"
|
||||
NameFsChmod = "chmod"
|
||||
NameFsFchmod = "fchmod"
|
||||
NameFsChown = "chown"
|
||||
NameFsFchown = "fchown"
|
||||
NameFsLchown = "lchown"
|
||||
NameFsTruncate = "truncate"
|
||||
NameFsFtruncate = "ftruncate"
|
||||
NameFsReadlink = "readlink"
|
||||
NameFsLink = "link"
|
||||
NameFsSymlink = "symlink"
|
||||
NameFsFsync = "fsync"
|
||||
)
|
||||
|
||||
// FsNameSection are the functions defined in the object named NameFs. Results
|
||||
@@ -25,12 +36,12 @@ const (
|
||||
var FsNameSection = map[string]*Names{
|
||||
NameFsOpen: {
|
||||
Name: NameFsOpen,
|
||||
ParamNames: []string{"name", "flags", "perm", NameCallback},
|
||||
ParamNames: []string{"path", "flags", "perm", NameCallback},
|
||||
ResultNames: []string{"err", "fd"},
|
||||
},
|
||||
NameFsStat: {
|
||||
Name: NameFsStat,
|
||||
ParamNames: []string{"name", NameCallback},
|
||||
ParamNames: []string{"path", NameCallback},
|
||||
ResultNames: []string{"err", "stat"},
|
||||
},
|
||||
NameFsFstat: {
|
||||
@@ -40,7 +51,7 @@ var FsNameSection = map[string]*Names{
|
||||
},
|
||||
NameFsLstat: {
|
||||
Name: NameFsLstat,
|
||||
ParamNames: []string{"name", NameCallback},
|
||||
ParamNames: []string{"path", NameCallback},
|
||||
ResultNames: []string{"err", "stat"},
|
||||
},
|
||||
NameFsClose: {
|
||||
@@ -60,7 +71,7 @@ var FsNameSection = map[string]*Names{
|
||||
},
|
||||
NameFsReaddir: {
|
||||
Name: NameFsReaddir,
|
||||
ParamNames: []string{"name", NameCallback},
|
||||
ParamNames: []string{"path", NameCallback},
|
||||
ResultNames: []string{"err", "dirents"},
|
||||
},
|
||||
NameFsMkdir: {
|
||||
@@ -88,4 +99,59 @@ var FsNameSection = map[string]*Names{
|
||||
ParamNames: []string{"path", "atime", "mtime", NameCallback},
|
||||
ResultNames: []string{"err", "ok"},
|
||||
},
|
||||
NameFsChmod: {
|
||||
Name: NameFsChmod,
|
||||
ParamNames: []string{"path", "mode", NameCallback},
|
||||
ResultNames: []string{"err", "ok"},
|
||||
},
|
||||
NameFsFchmod: {
|
||||
Name: NameFsFchmod,
|
||||
ParamNames: []string{"fd", "mode", NameCallback},
|
||||
ResultNames: []string{"err", "ok"},
|
||||
},
|
||||
NameFsChown: {
|
||||
Name: NameFsChown,
|
||||
ParamNames: []string{"path", "uid", "gid", NameCallback},
|
||||
ResultNames: []string{"err", "ok"},
|
||||
},
|
||||
NameFsFchown: {
|
||||
Name: NameFsFchown,
|
||||
ParamNames: []string{"fd", "uid", "gid", NameCallback},
|
||||
ResultNames: []string{"err", "ok"},
|
||||
},
|
||||
NameFsLchown: {
|
||||
Name: NameFsLchown,
|
||||
ParamNames: []string{"path", "uid", "gid", NameCallback},
|
||||
ResultNames: []string{"err", "ok"},
|
||||
},
|
||||
NameFsTruncate: {
|
||||
Name: NameFsTruncate,
|
||||
ParamNames: []string{"path", "length", NameCallback},
|
||||
ResultNames: []string{"err", "ok"},
|
||||
},
|
||||
NameFsFtruncate: {
|
||||
Name: NameFsFtruncate,
|
||||
ParamNames: []string{"fd", "length", NameCallback},
|
||||
ResultNames: []string{"err", "ok"},
|
||||
},
|
||||
NameFsReadlink: {
|
||||
Name: NameFsReadlink,
|
||||
ParamNames: []string{"path", NameCallback},
|
||||
ResultNames: []string{"err", "dst"},
|
||||
},
|
||||
NameFsLink: {
|
||||
Name: NameFsLink,
|
||||
ParamNames: []string{"path", "link", NameCallback},
|
||||
ResultNames: []string{"err", "ok"},
|
||||
},
|
||||
NameFsSymlink: {
|
||||
Name: NameFsSymlink,
|
||||
ParamNames: []string{"path", "link", NameCallback},
|
||||
ResultNames: []string{"err", "ok"},
|
||||
},
|
||||
NameFsFsync: {
|
||||
Name: NameFsFsync,
|
||||
ParamNames: []string{"fd", NameCallback},
|
||||
ResultNames: []string{"err", "ok"},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -26,32 +26,30 @@ var (
|
||||
addProperties(map[string]interface{}{
|
||||
"constants": jsfsConstants, // = jsfs.Get("constants") // init
|
||||
}).
|
||||
addFunction(custom.NameFsOpen, &jsfsOpen{}).
|
||||
addFunction(custom.NameFsStat, &jsfsStat{}).
|
||||
addFunction(custom.NameFsFstat, &jsfsFstat{}).
|
||||
addFunction(custom.NameFsLstat, &jsfsStat{}). // because fs.FS doesn't support symlink
|
||||
addFunction(custom.NameFsClose, &jsfsClose{}).
|
||||
addFunction(custom.NameFsRead, &jsfsRead{}).
|
||||
addFunction(custom.NameFsWrite, &jsfsWrite{}).
|
||||
addFunction(custom.NameFsReaddir, &jsfsReaddir{}).
|
||||
addFunction(custom.NameFsMkdir, &jsfsMkdir{}).
|
||||
addFunction(custom.NameFsRmdir, &jsfsRmdir{}).
|
||||
addFunction(custom.NameFsRename, &jsfsRename{}).
|
||||
addFunction(custom.NameFsUnlink, &jsfsUnlink{}).
|
||||
addFunction(custom.NameFsUtimes, &jsfsUtimes{})
|
||||
|
||||
// TODO: stub all these with syscall.ENOSYS
|
||||
// * _, err := fsCall("chmod", path, mode) // syscall.Chmod
|
||||
// * _, err := fsCall("fchmod", fd, mode) // syscall.Fchmod
|
||||
// * _, err := fsCall("chown", path, uint32(uid), uint32(gid)) // syscall.Chown
|
||||
// * _, err := fsCall("fchown", fd, uint32(uid), uint32(gid)) // syscall.Fchown
|
||||
// * _, err := fsCall("lchown", path, uint32(uid), uint32(gid)) // syscall.Lchown
|
||||
// * _, err := fsCall("truncate", path, length) // syscall.Truncate
|
||||
// * _, err := fsCall("ftruncate", fd, length) // syscall.Ftruncate
|
||||
// * dst, err := fsCall("readlink", path) // syscall.Readlink
|
||||
// * _, err := fsCall("link", path, link) // syscall.Link
|
||||
// * _, err := fsCall("symlink", path, link) // syscall.Symlink
|
||||
// * _, err := fsCall("fsync", fd) // syscall.Fsync
|
||||
addFunction(custom.NameFsOpen, jsfsOpen{}).
|
||||
addFunction(custom.NameFsStat, jsfsStat{}).
|
||||
addFunction(custom.NameFsFstat, jsfsFstat{}).
|
||||
addFunction(custom.NameFsLstat, jsfsLstat{}).
|
||||
addFunction(custom.NameFsClose, jsfsClose{}).
|
||||
addFunction(custom.NameFsRead, jsfsRead{}).
|
||||
addFunction(custom.NameFsWrite, jsfsWrite{}).
|
||||
addFunction(custom.NameFsReaddir, jsfsReaddir{}).
|
||||
addFunction(custom.NameFsMkdir, jsfsMkdir{}).
|
||||
addFunction(custom.NameFsRmdir, jsfsRmdir{}).
|
||||
addFunction(custom.NameFsRename, jsfsRename{}).
|
||||
addFunction(custom.NameFsUnlink, jsfsUnlink{}).
|
||||
addFunction(custom.NameFsUtimes, jsfsUtimes{}).
|
||||
addFunction(custom.NameFsChmod, jsfsChmod{}).
|
||||
addFunction(custom.NameFsFchmod, jsfsFchmod{}).
|
||||
addFunction(custom.NameFsChown, jsfsChown{}).
|
||||
addFunction(custom.NameFsFchown, jsfsFchown{}).
|
||||
addFunction(custom.NameFsLchown, jsfsLchown{}).
|
||||
addFunction(custom.NameFsTruncate, jsfsTruncate{}).
|
||||
addFunction(custom.NameFsFtruncate, jsfsFtruncate{}).
|
||||
addFunction(custom.NameFsReadlink, jsfsReadlink{}).
|
||||
addFunction(custom.NameFsLink, jsfsLink{}).
|
||||
addFunction(custom.NameFsSymlink, jsfsSymlink{}).
|
||||
addFunction(custom.NameFsFsync, jsfsFsync{})
|
||||
|
||||
// jsfsConstants = jsfs Get("constants") // fs_js.go init
|
||||
jsfsConstants = newJsVal(goos.RefJsfsConstants, "constants").
|
||||
@@ -83,33 +81,33 @@ var (
|
||||
oEXCL = float64(os.O_EXCL)
|
||||
)
|
||||
|
||||
// jsfsOpen implements fs.Open
|
||||
// jsfsOpen implements implements jsFn for syscall.Open
|
||||
//
|
||||
// jsFD /* Int */, err := fsCall("open", path, flags, perm)
|
||||
type jsfsOpen struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*jsfsOpen) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
name := args[0].(string)
|
||||
func (jsfsOpen) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
path := args[0].(string)
|
||||
flags := toUint64(args[1]) // flags are derived from constants like oWRONLY
|
||||
perm := toUint32(args[2])
|
||||
callback := args[3].(funcWrapper)
|
||||
|
||||
fd, err := syscallOpen(mod, name, flags, perm)
|
||||
fsc := mod.(*wasm.CallContext).Sys.FS()
|
||||
fd, err := fsc.OpenFile(path, int(flags), fs.FileMode(perm))
|
||||
|
||||
return callback.invoke(ctx, mod, goos.RefJsfs, err, fd) // note: error first
|
||||
}
|
||||
|
||||
// jsfsStat is used for syscall.Stat
|
||||
// jsfsStat implements jsFn for syscall.Stat
|
||||
//
|
||||
// jsSt, err := fsCall("stat", path)
|
||||
type jsfsStat struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*jsfsStat) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
name := args[0].(string)
|
||||
func (jsfsStat) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
path := args[0].(string)
|
||||
callback := args[1].(funcWrapper)
|
||||
|
||||
stat, err := syscallStat(mod, name)
|
||||
stat, err := syscallStat(mod, path)
|
||||
return callback.invoke(ctx, mod, goos.RefJsfs, err, stat) // note: error first
|
||||
}
|
||||
|
||||
@@ -124,13 +122,26 @@ func syscallStat(mod api.Module, name string) (*jsSt, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// jsfsStat is used for syscall.Open
|
||||
// jsfsLstat implements jsFn for syscall.Lstat
|
||||
//
|
||||
// jsSt, err := fsCall("lstat", path)
|
||||
type jsfsLstat struct{}
|
||||
|
||||
func (jsfsLstat) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
path := args[0].(string)
|
||||
callback := args[1].(funcWrapper)
|
||||
|
||||
lstat, err := syscallStat(mod, path) // TODO switch to lstat syscall
|
||||
|
||||
return callback.invoke(ctx, mod, goos.RefJsfs, err, lstat) // note: error first
|
||||
}
|
||||
|
||||
// jsfsFstat implements jsFn for syscall.Open
|
||||
//
|
||||
// stat, err := fsCall("fstat", fd); err == nil && stat.Call("isDirectory").Bool()
|
||||
type jsfsFstat struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*jsfsFstat) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
func (jsfsFstat) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
fsc := mod.(*wasm.CallContext).Sys.FS()
|
||||
|
||||
fd := toUint32(args[0])
|
||||
@@ -210,38 +221,30 @@ func getJsMode(mode fs.FileMode) (jsMode uint32) {
|
||||
return
|
||||
}
|
||||
|
||||
// jsfsClose is used for syscall.Close
|
||||
//
|
||||
// _, err := fsCall("close", fd)
|
||||
// jsfsClose implements jsFn for syscall.Close
|
||||
type jsfsClose struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*jsfsClose) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
func (jsfsClose) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
fsc := mod.(*wasm.CallContext).Sys.FS()
|
||||
|
||||
fd := toUint32(args[0])
|
||||
callback := args[1].(funcWrapper)
|
||||
|
||||
err := syscallClose(fsc, fd)
|
||||
return callback.invoke(ctx, mod, goos.RefJsfs, err, true) // note: error first
|
||||
}
|
||||
|
||||
// syscallClose is like syscall.Close
|
||||
func syscallClose(fsc *internalsys.FSContext, fd uint32) (err error) {
|
||||
var err error
|
||||
if ok := fsc.CloseFile(fd); !ok {
|
||||
err = syscall.EBADF // already closed
|
||||
}
|
||||
return
|
||||
|
||||
return jsfsInvoke(ctx, mod, callback, err)
|
||||
}
|
||||
|
||||
// jsfsRead is used in syscall.Read and syscall.Pread, called by
|
||||
// jsfsRead implements jsFn for syscall.Read and syscall.Pread, called by
|
||||
// src/internal/poll/fd_unix.go poll.Read.
|
||||
//
|
||||
// n, err := fsCall("read", fd, buf, 0, len(b), nil)
|
||||
type jsfsRead struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*jsfsRead) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
func (jsfsRead) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
fd := toUint32(args[0])
|
||||
buf, ok := args[1].(*byteArray)
|
||||
if !ok {
|
||||
@@ -285,15 +288,14 @@ func syscallRead(mod api.Module, fd uint32, offset interface{}, p []byte) (n uin
|
||||
return
|
||||
}
|
||||
|
||||
// jsfsWrite is used in syscall.Write and syscall.Pwrite.
|
||||
// jsfsWrite implements jsFn for syscall.Write and syscall.Pwrite.
|
||||
//
|
||||
// Notably, offset is non-nil in Pwrite.
|
||||
//
|
||||
// n, err := fsCall("write", fd, buf, 0, len(b), nil)
|
||||
type jsfsWrite struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*jsfsWrite) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
func (jsfsWrite) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
fd := toUint32(args[0])
|
||||
buf, ok := args[1].(*byteArray)
|
||||
if !ok {
|
||||
@@ -327,18 +329,17 @@ func syscallWrite(mod api.Module, fd uint32, offset interface{}, p []byte) (n ui
|
||||
return
|
||||
}
|
||||
|
||||
// jsfsReaddir is used in syscall.Open
|
||||
// jsfsReaddir implements jsFn for syscall.Open
|
||||
//
|
||||
// dir, err := fsCall("readdir", path)
|
||||
// dir.Length(), dir.Index(i).String()
|
||||
type jsfsReaddir struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*jsfsReaddir) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
name := args[0].(string)
|
||||
func (jsfsReaddir) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
path := args[0].(string)
|
||||
callback := args[1].(funcWrapper)
|
||||
|
||||
stat, err := syscallReaddir(ctx, mod, name)
|
||||
stat, err := syscallReaddir(ctx, mod, path)
|
||||
return callback.invoke(ctx, mod, goos.RefJsfs, err, stat) // note: error first
|
||||
}
|
||||
|
||||
@@ -366,40 +367,38 @@ func syscallReaddir(_ context.Context, mod api.Module, name string) (*objectArra
|
||||
}
|
||||
}
|
||||
|
||||
// returnZero implements jsFn
|
||||
type returnZero struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*returnZero) invoke(context.Context, api.Module, ...interface{}) (interface{}, error) {
|
||||
func (returnZero) invoke(context.Context, api.Module, ...interface{}) (interface{}, error) {
|
||||
return goos.RefValueZero, nil
|
||||
}
|
||||
|
||||
// returnSliceOfZero implements jsFn
|
||||
type returnSliceOfZero struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*returnSliceOfZero) invoke(context.Context, api.Module, ...interface{}) (interface{}, error) {
|
||||
func (returnSliceOfZero) invoke(context.Context, api.Module, ...interface{}) (interface{}, error) {
|
||||
return &objectArray{slice: []interface{}{goos.RefValueZero}}, nil
|
||||
}
|
||||
|
||||
// returnArg0 implements jsFn
|
||||
type returnArg0 struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*returnArg0) invoke(_ context.Context, _ api.Module, args ...interface{}) (interface{}, error) {
|
||||
func (returnArg0) invoke(_ context.Context, _ api.Module, args ...interface{}) (interface{}, error) {
|
||||
return args[0], nil
|
||||
}
|
||||
|
||||
// cwd for fs.Open syscall.Getcwd in fs_js.go
|
||||
type cwd struct{}
|
||||
// processCwd implements jsFn for fs.Open syscall.Getcwd in fs_js.go
|
||||
type processCwd struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*cwd) invoke(ctx context.Context, _ api.Module, _ ...interface{}) (interface{}, error) {
|
||||
func (processCwd) invoke(ctx context.Context, _ api.Module, _ ...interface{}) (interface{}, error) {
|
||||
return getState(ctx).cwd, nil
|
||||
}
|
||||
|
||||
// chdir for fs.Open syscall.Chdir in fs_js.go
|
||||
type chdir struct{}
|
||||
// processChdir implements jsFn for fs.Open syscall.Chdir in fs_js.go
|
||||
type processChdir struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*chdir) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
func (processChdir) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
fsc := mod.(*wasm.CallContext).Sys.FS()
|
||||
|
||||
path := args[0].(string)
|
||||
@@ -421,112 +420,261 @@ func (*chdir) invoke(ctx context.Context, mod api.Module, args ...interface{}) (
|
||||
}
|
||||
}
|
||||
|
||||
// jsfsMkdir implements fs.Mkdir
|
||||
// jsfsMkdir implements implements jsFn for fs.Mkdir
|
||||
//
|
||||
// jsFD /* Int */, err := fsCall("mkdir", path, perm)
|
||||
type jsfsMkdir struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*jsfsMkdir) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
name := args[0].(string)
|
||||
func (jsfsMkdir) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
path := args[0].(string)
|
||||
perm := toUint32(args[1])
|
||||
callback := args[2].(funcWrapper)
|
||||
|
||||
fd, err := syscallMkdir(mod, name, perm)
|
||||
fsc := mod.(*wasm.CallContext).Sys.FS()
|
||||
fd, err := fsc.Mkdir(path, fs.FileMode(perm))
|
||||
|
||||
return callback.invoke(ctx, mod, goos.RefJsfs, err, fd) // note: error first
|
||||
}
|
||||
|
||||
// syscallMkdir is like syscall.Mkdir
|
||||
func syscallMkdir(mod api.Module, name string, perm uint32) (uint32, error) {
|
||||
fsc := mod.(*wasm.CallContext).Sys.FS()
|
||||
return fsc.Mkdir(name, fs.FileMode(perm))
|
||||
}
|
||||
|
||||
// jsfsRmdir implements the following
|
||||
// jsfsRmdir implements jsFn for the following
|
||||
//
|
||||
// _, err := fsCall("rmdir", path) // syscall.Rmdir
|
||||
type jsfsRmdir struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*jsfsRmdir) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
name := args[0].(string)
|
||||
func (jsfsRmdir) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
path := args[0].(string)
|
||||
callback := args[1].(funcWrapper)
|
||||
|
||||
ok, err := syscallRmdir(mod, name)
|
||||
return callback.invoke(ctx, mod, goos.RefJsfs, err, ok) // note: error first
|
||||
}
|
||||
|
||||
// syscallRmdir is like syscall.Rmdir
|
||||
func syscallRmdir(mod api.Module, name string) (interface{}, error) {
|
||||
fsc := mod.(*wasm.CallContext).Sys.FS()
|
||||
err := fsc.Rmdir(name)
|
||||
return err != nil, err
|
||||
err := fsc.Rmdir(path)
|
||||
|
||||
return jsfsInvoke(ctx, mod, callback, err)
|
||||
}
|
||||
|
||||
// jsfsRename implements the following
|
||||
// jsfsRename implements jsFn for the following
|
||||
//
|
||||
// - _, err := fsCall("rename", from, to) // syscall.Rename
|
||||
// _, err := fsCall("rename", from, to) // syscall.Rename
|
||||
type jsfsRename struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*jsfsRename) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
func (jsfsRename) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
from := args[0].(string)
|
||||
to := args[1].(string)
|
||||
callback := args[2].(funcWrapper)
|
||||
|
||||
ok, err := syscallRename(mod, from, to)
|
||||
return callback.invoke(ctx, mod, goos.RefJsfs, err, ok) // note: error first
|
||||
}
|
||||
|
||||
// syscallRename is like syscall.Rename
|
||||
func syscallRename(mod api.Module, from, to string) (interface{}, error) {
|
||||
fsc := mod.(*wasm.CallContext).Sys.FS()
|
||||
err := fsc.Rename(from, to)
|
||||
return err != nil, err
|
||||
|
||||
return jsfsInvoke(ctx, mod, callback, err)
|
||||
}
|
||||
|
||||
// jsfsUnlink implements the following
|
||||
// jsfsUnlink implements jsFn for the following
|
||||
//
|
||||
// _, err := fsCall("unlink", path) // syscall.Unlink
|
||||
type jsfsUnlink struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*jsfsUnlink) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
name := args[0].(string)
|
||||
func (jsfsUnlink) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
path := args[0].(string)
|
||||
callback := args[1].(funcWrapper)
|
||||
|
||||
ok, err := syscallUnlink(mod, name)
|
||||
return callback.invoke(ctx, mod, goos.RefJsfs, err, ok) // note: error first
|
||||
}
|
||||
|
||||
// syscallUnlink is like syscall.Unlink
|
||||
func syscallUnlink(mod api.Module, name string) (interface{}, error) {
|
||||
fsc := mod.(*wasm.CallContext).Sys.FS()
|
||||
err := fsc.Unlink(name)
|
||||
return err != nil, err
|
||||
err := fsc.Unlink(path)
|
||||
|
||||
return jsfsInvoke(ctx, mod, callback, err)
|
||||
}
|
||||
|
||||
// jsfsUtimes implements the following
|
||||
// jsfsUtimes implements jsFn for the following
|
||||
//
|
||||
// _, err := fsCall("utimes", path, atime, mtime) // syscall.UtimesNano
|
||||
type jsfsUtimes struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*jsfsUtimes) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
name := args[0].(string)
|
||||
func (jsfsUtimes) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
path := args[0].(string)
|
||||
atimeSec := toInt64(args[1])
|
||||
mtimeSec := toInt64(args[2])
|
||||
callback := args[3].(funcWrapper)
|
||||
|
||||
ok, err := syscallUtimes(mod, name, atimeSec, mtimeSec)
|
||||
return callback.invoke(ctx, mod, goos.RefJsfs, err, ok) // note: error first
|
||||
fsc := mod.(*wasm.CallContext).Sys.FS()
|
||||
err := fsc.Utimes(path, atimeSec*1e9, mtimeSec*1e9)
|
||||
|
||||
return jsfsInvoke(ctx, mod, callback, err)
|
||||
}
|
||||
|
||||
// syscallUtimes is like syscall.Utimes
|
||||
func syscallUtimes(mod api.Module, name string, atimeSec, mtimeSec int64) (interface{}, error) {
|
||||
fsc := mod.(*wasm.CallContext).Sys.FS()
|
||||
err := fsc.Utimes(name, atimeSec*1e9, mtimeSec*1e9)
|
||||
return err != nil, err
|
||||
// jsfsChmod implements jsFn for the following
|
||||
//
|
||||
// _, err := fsCall("chmod", path, mode) // syscall.Chmod
|
||||
type jsfsChmod struct{}
|
||||
|
||||
func (jsfsChmod) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
path := args[0].(string)
|
||||
mode := toUint32(args[1])
|
||||
callback := args[2].(funcWrapper)
|
||||
|
||||
_, _ = path, mode // TODO
|
||||
var err error = syscall.ENOSYS
|
||||
|
||||
return jsfsInvoke(ctx, mod, callback, err)
|
||||
}
|
||||
|
||||
// jsfsFchmod implements jsFn for the following
|
||||
//
|
||||
// _, err := fsCall("fchmod", fd, mode) // syscall.Fchmod
|
||||
type jsfsFchmod struct{}
|
||||
|
||||
func (jsfsFchmod) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
fd := toUint32(args[0])
|
||||
mode := toUint32(args[1])
|
||||
callback := args[2].(funcWrapper)
|
||||
|
||||
_, _ = fd, mode // TODO
|
||||
var err error = syscall.ENOSYS
|
||||
|
||||
return jsfsInvoke(ctx, mod, callback, err)
|
||||
}
|
||||
|
||||
// jsfsChown implements jsFn for the following
|
||||
//
|
||||
// _, err := fsCall("chown", path, uint32(uid), uint32(gid)) // syscall.Chown
|
||||
type jsfsChown struct{}
|
||||
|
||||
func (jsfsChown) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
path := args[0].(string)
|
||||
uid := toUint32(args[1])
|
||||
gid := toUint32(args[2])
|
||||
callback := args[3].(funcWrapper)
|
||||
|
||||
_, _, _ = path, uid, gid // TODO
|
||||
var err error = syscall.ENOSYS
|
||||
|
||||
return jsfsInvoke(ctx, mod, callback, err)
|
||||
}
|
||||
|
||||
// jsfsFchown implements jsFn for the following
|
||||
//
|
||||
// _, err := fsCall("fchown", fd, uint32(uid), uint32(gid)) // syscall.Fchown
|
||||
type jsfsFchown struct{}
|
||||
|
||||
func (jsfsFchown) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
fd := toUint32(args[0])
|
||||
uid := toUint32(args[1])
|
||||
gid := toUint32(args[2])
|
||||
callback := args[3].(funcWrapper)
|
||||
|
||||
_, _, _ = fd, uid, gid // TODO
|
||||
var err error = syscall.ENOSYS
|
||||
|
||||
return jsfsInvoke(ctx, mod, callback, err)
|
||||
}
|
||||
|
||||
// jsfsLchown implements jsFn for the following
|
||||
//
|
||||
// _, err := fsCall("lchown", path, uint32(uid), uint32(gid)) // syscall.Lchown
|
||||
type jsfsLchown struct{}
|
||||
|
||||
func (jsfsLchown) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
path := args[0].(string)
|
||||
uid := toUint32(args[1])
|
||||
gid := toUint32(args[2])
|
||||
callback := args[3].(funcWrapper)
|
||||
|
||||
_, _, _ = path, uid, gid // TODO
|
||||
var err error = syscall.ENOSYS
|
||||
|
||||
return jsfsInvoke(ctx, mod, callback, err)
|
||||
}
|
||||
|
||||
// jsfsTruncate implements jsFn for the following
|
||||
//
|
||||
// _, err := fsCall("truncate", path, length) // syscall.Truncate
|
||||
type jsfsTruncate struct{}
|
||||
|
||||
func (jsfsTruncate) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
path := args[0].(string)
|
||||
length := toInt64(args[1])
|
||||
callback := args[2].(funcWrapper)
|
||||
|
||||
_, _ = path, length // TODO
|
||||
var err error = syscall.ENOSYS
|
||||
|
||||
return jsfsInvoke(ctx, mod, callback, err)
|
||||
}
|
||||
|
||||
// jsfsFtruncate implements jsFn for the following
|
||||
//
|
||||
// _, err := fsCall("ftruncate", fd, length) // syscall.Ftruncate
|
||||
type jsfsFtruncate struct{}
|
||||
|
||||
func (jsfsFtruncate) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
fd := toUint32(args[0])
|
||||
length := toInt64(args[1])
|
||||
callback := args[2].(funcWrapper)
|
||||
|
||||
_, _ = fd, length // TODO
|
||||
var err error = syscall.ENOSYS
|
||||
|
||||
return jsfsInvoke(ctx, mod, callback, err)
|
||||
}
|
||||
|
||||
// jsfsReadlink implements jsFn for syscall.Readlink
|
||||
//
|
||||
// dst, err := fsCall("readlink", path) // syscall.Readlink
|
||||
type jsfsReadlink struct{}
|
||||
|
||||
func (jsfsReadlink) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
path := args[0].(string)
|
||||
callback := args[1].(funcWrapper)
|
||||
|
||||
_ = path // TODO
|
||||
var dst string
|
||||
var err error = syscall.ENOSYS
|
||||
|
||||
return callback.invoke(ctx, mod, goos.RefJsfs, err, dst) // note: error first
|
||||
}
|
||||
|
||||
// jsfsLink implements jsFn for the following
|
||||
//
|
||||
// _, err := fsCall("link", path, link) // syscall.Link
|
||||
type jsfsLink struct{}
|
||||
|
||||
func (jsfsLink) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
path := args[0].(string)
|
||||
link := args[1].(string)
|
||||
callback := args[2].(funcWrapper)
|
||||
|
||||
_, _ = path, link // TODO
|
||||
var err error = syscall.ENOSYS
|
||||
|
||||
return jsfsInvoke(ctx, mod, callback, err)
|
||||
}
|
||||
|
||||
// jsfsSymlink implements jsFn for the following
|
||||
//
|
||||
// _, err := fsCall("symlink", path, link) // syscall.Symlink
|
||||
type jsfsSymlink struct{}
|
||||
|
||||
func (jsfsSymlink) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
path := args[0].(string)
|
||||
link := args[1].(string)
|
||||
callback := args[2].(funcWrapper)
|
||||
|
||||
_, _ = path, link // TODO
|
||||
var err error = syscall.ENOSYS
|
||||
|
||||
return jsfsInvoke(ctx, mod, callback, err)
|
||||
}
|
||||
|
||||
// jsfsFsync implements jsFn for the following
|
||||
//
|
||||
// _, err := fsCall("fsync", fd) // syscall.Fsync
|
||||
type jsfsFsync struct{}
|
||||
|
||||
func (jsfsFsync) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
fd := toUint32(args[0])
|
||||
callback := args[1].(funcWrapper)
|
||||
|
||||
_ = fd // TODO
|
||||
var err error = syscall.ENOSYS
|
||||
|
||||
return jsfsInvoke(ctx, mod, callback, err)
|
||||
}
|
||||
|
||||
// jsSt is pre-parsed from fs_js.go setStat to avoid thrashing
|
||||
@@ -592,3 +740,7 @@ func (s *jsSt) call(_ context.Context, _ api.Module, _ goos.Ref, method string,
|
||||
}
|
||||
panic(fmt.Sprintf("TODO: stat.%s", method))
|
||||
}
|
||||
|
||||
func jsfsInvoke(ctx context.Context, mod api.Module, callback funcWrapper, err error) (interface{}, error) {
|
||||
return callback.invoke(ctx, mod, goos.RefJsfs, err, err == nil) // note: error first
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ func getRoundTripper(ctx context.Context) http.RoundTripper {
|
||||
return nil
|
||||
}
|
||||
|
||||
// fetch is used to implement http.RoundTripper
|
||||
// httpFetch implements jsFn for http.RoundTripper
|
||||
//
|
||||
// Reference in roundtrip_js.go init
|
||||
//
|
||||
@@ -33,10 +33,9 @@ func getRoundTripper(ctx context.Context) http.RoundTripper {
|
||||
// In http.Transport RoundTrip, this returns a promise
|
||||
//
|
||||
// fetchPromise := js.Global().Call("fetch", req.URL.String(), opt)
|
||||
type fetch struct{}
|
||||
type httpFetch struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*fetch) invoke(ctx context.Context, _ api.Module, args ...interface{}) (interface{}, error) {
|
||||
func (httpFetch) invoke(ctx context.Context, _ api.Module, args ...interface{}) (interface{}, error) {
|
||||
rt := getRoundTripper(ctx)
|
||||
if rt == nil {
|
||||
panic("unexpected to reach here without roundtripper as property is nil checked")
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
)
|
||||
|
||||
// jsFn is a jsCall.call function, configured via jsVal.addFunction.
|
||||
//
|
||||
// Note: This is not a `func` because we need it to be a hashable type.
|
||||
type jsFn interface {
|
||||
invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error)
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ func syscallValueCallParamLogger(ctx context.Context, mod api.Module, w logging.
|
||||
|
||||
if m == custom.NameFsOpen {
|
||||
w.WriteString("fs.open(") //nolint
|
||||
w.WriteString("name=") //nolint
|
||||
w.WriteString("path=") //nolint
|
||||
w.WriteString(args[0].(string)) //nolint
|
||||
w.WriteString(",flags=") //nolint
|
||||
writeOFlags(w, int(args[1].(float64)))
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/tetratelabs/wazero/internal/gojs/custom"
|
||||
"github.com/tetratelabs/wazero/internal/gojs/goarch"
|
||||
"github.com/tetratelabs/wazero/internal/gojs/goos"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
"github.com/tetratelabs/wazero/sys"
|
||||
)
|
||||
|
||||
@@ -405,18 +404,12 @@ func mapJSError(err error) *syscallErr {
|
||||
}
|
||||
}
|
||||
|
||||
// syscallOpen is like syscall.Open
|
||||
func syscallOpen(mod api.Module, name string, flags uint64, perm uint32) (uint32, error) {
|
||||
fsc := mod.(*wasm.CallContext).Sys.FS()
|
||||
return fsc.OpenFile(name, int(flags), fs.FileMode(perm))
|
||||
}
|
||||
|
||||
// funcWrapper is the result of go's js.FuncOf ("_makeFuncWrapper" here).
|
||||
//
|
||||
// This ID is managed on the Go side an increments (possibly rolling over).
|
||||
type funcWrapper uint32
|
||||
|
||||
// jsFn implements jsFn.invoke
|
||||
// invoke implements jsFn
|
||||
func (f funcWrapper) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
|
||||
e := &event{id: uint32(f), this: args[0].(goos.Ref)}
|
||||
|
||||
|
||||
@@ -16,12 +16,12 @@ var (
|
||||
// jsDate is used inline in zoneinfo_js.go for time.initLocal.
|
||||
// `.Call("getTimezoneOffset").Int()` returns a timezone offset.
|
||||
jsDate = newJsVal(goos.RefJsDate, "jsDate").
|
||||
addFunction("getTimezoneOffset", &getTimezoneOffset{})
|
||||
addFunction("getTimezoneOffset", jsDateGetTimezoneOffset{})
|
||||
)
|
||||
|
||||
type getTimezoneOffset struct{}
|
||||
// jsDateGetTimezoneOffset implements jsFn
|
||||
type jsDateGetTimezoneOffset struct{}
|
||||
|
||||
// invoke implements jsFn.invoke
|
||||
func (*getTimezoneOffset) invoke(context.Context, api.Module, ...interface{}) (interface{}, error) {
|
||||
func (jsDateGetTimezoneOffset) invoke(context.Context, api.Module, ...interface{}) (interface{}, error) {
|
||||
return uint32(0), nil // UTC
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
pathutil "path"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -298,11 +298,11 @@ func (c *FSContext) Mkdir(name string, perm fs.FileMode) (newFD uint32, err erro
|
||||
}
|
||||
|
||||
// OpenFile is like syscall.Open and returns the file descriptor of the new file or an error.
|
||||
func (c *FSContext) OpenFile(name string, flags int, perm fs.FileMode) (newFD uint32, err error) {
|
||||
func (c *FSContext) OpenFile(path string, flags int, perm fs.FileMode) (newFD uint32, err error) {
|
||||
var f fs.File
|
||||
if wfs, ok := c.fs.(syscallfs.FS); ok {
|
||||
name = c.cleanPath(name)
|
||||
f, err = wfs.OpenFile(name, flags, perm)
|
||||
path = c.cleanPath(path)
|
||||
f, err = wfs.OpenFile(path, flags, perm)
|
||||
} else {
|
||||
// While os.Open says it is read-only, in reality the files returned
|
||||
// are often writable. Fail only on the flags which won't work.
|
||||
@@ -315,7 +315,7 @@ func (c *FSContext) OpenFile(name string, flags int, perm fs.FileMode) (newFD ui
|
||||
return 0, syscall.ENOSYS
|
||||
default:
|
||||
// only time fs.FS is used
|
||||
f, err = c.fs.Open(c.cleanPath(name))
|
||||
f, err = c.fs.Open(c.cleanPath(path))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,22 +323,22 @@ func (c *FSContext) OpenFile(name string, flags int, perm fs.FileMode) (newFD ui
|
||||
return 0, err
|
||||
}
|
||||
|
||||
newFD = c.openedFiles.Insert(&FileEntry{Name: path.Base(name), File: f})
|
||||
newFD = c.openedFiles.Insert(&FileEntry{Name: pathutil.Base(path), File: f})
|
||||
return newFD, nil
|
||||
}
|
||||
|
||||
// Rmdir is like syscall.Rmdir.
|
||||
func (c *FSContext) Rmdir(name string) (err error) {
|
||||
func (c *FSContext) Rmdir(path string) (err error) {
|
||||
if wfs, ok := c.fs.(syscallfs.FS); ok {
|
||||
name = c.cleanPath(name)
|
||||
return wfs.Rmdir(name)
|
||||
path = c.cleanPath(path)
|
||||
return wfs.Rmdir(path)
|
||||
}
|
||||
err = syscall.ENOSYS
|
||||
return
|
||||
}
|
||||
|
||||
func (c *FSContext) StatPath(name string) (fs.FileInfo, error) {
|
||||
fd, err := c.OpenFile(name, os.O_RDONLY, 0)
|
||||
func (c *FSContext) StatPath(path string) (fs.FileInfo, error) {
|
||||
fd, err := c.OpenFile(path, os.O_RDONLY, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -358,35 +358,35 @@ func (c *FSContext) Rename(from, to string) (err error) {
|
||||
}
|
||||
|
||||
// Unlink is like syscall.Unlink.
|
||||
func (c *FSContext) Unlink(name string) (err error) {
|
||||
func (c *FSContext) Unlink(path string) (err error) {
|
||||
if wfs, ok := c.fs.(syscallfs.FS); ok {
|
||||
name = c.cleanPath(name)
|
||||
return wfs.Unlink(name)
|
||||
path = c.cleanPath(path)
|
||||
return wfs.Unlink(path)
|
||||
}
|
||||
err = syscall.ENOSYS
|
||||
return
|
||||
}
|
||||
|
||||
// Utimes is like syscall.Utimes.
|
||||
func (c *FSContext) Utimes(name string, atimeNsec, mtimeNsec int64) (err error) {
|
||||
func (c *FSContext) Utimes(path string, atimeNsec, mtimeNsec int64) (err error) {
|
||||
if wfs, ok := c.fs.(syscallfs.FS); ok {
|
||||
name = c.cleanPath(name)
|
||||
return wfs.Utimes(name, atimeNsec, mtimeNsec)
|
||||
path = c.cleanPath(path)
|
||||
return wfs.Utimes(path, atimeNsec, mtimeNsec)
|
||||
}
|
||||
err = syscall.ENOSYS
|
||||
return
|
||||
}
|
||||
|
||||
func (c *FSContext) cleanPath(name string) string {
|
||||
if len(name) == 0 {
|
||||
return name
|
||||
func (c *FSContext) cleanPath(path string) string {
|
||||
if len(path) == 0 {
|
||||
return path
|
||||
}
|
||||
// fs.ValidFile cannot be rooted (start with '/')
|
||||
cleaned := name
|
||||
if name[0] == '/' {
|
||||
cleaned = name[1:]
|
||||
cleaned := path
|
||||
if path[0] == '/' {
|
||||
cleaned = path[1:]
|
||||
}
|
||||
cleaned = path.Clean(cleaned) // e.g. "sub/." -> "sub"
|
||||
cleaned = pathutil.Clean(cleaned) // e.g. "sub/." -> "sub"
|
||||
return cleaned
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user