github.com/afumu/libc@v0.0.6/libc_linux_amd64.go (about)

     1  // Copyright 2020 The Libc Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package libc // import "github.com/afumu/libc"
     6  
     7  import (
     8  	"os"
     9  	"strings"
    10  	"unicode"
    11  	"unsafe"
    12  
    13  	"github.com/afumu/libc/errno"
    14  	"github.com/afumu/libc/fcntl"
    15  	"github.com/afumu/libc/signal"
    16  	"github.com/afumu/libc/sys/types"
    17  	"github.com/afumu/libc/wctype"
    18  	"golang.org/x/sys/unix"
    19  )
    20  
    21  // int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
    22  func Xsigaction(t *TLS, signum int32, act, oldact uintptr) int32 {
    23  	// 	musl/arch/x86_64/ksigaction.h
    24  	//
    25  	//	struct k_sigaction {
    26  	//		void (*handler)(int);
    27  	//		unsigned long flags;
    28  	//		void (*restorer)(void);
    29  	//		unsigned mask[2];
    30  	//	};
    31  	type k_sigaction struct {
    32  		handler  uintptr
    33  		flags    ulong
    34  		restorer uintptr
    35  		mask     [2]uint32
    36  	}
    37  
    38  	var kact, koldact uintptr
    39  	if act != 0 {
    40  		sz := int(unsafe.Sizeof(k_sigaction{}))
    41  		kact = t.Alloc(sz)
    42  		defer t.Free(sz)
    43  		*(*k_sigaction)(unsafe.Pointer(kact)) = k_sigaction{
    44  			handler:  (*signal.Sigaction)(unsafe.Pointer(act)).F__sigaction_handler.Fsa_handler,
    45  			flags:    ulong((*signal.Sigaction)(unsafe.Pointer(act)).Fsa_flags),
    46  			restorer: (*signal.Sigaction)(unsafe.Pointer(act)).Fsa_restorer,
    47  		}
    48  		Xmemcpy(t, kact+unsafe.Offsetof(k_sigaction{}.mask), act+unsafe.Offsetof(signal.Sigaction{}.Fsa_mask), types.Size_t(unsafe.Sizeof(k_sigaction{}.mask)))
    49  	}
    50  	if oldact != 0 {
    51  		panic(todo(""))
    52  	}
    53  
    54  	if _, _, err := unix.Syscall6(unix.SYS_RT_SIGACTION, uintptr(signum), kact, koldact, unsafe.Sizeof(k_sigaction{}.mask), 0, 0); err != 0 {
    55  		t.setErrno(err)
    56  		return -1
    57  	}
    58  
    59  	if oldact != 0 {
    60  		panic(todo(""))
    61  	}
    62  
    63  	return 0
    64  }
    65  
    66  // int fcntl(int fd, int cmd, ... /* arg */ );
    67  func Xfcntl64(t *TLS, fd, cmd int32, args uintptr) int32 {
    68  	var arg uintptr
    69  	if args != 0 {
    70  		arg = *(*uintptr)(unsafe.Pointer(args))
    71  	}
    72  	if cmd == fcntl.F_SETFL {
    73  		arg |= unix.O_LARGEFILE
    74  	}
    75  	n, _, err := unix.Syscall(unix.SYS_FCNTL, uintptr(fd), uintptr(cmd), arg)
    76  	if err != 0 {
    77  		// if dmesgs {
    78  		// 	dmesg("%v: fd %v cmd %v", origin(1), fcntlCmdStr(fd), cmd)
    79  		// }
    80  		t.setErrno(err)
    81  		return -1
    82  	}
    83  
    84  	// if dmesgs {
    85  	// 	dmesg("%v: %d %s %#x: %d", origin(1), fd, fcntlCmdStr(cmd), arg, n)
    86  	// }
    87  	return int32(n)
    88  }
    89  
    90  // int lstat(const char *pathname, struct stat *statbuf);
    91  func Xlstat64(t *TLS, pathname, statbuf uintptr) int32 {
    92  	if _, _, err := unix.Syscall(unix.SYS_LSTAT, pathname, statbuf, 0); err != 0 {
    93  		// if dmesgs {
    94  		// 	dmesg("%v: %q: %v", origin(1), GoString(pathname), err)
    95  		// }
    96  		t.setErrno(err)
    97  		return -1
    98  	}
    99  
   100  	// if dmesgs {
   101  	// 	dmesg("%v: %q: ok", origin(1), GoString(pathname))
   102  	// }
   103  	return 0
   104  }
   105  
   106  // int stat(const char *pathname, struct stat *statbuf);
   107  func Xstat64(t *TLS, pathname, statbuf uintptr) int32 {
   108  	if _, _, err := unix.Syscall(unix.SYS_STAT, pathname, statbuf, 0); err != 0 {
   109  		// if dmesgs {
   110  		// 	dmesg("%v: %q: %v", origin(1), GoString(pathname), err)
   111  		// }
   112  		t.setErrno(err)
   113  		return -1
   114  	}
   115  
   116  	// if dmesgs {
   117  	// 	dmesg("%v: %q: ok", origin(1), GoString(pathname))
   118  	// }
   119  	return 0
   120  }
   121  
   122  // int fstat(int fd, struct stat *statbuf);
   123  func Xfstat64(t *TLS, fd int32, statbuf uintptr) int32 {
   124  	if _, _, err := unix.Syscall(unix.SYS_FSTAT, uintptr(fd), statbuf, 0); err != 0 {
   125  		// if dmesgs {
   126  		// 	dmesg("%v: fd %d: %v", origin(1), fd, err)
   127  		// }
   128  		t.setErrno(err)
   129  		return -1
   130  	}
   131  
   132  	// if dmesgs {
   133  	// 	dmesg("%v: %d size %#x: ok\n%+v", origin(1), fd, (*stat.Stat)(unsafe.Pointer(statbuf)).Fst_size, (*stat.Stat)(unsafe.Pointer(statbuf)))
   134  	// }
   135  	return 0
   136  }
   137  
   138  func Xmmap(t *TLS, addr uintptr, length types.Size_t, prot, flags, fd int32, offset types.Off_t) uintptr {
   139  	return Xmmap64(t, addr, length, prot, flags, fd, offset)
   140  }
   141  
   142  // void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
   143  func Xmmap64(t *TLS, addr uintptr, length types.Size_t, prot, flags, fd int32, offset types.Off_t) uintptr {
   144  	data, _, err := unix.Syscall6(unix.SYS_MMAP, addr, uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset))
   145  	if err != 0 {
   146  		// if dmesgs {
   147  		// 	dmesg("%v: %v", origin(1), err)
   148  		// }
   149  		t.setErrno(err)
   150  		return ^uintptr(0) // (void*)-1
   151  	}
   152  
   153  	// if dmesgs {
   154  	// 	dmesg("%v: %#x", origin(1), data)
   155  	// }
   156  	return data
   157  }
   158  
   159  // void *mremap(void *old_address, size_t old_size, size_t new_size, int flags, ... /* void *new_address */);
   160  func Xmremap(t *TLS, old_address uintptr, old_size, new_size types.Size_t, flags int32, args uintptr) uintptr {
   161  	var arg uintptr
   162  	if args != 0 {
   163  		arg = *(*uintptr)(unsafe.Pointer(args))
   164  	}
   165  	data, _, err := unix.Syscall6(unix.SYS_MREMAP, old_address, uintptr(old_size), uintptr(new_size), uintptr(flags), arg, 0)
   166  	if err != 0 {
   167  		// if dmesgs {
   168  		// 	dmesg("%v: %v", origin(1), err)
   169  		// }
   170  		t.setErrno(err)
   171  		return ^uintptr(0) // (void*)-1
   172  	}
   173  
   174  	// if dmesgs {
   175  	// 	dmesg("%v: %#x", origin(1), data)
   176  	// }
   177  	return data
   178  }
   179  
   180  // int ftruncate(int fd, off_t length);
   181  func Xftruncate64(t *TLS, fd int32, length types.Off_t) int32 {
   182  	if _, _, err := unix.Syscall(unix.SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0); err != 0 {
   183  		// if dmesgs {
   184  		// 	dmesg("%v: fd %d: %v", origin(1), fd, err)
   185  		// }
   186  		t.setErrno(err)
   187  		return -1
   188  	}
   189  
   190  	// if dmesgs {
   191  	// 	dmesg("%v: %d %#x: ok", origin(1), fd, length)
   192  	// }
   193  	return 0
   194  }
   195  
   196  // off64_t lseek64(int fd, off64_t offset, int whence);
   197  func Xlseek64(t *TLS, fd int32, offset types.Off_t, whence int32) types.Off_t {
   198  	n, _, err := unix.Syscall(unix.SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
   199  	if err != 0 {
   200  		// if dmesgs {
   201  		// 	dmesg("%v: fd %v, off %#x, whence %v: %v", origin(1), fd, offset, whenceStr(whence), err)
   202  		// }
   203  		t.setErrno(err)
   204  		return -1
   205  	}
   206  
   207  	// if dmesgs {
   208  	// 	dmesg("%v: fd %v, off %#x, whence %v: %#x", origin(1), fd, offset, whenceStr(whence), n)
   209  	// }
   210  	return types.Off_t(n)
   211  }
   212  
   213  // int utime(const char *filename, const struct utimbuf *times);
   214  func Xutime(t *TLS, filename, times uintptr) int32 {
   215  	if _, _, err := unix.Syscall(unix.SYS_UTIME, filename, times, 0); err != 0 {
   216  		t.setErrno(err)
   217  		return -1
   218  	}
   219  
   220  	return 0
   221  }
   222  
   223  // unsigned int alarm(unsigned int seconds);
   224  func Xalarm(t *TLS, seconds uint32) uint32 {
   225  	n, _, err := unix.Syscall(unix.SYS_ALARM, uintptr(seconds), 0, 0)
   226  	if err != 0 {
   227  		panic(todo(""))
   228  	}
   229  
   230  	return uint32(n)
   231  }
   232  
   233  // time_t time(time_t *tloc);
   234  func Xtime(t *TLS, tloc uintptr) types.Time_t {
   235  	n, _, err := unix.Syscall(unix.SYS_TIME, tloc, 0, 0)
   236  	if err != 0 {
   237  		t.setErrno(err)
   238  		return types.Time_t(-1)
   239  	}
   240  
   241  	if tloc != 0 {
   242  		*(*types.Time_t)(unsafe.Pointer(tloc)) = types.Time_t(n)
   243  	}
   244  	return types.Time_t(n)
   245  }
   246  
   247  // int getrlimit(int resource, struct rlimit *rlim);
   248  func Xgetrlimit64(t *TLS, resource int32, rlim uintptr) int32 {
   249  	if _, _, err := unix.Syscall(unix.SYS_GETRLIMIT, uintptr(resource), uintptr(rlim), 0); err != 0 {
   250  		t.setErrno(err)
   251  		return -1
   252  	}
   253  
   254  	return 0
   255  }
   256  
   257  // int mkdir(const char *path, mode_t mode);
   258  func Xmkdir(t *TLS, path uintptr, mode types.Mode_t) int32 {
   259  	if _, _, err := unix.Syscall(unix.SYS_MKDIR, path, uintptr(mode), 0); err != 0 {
   260  		t.setErrno(err)
   261  		return -1
   262  	}
   263  
   264  	// if dmesgs {
   265  	// 	dmesg("%v: %q: ok", origin(1), GoString(path))
   266  	// }
   267  	return 0
   268  }
   269  
   270  // int symlink(const char *target, const char *linkpath);
   271  func Xsymlink(t *TLS, target, linkpath uintptr) int32 {
   272  	if _, _, err := unix.Syscall(unix.SYS_SYMLINK, target, linkpath, 0); err != 0 {
   273  		t.setErrno(err)
   274  		return -1
   275  	}
   276  
   277  	// if dmesgs {
   278  	// 	dmesg("%v: %q %q: ok", origin(1), GoString(target), GoString(linkpath))
   279  	// }
   280  	return 0
   281  }
   282  
   283  // int chmod(const char *pathname, mode_t mode)
   284  func Xchmod(t *TLS, pathname uintptr, mode types.Mode_t) int32 {
   285  	if _, _, err := unix.Syscall(unix.SYS_CHMOD, pathname, uintptr(mode), 0); err != 0 {
   286  		t.setErrno(err)
   287  		return -1
   288  	}
   289  
   290  	// if dmesgs {
   291  	// 	dmesg("%v: %q %#o: ok", origin(1), GoString(pathname), mode)
   292  	// }
   293  	return 0
   294  }
   295  
   296  // int utimes(const char *filename, const struct timeval times[2]);
   297  func Xutimes(t *TLS, filename, times uintptr) int32 {
   298  	if _, _, err := unix.Syscall(unix.SYS_UTIMES, filename, times, 0); err != 0 {
   299  		t.setErrno(err)
   300  		return -1
   301  	}
   302  
   303  	// if dmesgs {
   304  	// 	dmesg("%v: %q: ok", origin(1), GoString(filename))
   305  	// }
   306  	return 0
   307  }
   308  
   309  // int unlink(const char *pathname);
   310  func Xunlink(t *TLS, pathname uintptr) int32 {
   311  	if _, _, err := unix.Syscall(unix.SYS_UNLINK, pathname, 0, 0); err != 0 {
   312  		t.setErrno(err)
   313  		return -1
   314  	}
   315  
   316  	// if dmesgs {
   317  	// 	dmesg("%v: %q: ok", origin(1), GoString(pathname))
   318  	// }
   319  	return 0
   320  }
   321  
   322  // int access(const char *pathname, int mode);
   323  func Xaccess(t *TLS, pathname uintptr, mode int32) int32 {
   324  	if _, _, err := unix.Syscall(unix.SYS_ACCESS, pathname, uintptr(mode), 0); err != 0 {
   325  		// if dmesgs {
   326  		// 	dmesg("%v: %q: %v", origin(1), GoString(pathname), err)
   327  		// }
   328  		t.setErrno(err)
   329  		return -1
   330  	}
   331  
   332  	// if dmesgs {
   333  	// 	dmesg("%v: %q %#o: ok", origin(1), GoString(pathname), mode)
   334  	// }
   335  	return 0
   336  }
   337  
   338  // int rmdir(const char *pathname);
   339  func Xrmdir(t *TLS, pathname uintptr) int32 {
   340  	if _, _, err := unix.Syscall(unix.SYS_RMDIR, pathname, 0, 0); err != 0 {
   341  		t.setErrno(err)
   342  		return -1
   343  	}
   344  
   345  	// if dmesgs {
   346  	// 	dmesg("%v: %q: ok", origin(1), GoString(pathname))
   347  	// }
   348  	return 0
   349  }
   350  
   351  // int rename(const char *oldpath, const char *newpath);
   352  func Xrename(t *TLS, oldpath, newpath uintptr) int32 {
   353  	if _, _, err := unix.Syscall(unix.SYS_RENAME, oldpath, newpath, 0); err != 0 {
   354  		t.setErrno(err)
   355  		return -1
   356  	}
   357  
   358  	return 0
   359  }
   360  
   361  // int mknod(const char *pathname, mode_t mode, dev_t dev);
   362  func Xmknod(t *TLS, pathname uintptr, mode types.Mode_t, dev types.Dev_t) int32 {
   363  	if _, _, err := unix.Syscall(unix.SYS_MKNOD, pathname, uintptr(mode), uintptr(dev)); err != 0 {
   364  		t.setErrno(err)
   365  		return -1
   366  	}
   367  
   368  	return 0
   369  }
   370  
   371  // int chown(const char *pathname, uid_t owner, gid_t group);
   372  func Xchown(t *TLS, pathname uintptr, owner types.Uid_t, group types.Gid_t) int32 {
   373  	if _, _, err := unix.Syscall(unix.SYS_CHOWN, pathname, uintptr(owner), uintptr(group)); err != 0 {
   374  		t.setErrno(err)
   375  		return -1
   376  	}
   377  
   378  	return 0
   379  }
   380  
   381  // int link(const char *oldpath, const char *newpath);
   382  func Xlink(t *TLS, oldpath, newpath uintptr) int32 {
   383  	if _, _, err := unix.Syscall(unix.SYS_LINK, oldpath, newpath, 0); err != 0 {
   384  		t.setErrno(err)
   385  		return -1
   386  	}
   387  
   388  	return 0
   389  }
   390  
   391  // int pipe(int pipefd[2]);
   392  func Xpipe(t *TLS, pipefd uintptr) int32 {
   393  	if _, _, err := unix.Syscall(unix.SYS_PIPE, pipefd, 0, 0); err != 0 {
   394  		t.setErrno(err)
   395  		return -1
   396  	}
   397  
   398  	return 0
   399  }
   400  
   401  // int dup2(int oldfd, int newfd);
   402  func Xdup2(t *TLS, oldfd, newfd int32) int32 {
   403  	n, _, err := unix.Syscall(unix.SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
   404  	if err != 0 {
   405  		t.setErrno(err)
   406  		return -1
   407  	}
   408  
   409  	return int32(n)
   410  }
   411  
   412  // ssize_t readlink(const char *restrict path, char *restrict buf, size_t bufsize);
   413  func Xreadlink(t *TLS, path, buf uintptr, bufsize types.Size_t) types.Ssize_t {
   414  	n, _, err := unix.Syscall(unix.SYS_READLINK, path, buf, uintptr(bufsize))
   415  	if err != 0 {
   416  		t.setErrno(err)
   417  		return -1
   418  	}
   419  
   420  	return types.Ssize_t(n)
   421  }
   422  
   423  // FILE *fopen64(const char *pathname, const char *mode);
   424  func Xfopen64(t *TLS, pathname, mode uintptr) uintptr {
   425  	m := strings.ReplaceAll(GoString(mode), "b", "")
   426  	var flags int
   427  	switch m {
   428  	case "r":
   429  		flags = os.O_RDONLY
   430  	case "r+":
   431  		flags = os.O_RDWR
   432  	case "w":
   433  		flags = os.O_WRONLY | os.O_CREATE | os.O_TRUNC
   434  	case "w+":
   435  		flags = os.O_RDWR | os.O_CREATE | os.O_TRUNC
   436  	case "a":
   437  		flags = os.O_WRONLY | os.O_CREATE | os.O_APPEND
   438  	case "a+":
   439  		flags = os.O_RDWR | os.O_CREATE | os.O_APPEND
   440  	default:
   441  		panic(m)
   442  	}
   443  	//TODO- flags |= fcntl.O_LARGEFILE
   444  	fd, _, err := unix.Syscall(unix.SYS_OPEN, pathname, uintptr(flags|unix.O_LARGEFILE), 0666)
   445  	if err != 0 {
   446  		t.setErrno(err)
   447  		return 0
   448  	}
   449  
   450  	if p := newFile(t, int32(fd)); p != 0 {
   451  		return p
   452  	}
   453  
   454  	Xclose(t, int32(fd))
   455  	t.setErrno(errno.ENOMEM)
   456  	return 0
   457  }
   458  
   459  // int iswspace(wint_t wc);
   460  func Xiswspace(t *TLS, wc wctype.Wint_t) int32 {
   461  	return Bool32(unicode.IsSpace(rune(wc)))
   462  }
   463  
   464  // int iswalnum(wint_t wc);
   465  func Xiswalnum(t *TLS, wc wctype.Wint_t) int32 {
   466  	return Bool32(unicode.IsLetter(rune(wc)) || unicode.IsNumber(rune(wc)))
   467  }