diff options
author | 2025-03-09 17:47:56 +0100 | |
---|---|---|
committer | 2025-03-10 01:59:49 +0100 | |
commit | 3ac1ee16f377d31a0fb80c8dae28b6239ac4229e (patch) | |
tree | f61faa581feaaeaba2542b9f2b8234a590684413 /vendor/github.com/tetratelabs/wazero/internal/sysfs/file.go | |
parent | [chore] update URLs to forked source (diff) | |
download | gotosocial-3ac1ee16f377d31a0fb80c8dae28b6239ac4229e.tar.xz |
[chore] remove vendor
Diffstat (limited to 'vendor/github.com/tetratelabs/wazero/internal/sysfs/file.go')
-rw-r--r-- | vendor/github.com/tetratelabs/wazero/internal/sysfs/file.go | 523 |
1 files changed, 0 insertions, 523 deletions
diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/file.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/file.go deleted file mode 100644 index 1b6d5f3de..000000000 --- a/vendor/github.com/tetratelabs/wazero/internal/sysfs/file.go +++ /dev/null @@ -1,523 +0,0 @@ -package sysfs - -import ( - "io" - "io/fs" - "os" - "time" - - experimentalsys "github.com/tetratelabs/wazero/experimental/sys" - "github.com/tetratelabs/wazero/internal/fsapi" - "github.com/tetratelabs/wazero/sys" -) - -func NewStdioFile(stdin bool, f fs.File) (fsapi.File, error) { - // Return constant stat, which has fake times, but keep the underlying - // file mode. Fake times are needed to pass wasi-testsuite. - // https://github.com/WebAssembly/wasi-testsuite/blob/af57727/tests/rust/src/bin/fd_filestat_get.rs#L1-L19 - var mode fs.FileMode - if st, err := f.Stat(); err != nil { - return nil, err - } else { - mode = st.Mode() - } - var flag experimentalsys.Oflag - if stdin { - flag = experimentalsys.O_RDONLY - } else { - flag = experimentalsys.O_WRONLY - } - var file fsapi.File - if of, ok := f.(*os.File); ok { - // This is ok because functions that need path aren't used by stdioFile - file = newOsFile("", flag, 0, of) - } else { - file = &fsFile{file: f} - } - return &stdioFile{File: file, st: sys.Stat_t{Mode: mode, Nlink: 1}}, nil -} - -func OpenFile(path string, flag experimentalsys.Oflag, perm fs.FileMode) (*os.File, experimentalsys.Errno) { - return openFile(path, flag, perm) -} - -func OpenOSFile(path string, flag experimentalsys.Oflag, perm fs.FileMode) (experimentalsys.File, experimentalsys.Errno) { - f, errno := OpenFile(path, flag, perm) - if errno != 0 { - return nil, errno - } - return newOsFile(path, flag, perm, f), 0 -} - -func OpenFSFile(fs fs.FS, path string, flag experimentalsys.Oflag, perm fs.FileMode) (experimentalsys.File, experimentalsys.Errno) { - if flag&experimentalsys.O_DIRECTORY != 0 && flag&(experimentalsys.O_WRONLY|experimentalsys.O_RDWR) != 0 { - return nil, experimentalsys.EISDIR // invalid to open a directory writeable - } - f, err := fs.Open(path) - if errno := experimentalsys.UnwrapOSError(err); errno != 0 { - return nil, errno - } - // Don't return an os.File because the path is not absolute. osFile needs - // the path to be real and certain FS.File impls are subrooted. - return &fsFile{fs: fs, name: path, file: f}, 0 -} - -type stdioFile struct { - fsapi.File - st sys.Stat_t -} - -// SetAppend implements File.SetAppend -func (f *stdioFile) SetAppend(bool) experimentalsys.Errno { - // Ignore for stdio. - return 0 -} - -// IsAppend implements File.SetAppend -func (f *stdioFile) IsAppend() bool { - return true -} - -// Stat implements File.Stat -func (f *stdioFile) Stat() (sys.Stat_t, experimentalsys.Errno) { - return f.st, 0 -} - -// Close implements File.Close -func (f *stdioFile) Close() experimentalsys.Errno { - return 0 -} - -// fsFile is used for wrapped fs.File, like os.Stdin or any fs.File -// implementation. Notably, this does not have access to the full file path. -// so certain operations can't be supported, such as inode lookups on Windows. -type fsFile struct { - experimentalsys.UnimplementedFile - - // fs is the file-system that opened the file, or nil when wrapped for - // pre-opens like stdio. - fs fs.FS - - // name is what was used in fs for Open, so it may not be the actual path. - name string - - // file is always set, possibly an os.File like os.Stdin. - file fs.File - - // reopenDir is true if reopen should be called before Readdir. This flag - // is deferred until Readdir to prevent redundant rewinds. This could - // happen if Seek(0) was called twice, or if in Windows, Seek(0) was called - // before Readdir. - reopenDir bool - - // closed is true when closed was called. This ensures proper sys.EBADF - closed bool - - // cachedStat includes fields that won't change while a file is open. - cachedSt *cachedStat -} - -type cachedStat struct { - // dev is the same as sys.Stat_t Dev. - dev uint64 - - // dev is the same as sys.Stat_t Ino. - ino sys.Inode - - // isDir is sys.Stat_t Mode masked with fs.ModeDir - isDir bool -} - -// cachedStat returns the cacheable parts of sys.Stat_t or an error if they -// couldn't be retrieved. -func (f *fsFile) cachedStat() (dev uint64, ino sys.Inode, isDir bool, errno experimentalsys.Errno) { - if f.cachedSt == nil { - if _, errno = f.Stat(); errno != 0 { - return - } - } - return f.cachedSt.dev, f.cachedSt.ino, f.cachedSt.isDir, 0 -} - -// Dev implements the same method as documented on sys.File -func (f *fsFile) Dev() (uint64, experimentalsys.Errno) { - dev, _, _, errno := f.cachedStat() - return dev, errno -} - -// Ino implements the same method as documented on sys.File -func (f *fsFile) Ino() (sys.Inode, experimentalsys.Errno) { - _, ino, _, errno := f.cachedStat() - return ino, errno -} - -// IsDir implements the same method as documented on sys.File -func (f *fsFile) IsDir() (bool, experimentalsys.Errno) { - _, _, isDir, errno := f.cachedStat() - return isDir, errno -} - -// IsAppend implements the same method as documented on sys.File -func (f *fsFile) IsAppend() bool { - return false -} - -// SetAppend implements the same method as documented on sys.File -func (f *fsFile) SetAppend(bool) (errno experimentalsys.Errno) { - return fileError(f, f.closed, experimentalsys.ENOSYS) -} - -// Stat implements the same method as documented on sys.File -func (f *fsFile) Stat() (sys.Stat_t, experimentalsys.Errno) { - if f.closed { - return sys.Stat_t{}, experimentalsys.EBADF - } - - st, errno := statFile(f.file) - switch errno { - case 0: - f.cachedSt = &cachedStat{dev: st.Dev, ino: st.Ino, isDir: st.Mode&fs.ModeDir == fs.ModeDir} - case experimentalsys.EIO: - errno = experimentalsys.EBADF - } - return st, errno -} - -// Read implements the same method as documented on sys.File -func (f *fsFile) Read(buf []byte) (n int, errno experimentalsys.Errno) { - if n, errno = read(f.file, buf); errno != 0 { - // Defer validation overhead until we've already had an error. - errno = fileError(f, f.closed, errno) - } - return -} - -// Pread implements the same method as documented on sys.File -func (f *fsFile) Pread(buf []byte, off int64) (n int, errno experimentalsys.Errno) { - if ra, ok := f.file.(io.ReaderAt); ok { - if n, errno = pread(ra, buf, off); errno != 0 { - // Defer validation overhead until we've already had an error. - errno = fileError(f, f.closed, errno) - } - return - } - - // See /RATIONALE.md "fd_pread: io.Seeker fallback when io.ReaderAt is not supported" - if rs, ok := f.file.(io.ReadSeeker); ok { - // Determine the current position in the file, as we need to revert it. - currentOffset, err := rs.Seek(0, io.SeekCurrent) - if err != nil { - return 0, fileError(f, f.closed, experimentalsys.UnwrapOSError(err)) - } - - // Put the read position back when complete. - defer func() { _, _ = rs.Seek(currentOffset, io.SeekStart) }() - - // If the current offset isn't in sync with this reader, move it. - if off != currentOffset { - if _, err = rs.Seek(off, io.SeekStart); err != nil { - return 0, fileError(f, f.closed, experimentalsys.UnwrapOSError(err)) - } - } - - n, err = rs.Read(buf) - if errno = experimentalsys.UnwrapOSError(err); errno != 0 { - // Defer validation overhead until we've already had an error. - errno = fileError(f, f.closed, errno) - } - } else { - errno = experimentalsys.ENOSYS // unsupported - } - return -} - -// Seek implements the same method as documented on sys.File -func (f *fsFile) Seek(offset int64, whence int) (newOffset int64, errno experimentalsys.Errno) { - // If this is a directory, and we're attempting to seek to position zero, - // we have to re-open the file to ensure the directory state is reset. - var isDir bool - if offset == 0 && whence == io.SeekStart { - if isDir, errno = f.IsDir(); errno == 0 && isDir { - f.reopenDir = true - return - } - } - - if s, ok := f.file.(io.Seeker); ok { - if newOffset, errno = seek(s, offset, whence); errno != 0 { - // Defer validation overhead until we've already had an error. - errno = fileError(f, f.closed, errno) - } - } else { - errno = experimentalsys.ENOSYS // unsupported - } - return -} - -// Readdir implements the same method as documented on sys.File -// -// Notably, this uses readdirFile or fs.ReadDirFile if available. This does not -// return inodes on windows. -func (f *fsFile) Readdir(n int) (dirents []experimentalsys.Dirent, errno experimentalsys.Errno) { - // Windows lets you Readdir after close, FS.File also may not implement - // close in a meaningful way. read our closed field to return consistent - // results. - if f.closed { - errno = experimentalsys.EBADF - return - } - - if f.reopenDir { // re-open the directory if needed. - f.reopenDir = false - if errno = adjustReaddirErr(f, f.closed, f.rewindDir()); errno != 0 { - return - } - } - - if of, ok := f.file.(readdirFile); ok { - // We can't use f.name here because it is the path up to the sys.FS, - // not necessarily the real path. For this reason, Windows may not be - // able to populate inodes. However, Darwin and Linux will. - if dirents, errno = readdir(of, "", n); errno != 0 { - errno = adjustReaddirErr(f, f.closed, errno) - } - return - } - - // Try with FS.ReadDirFile which is available on api.FS implementations - // like embed:FS. - if rdf, ok := f.file.(fs.ReadDirFile); ok { - entries, e := rdf.ReadDir(n) - if errno = adjustReaddirErr(f, f.closed, e); errno != 0 { - return - } - dirents = make([]experimentalsys.Dirent, 0, len(entries)) - for _, e := range entries { - // By default, we don't attempt to read inode data - dirents = append(dirents, experimentalsys.Dirent{Name: e.Name(), Type: e.Type()}) - } - } else { - errno = experimentalsys.EBADF // not a directory - } - return -} - -// Write implements the same method as documented on sys.File. -func (f *fsFile) Write(buf []byte) (n int, errno experimentalsys.Errno) { - if w, ok := f.file.(io.Writer); ok { - if n, errno = write(w, buf); errno != 0 { - // Defer validation overhead until we've already had an error. - errno = fileError(f, f.closed, errno) - } - } else { - errno = experimentalsys.ENOSYS // unsupported - } - return -} - -// Pwrite implements the same method as documented on sys.File. -func (f *fsFile) Pwrite(buf []byte, off int64) (n int, errno experimentalsys.Errno) { - if wa, ok := f.file.(io.WriterAt); ok { - if n, errno = pwrite(wa, buf, off); errno != 0 { - // Defer validation overhead until we've already had an error. - errno = fileError(f, f.closed, errno) - } - } else { - errno = experimentalsys.ENOSYS // unsupported - } - return -} - -// Close implements the same method as documented on sys.File. -func (f *fsFile) Close() experimentalsys.Errno { - if f.closed { - return 0 - } - f.closed = true - return f.close() -} - -func (f *fsFile) close() experimentalsys.Errno { - return experimentalsys.UnwrapOSError(f.file.Close()) -} - -// IsNonblock implements the same method as documented on fsapi.File -func (f *fsFile) IsNonblock() bool { - return false -} - -// SetNonblock implements the same method as documented on fsapi.File -func (f *fsFile) SetNonblock(bool) experimentalsys.Errno { - return experimentalsys.ENOSYS -} - -// Poll implements the same method as documented on fsapi.File -func (f *fsFile) Poll(fsapi.Pflag, int32) (ready bool, errno experimentalsys.Errno) { - return false, experimentalsys.ENOSYS -} - -// dirError is used for commands that work against a directory, but not a file. -func dirError(f experimentalsys.File, isClosed bool, errno experimentalsys.Errno) experimentalsys.Errno { - if vErrno := validate(f, isClosed, false, true); vErrno != 0 { - return vErrno - } - return errno -} - -// fileError is used for commands that work against a file, but not a directory. -func fileError(f experimentalsys.File, isClosed bool, errno experimentalsys.Errno) experimentalsys.Errno { - if vErrno := validate(f, isClosed, true, false); vErrno != 0 { - return vErrno - } - return errno -} - -// validate is used to making syscalls which will fail. -func validate(f experimentalsys.File, isClosed, wantFile, wantDir bool) experimentalsys.Errno { - if isClosed { - return experimentalsys.EBADF - } - - isDir, errno := f.IsDir() - if errno != 0 { - return errno - } - - if wantFile && isDir { - return experimentalsys.EISDIR - } else if wantDir && !isDir { - return experimentalsys.ENOTDIR - } - return 0 -} - -func read(r io.Reader, buf []byte) (n int, errno experimentalsys.Errno) { - if len(buf) == 0 { - return 0, 0 // less overhead on zero-length reads. - } - - n, err := r.Read(buf) - return n, experimentalsys.UnwrapOSError(err) -} - -func pread(ra io.ReaderAt, buf []byte, off int64) (n int, errno experimentalsys.Errno) { - if len(buf) == 0 { - return 0, 0 // less overhead on zero-length reads. - } - - n, err := ra.ReadAt(buf, off) - return n, experimentalsys.UnwrapOSError(err) -} - -func seek(s io.Seeker, offset int64, whence int) (int64, experimentalsys.Errno) { - if uint(whence) > io.SeekEnd { - return 0, experimentalsys.EINVAL // negative or exceeds the largest valid whence - } - - newOffset, err := s.Seek(offset, whence) - return newOffset, experimentalsys.UnwrapOSError(err) -} - -func (f *fsFile) rewindDir() experimentalsys.Errno { - // Reopen the directory to rewind it. - file, err := f.fs.Open(f.name) - if err != nil { - return experimentalsys.UnwrapOSError(err) - } - fi, err := file.Stat() - if err != nil { - return experimentalsys.UnwrapOSError(err) - } - // Can't check if it's still the same file, - // but is it still a directory, at least? - if !fi.IsDir() { - return experimentalsys.ENOTDIR - } - // Only update f on success. - _ = f.file.Close() - f.file = file - return 0 -} - -// readdirFile allows masking the `Readdir` function on os.File. -type readdirFile interface { - Readdir(n int) ([]fs.FileInfo, error) -} - -// readdir uses readdirFile.Readdir, special casing windows when path !="". -func readdir(f readdirFile, path string, n int) (dirents []experimentalsys.Dirent, errno experimentalsys.Errno) { - fis, e := f.Readdir(n) - if errno = experimentalsys.UnwrapOSError(e); errno != 0 { - return - } - - dirents = make([]experimentalsys.Dirent, 0, len(fis)) - - // linux/darwin won't have to fan out to lstat, but windows will. - var ino sys.Inode - for fi := range fis { - t := fis[fi] - // inoFromFileInfo is more efficient than sys.NewStat_t, as it gets the - // inode without allocating an instance and filling other fields. - if ino, errno = inoFromFileInfo(path, t); errno != 0 { - return - } - dirents = append(dirents, experimentalsys.Dirent{Name: t.Name(), Ino: ino, Type: t.Mode().Type()}) - } - return -} - -func write(w io.Writer, buf []byte) (n int, errno experimentalsys.Errno) { - if len(buf) == 0 { - return 0, 0 // less overhead on zero-length writes. - } - - n, err := w.Write(buf) - return n, experimentalsys.UnwrapOSError(err) -} - -func pwrite(w io.WriterAt, buf []byte, off int64) (n int, errno experimentalsys.Errno) { - if len(buf) == 0 { - return 0, 0 // less overhead on zero-length writes. - } - - n, err := w.WriteAt(buf, off) - return n, experimentalsys.UnwrapOSError(err) -} - -func chtimes(path string, atim, mtim int64) (errno experimentalsys.Errno) { //nolint:unused - // When both inputs are omitted, there is nothing to change. - if atim == experimentalsys.UTIME_OMIT && mtim == experimentalsys.UTIME_OMIT { - return - } - - // UTIME_OMIT is expensive until progress is made in Go, as it requires a - // stat to read-back the value to re-apply. - // - https://github.com/golang/go/issues/32558. - // - https://go-review.googlesource.com/c/go/+/219638 (unmerged) - var st sys.Stat_t - if atim == experimentalsys.UTIME_OMIT || mtim == experimentalsys.UTIME_OMIT { - if st, errno = stat(path); errno != 0 { - return - } - } - - var atime, mtime time.Time - if atim == experimentalsys.UTIME_OMIT { - atime = epochNanosToTime(st.Atim) - mtime = epochNanosToTime(mtim) - } else if mtim == experimentalsys.UTIME_OMIT { - atime = epochNanosToTime(atim) - mtime = epochNanosToTime(st.Mtim) - } else { - atime = epochNanosToTime(atim) - mtime = epochNanosToTime(mtim) - } - return experimentalsys.UnwrapOSError(os.Chtimes(path, atime, mtime)) -} - -func epochNanosToTime(epochNanos int64) time.Time { //nolint:unused - seconds := epochNanos / 1e9 - nanos := epochNanos % 1e9 - return time.Unix(seconds, nanos) -} |