modernc.org/libc@v1.24.1/libc_linux_386.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 "modernc.org/libc"
     6  
     7  import (
     8  	"os"
     9  	"strings"
    10  	"unsafe"
    11  
    12  	"golang.org/x/sys/unix"
    13  	"modernc.org/libc/errno"
    14  	"modernc.org/libc/fcntl"
    15  	"modernc.org/libc/signal"
    16  	"modernc.org/libc/sys/stat"
    17  	"modernc.org/libc/sys/types"
    18  )
    19  
    20  // int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
    21  func Xsigaction(t *TLS, signum int32, act, oldact uintptr) int32 {
    22  	// 	musl/arch/x32/ksigaction.h
    23  	//
    24  	//	struct k_sigaction {
    25  	//		void (*handler)(int);
    26  	//		unsigned long flags;
    27  	//		void (*restorer)(void);
    28  	//		unsigned mask[2];
    29  	//	};
    30  	type k_sigaction struct {
    31  		handler  uintptr
    32  		flags    ulong
    33  		restorer uintptr
    34  		mask     [2]uint32
    35  	}
    36  
    37  	var kact, koldact uintptr
    38  	if act != 0 {
    39  		sz := int(unsafe.Sizeof(k_sigaction{}))
    40  		kact = t.Alloc(sz)
    41  		defer t.Free(sz)
    42  		*(*k_sigaction)(unsafe.Pointer(kact)) = k_sigaction{
    43  			handler:  (*signal.Sigaction)(unsafe.Pointer(act)).F__sigaction_handler.Fsa_handler,
    44  			flags:    ulong((*signal.Sigaction)(unsafe.Pointer(act)).Fsa_flags),
    45  			restorer: (*signal.Sigaction)(unsafe.Pointer(act)).Fsa_restorer,
    46  		}
    47  		Xmemcpy(t, kact+unsafe.Offsetof(k_sigaction{}.mask), act+unsafe.Offsetof(signal.Sigaction{}.Fsa_mask), types.Size_t(unsafe.Sizeof(k_sigaction{}.mask)))
    48  	}
    49  	if oldact != 0 {
    50  		panic(todo(""))
    51  	}
    52  
    53  	if _, _, err := unix.Syscall6(unix.SYS_RT_SIGACTION, uintptr(signum), kact, koldact, unsafe.Sizeof(k_sigaction{}.mask), 0, 0); err != 0 {
    54  		t.setErrno(err)
    55  		return -1
    56  	}
    57  
    58  	if oldact != 0 {
    59  		panic(todo(""))
    60  	}
    61  
    62  	return 0
    63  }
    64  
    65  // int fcntl(int fd, int cmd, ... /* arg */ );
    66  func Xfcntl64(t *TLS, fd, cmd int32, args uintptr) int32 {
    67  	var arg uintptr
    68  	if args != 0 {
    69  		arg = *(*uintptr)(unsafe.Pointer(args))
    70  	}
    71  	if cmd == fcntl.F_SETFL {
    72  		arg |= unix.O_LARGEFILE
    73  	}
    74  	n, _, err := unix.Syscall(unix.SYS_FCNTL64, uintptr(fd), uintptr(cmd), arg)
    75  	if err != 0 {
    76  		if dmesgs {
    77  			dmesg("%v: fd %v cmd %v", origin(1), fcntlCmdStr(fd), cmd)
    78  		}
    79  		t.setErrno(err)
    80  		return -1
    81  	}
    82  
    83  	if dmesgs {
    84  		dmesg("%v: %d %s %#x: %d", origin(1), fd, fcntlCmdStr(cmd), arg, n)
    85  	}
    86  	return int32(n)
    87  }
    88  
    89  // int lstat(const char *pathname, struct stat *statbuf);
    90  func Xlstat64(t *TLS, pathname, statbuf uintptr) int32 {
    91  	if _, _, err := unix.Syscall(unix.SYS_LSTAT64, pathname, statbuf, 0); err != 0 {
    92  		if dmesgs {
    93  			dmesg("%v: %q: %v", origin(1), GoString(pathname), err)
    94  		}
    95  		t.setErrno(err)
    96  		return -1
    97  	}
    98  
    99  	if dmesgs {
   100  		dmesg("%v: %q: ok", origin(1), GoString(pathname))
   101  	}
   102  	return 0
   103  }
   104  
   105  // int stat(const char *pathname, struct stat *statbuf);
   106  func Xstat64(t *TLS, pathname, statbuf uintptr) int32 {
   107  	if _, _, err := unix.Syscall(unix.SYS_STAT64, pathname, statbuf, 0); err != 0 {
   108  		if dmesgs {
   109  			dmesg("%v: %q: %v", origin(1), GoString(pathname), err)
   110  		}
   111  		t.setErrno(err)
   112  		return -1
   113  	}
   114  
   115  	if dmesgs {
   116  		dmesg("%v: %q: ok", origin(1), GoString(pathname))
   117  	}
   118  	return 0
   119  }
   120  
   121  // int fstat(int fd, struct stat *statbuf);
   122  func Xfstat64(t *TLS, fd int32, statbuf uintptr) int32 {
   123  	if _, _, err := unix.Syscall(unix.SYS_FSTAT64, uintptr(fd), statbuf, 0); err != 0 {
   124  		if dmesgs {
   125  			dmesg("%v: fd %d: %v", origin(1), fd, err)
   126  		}
   127  		t.setErrno(err)
   128  		return -1
   129  	}
   130  
   131  	if dmesgs {
   132  		dmesg("%v: %d, size %#x: ok\n%+v", origin(1), fd, (*stat.Stat)(unsafe.Pointer(statbuf)).Fst_size, (*stat.Stat)(unsafe.Pointer(statbuf)))
   133  	}
   134  	return 0
   135  }
   136  
   137  // void *mremap(void *old_address, size_t old_size, size_t new_size, int flags, ... /* void *new_address */);
   138  func Xmremap(t *TLS, old_address uintptr, old_size, new_size types.Size_t, flags int32, args uintptr) uintptr {
   139  	var arg uintptr
   140  	if args != 0 {
   141  		arg = *(*uintptr)(unsafe.Pointer(args))
   142  	}
   143  	data, _, err := unix.Syscall6(unix.SYS_MREMAP, old_address, uintptr(old_size), uintptr(new_size), uintptr(flags), arg, 0)
   144  	if err != 0 {
   145  		if dmesgs {
   146  			dmesg("%v: %v", origin(1), err)
   147  		}
   148  		t.setErrno(err)
   149  		return ^uintptr(0) // (void*)-1
   150  	}
   151  
   152  	if dmesgs {
   153  		dmesg("%v: %#x", origin(1), data)
   154  	}
   155  	return data
   156  }
   157  
   158  func Xmmap(t *TLS, addr uintptr, length types.Size_t, prot, flags, fd int32, offset types.Off_t) uintptr {
   159  	return Xmmap64(t, addr, length, prot, flags, fd, offset)
   160  }
   161  
   162  // void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
   163  func Xmmap64(t *TLS, addr uintptr, length types.Size_t, prot, flags, fd int32, offset types.Off_t) uintptr {
   164  	data, _, err := unix.Syscall6(unix.SYS_MMAP2, addr, uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset>>12))
   165  	if err != 0 {
   166  		if dmesgs {
   167  			dmesg("%v: %v", origin(1), err)
   168  		}
   169  		t.setErrno(err)
   170  		return ^uintptr(0) // (void*)-1
   171  	}
   172  
   173  	if dmesgs {
   174  		dmesg("%v: %#x", origin(1), data)
   175  	}
   176  	return data
   177  }
   178  
   179  // int ftruncate(int fd, off_t length);
   180  func Xftruncate64(t *TLS, fd int32, length types.Off_t) int32 {
   181  	if _, _, err := unix.Syscall(unix.SYS_FTRUNCATE64, uintptr(fd), uintptr(length), uintptr(length>>32)); err != 0 {
   182  		if dmesgs {
   183  			dmesg("%v: fd %d: %v", origin(1), fd, err)
   184  		}
   185  		t.setErrno(err)
   186  		return -1
   187  	}
   188  
   189  	if dmesgs {
   190  		dmesg("%v: %d %#x: ok", origin(1), fd, length)
   191  	}
   192  	return 0
   193  }
   194  
   195  // off64_t lseek64(int fd, off64_t offset, int whence);
   196  func Xlseek64(t *TLS, fd int32, offset types.Off_t, whence int32) types.Off_t {
   197  	bp := t.Alloc(int(unsafe.Sizeof(types.X__loff_t(0))))
   198  	defer t.Free(int(unsafe.Sizeof(types.X__loff_t(0))))
   199  	if _, _, err := unix.Syscall6(unix.SYS__LLSEEK, uintptr(fd), uintptr(offset>>32), uintptr(offset), bp, uintptr(whence), 0); 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), *(*types.Off_t)(unsafe.Pointer(bp)))
   209  	}
   210  	return *(*types.Off_t)(unsafe.Pointer(bp))
   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  // int getrlimit(int resource, struct rlimit *rlim);
   234  func Xgetrlimit64(t *TLS, resource int32, rlim uintptr) int32 {
   235  	if _, _, err := unix.Syscall(unix.SYS_GETRLIMIT, uintptr(resource), uintptr(rlim), 0); err != 0 {
   236  		t.setErrno(err)
   237  		return -1
   238  	}
   239  
   240  	return 0
   241  }
   242  
   243  // time_t time(time_t *tloc);
   244  func Xtime(t *TLS, tloc uintptr) types.Time_t {
   245  	n, _, err := unix.Syscall(unix.SYS_TIME, tloc, 0, 0)
   246  	if err != 0 {
   247  		t.setErrno(err)
   248  		return types.Time_t(-1)
   249  	}
   250  
   251  	if tloc != 0 {
   252  		*(*types.Time_t)(unsafe.Pointer(tloc)) = types.Time_t(n)
   253  	}
   254  	return types.Time_t(n)
   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 setrlimit(int resource, const struct rlimit *rlim);
   460  func Xsetrlimit64(t *TLS, resource int32, rlim uintptr) int32 {
   461  	if _, _, err := unix.Syscall(unix.SYS_SETRLIMIT, uintptr(resource), uintptr(rlim), 0); err != 0 {
   462  		t.setErrno(err)
   463  		return -1
   464  	}
   465  
   466  	return 0
   467  }