github.com/gaukas/wazerofs@v0.1.0/wraplogfs/fs.go (about) 1 // wraplogfs is a wazero filesystem that wraps another, existing filesystem, and logs 2 // all inputs/outputs to writer. 3 // 4 // Was first generated by hexdigest/gowrap, but then edited for better outputs in some cases 5 package wraplogfs 6 7 import ( 8 "fmt" 9 "io" 10 "io/fs" 11 "log" 12 "strings" 13 14 expsys "github.com/tetratelabs/wazero/experimental/sys" 15 wasys "github.com/tetratelabs/wazero/sys" 16 ) 17 18 type fsWithLog struct { 19 // intentionally does NOT embed unimplemented; I do NOT want to be forward-compatible; 20 // I want to break on missing funcs 21 22 stdlog *log.Logger 23 base expsys.FS 24 writeBytes bool 25 fsName string 26 } 27 28 // New returns a new filesystem on top of another filesystem. 29 // writeBytes controls if all bytes are written on stdout on reads/writes, or just "(data)". 30 func New(base expsys.FS, stdout io.Writer, writeBytes bool, name string) expsys.FS { 31 return fsWithLog{ 32 base: base, 33 stdlog: log.New(stdout, "", log.LstdFlags), 34 writeBytes: writeBytes, 35 fsName: name, 36 } 37 } 38 39 func (d fsWithLog) log(nm string) func(format string, params ...any) { 40 return func(format string, params ...any) { 41 txt := fmt.Sprintf(format, params...) 42 txt = fmt.Sprintf("WrapLogFS %s %s: %s", d.fsName, nm, txt) 43 d.stdlog.Println(txt) 44 } 45 } 46 47 // Chmod implements sys.FS 48 func (d fsWithLog) Chmod(path string, perm fs.FileMode) (e1 expsys.Errno) { 49 l := d.log("Chmod") 50 l("calling with params: %q %s", path, perm) 51 defer func() { 52 l("returned results: %s", e1) 53 }() 54 return d.base.Chmod(path, perm) 55 } 56 57 // Link implements sys.FS 58 func (d fsWithLog) Link(oldPath string, newPath string) (e1 expsys.Errno) { 59 l := d.log("Link") 60 l("calling with params: %q %q", oldPath, newPath) 61 defer func() { 62 l("returned results: %s", e1) 63 }() 64 return d.base.Link(oldPath, newPath) 65 } 66 67 // Lstat implements sys.FS 68 func (d fsWithLog) Lstat(path string) (s1 wasys.Stat_t, e1 expsys.Errno) { 69 l := d.log("Lstat") 70 l("calling with params: %q", path) 71 72 defer func() { 73 l("returned results: %+v %s", s1, e1) 74 }() 75 return d.base.Lstat(path) 76 } 77 78 // Mkdir implements sys.FS 79 func (d fsWithLog) Mkdir(path string, perm fs.FileMode) (e1 expsys.Errno) { 80 l := d.log("Mkdir") 81 l("calling with params: %q %s", path, perm) 82 83 defer func() { 84 l("returned results: %+v %s", e1) 85 }() 86 return d.base.Mkdir(path, perm) 87 } 88 89 func printOflags(flag expsys.Oflag) string { 90 st := []string{} 91 flags := map[expsys.Oflag]string{ 92 93 expsys.O_RDONLY: "O_RDONLY", 94 expsys.O_RDWR: "O_RDWR", 95 expsys.O_WRONLY: "O_WRONLY", 96 expsys.O_APPEND: "O_APPEND", 97 expsys.O_CREAT: "O_CREAT", 98 expsys.O_DIRECTORY: "O_DIRECTORY", 99 expsys.O_DSYNC: "O_DSYNC", 100 expsys.O_EXCL: "O_EXCL", 101 expsys.O_NOFOLLOW: "O_NOFOLLOW", 102 expsys.O_NONBLOCK: "O_NONBLOCK", 103 expsys.O_RSYNC: "O_RSYNC", 104 expsys.O_SYNC: "O_SYNC", 105 expsys.O_TRUNC: "O_TRUNC", 106 } 107 for f, d := range flags { 108 if flag&f != 0 { 109 st = append(st, d) 110 } 111 } 112 if len(st) == 0 { 113 return "(none)" 114 } else { 115 return strings.Join(st, "|") 116 } 117 } 118 119 // OpenFile implements sys.FS 120 func (d fsWithLog) OpenFile(path string, flag expsys.Oflag, perm fs.FileMode) (f1 expsys.File, e1 expsys.Errno) { 121 l := d.log("OpenFile") 122 l("calling with params: %q %s; %s", path, printOflags(flag), perm) 123 124 defer func() { 125 l("returned results: %T %+v %s", f1, f1, e1) 126 }() 127 fl, errno := d.base.OpenFile(path, flag, perm) 128 return fileWithLog{ 129 base: fl, 130 stdlog: d.stdlog, 131 writeBytes: d.writeBytes, 132 name: path, 133 fsName: d.fsName, 134 }, errno 135 } 136 137 // Readlink implements sys.FS 138 func (d fsWithLog) Readlink(path string) (s1 string, e1 expsys.Errno) { 139 l := d.log("Readlink") 140 l("calling with params: %q", path) 141 142 defer func() { 143 l("returned results: %q %s", s1, e1) 144 }() 145 return d.base.Readlink(path) 146 } 147 148 // Rename implements sys.FS 149 func (d fsWithLog) Rename(from string, to string) (e1 expsys.Errno) { 150 l := d.log("Rename") 151 l("calling with params: %q %q", from, to) 152 153 defer func() { 154 l("returned results: %s", e1) 155 }() 156 return d.base.Rename(from, to) 157 } 158 159 // Rmdir implements sys.FS 160 func (d fsWithLog) Rmdir(path string) (e1 expsys.Errno) { 161 l := d.log("Rmdir") 162 l("calling with params: %q", path) 163 164 defer func() { 165 l("returned results: %s", e1) 166 }() 167 return d.base.Rmdir(path) 168 } 169 170 // Stat implements sys.FS 171 func (d fsWithLog) Stat(path string) (s1 wasys.Stat_t, e1 expsys.Errno) { 172 l := d.log("Stat") 173 l("calling with params: %q", path) 174 175 defer func() { 176 l("returned results: %s", e1) 177 }() 178 179 return d.base.Stat(path) 180 } 181 182 // Symlink implements sys.FS 183 func (d fsWithLog) Symlink(oldPath string, linkName string) (e1 expsys.Errno) { 184 l := d.log("Symlink") 185 l("calling with params: %q %q", oldPath, linkName) 186 187 defer func() { 188 l("returned results: %s", e1) 189 }() 190 return d.base.Symlink(oldPath, linkName) 191 } 192 193 // Unlink implements sys.FS 194 func (d fsWithLog) Unlink(path string) (e1 expsys.Errno) { 195 l := d.log("Unlink") 196 l("calling with params: %q", path) 197 198 defer func() { 199 l("returned results: %s", e1) 200 }() 201 return d.base.Unlink(path) 202 } 203 204 // Utimens implements sys.FS 205 func (d fsWithLog) Utimens(path string, atim int64, mtim int64) (e1 expsys.Errno) { 206 l := d.log("Symlink") 207 l("calling with params: %q %d %d", path, atim, mtim) 208 209 defer func() { 210 l("returned results: %s", e1) 211 }() 212 return d.base.Utimens(path, atim, mtim) 213 }