github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/internal/sysfs/adapter.go (about)

     1  package sysfs
     2  
     3  import (
     4  	"fmt"
     5  	"io/fs"
     6  	"path"
     7  
     8  	experimentalsys "github.com/tetratelabs/wazero/experimental/sys"
     9  	"github.com/tetratelabs/wazero/sys"
    10  )
    11  
    12  type AdaptFS struct {
    13  	FS fs.FS
    14  }
    15  
    16  // String implements fmt.Stringer
    17  func (a *AdaptFS) String() string {
    18  	return fmt.Sprintf("%v", a.FS)
    19  }
    20  
    21  // OpenFile implements the same method as documented on sys.FS
    22  func (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
    27  func (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
    40  func (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
    50  func (a *AdaptFS) Readlink(string) (string, experimentalsys.Errno) {
    51  	return "", experimentalsys.ENOSYS
    52  }
    53  
    54  // Mkdir implements the same method as documented on sys.FS
    55  func (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
    60  func (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
    65  func (a *AdaptFS) Rename(string, string) experimentalsys.Errno {
    66  	return experimentalsys.ENOSYS
    67  }
    68  
    69  // Rmdir implements the same method as documented on sys.FS
    70  func (a *AdaptFS) Rmdir(string) experimentalsys.Errno {
    71  	return experimentalsys.ENOSYS
    72  }
    73  
    74  // Link implements the same method as documented on sys.FS
    75  func (a *AdaptFS) Link(string, string) experimentalsys.Errno {
    76  	return experimentalsys.ENOSYS
    77  }
    78  
    79  // Symlink implements the same method as documented on sys.FS
    80  func (a *AdaptFS) Symlink(string, string) experimentalsys.Errno {
    81  	return experimentalsys.ENOSYS
    82  }
    83  
    84  // Unlink implements the same method as documented on sys.FS
    85  func (a *AdaptFS) Unlink(string) experimentalsys.Errno {
    86  	return experimentalsys.ENOSYS
    87  }
    88  
    89  // Utimens implements the same method as documented on sys.FS
    90  func (a *AdaptFS) Utimens(string, int64, int64) experimentalsys.Errno {
    91  	return experimentalsys.ENOSYS
    92  }
    93  
    94  func 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  }