syscall_libc.mx raw

   1  //go:build js || nintendoswitch || wasip1 || wasip2
   2  
   3  package syscall
   4  
   5  import (
   6  	"unsafe"
   7  )
   8  
   9  type sliceHeader struct {
  10  	buf *byte
  11  	len uintptr
  12  	cap uintptr
  13  }
  14  
  15  func Close(fd int) (err error) {
  16  	if libc_close(int32(fd)) < 0 {
  17  		err = getErrno()
  18  	}
  19  	return
  20  }
  21  
  22  func Dup(fd int) (fd2 int, err error) {
  23  	fd2 = int(libc_dup(int32(fd)))
  24  	if fd2 < 0 {
  25  		err = getErrno()
  26  	}
  27  	return
  28  }
  29  
  30  func Write(fd int, p []byte) (n int, err error) {
  31  	buf, count := splitSlice(p)
  32  	n = libc_write(int32(fd), buf, uint(count))
  33  	if n < 0 {
  34  		err = getErrno()
  35  	}
  36  	return
  37  }
  38  
  39  func Read(fd int, p []byte) (n int, err error) {
  40  	buf, count := splitSlice(p)
  41  	n = libc_read(int32(fd), buf, uint(count))
  42  	if n < 0 {
  43  		err = getErrno()
  44  	}
  45  	return
  46  }
  47  
  48  func Pread(fd int, p []byte, offset int64) (n int, err error) {
  49  	buf, count := splitSlice(p)
  50  	n = libc_pread(int32(fd), buf, uint(count), offset)
  51  	if n < 0 {
  52  		err = getErrno()
  53  	}
  54  	return
  55  }
  56  
  57  func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
  58  	buf, count := splitSlice(p)
  59  	n = libc_pwrite(int32(fd), buf, uint(count), offset)
  60  	if n < 0 {
  61  		err = getErrno()
  62  	}
  63  	return
  64  }
  65  
  66  func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
  67  	newoffset = libc_lseek(int32(fd), offset, whence)
  68  	if newoffset < 0 {
  69  		err = getErrno()
  70  	}
  71  	return
  72  }
  73  
  74  func Open(path string, flag int, mode uint32) (fd int, err error) {
  75  	data := cstring(path)
  76  	fd = int(libc_open(&data[0], int32(flag), mode))
  77  	if fd < 0 {
  78  		err = getErrno()
  79  	}
  80  	return
  81  }
  82  
  83  func Fsync(fd int) (err error) {
  84  	if libc_fsync(int32(fd)) < 0 {
  85  		err = getErrno()
  86  	}
  87  	return
  88  }
  89  
  90  func Readlink(path string, p []byte) (n int, err error) {
  91  	data := cstring(path)
  92  	buf, count := splitSlice(p)
  93  	n = libc_readlink(&data[0], buf, uint(count))
  94  	if n < 0 {
  95  		err = getErrno()
  96  	}
  97  	return
  98  }
  99  
 100  func Chdir(path string) (err error) {
 101  	data := cstring(path)
 102  	fail := int(libc_chdir(&data[0]))
 103  	if fail < 0 {
 104  		err = getErrno()
 105  	}
 106  	return
 107  }
 108  
 109  func Mkdir(path string, mode uint32) (err error) {
 110  	data := cstring(path)
 111  	fail := int(libc_mkdir(&data[0], mode))
 112  	if fail < 0 {
 113  		err = getErrno()
 114  	}
 115  	return
 116  }
 117  
 118  func Rmdir(path string) (err error) {
 119  	data := cstring(path)
 120  	fail := int(libc_rmdir(&data[0]))
 121  	if fail < 0 {
 122  		err = getErrno()
 123  	}
 124  	return
 125  }
 126  
 127  func Rename(from, to string) (err error) {
 128  	fromdata := cstring(from)
 129  	todata := cstring(to)
 130  	fail := int(libc_rename(&fromdata[0], &todata[0]))
 131  	if fail < 0 {
 132  		err = getErrno()
 133  	}
 134  	return
 135  }
 136  
 137  func Link(oldname, newname string) (err error) {
 138  	fromdata := cstring(oldname)
 139  	todata := cstring(newname)
 140  	fail := int(libc_link(&fromdata[0], &todata[0]))
 141  	if fail < 0 {
 142  		err = getErrno()
 143  	}
 144  	return
 145  }
 146  
 147  func Symlink(from, to string) (err error) {
 148  	fromdata := cstring(from)
 149  	todata := cstring(to)
 150  	fail := int(libc_symlink(&fromdata[0], &todata[0]))
 151  	if fail < 0 {
 152  		err = getErrno()
 153  	}
 154  	return
 155  }
 156  
 157  func Unlink(path string) (err error) {
 158  	data := cstring(path)
 159  	fail := int(libc_unlink(&data[0]))
 160  	if fail < 0 {
 161  		err = getErrno()
 162  	}
 163  	return
 164  }
 165  
 166  func Chown(path string, uid, gid int) (err error) {
 167  	data := cstring(path)
 168  	fail := int(libc_chown(&data[0], uid, gid))
 169  	if fail < 0 {
 170  		err = getErrno()
 171  	}
 172  	return
 173  }
 174  
 175  func Fork() (err error) {
 176  	fail := int(libc_fork())
 177  	if fail < 0 {
 178  		err = getErrno()
 179  	}
 180  	return
 181  }
 182  
 183  func Execve(pathname string, argv []string, envv []string) (err error) {
 184  	argv0 := cstring(pathname)
 185  
 186  	// transform argv and envv into the format expected by execve
 187  	argv1 := make([]*byte, len(argv)+1)
 188  	for i, arg := range argv {
 189  		argv1[i] = &cstring(arg)[0]
 190  	}
 191  	argv1[len(argv)] = nil
 192  
 193  	env1 := make([]*byte, len(envv)+1)
 194  	for i, env := range envv {
 195  		env1[i] = &cstring(env)[0]
 196  	}
 197  	env1[len(envv)] = nil
 198  
 199  	fail := int(libc_execve(&argv0[0], &argv1[0], &env1[0]))
 200  	if fail < 0 {
 201  		err = getErrno()
 202  	}
 203  	return
 204  }
 205  
 206  func Truncate(path string, length int64) (err error) {
 207  	data := cstring(path)
 208  	fail := int(libc_truncate(&data[0], length))
 209  	if fail < 0 {
 210  		err = getErrno()
 211  	}
 212  	return
 213  }
 214  
 215  func Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
 216  
 217  func Kill(pid int, sig Signal) (err error) {
 218  	return ENOSYS // TODO
 219  }
 220  
 221  type SysProcAttr struct{}
 222  
 223  // TODO
 224  type WaitStatus uint32
 225  
 226  func (w WaitStatus) Exited() bool       { return false }
 227  func (w WaitStatus) ExitStatus() int    { return 0 }
 228  func (w WaitStatus) Signaled() bool     { return false }
 229  func (w WaitStatus) Signal() Signal     { return 0 }
 230  func (w WaitStatus) CoreDump() bool     { return false }
 231  func (w WaitStatus) Stopped() bool      { return false }
 232  func (w WaitStatus) Continued() bool    { return false }
 233  func (w WaitStatus) StopSignal() Signal { return 0 }
 234  func (w WaitStatus) TrapCause() int     { return 0 }
 235  
 236  // Purely here for compatibility.
 237  type Rusage struct {
 238  }
 239  
 240  // since rusage is quite a big struct and we stub it out anyway no need to define it here
 241  func Wait4(pid int, wstatus *WaitStatus, options int, rusage uintptr) (wpid int, err error) {
 242  	return 0, ENOSYS // TODO
 243  }
 244  
 245  func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
 246  	addr := libc_mmap(nil, uintptr(length), int32(prot), int32(flags), int32(fd), uintptr(offset))
 247  	if addr == unsafe.Pointer(^uintptr(0)) {
 248  		return nil, getErrno()
 249  	}
 250  	return (*[1 << 30]byte)(addr)[:length:length], nil
 251  }
 252  
 253  func Munmap(b []byte) (err error) {
 254  	errCode := libc_munmap(unsafe.Pointer(&b[0]), uintptr(len(b)))
 255  	if errCode != 0 {
 256  		err = getErrno()
 257  	}
 258  	return err
 259  }
 260  
 261  func Mprotect(b []byte, prot int) (err error) {
 262  	errCode := libc_mprotect(unsafe.Pointer(&b[0]), uintptr(len(b)), int32(prot))
 263  	if errCode != 0 {
 264  		err = getErrno()
 265  	}
 266  	return
 267  }
 268  
 269  // BytePtrFromString returns a pointer to a NUL-terminated array of
 270  // bytes containing the text of s. If s contains a NUL byte at any
 271  // location, it returns (nil, EINVAL).
 272  func BytePtrFromString(s string) (*byte, error) {
 273  	for i := 0; i < len(s); i++ {
 274  		if s[i] == 0 {
 275  			return nil, EINVAL
 276  		}
 277  	}
 278  	return &cstring(s)[0], nil
 279  }
 280  
 281  // cstring converts a Go string to a C string.
 282  func cstring(s string) []byte {
 283  	data := make([]byte, len(s)+1)
 284  	copy(data, s)
 285  	// final byte should be zero from the initial allocation
 286  	return data
 287  }
 288  
 289  func splitSlice(p []byte) (buf *byte, len uintptr) {
 290  	slice := (*sliceHeader)(unsafe.Pointer(&p))
 291  	return slice.buf, slice.len
 292  }
 293  
 294  // These two functions are provided by the runtime.
 295  func runtimeSetenv(key, value string)
 296  func runtimeUnsetenv(key string)
 297  
 298  //export strlen
 299  func libc_strlen(ptr unsafe.Pointer) uintptr
 300  
 301  // ssize_t write(int fd, const void *buf, size_t count)
 302  //
 303  //export write
 304  func libc_write(fd int32, buf *byte, count uint) int
 305  
 306  // char *getenv(const char *name);
 307  //
 308  //export getenv
 309  func libc_getenv(name *byte) *byte
 310  
 311  // ssize_t read(int fd, void *buf, size_t count);
 312  //
 313  //export read
 314  func libc_read(fd int32, buf *byte, count uint) int
 315  
 316  // ssize_t pread(int fd, void *buf, size_t count, off_t offset);
 317  //
 318  //export pread
 319  func libc_pread(fd int32, buf *byte, count uint, offset int64) int
 320  
 321  // ssize_t pwrite(int fd, void *buf, size_t count, off_t offset);
 322  //
 323  //export pwrite
 324  func libc_pwrite(fd int32, buf *byte, count uint, offset int64) int
 325  
 326  // ssize_t lseek(int fd, off_t offset, int whence);
 327  //
 328  //export lseek
 329  func libc_lseek(fd int32, offset int64, whence int) int64
 330  
 331  // int close(int fd)
 332  //
 333  //export close
 334  func libc_close(fd int32) int32
 335  
 336  // int dup(int fd)
 337  //
 338  //export dup
 339  func libc_dup(fd int32) int32
 340  
 341  // void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
 342  //
 343  //export mmap
 344  func libc_mmap(addr unsafe.Pointer, length uintptr, prot, flags, fd int32, offset uintptr) unsafe.Pointer
 345  
 346  // int munmap(void *addr, size_t length);
 347  //
 348  //export munmap
 349  func libc_munmap(addr unsafe.Pointer, length uintptr) int32
 350  
 351  // int mprotect(void *addr, size_t len, int prot);
 352  //
 353  //export mprotect
 354  func libc_mprotect(addr unsafe.Pointer, len uintptr, prot int32) int32
 355  
 356  // int chdir(const char *pathname, mode_t mode);
 357  //
 358  //export chdir
 359  func libc_chdir(pathname *byte) int32
 360  
 361  // int chmod(const char *pathname, mode_t mode);
 362  //
 363  //export chmod
 364  func libc_chmod(pathname *byte, mode uint32) int32
 365  
 366  // int chown(const char *pathname, uid_t owner, gid_t group);
 367  //
 368  //export chown
 369  func libc_chown(pathname *byte, owner, group int) int32
 370  
 371  // int mkdir(const char *pathname, mode_t mode);
 372  //
 373  //export mkdir
 374  func libc_mkdir(pathname *byte, mode uint32) int32
 375  
 376  // int rmdir(const char *pathname);
 377  //
 378  //export rmdir
 379  func libc_rmdir(pathname *byte) int32
 380  
 381  // int rename(const char *from, *to);
 382  //
 383  //export rename
 384  func libc_rename(from, to *byte) int32
 385  
 386  // int symlink(const char *from, *to);
 387  //
 388  //export symlink
 389  func libc_symlink(from, to *byte) int32
 390  
 391  // int link(const char *oldname, *newname);
 392  //
 393  //export link
 394  func libc_link(oldname, newname *byte) int32
 395  
 396  // int fsync(int fd);
 397  //
 398  //export fsync
 399  func libc_fsync(fd int32) int32
 400  
 401  // ssize_t readlink(const char *path, void *buf, size_t count);
 402  //
 403  //export readlink
 404  func libc_readlink(path *byte, buf *byte, count uint) int
 405  
 406  // int unlink(const char *pathname);
 407  //
 408  //export unlink
 409  func libc_unlink(pathname *byte) int32
 410  
 411  // pid_t fork(void);
 412  //
 413  //export fork
 414  func libc_fork() int32
 415  
 416  // int execve(const char *filename, char *const argv[], char *const envp[]);
 417  //
 418  //export execve
 419  func libc_execve(filename *byte, argv **byte, envp **byte) int
 420  
 421  // int truncate(const char *path, off_t length);
 422  //
 423  //export truncate
 424  func libc_truncate(path *byte, length int64) int32
 425