github.com/afumu/libc@v0.0.6/libc_linux_arm.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  	"time"
    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/stat"
    17  	"github.com/afumu/libc/sys/types"
    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/x32/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_FCNTL64, 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.Lstat(GoString(pathname), (*unix.Stat_t)(unsafe.Pointer(statbuf))); err != nil {
    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_STAT64, 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_FSTAT64, 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  // void *mremap(void *old_address, size_t old_size, size_t new_size, int flags, ... /* void *new_address */);
   139  func Xmremap(t *TLS, old_address uintptr, old_size, new_size types.Size_t, flags int32, args uintptr) uintptr {
   140  	var arg uintptr
   141  	if args != 0 {
   142  		arg = *(*uintptr)(unsafe.Pointer(args))
   143  	}
   144  	data, _, err := unix.Syscall6(unix.SYS_MREMAP, old_address, uintptr(old_size), uintptr(new_size), uintptr(flags), arg, 0)
   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 *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
   160  func Xmmap(t *TLS, addr uintptr, length types.Size_t, prot, flags, fd int32, offset types.Off_t) uintptr {
   161  	return Xmmap64(t, addr, length, prot, flags, fd, offset)
   162  }
   163  
   164  // void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
   165  func Xmmap64(t *TLS, addr uintptr, length types.Size_t, prot, flags, fd int32, offset types.Off_t) uintptr {
   166  	data, _, err := unix.Syscall6(unix.SYS_MMAP2, addr, uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset>>12))
   167  	if err != 0 {
   168  		if dmesgs {
   169  			dmesg("%v: %v", origin(1), err)
   170  		}
   171  		t.setErrno(err)
   172  		return ^uintptr(0) // (void*)-1
   173  	}
   174  
   175  	if dmesgs {
   176  		dmesg("%v: %#x", origin(1), data)
   177  	}
   178  	return data
   179  }
   180  
   181  // int symlink(const char *target, const char *linkpath);
   182  func Xsymlink(t *TLS, target, linkpath uintptr) int32 {
   183  	if err := unix.Symlink(GoString(target), GoString(linkpath)); err != nil {
   184  		t.setErrno(err)
   185  		return -1
   186  	}
   187  
   188  	if dmesgs {
   189  		dmesg("%v: %q %q: ok", origin(1), GoString(target), GoString(linkpath))
   190  	}
   191  	return 0
   192  }
   193  
   194  // int chmod(const char *pathname, mode_t mode)
   195  func Xchmod(t *TLS, pathname uintptr, mode types.Mode_t) int32 {
   196  	if err := unix.Chmod(GoString(pathname), uint32(mode)); err != nil {
   197  		t.setErrno(err)
   198  		return -1
   199  	}
   200  
   201  	if dmesgs {
   202  		dmesg("%v: %q %#o: ok", origin(1), GoString(pathname), mode)
   203  	}
   204  	return 0
   205  }
   206  
   207  // int ftruncate(int fd, off_t length);
   208  func Xftruncate64(t *TLS, fd int32, length types.Off_t) int32 {
   209  	if _, _, err := unix.Syscall6(unix.SYS_FTRUNCATE64, uintptr(fd), 0, uintptr(length), uintptr(length>>32), 0, 0); err != 0 {
   210  		if dmesgs {
   211  			dmesg("%v: fd %d: %v", origin(1), fd, err)
   212  		}
   213  		t.setErrno(err)
   214  		return -1
   215  	}
   216  
   217  	if dmesgs {
   218  		dmesg("%v: %d %#x: ok", origin(1), fd, length)
   219  	}
   220  	return 0
   221  }
   222  
   223  // off64_t lseek64(int fd, off64_t offset, int whence);
   224  func Xlseek64(t *TLS, fd int32, offset types.Off_t, whence int32) types.Off_t {
   225  	n, err := unix.Seek(int(fd), int64(offset), int(whence))
   226  	if err != nil {
   227  		if dmesgs {
   228  			dmesg("%v: fd %v, off %#x, whence %v: %v", origin(1), fd, offset, whenceStr(whence), err)
   229  		}
   230  		t.setErrno(err)
   231  		return -1
   232  	}
   233  
   234  	if dmesgs {
   235  		dmesg("%v: fd %v, off %#x, whence %v: %#x", origin(1), fd, offset, whenceStr(whence), n)
   236  	}
   237  	return types.Off_t(n)
   238  }
   239  
   240  // int utime(const char *filename, const struct utimbuf *times);
   241  func Xutime(t *TLS, filename, times uintptr) int32 {
   242  	if err := unix.Utime(GoString(filename), (*unix.Utimbuf)(unsafe.Pointer(times))); err != nil {
   243  		t.setErrno(err)
   244  		return -1
   245  	}
   246  
   247  	return 0
   248  }
   249  
   250  // unsigned int alarm(unsigned int seconds);
   251  func Xalarm(t *TLS, seconds uint32) uint32 {
   252  	panic(todo(""))
   253  }
   254  
   255  // int getrlimit(int resource, struct rlimit *rlim);
   256  func Xgetrlimit64(t *TLS, resource int32, rlim uintptr) int32 {
   257  	if err := unix.Getrlimit(int(resource), (*unix.Rlimit)(unsafe.Pointer(rlim))); err != nil {
   258  		t.setErrno(err)
   259  		return -1
   260  	}
   261  
   262  	return 0
   263  }
   264  
   265  // time_t time(time_t *tloc);
   266  func Xtime(t *TLS, tloc uintptr) types.Time_t {
   267  	n := time.Now().UTC().Unix()
   268  	if tloc != 0 {
   269  		*(*types.Time_t)(unsafe.Pointer(tloc)) = types.Time_t(n)
   270  	}
   271  	return types.Time_t(n)
   272  }
   273  
   274  // int utimes(const char *filename, const struct timeval times[2]);
   275  func Xutimes(t *TLS, filename, times uintptr) int32 {
   276  	var tv []unix.Timeval
   277  	if times != 0 {
   278  		tv = make([]unix.Timeval, 2)
   279  		*(*[2]unix.Timeval)(unsafe.Pointer(&tv[0])) = *(*[2]unix.Timeval)(unsafe.Pointer(times))
   280  	}
   281  	if err := unix.Utimes(GoString(filename), tv); err != nil {
   282  		t.setErrno(err)
   283  		return -1
   284  	}
   285  
   286  	if times != 0 {
   287  		*(*[2]unix.Timeval)(unsafe.Pointer(times)) = *(*[2]unix.Timeval)(unsafe.Pointer(&tv[0]))
   288  	}
   289  	if dmesgs {
   290  		dmesg("%v: %q: ok", origin(1), GoString(filename))
   291  	}
   292  	return 0
   293  }
   294  
   295  // int unlink(const char *pathname);
   296  func Xunlink(t *TLS, pathname uintptr) int32 {
   297  	if err := unix.Unlinkat(unix.AT_FDCWD, GoString(pathname), 0); err != nil {
   298  		t.setErrno(err)
   299  		return -1
   300  	}
   301  
   302  	if dmesgs {
   303  		dmesg("%v: %q: ok", origin(1), GoString(pathname))
   304  	}
   305  	return 0
   306  }
   307  
   308  // int access(const char *pathname, int mode);
   309  func Xaccess(t *TLS, pathname uintptr, mode int32) int32 {
   310  	if err := unix.Faccessat(unix.AT_FDCWD, GoString(pathname), uint32(mode), 0); err != nil {
   311  		if dmesgs {
   312  			dmesg("%v: %q: %v", origin(1), GoString(pathname), err)
   313  		}
   314  		t.setErrno(err)
   315  		return -1
   316  	}
   317  
   318  	if dmesgs {
   319  		dmesg("%v: %q %#o: ok", origin(1), GoString(pathname), mode)
   320  	}
   321  	return 0
   322  }
   323  
   324  // int rmdir(const char *pathname);
   325  func Xrmdir(t *TLS, pathname uintptr) int32 {
   326  	if err := unix.Rmdir(GoString(pathname)); err != nil {
   327  		t.setErrno(err)
   328  		return -1
   329  	}
   330  
   331  	if dmesgs {
   332  		dmesg("%v: %q: ok", origin(1), GoString(pathname))
   333  	}
   334  	return 0
   335  }
   336  
   337  // int rename(const char *oldpath, const char *newpath);
   338  func Xrename(t *TLS, oldpath, newpath uintptr) int32 {
   339  	if err := unix.Rename(GoString(oldpath), GoString(newpath)); err != nil {
   340  		t.setErrno(err)
   341  		return -1
   342  	}
   343  
   344  	return 0
   345  }
   346  
   347  // int mknod(const char *pathname, mode_t mode, dev_t dev);
   348  func Xmknod(t *TLS, pathname uintptr, mode types.Mode_t, dev types.Dev_t) int32 {
   349  	panic(todo(""))
   350  }
   351  
   352  // int chown(const char *pathname, uid_t owner, gid_t group);
   353  func Xchown(t *TLS, pathname uintptr, owner types.Uid_t, group types.Gid_t) int32 {
   354  	if err := unix.Chown(GoString(pathname), int(owner), int(group)); err != nil {
   355  		t.setErrno(err)
   356  		return -1
   357  	}
   358  
   359  	return 0
   360  }
   361  
   362  // int link(const char *oldpath, const char *newpath);
   363  func Xlink(t *TLS, oldpath, newpath uintptr) int32 {
   364  	panic(todo(""))
   365  }
   366  
   367  // int pipe(int pipefd[2]);
   368  func Xpipe(t *TLS, pipefd uintptr) int32 {
   369  	if _, _, err := unix.Syscall(unix.SYS_PIPE2, pipefd, 0, 0); err != 0 {
   370  		t.setErrno(err)
   371  		return -1
   372  	}
   373  
   374  	return 0
   375  }
   376  
   377  // int dup2(int oldfd, int newfd);
   378  func Xdup2(t *TLS, oldfd, newfd int32) int32 {
   379  	panic(todo(""))
   380  }
   381  
   382  // ssize_t readlink(const char *restrict path, char *restrict buf, size_t bufsize);
   383  func Xreadlink(t *TLS, path, buf uintptr, bufsize types.Size_t) types.Ssize_t {
   384  	n, err := unix.Readlink(GoString(path), GoBytes(buf, int(bufsize)))
   385  	if err != nil {
   386  		t.setErrno(err)
   387  		return -1
   388  	}
   389  
   390  	return types.Ssize_t(n)
   391  }
   392  
   393  // FILE *fopen64(const char *pathname, const char *mode);
   394  func Xfopen64(t *TLS, pathname, mode uintptr) uintptr {
   395  	m := strings.ReplaceAll(GoString(mode), "b", "")
   396  	var flags int
   397  	switch m {
   398  	case "r":
   399  		flags = os.O_RDONLY
   400  	case "r+":
   401  		flags = os.O_RDWR
   402  	case "w":
   403  		flags = os.O_WRONLY | os.O_CREATE | os.O_TRUNC
   404  	case "w+":
   405  		flags = os.O_RDWR | os.O_CREATE | os.O_TRUNC
   406  	case "a":
   407  		flags = os.O_WRONLY | os.O_CREATE | os.O_APPEND
   408  	case "a+":
   409  		flags = os.O_RDWR | os.O_CREATE | os.O_APPEND
   410  	default:
   411  		panic(m)
   412  	}
   413  	//TODO- flags |= fcntl.O_LARGEFILE
   414  	fd, _, err := unix.Syscall(unix.SYS_OPEN, pathname, uintptr(flags|unix.O_LARGEFILE), 0666)
   415  	if err != 0 {
   416  		t.setErrno(err)
   417  		return 0
   418  	}
   419  
   420  	if p := newFile(t, int32(fd)); p != 0 {
   421  		return p
   422  	}
   423  
   424  	Xclose(t, int32(fd))
   425  	t.setErrno(errno.ENOMEM)
   426  	return 0
   427  }
   428  
   429  // int mkdir(const char *path, mode_t mode);
   430  func Xmkdir(t *TLS, path uintptr, mode types.Mode_t) int32 {
   431  	if err := unix.Mkdir(GoString(path), uint32(mode)); err != nil {
   432  		t.setErrno(err)
   433  		return -1
   434  	}
   435  
   436  	if dmesgs {
   437  		dmesg("%v: %q: ok", origin(1), GoString(path))
   438  	}
   439  	return 0
   440  }
   441  
   442  //TODO- // int sscanf(const char *str, const char *format, ...);
   443  //TODO- func Xsscanf(t *TLS, str, format, va uintptr) int32 {
   444  //TODO- 	r := scanf(strings.NewReader(GoString(str)), format, va)
   445  //TODO- 	// if dmesgs {
   446  //TODO- 	// 	dmesg("%v: %q %q: %d", origin(1), GoString(str), GoString(format), r)
   447  //TODO- 	// }
   448  //TODO- 	return r
   449  //TODO- }