Files
wazero/internal/syscallfs/adapter.go
Crypt Keeper 319d6cca62 fs: adds base UnimplementedFS type and unwraps PathError (#1046)
This reduces some boilerplate by extracting UnimplementedFS from the
existing FS implementations, such that it returns ENOSYS. This also
removes inconsistency where some methods on FS returned syscall.Errno
and others PathError.

Note: this doesn't get rid of all PathError, yet. We still need to
create a syscallfs.File type which would be able to do that. This is
just one preliminary cleanup before refactoring out the `fs.FS`
embedding from `syscallfs.DS`.

P.S. naming convention is arbitrary, so I took UnimplementedXXX from
grpc. This pattern is used a lot of places, also proxy-wasm-go-sdk, e.g.
`DefaultVMContext`.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-18 09:37:12 -06:00

66 lines
1.5 KiB
Go

package syscallfs
import (
"fmt"
"io/fs"
"os"
pathutil "path"
)
// Adapt adapts the input to FS unless it is already one. NewDirFS should be
// used instead, if the input is os.DirFS.
//
// Note: This performs no flag verification on FS.OpenFile. fs.FS cannot read
// flags as there is no parameter to pass them through with. Moreover, fs.FS
// documentation does not require the file to be present. In summary, we can't
// enforce flag behavior.
func Adapt(fs fs.FS, guestDir string) FS {
if sys, ok := fs.(FS); ok {
return sys
}
return &adapter{fs: fs, guestDir: guestDir}
}
type adapter struct {
UnimplementedFS
fs fs.FS
guestDir string
}
// String implements fmt.Stringer
func (a *adapter) String() string {
return fmt.Sprintf("%v:%s:ro", a.fs, a.guestDir)
}
// GuestDir implements FS.GuestDir
func (a *adapter) GuestDir() string {
return a.guestDir
}
// OpenFile implements FS.OpenFile
func (a *adapter) OpenFile(path string, flag int, perm fs.FileMode) (fs.File, error) {
path = cleanPath(path)
f, err := a.fs.Open(path)
if err != nil {
return nil, unwrapPathError(err)
} else if osF, ok := f.(*os.File); ok {
// If this is an OS file, it has same portability issues as dirFS.
return maybeWrapFile(osF), nil
}
return f, nil
}
func cleanPath(name string) string {
if len(name) == 0 {
return name
}
// fs.ValidFile cannot be rooted (start with '/')
cleaned := name
if name[0] == '/' {
cleaned = name[1:]
}
cleaned = pathutil.Clean(cleaned) // e.g. "sub/." -> "sub"
return cleaned
}