github.com/tetratelabs/wazero@v1.2.1/internal/sys/lazy.go (about) 1 package sys 2 3 import ( 4 "io/fs" 5 "os" 6 "syscall" 7 8 "github.com/tetratelabs/wazero/internal/fsapi" 9 ) 10 11 // compile-time check to ensure lazyDir implements internalapi.File. 12 var _ fsapi.File = (*lazyDir)(nil) 13 14 type lazyDir struct { 15 fsapi.DirFile 16 17 fs fsapi.FS 18 f fsapi.File 19 } 20 21 // Ino implements the same method as documented on internalapi.File 22 func (r *lazyDir) Ino() (uint64, syscall.Errno) { 23 if f, ok := r.file(); !ok { 24 return 0, syscall.EBADF 25 } else { 26 return f.Ino() 27 } 28 } 29 30 // IsAppend implements the same method as documented on internalapi.File 31 func (r *lazyDir) IsAppend() bool { 32 return false 33 } 34 35 // SetAppend implements the same method as documented on internalapi.File 36 func (r *lazyDir) SetAppend(bool) syscall.Errno { 37 return syscall.EISDIR 38 } 39 40 // Seek implements the same method as documented on internalapi.File 41 func (r *lazyDir) Seek(offset int64, whence int) (newOffset int64, errno syscall.Errno) { 42 if f, ok := r.file(); !ok { 43 return 0, syscall.EBADF 44 } else { 45 return f.Seek(offset, whence) 46 } 47 } 48 49 // Stat implements the same method as documented on internalapi.File 50 func (r *lazyDir) Stat() (fsapi.Stat_t, syscall.Errno) { 51 if f, ok := r.file(); !ok { 52 return fsapi.Stat_t{}, syscall.EBADF 53 } else { 54 return f.Stat() 55 } 56 } 57 58 // Readdir implements the same method as documented on internalapi.File 59 func (r *lazyDir) Readdir(n int) (dirents []fsapi.Dirent, errno syscall.Errno) { 60 if f, ok := r.file(); !ok { 61 return nil, syscall.EBADF 62 } else { 63 return f.Readdir(n) 64 } 65 } 66 67 // Sync implements the same method as documented on internalapi.File 68 func (r *lazyDir) Sync() syscall.Errno { 69 if f, ok := r.file(); !ok { 70 return syscall.EBADF 71 } else { 72 return f.Sync() 73 } 74 } 75 76 // Datasync implements the same method as documented on internalapi.File 77 func (r *lazyDir) Datasync() syscall.Errno { 78 if f, ok := r.file(); !ok { 79 return syscall.EBADF 80 } else { 81 return f.Datasync() 82 } 83 } 84 85 // Chmod implements the same method as documented on internalapi.File 86 func (r *lazyDir) Chmod(mode fs.FileMode) syscall.Errno { 87 if f, ok := r.file(); !ok { 88 return syscall.EBADF 89 } else { 90 return f.Chmod(mode) 91 } 92 } 93 94 // Chown implements the same method as documented on internalapi.File 95 func (r *lazyDir) Chown(uid, gid int) syscall.Errno { 96 if f, ok := r.file(); !ok { 97 return syscall.EBADF 98 } else { 99 return f.Chown(uid, gid) 100 } 101 } 102 103 // Utimens implements the same method as documented on internalapi.File 104 func (r *lazyDir) Utimens(times *[2]syscall.Timespec) syscall.Errno { 105 if f, ok := r.file(); !ok { 106 return syscall.EBADF 107 } else { 108 return f.Utimens(times) 109 } 110 } 111 112 // file returns the underlying file or false if it doesn't exist. 113 func (r *lazyDir) file() (fsapi.File, bool) { 114 if f := r.f; r.f != nil { 115 return f, true 116 } 117 var errno syscall.Errno 118 r.f, errno = r.fs.OpenFile(".", os.O_RDONLY, 0) 119 switch errno { 120 case 0: 121 return r.f, true 122 case syscall.ENOENT: 123 return nil, false 124 default: 125 panic(errno) // unexpected 126 } 127 } 128 129 // Close implements fs.File 130 func (r *lazyDir) Close() syscall.Errno { 131 f := r.f 132 if f == nil { 133 return 0 // never opened 134 } 135 return f.Close() 136 }