libc_linux_amd64.go (11976B)
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 "unicode" 11 "unsafe" 12 13 "golang.org/x/sys/unix" 14 "modernc.org/libc/errno" 15 "modernc.org/libc/fcntl" 16 "modernc.org/libc/signal" 17 "modernc.org/libc/sys/types" 18 "modernc.org/libc/wctype" 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 }