adapter.go

  1package sysfs
  2
  3import (
  4	"fmt"
  5	"io/fs"
  6	"path"
  7
  8	experimentalsys "github.com/tetratelabs/wazero/experimental/sys"
  9	"github.com/tetratelabs/wazero/sys"
 10)
 11
 12type AdaptFS struct {
 13	FS fs.FS
 14}
 15
 16// String implements fmt.Stringer
 17func (a *AdaptFS) String() string {
 18	return fmt.Sprintf("%v", a.FS)
 19}
 20
 21// OpenFile implements the same method as documented on sys.FS
 22func (a *AdaptFS) OpenFile(path string, flag experimentalsys.Oflag, perm fs.FileMode) (experimentalsys.File, experimentalsys.Errno) {
 23	return OpenFSFile(a.FS, cleanPath(path), flag, perm)
 24}
 25
 26// Lstat implements the same method as documented on sys.FS
 27func (a *AdaptFS) Lstat(path string) (sys.Stat_t, experimentalsys.Errno) {
 28	// At this time, we make the assumption sys.FS instances do not support
 29	// symbolic links, therefore Lstat is the same as Stat. This is obviously
 30	// not true, but until FS.FS has a solid story for how to handle symlinks,
 31	// we are better off not making a decision that would be difficult to
 32	// revert later on.
 33	//
 34	// For further discussions on the topic, see:
 35	// https://github.com/golang/go/issues/49580
 36	return a.Stat(path)
 37}
 38
 39// Stat implements the same method as documented on sys.FS
 40func (a *AdaptFS) Stat(path string) (sys.Stat_t, experimentalsys.Errno) {
 41	f, errno := a.OpenFile(path, experimentalsys.O_RDONLY, 0)
 42	if errno != 0 {
 43		return sys.Stat_t{}, errno
 44	}
 45	defer f.Close()
 46	return f.Stat()
 47}
 48
 49// Readlink implements the same method as documented on sys.FS
 50func (a *AdaptFS) Readlink(string) (string, experimentalsys.Errno) {
 51	return "", experimentalsys.ENOSYS
 52}
 53
 54// Mkdir implements the same method as documented on sys.FS
 55func (a *AdaptFS) Mkdir(string, fs.FileMode) experimentalsys.Errno {
 56	return experimentalsys.ENOSYS
 57}
 58
 59// Chmod implements the same method as documented on sys.FS
 60func (a *AdaptFS) Chmod(string, fs.FileMode) experimentalsys.Errno {
 61	return experimentalsys.ENOSYS
 62}
 63
 64// Rename implements the same method as documented on sys.FS
 65func (a *AdaptFS) Rename(string, string) experimentalsys.Errno {
 66	return experimentalsys.ENOSYS
 67}
 68
 69// Rmdir implements the same method as documented on sys.FS
 70func (a *AdaptFS) Rmdir(string) experimentalsys.Errno {
 71	return experimentalsys.ENOSYS
 72}
 73
 74// Link implements the same method as documented on sys.FS
 75func (a *AdaptFS) Link(string, string) experimentalsys.Errno {
 76	return experimentalsys.ENOSYS
 77}
 78
 79// Symlink implements the same method as documented on sys.FS
 80func (a *AdaptFS) Symlink(string, string) experimentalsys.Errno {
 81	return experimentalsys.ENOSYS
 82}
 83
 84// Unlink implements the same method as documented on sys.FS
 85func (a *AdaptFS) Unlink(string) experimentalsys.Errno {
 86	return experimentalsys.ENOSYS
 87}
 88
 89// Utimens implements the same method as documented on sys.FS
 90func (a *AdaptFS) Utimens(string, int64, int64) experimentalsys.Errno {
 91	return experimentalsys.ENOSYS
 92}
 93
 94func cleanPath(name string) string {
 95	if len(name) == 0 {
 96		return name
 97	}
 98	// fs.ValidFile cannot be rooted (start with '/')
 99	cleaned := name
100	if name[0] == '/' {
101		cleaned = name[1:]
102	}
103	cleaned = path.Clean(cleaned) // e.g. "sub/." -> "sub"
104	return cleaned
105}