libc_linux_386.go (11702B)
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 }