github.com/primecitizens/pcz/std@v0.2.1/ffi/wasm/wasi/00-types.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright 2023 The Prime Citizens 3 // 4 // Copyright 2023 The Go Authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file. 7 8 //go:build wasip1 9 10 package wasi 11 12 import ( 13 "unsafe" 14 15 "github.com/primecitizens/pcz/std/io" 16 ) 17 18 // An Errno is an unsigned number describing an error condition. 19 // The zero Errno is by convention a non-error. 20 type Errno uint32 21 22 func (e Errno) Temporary() bool { 23 return e == EINTR || e == EMFILE || e.Timeout() 24 } 25 26 func (e Errno) Timeout() bool { 27 return e == EAGAIN || e == ETIMEDOUT 28 } 29 30 const ( 31 E2BIG Errno = 1 32 EACCES Errno = 2 33 EADDRINUSE Errno = 3 34 EADDRNOTAVAIL Errno = 4 35 EAFNOSUPPORT Errno = 5 36 EAGAIN Errno = 6 37 EALREADY Errno = 7 38 EBADF Errno = 8 39 EBADMSG Errno = 9 40 EBUSY Errno = 10 41 ECANCELED Errno = 11 42 ECHILD Errno = 12 43 ECONNABORTED Errno = 13 44 ECONNREFUSED Errno = 14 45 ECONNRESET Errno = 15 46 EDEADLK Errno = 16 47 EDESTADDRREQ Errno = 17 48 EDOM Errno = 18 49 EDQUOT Errno = 19 50 EEXIST Errno = 20 51 EFAULT Errno = 21 52 EFBIG Errno = 22 53 EHOSTUNREACH Errno = 23 54 EIDRM Errno = 24 55 EILSEQ Errno = 25 56 EINPROGRESS Errno = 26 57 EINTR Errno = 27 58 EINVAL Errno = 28 59 EIO Errno = 29 60 EISCONN Errno = 30 61 EISDIR Errno = 31 62 ELOOP Errno = 32 63 EMFILE Errno = 33 64 EMLINK Errno = 34 65 EMSGSIZE Errno = 35 66 EMULTIHOP Errno = 36 67 ENAMETOOLONG Errno = 37 68 ENETDOWN Errno = 38 69 ENETRESET Errno = 39 70 ENETUNREACH Errno = 40 71 ENFILE Errno = 41 72 ENOBUFS Errno = 42 73 ENODEV Errno = 43 74 ENOENT Errno = 44 75 ENOEXEC Errno = 45 76 ENOLCK Errno = 46 77 ENOLINK Errno = 47 78 ENOMEM Errno = 48 79 ENOMSG Errno = 49 80 ENOPROTOOPT Errno = 50 81 ENOSPC Errno = 51 82 ENOSYS Errno = 52 83 ENOTCONN Errno = 53 84 ENOTDIR Errno = 54 85 ENOTEMPTY Errno = 55 86 ENOTRECOVERABLE Errno = 56 87 ENOTSOCK Errno = 57 88 ENOTSUP Errno = 58 89 ENOTTY Errno = 59 90 ENXIO Errno = 60 91 EOVERFLOW Errno = 61 92 EOWNERDEAD Errno = 62 93 EPERM Errno = 63 94 EPIPE Errno = 64 95 EPROTO Errno = 65 96 EPROTONOSUPPORT Errno = 66 97 EPROTOTYPE Errno = 67 98 ERANGE Errno = 68 99 EROFS Errno = 69 100 ESPIPE Errno = 70 101 ESRCH Errno = 71 102 ESTALE Errno = 72 103 ETIMEDOUT Errno = 73 104 ETXTBSY Errno = 74 105 EXDEV Errno = 75 106 ENOTCAPABLE Errno = 76 107 ) 108 109 func (errno Errno) IOErr() io.Status { 110 if errno == 0 { 111 return io.StatusOK 112 } 113 114 switch errno { 115 case ENOTDIR: 116 return io.StatusNotDir 117 case ENOTSUP: 118 return io.StatusUnsupported 119 default: 120 return io.StatusUnkown 121 } 122 } 123 124 type ( 125 FD int32 126 uintptr32 = uint32 127 Size uint32 128 FDflags uint32 129 Filesize uint64 130 Filetype uint8 131 LookupFlags uint32 132 OFlags uint32 133 Rights uint64 134 Timestamp uint64 135 Dircookie uint64 136 FileDelta int64 137 FstFlags uint32 138 ) 139 140 func Uintptr(p unsafe.Pointer) uintptr32 { 141 return uintptr32(uintptr(p)) 142 } 143 144 type IOBuffer struct { 145 Ptr uintptr32 146 Len Size 147 } 148 149 const ( 150 LOOKUP_SYMLINK_FOLLOW LookupFlags = 0x00000001 151 ) 152 153 const ( 154 OFlag_CREAT OFlags = 0x0001 // Create file if it does not exist. 155 OFlag_DIRECTORY OFlags = 0x0002 // Fail if not a directory. 156 OFlag_EXCL OFlags = 0x0004 // Fail if file already exists. 157 OFlag_TRUNC OFlags = 0x0008 // Truncate file to size 0. 158 ) 159 160 const ( 161 FDflag_APPEND FDflags = 0x0001 // 162 FDflag_DSYNC FDflags = 0x0002 // 163 FDflag_NONBLOCK FDflags = 0x0004 // 164 FDflag_RSYNC FDflags = 0x0008 // 165 FDflag_SYNC FDflags = 0x0010 // 166 ) 167 168 const ( 169 Right_FD_DATASYNC Rights = 1 << iota // 170 Right_FD_READ // 171 Right_FD_SEEK // 172 Right_FDSTAT_SET_FLAGS // 173 Right_FD_SYNC // 174 Right_FD_TELL // 175 Right_FD_WRITE // 176 Right_FD_ADVISE // 177 Right_FD_ALLOCATE // 178 Right_PATH_CREATE_DIRECTORY // 179 Right_PATH_CREATE_FILE // 180 Right_PATH_LINK_SOURCE // 181 Right_PATH_LINK_TARGET // 182 Right_PATH_OPEN // 183 Right_FD_READDIR // 184 Right_PATH_READLINK // 185 Right_PATH_RENAME_SOURCE // 186 Right_PATH_RENAME_TARGET // 187 Right_PATH_FILESTAT_GET // 188 Right_PATH_FILESTAT_SET_SIZE // 189 Right_PATH_FILESTAT_SET_TIMES // 190 Right_FD_FILESTAT_GET // 191 Right_FD_FILESTAT_SET_SIZE // 192 Right_FD_FILESTAT_SET_TIMES // 193 Right_PATH_SYMLINK // 194 Right_PATH_REMOVE_DIRECTORY // 195 Right_PATH_UNLINK_FILE // 196 Right_POLL_FD_READWRITE // 197 Right_SOCK_SHUTDOWN // 198 Right_SOCK_ACCEPT // 199 ) 200 201 const ( 202 WHENCE_SET = 0 203 WHENCE_CUR = 1 204 WHENCE_END = 2 205 ) 206 207 const ( 208 FILESTAT_SET_ATIM = 0x0001 209 FILESTAT_SET_ATIM_NOW = 0x0002 210 FILESTAT_SET_MTIM = 0x0004 211 FILESTAT_SET_MTIM_NOW = 0x0008 212 ) 213 214 const ( 215 // Despite the rights being defined as a 64 bits integer in the spec, 216 // wasmtime crashes the program if we set any of the upper 32 bits. 217 FullRights Rights = ^Rights(0) 218 ReadRights Rights = Right_FD_READ | Right_FD_READDIR 219 WriteRights Rights = Right_FD_DATASYNC | Right_FD_WRITE | Right_FD_ALLOCATE | Right_PATH_FILESTAT_SET_SIZE 220 221 // Some runtimes have very strict expectations when it comes to which 222 // rights can be enabled on files opened by path_open. The fileRights 223 // constant is used as a mask to retain only bits for operations that 224 // are supported on files. 225 FileRights Rights = 0 | 226 Right_FD_DATASYNC | 227 Right_FD_READ | 228 Right_FD_SEEK | 229 Right_FDSTAT_SET_FLAGS | 230 Right_FD_SYNC | 231 Right_FD_TELL | 232 Right_FD_WRITE | 233 Right_FD_ADVISE | 234 Right_FD_ALLOCATE | 235 Right_PATH_CREATE_DIRECTORY | 236 Right_PATH_CREATE_FILE | 237 Right_PATH_LINK_SOURCE | 238 Right_PATH_LINK_TARGET | 239 Right_PATH_OPEN | 240 Right_FD_READDIR | 241 Right_PATH_READLINK | 242 Right_PATH_RENAME_SOURCE | 243 Right_PATH_RENAME_TARGET | 244 Right_PATH_FILESTAT_GET | 245 Right_PATH_FILESTAT_SET_SIZE | 246 Right_PATH_FILESTAT_SET_TIMES | 247 Right_FD_FILESTAT_GET | 248 Right_FD_FILESTAT_SET_SIZE | 249 Right_FD_FILESTAT_SET_TIMES | 250 Right_PATH_SYMLINK | 251 Right_PATH_REMOVE_DIRECTORY | 252 Right_PATH_UNLINK_FILE | 253 Right_POLL_FD_READWRITE | 254 0 255 256 // Runtimes like wasmtime and wasmedge will refuse to open directories 257 // if the rights requested by the application exceed the operations that 258 // can be performed on a directory. 259 DirRights Rights = 0 | 260 Right_FD_SEEK | 261 Right_FDSTAT_SET_FLAGS | 262 Right_FD_SYNC | 263 Right_PATH_CREATE_DIRECTORY | 264 Right_PATH_CREATE_FILE | 265 Right_PATH_LINK_SOURCE | 266 Right_PATH_LINK_TARGET | 267 Right_PATH_OPEN | 268 Right_FD_READDIR | 269 Right_PATH_READLINK | 270 Right_PATH_RENAME_SOURCE | 271 Right_PATH_RENAME_TARGET | 272 Right_PATH_FILESTAT_GET | 273 Right_PATH_FILESTAT_SET_SIZE | 274 Right_PATH_FILESTAT_SET_TIMES | 275 Right_FD_FILESTAT_GET | 276 Right_FD_FILESTAT_SET_TIMES | 277 Right_PATH_SYMLINK | 278 Right_PATH_REMOVE_DIRECTORY | 279 Right_PATH_UNLINK_FILE | 280 0 281 ) 282 283 const ( 284 Filetype_UNKNOWN Filetype = iota 285 Filetype_BLOCK_DEVICE // 286 Filetype_CHARACTER_DEVICE // 287 Filetype_DIRECTORY // 288 Filetype_REGULAR_FILE // 289 Filetype_SOCKET_DGRAM // 290 Filetype_SOCKET_STREAM // 291 Filetype_SYMBOLIC_LINK // 292 ) 293 294 const ( 295 Stdin FD = 0 296 Stdout FD = 1 297 Stderr FD = 2 298 ) 299 300 // func init() { 301 // dirNameBuf := make([]byte, 256) 302 // // We start looking for preopens at fd=3 because 0, 1, and 2 are reserved 303 // // for standard input and outputs. 304 // for preopenFd := int32(3); ; preopenFd++ { 305 // var prestat prestat 306 // 307 // errno := fd_prestat_get(preopenFd, unsafe.Pointer(&prestat)) 308 // if errno == EBADF { 309 // break 310 // } 311 // if errno == ENOTDIR || prestat.typ != preopentypeDir { 312 // continue 313 // } 314 // if errno != 0 { 315 // panic("fd_prestat: " + errno.Error()) 316 // } 317 // if int(prestat.dir.prNameLen) > len(dirNameBuf) { 318 // dirNameBuf = make([]byte, prestat.dir.prNameLen) 319 // } 320 // 321 // errno = fd_prestat_dir_name(preopenFd, unsafe.Pointer(&dirNameBuf[0]), prestat.dir.prNameLen) 322 // if errno != 0 { 323 // panic("fd_prestat_dir_name: " + errno.Error()) 324 // } 325 // 326 // preopens = append(preopens, opendir{ 327 // fd: preopenFd, 328 // name: string(dirNameBuf[:prestat.dir.prNameLen]), 329 // }) 330 // } 331 // 332 // if cwd, _ = Getenv("PWD"); cwd != "" { 333 // cwd = joinPath("/", cwd) 334 // } else if len(preopens) > 0 { 335 // cwd = preopens[0].name 336 // } 337 // } 338 // 339 // //go:nosplit 340 // func appendCleanPath(buf []byte, path string, lookupParent bool) ([]byte, bool) { 341 // i := 0 342 // for i < len(path) { 343 // for i < len(path) && path[i] == '/' { 344 // i++ 345 // } 346 // 347 // j := i 348 // for j < len(path) && path[j] != '/' { 349 // j++ 350 // } 351 // 352 // s := path[i:j] 353 // i = j 354 // 355 // switch s { 356 // case "": 357 // continue 358 // case ".": 359 // continue 360 // case "..": 361 // if !lookupParent { 362 // k := len(buf) 363 // for k > 0 && buf[k-1] != '/' { 364 // k-- 365 // } 366 // for k > 1 && buf[k-1] == '/' { 367 // k-- 368 // } 369 // buf = buf[:k] 370 // if k == 0 { 371 // lookupParent = true 372 // } else { 373 // s = "" 374 // continue 375 // } 376 // } 377 // default: 378 // lookupParent = false 379 // } 380 // 381 // if len(buf) > 0 && buf[len(buf)-1] != '/' { 382 // buf = append(buf, '/') 383 // } 384 // buf = append(buf, s...) 385 // } 386 // return buf, lookupParent 387 // } 388 // 389 390 // // preparePath returns the preopen file descriptor of the directory to perform 391 // // path resolution from, along with the pair of pointer and length for the 392 // // relative expression of path from the directory. 393 // // 394 // // If the path argument is not absolute, it is first appended to the current 395 // // working directory before resolution. 396 // func preparePath(path string) (int32, unsafe.Pointer, Size) { 397 // var dirFd = int32(-1) 398 // var dirName string 399 // 400 // dir := "/" 401 // if !isAbs(path) { 402 // dir = cwd 403 // } 404 // path = joinPath(dir, path) 405 // 406 // for _, p := range preopens { 407 // if len(p.name) > len(dirName) && hasPrefix(path, p.name) { 408 // dirFd, dirName = p.fd, p.name 409 // } 410 // } 411 // 412 // path = path[len(dirName):] 413 // for isAbs(path) { 414 // path = path[1:] 415 // } 416 // if len(path) == 0 { 417 // path = "." 418 // } 419 // 420 // return dirFd, stringPointer(path), Size(len(path)) 421 // }