github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/internal/sys/lazy.go (about) 1 package sys 2 3 import ( 4 experimentalsys "github.com/bananabytelabs/wazero/experimental/sys" 5 "github.com/bananabytelabs/wazero/internal/fsapi" 6 "github.com/bananabytelabs/wazero/sys" 7 ) 8 9 // compile-time check to ensure lazyDir implements sys.File. 10 var _ experimentalsys.File = (*lazyDir)(nil) 11 12 type lazyDir struct { 13 experimentalsys.DirFile 14 15 fs experimentalsys.FS 16 f experimentalsys.File 17 } 18 19 // Dev implements the same method as documented on sys.File 20 func (d *lazyDir) Dev() (uint64, experimentalsys.Errno) { 21 if f, ok := d.file(); !ok { 22 return 0, experimentalsys.EBADF 23 } else { 24 return f.Dev() 25 } 26 } 27 28 // Ino implements the same method as documented on sys.File 29 func (d *lazyDir) Ino() (sys.Inode, experimentalsys.Errno) { 30 if f, ok := d.file(); !ok { 31 return 0, experimentalsys.EBADF 32 } else { 33 return f.Ino() 34 } 35 } 36 37 // IsDir implements the same method as documented on sys.File 38 func (d *lazyDir) IsDir() (bool, experimentalsys.Errno) { 39 // Note: we don't return a constant because we don't know if this is really 40 // backed by a dir, until the first call. 41 if f, ok := d.file(); !ok { 42 return false, experimentalsys.EBADF 43 } else { 44 return f.IsDir() 45 } 46 } 47 48 // IsAppend implements the same method as documented on sys.File 49 func (d *lazyDir) IsAppend() bool { 50 return false 51 } 52 53 // SetAppend implements the same method as documented on sys.File 54 func (d *lazyDir) SetAppend(bool) experimentalsys.Errno { 55 return experimentalsys.EISDIR 56 } 57 58 // Seek implements the same method as documented on sys.File 59 func (d *lazyDir) Seek(offset int64, whence int) (newOffset int64, errno experimentalsys.Errno) { 60 if f, ok := d.file(); !ok { 61 return 0, experimentalsys.EBADF 62 } else { 63 return f.Seek(offset, whence) 64 } 65 } 66 67 // Stat implements the same method as documented on sys.File 68 func (d *lazyDir) Stat() (sys.Stat_t, experimentalsys.Errno) { 69 if f, ok := d.file(); !ok { 70 return sys.Stat_t{}, experimentalsys.EBADF 71 } else { 72 return f.Stat() 73 } 74 } 75 76 // Readdir implements the same method as documented on sys.File 77 func (d *lazyDir) Readdir(n int) (dirents []experimentalsys.Dirent, errno experimentalsys.Errno) { 78 if f, ok := d.file(); !ok { 79 return nil, experimentalsys.EBADF 80 } else { 81 return f.Readdir(n) 82 } 83 } 84 85 // Sync implements the same method as documented on sys.File 86 func (d *lazyDir) Sync() experimentalsys.Errno { 87 if f, ok := d.file(); !ok { 88 return experimentalsys.EBADF 89 } else { 90 return f.Sync() 91 } 92 } 93 94 // Datasync implements the same method as documented on sys.File 95 func (d *lazyDir) Datasync() experimentalsys.Errno { 96 if f, ok := d.file(); !ok { 97 return experimentalsys.EBADF 98 } else { 99 return f.Datasync() 100 } 101 } 102 103 // Utimens implements the same method as documented on sys.File 104 func (d *lazyDir) Utimens(atim, mtim int64) experimentalsys.Errno { 105 if f, ok := d.file(); !ok { 106 return experimentalsys.EBADF 107 } else { 108 return f.Utimens(atim, mtim) 109 } 110 } 111 112 // file returns the underlying file or false if it doesn't exist. 113 func (d *lazyDir) file() (experimentalsys.File, bool) { 114 if f := d.f; d.f != nil { 115 return f, true 116 } 117 var errno experimentalsys.Errno 118 d.f, errno = d.fs.OpenFile(".", experimentalsys.O_RDONLY, 0) 119 switch errno { 120 case 0: 121 return d.f, true 122 case experimentalsys.ENOENT: 123 return nil, false 124 default: 125 panic(errno) // unexpected 126 } 127 } 128 129 // Close implements fs.File 130 func (d *lazyDir) Close() experimentalsys.Errno { 131 f := d.f 132 if f == nil { 133 return 0 // never opened 134 } 135 return f.Close() 136 } 137 138 // IsNonblock implements the same method as documented on fsapi.File 139 func (d *lazyDir) IsNonblock() bool { 140 return false 141 } 142 143 // SetNonblock implements the same method as documented on fsapi.File 144 func (d *lazyDir) SetNonblock(bool) experimentalsys.Errno { 145 return experimentalsys.EISDIR 146 } 147 148 // Poll implements the same method as documented on fsapi.File 149 func (d *lazyDir) Poll(fsapi.Pflag, int32) (ready bool, errno experimentalsys.Errno) { 150 return false, experimentalsys.ENOSYS 151 }