modernc.org/libc@v1.24.1/libc_unix.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 //go:build unix 6 // +build unix 7 8 package libc // import "modernc.org/libc" 9 10 import ( 11 "bufio" 12 "encoding/hex" 13 "io/ioutil" 14 "math" 15 "math/rand" 16 "os" 17 gosignal "os/signal" 18 "reflect" 19 "strconv" 20 "strings" 21 "sync" 22 "syscall" 23 "time" 24 "unsafe" 25 26 guuid "github.com/google/uuid" 27 "golang.org/x/sys/unix" 28 "modernc.org/libc/errno" 29 "modernc.org/libc/grp" 30 "modernc.org/libc/poll" 31 "modernc.org/libc/pwd" 32 "modernc.org/libc/signal" 33 "modernc.org/libc/stdio" 34 "modernc.org/libc/stdlib" 35 "modernc.org/libc/sys/types" 36 ctime "modernc.org/libc/time" 37 ) 38 39 var staticGetpwnam pwd.Passwd 40 41 func init() { 42 atExit = append(atExit, func() { closePasswd(&staticGetpwnam) }) 43 } 44 45 // sighandler_t signal(int signum, sighandler_t handler); 46 func Xsignal(t *TLS, signum int32, handler uintptr) uintptr { //TODO use sigaction? 47 signalsMu.Lock() 48 49 defer signalsMu.Unlock() 50 51 r := signals[signum] 52 signals[signum] = handler 53 switch handler { 54 case signal.SIG_DFL: 55 panic(todo("%v %#x", syscall.Signal(signum), handler)) 56 case signal.SIG_IGN: 57 switch r { 58 case signal.SIG_DFL: 59 gosignal.Ignore(syscall.Signal(signum)) //TODO 60 case signal.SIG_IGN: 61 gosignal.Ignore(syscall.Signal(signum)) 62 default: 63 panic(todo("%v %#x", syscall.Signal(signum), handler)) 64 } 65 default: 66 switch r { 67 case signal.SIG_DFL: 68 c := make(chan os.Signal, 1) 69 gosignal.Notify(c, syscall.Signal(signum)) 70 go func() { //TODO mechanism to stop/cancel 71 for { 72 <-c 73 var f func(*TLS, int32) 74 *(*uintptr)(unsafe.Pointer(&f)) = handler 75 tls := NewTLS() 76 f(tls, signum) 77 tls.Close() 78 } 79 }() 80 case signal.SIG_IGN: 81 panic(todo("%v %#x", syscall.Signal(signum), handler)) 82 default: 83 panic(todo("%v %#x", syscall.Signal(signum), handler)) 84 } 85 } 86 return r 87 } 88 89 // void rewind(FILE *stream); 90 func Xrewind(t *TLS, stream uintptr) { 91 Xfseek(t, stream, 0, stdio.SEEK_SET) 92 } 93 94 // int putchar(int c); 95 func Xputchar(t *TLS, c int32) int32 { 96 if _, err := write([]byte{byte(c)}); err != nil { 97 return stdio.EOF 98 } 99 100 return int32(c) 101 } 102 103 // int gethostname(char *name, size_t len); 104 func Xgethostname(t *TLS, name uintptr, slen types.Size_t) int32 { 105 if slen < 0 { 106 t.setErrno(errno.EINVAL) 107 return -1 108 } 109 110 if slen == 0 { 111 return 0 112 } 113 114 s, err := os.Hostname() 115 if err != nil { 116 panic(todo("")) 117 } 118 119 n := len(s) 120 if len(s) >= int(slen) { 121 n = int(slen) - 1 122 } 123 sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) 124 copy((*RawMem)(unsafe.Pointer(name))[:n:n], (*RawMem)(unsafe.Pointer(sh.Data))[:n:n]) 125 *(*byte)(unsafe.Pointer(name + uintptr(n))) = 0 126 return 0 127 } 128 129 // int remove(const char *pathname); 130 func Xremove(t *TLS, pathname uintptr) int32 { 131 panic(todo("")) 132 } 133 134 // long pathconf(const char *path, int name); 135 func Xpathconf(t *TLS, path uintptr, name int32) long { 136 panic(todo("")) 137 } 138 139 // ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); 140 func Xrecvfrom(t *TLS, sockfd int32, buf uintptr, len types.Size_t, flags int32, src_addr, addrlen uintptr) types.Ssize_t { 141 panic(todo("")) 142 } 143 144 // ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); 145 func Xsendto(t *TLS, sockfd int32, buf uintptr, len types.Size_t, flags int32, src_addr uintptr, addrlen socklen_t) types.Ssize_t { 146 panic(todo("")) 147 } 148 149 // void srand48(long int seedval); 150 func Xsrand48(t *TLS, seedval long) { 151 panic(todo("")) 152 } 153 154 // long int lrand48(void); 155 func Xlrand48(t *TLS) long { 156 panic(todo("")) 157 } 158 159 // ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); 160 func Xsendmsg(t *TLS, sockfd int32, msg uintptr, flags int32) types.Ssize_t { 161 panic(todo("")) 162 } 163 164 // int poll(struct pollfd *fds, nfds_t nfds, int timeout); 165 func Xpoll(t *TLS, fds uintptr, nfds poll.Nfds_t, timeout int32) int32 { 166 if nfds == 0 { 167 panic(todo("")) 168 } 169 170 // if dmesgs { 171 // dmesg("%v: %#x %v %v, %+v", origin(1), fds, nfds, timeout, (*[1000]unix.PollFd)(unsafe.Pointer(fds))[:nfds:nfds]) 172 // } 173 n, err := unix.Poll((*[1000]unix.PollFd)(unsafe.Pointer(fds))[:nfds:nfds], int(timeout)) 174 // if dmesgs { 175 // dmesg("%v: %v %v", origin(1), n, err) 176 // } 177 if err != nil { 178 t.setErrno(err) 179 return -1 180 } 181 182 return int32(n) 183 } 184 185 // ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags); 186 func Xrecvmsg(t *TLS, sockfd int32, msg uintptr, flags int32) types.Ssize_t { 187 n, _, err := unix.Syscall(unix.SYS_RECVMSG, uintptr(sockfd), msg, uintptr(flags)) 188 if err != 0 { 189 t.setErrno(err) 190 return -1 191 } 192 193 return types.Ssize_t(n) 194 } 195 196 // struct cmsghdr *CMSG_NXTHDR(struct msghdr *msgh, struct cmsghdr *cmsg); 197 func X__cmsg_nxthdr(t *TLS, msgh, cmsg uintptr) uintptr { 198 panic(todo("")) 199 } 200 201 // wchar_t *wcschr(const wchar_t *wcs, wchar_t wc); 202 func Xwcschr(t *TLS, wcs uintptr, wc wchar_t) wchar_t { 203 panic(todo("")) 204 } 205 206 // gid_t getegid(void); 207 func Xgetegid(t *TLS) types.Gid_t { 208 panic(todo("")) 209 } 210 211 // gid_t getgid(void); 212 func Xgetgid(t *TLS) types.Gid_t { 213 panic(todo("")) 214 } 215 216 // void *shmat(int shmid, const void *shmaddr, int shmflg); 217 func Xshmat(t *TLS, shmid int32, shmaddr uintptr, shmflg int32) uintptr { 218 panic(todo("")) 219 } 220 221 // int shmctl(int shmid, int cmd, struct shmid_ds *buf); 222 func Xshmctl(t *TLS, shmid, cmd int32, buf uintptr) int32 { 223 panic(todo("")) 224 } 225 226 // int shmdt(const void *shmaddr); 227 func Xshmdt(t *TLS, shmaddr uintptr) int32 { 228 panic(todo("")) 229 } 230 231 // int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); 232 func Xgetresuid(t *TLS, ruid, euid, suid uintptr) int32 { 233 panic(todo("")) 234 } 235 236 // int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); 237 func Xgetresgid(t *TLS, rgid, egid, sgid uintptr) int32 { 238 panic(todo("")) 239 } 240 241 // FILE *tmpfile(void); 242 func Xtmpfile(t *TLS) uintptr { 243 f, err := ioutil.TempFile("", "tmpfile-") 244 if err != nil { 245 t.setErrno(err) 246 return 0 247 } 248 249 cf := newFile(t, int32(f.Fd())) 250 AtExit(func() { 251 nm := f.Name() 252 file(cf).close(t) 253 os.Remove(nm) 254 }) 255 256 return cf 257 } 258 259 // FILE *fdopen(int fd, const char *mode); 260 func Xfdopen(t *TLS, fd int32, mode uintptr) uintptr { 261 m := strings.ReplaceAll(GoString(mode), "b", "") 262 switch m { 263 case 264 "a", 265 "a+", 266 "r", 267 "r+", 268 "w", 269 "w+": 270 default: 271 t.setErrno(errno.EINVAL) 272 return 0 273 } 274 275 if p := newFile(t, fd); p != 0 { 276 return p 277 } 278 279 t.setErrno(errno.EINVAL) 280 return 0 281 } 282 283 // struct passwd *getpwnam(const char *name); 284 func Xgetpwnam(t *TLS, name uintptr) uintptr { 285 f, err := os.Open("/etc/passwd") 286 if err != nil { 287 panic(todo("", err)) 288 } 289 290 defer f.Close() 291 292 sname := GoString(name) 293 sc := bufio.NewScanner(f) 294 for sc.Scan() { 295 s := strings.TrimSpace(sc.Text()) 296 if s == "" || strings.HasPrefix(s, "#") { 297 continue 298 } 299 300 // eg. "root:x:0:0:root:/root:/bin/bash" 301 a := strings.Split(s, ":") 302 if len(a) < 7 { 303 panic(todo("")) 304 } 305 306 if a[0] == sname { 307 uid, err := strconv.Atoi(a[2]) 308 if err != nil { 309 panic(todo("")) 310 } 311 312 gid, err := strconv.Atoi(a[3]) 313 if err != nil { 314 panic(todo("")) 315 } 316 317 closePasswd(&staticGetpwnam) 318 gecos := a[4] 319 if strings.Contains(gecos, ",") { 320 a := strings.Split(gecos, ",") 321 gecos = a[0] 322 } 323 initPasswd(t, &staticGetpwnam, a[0], a[1], uint32(uid), uint32(gid), gecos, a[5], a[6]) 324 return uintptr(unsafe.Pointer(&staticGetpwnam)) 325 } 326 } 327 328 if sc.Err() != nil { 329 panic(todo("")) 330 } 331 332 return 0 333 } 334 335 // int getpwnam_r(char *name, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result); 336 func Xgetpwnam_r(t *TLS, name, cpwd, buf uintptr, buflen types.Size_t, result uintptr) int32 { 337 f, err := os.Open("/etc/passwd") 338 if err != nil { 339 panic(todo("", err)) 340 } 341 342 defer f.Close() 343 344 sname := GoString(name) 345 sc := bufio.NewScanner(f) 346 for sc.Scan() { 347 s := strings.TrimSpace(sc.Text()) 348 if s == "" || strings.HasPrefix(s, "#") { 349 continue 350 } 351 352 // eg. "root:x:0:0:root:/root:/bin/bash" 353 a := strings.Split(s, ":") 354 if len(a) < 7 { 355 panic(todo("%q", s)) 356 } 357 358 if a[0] == sname { 359 uid, err := strconv.Atoi(a[2]) 360 if err != nil { 361 panic(todo("")) 362 } 363 364 gid, err := strconv.Atoi(a[3]) 365 if err != nil { 366 panic(todo("")) 367 } 368 369 gecos := a[4] 370 if strings.Contains(gecos, ",") { 371 a := strings.Split(gecos, ",") 372 gecos = a[0] 373 } 374 var v pwd.Passwd 375 if initPasswd2(t, buf, buflen, &v, a[0], a[1], uint32(uid), uint32(gid), gecos, a[5], a[6]) { 376 *(*pwd.Passwd)(unsafe.Pointer(cpwd)) = v 377 *(*uintptr)(unsafe.Pointer(result)) = cpwd 378 return 0 379 } 380 381 *(*uintptr)(unsafe.Pointer(result)) = 0 382 return errno.ERANGE 383 } 384 } 385 386 if sc.Err() != nil { 387 panic(todo("")) 388 } 389 390 *(*uintptr)(unsafe.Pointer(result)) = 0 391 return 0 392 } 393 394 func init() { 395 atExit = append(atExit, func() { closeGroup(&staticGetgrgid) }) 396 } 397 398 var staticGetgrgid grp.Group 399 400 // struct group *getgrgid(gid_t gid); 401 func Xgetgrgid(t *TLS, gid uint32) uintptr { 402 f, err := os.Open("/etc/group") 403 if err != nil { 404 panic(todo("")) 405 } 406 407 defer f.Close() 408 409 sid := strconv.Itoa(int(gid)) 410 sc := bufio.NewScanner(f) 411 for sc.Scan() { 412 s := strings.TrimSpace(sc.Text()) 413 if s == "" || strings.HasPrefix(s, "#") { 414 continue 415 } 416 417 // eg. "root:x:0:" 418 a := strings.Split(s, ":") 419 if len(a) < 4 { 420 panic(todo("%q", s)) 421 } 422 423 if a[2] == sid { 424 closeGroup(&staticGetgrgid) 425 var names []string 426 if a[3] != "" { 427 names = strings.Split(a[3], ",") 428 } 429 initGroup(t, &staticGetgrgid, a[0], a[1], gid, names) 430 return uintptr(unsafe.Pointer(&staticGetgrgid)) 431 } 432 } 433 434 if sc.Err() != nil { 435 panic(todo("")) 436 } 437 438 return 0 439 } 440 441 // int getgrgid_r(gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result); 442 func Xgetgrgid_r(t *TLS, gid uint32, pGrp, buf uintptr, buflen types.Size_t, result uintptr) int32 { 443 f, err := os.Open("/etc/group") 444 if err != nil { 445 panic(todo("")) 446 } 447 448 defer f.Close() 449 450 sid := strconv.Itoa(int(gid)) 451 sc := bufio.NewScanner(f) 452 for sc.Scan() { 453 s := strings.TrimSpace(sc.Text()) 454 if s == "" || strings.HasPrefix(s, "#") { 455 continue 456 } 457 458 // eg. "root:x:0:" 459 a := strings.Split(s, ":") 460 if len(a) < 4 { 461 panic(todo("%q", s)) 462 } 463 464 if a[2] == sid { 465 var names []string 466 if a[3] != "" { 467 names = strings.Split(a[3], ",") 468 } 469 var x grp.Group 470 if initGroup2(buf, buflen, &x, a[0], a[1], gid, names) { 471 *(*grp.Group)(unsafe.Pointer(pGrp)) = x 472 *(*uintptr)(unsafe.Pointer(result)) = pGrp 473 return 0 474 } 475 476 *(*uintptr)(unsafe.Pointer(result)) = 0 477 return 0 478 } 479 } 480 481 if sc.Err() != nil { 482 panic(todo("")) 483 } 484 485 *(*uintptr)(unsafe.Pointer(result)) = 0 486 return 0 487 } 488 489 func initPasswd2(t *TLS, buf uintptr, buflen types.Size_t, p *pwd.Passwd, name, pwd string, uid, gid uint32, gecos, dir, shell string) bool { 490 p.Fpw_name, buf, buflen = bufString(buf, buflen, name) 491 if buf == 0 { 492 return false 493 } 494 495 p.Fpw_passwd, buf, buflen = bufString(buf, buflen, pwd) 496 if buf == 0 { 497 return false 498 } 499 500 p.Fpw_uid = uid 501 p.Fpw_gid = gid 502 if buf == 0 { 503 return false 504 } 505 506 p.Fpw_gecos, buf, buflen = bufString(buf, buflen, gecos) 507 if buf == 0 { 508 return false 509 } 510 511 p.Fpw_dir, buf, buflen = bufString(buf, buflen, dir) 512 if buf == 0 { 513 return false 514 } 515 516 p.Fpw_shell, buf, buflen = bufString(buf, buflen, shell) 517 if buf == 0 { 518 return false 519 } 520 521 return true 522 } 523 524 func bufString(buf uintptr, buflen types.Size_t, s string) (uintptr, uintptr, types.Size_t) { 525 buf0 := buf 526 rq := len(s) + 1 527 if rq > int(buflen) { 528 return 0, 0, 0 529 } 530 531 copy((*RawMem)(unsafe.Pointer(buf))[:len(s):len(s)], s) 532 buf += uintptr(len(s)) 533 *(*byte)(unsafe.Pointer(buf)) = 0 534 return buf0, buf + 1, buflen - types.Size_t(rq) 535 } 536 537 func closeGroup(p *grp.Group) { 538 Xfree(nil, p.Fgr_name) 539 Xfree(nil, p.Fgr_passwd) 540 if p := p.Fgr_mem; p != 0 { 541 for { 542 q := *(*uintptr)(unsafe.Pointer(p)) 543 if q == 0 { 544 break 545 } 546 547 Xfree(nil, q) 548 p += unsafe.Sizeof(uintptr(0)) 549 } 550 } 551 *p = grp.Group{} 552 } 553 554 func initGroup(t *TLS, p *grp.Group, name, pwd string, gid uint32, names []string) { 555 p.Fgr_name = cString(t, name) 556 p.Fgr_passwd = cString(t, pwd) 557 p.Fgr_gid = gid 558 a := Xcalloc(t, 1, types.Size_t(unsafe.Sizeof(uintptr(0)))*types.Size_t((len(names)+1))) 559 if a == 0 { 560 panic("OOM") 561 } 562 563 for p := a; len(names) != 0; p += unsafe.Sizeof(uintptr(0)) { 564 *(*uintptr)(unsafe.Pointer(p)) = cString(t, names[0]) 565 names = names[1:] 566 } 567 p.Fgr_mem = a 568 } 569 570 func initGroup2(buf uintptr, buflen types.Size_t, p *grp.Group, name, pwd string, gid uint32, names []string) bool { 571 p.Fgr_name, buf, buflen = bufString(buf, buflen, name) 572 if buf == 0 { 573 return false 574 } 575 576 p.Fgr_passwd, buf, buflen = bufString(buf, buflen, pwd) 577 if buf == 0 { 578 return false 579 } 580 581 p.Fgr_gid = gid 582 rq := unsafe.Sizeof(uintptr(0)) * uintptr(len(names)+1) 583 if rq > uintptr(buflen) { 584 return false 585 } 586 587 a := buf 588 buf += rq 589 for ; len(names) != 0; buf += unsafe.Sizeof(uintptr(0)) { 590 if len(names[0])+1 > int(buflen) { 591 return false 592 } 593 594 *(*uintptr)(unsafe.Pointer(buf)), buf, buflen = bufString(buf, buflen, names[0]) 595 names = names[1:] 596 } 597 *(*uintptr)(unsafe.Pointer(buf)) = 0 598 p.Fgr_mem = a 599 return true 600 } 601 602 func init() { 603 atExit = append(atExit, func() { closeGroup(&staticGetgrgid) }) 604 } 605 606 var staticGetpwuid pwd.Passwd 607 608 func init() { 609 atExit = append(atExit, func() { closePasswd(&staticGetpwuid) }) 610 } 611 612 func closePasswd(p *pwd.Passwd) { 613 Xfree(nil, p.Fpw_name) 614 Xfree(nil, p.Fpw_passwd) 615 Xfree(nil, p.Fpw_gecos) 616 Xfree(nil, p.Fpw_dir) 617 Xfree(nil, p.Fpw_shell) 618 *p = pwd.Passwd{} 619 } 620 621 var staticGetgrnam grp.Group 622 623 func init() { 624 atExit = append(atExit, func() { closeGroup(&staticGetgrnam) }) 625 } 626 627 // struct passwd *getpwuid(uid_t uid); 628 func Xgetpwuid(t *TLS, uid uint32) uintptr { 629 f, err := os.Open("/etc/passwd") 630 if err != nil { 631 panic(todo("", err)) 632 } 633 634 defer f.Close() 635 636 sid := strconv.Itoa(int(uid)) 637 sc := bufio.NewScanner(f) 638 for sc.Scan() { 639 s := strings.TrimSpace(sc.Text()) 640 if len(s) == 0 || strings.HasPrefix(s, "#") { 641 continue 642 } 643 644 // eg. "root:x:0:0:root:/root:/bin/bash" 645 a := strings.Split(s, ":") 646 if len(a) < 7 { 647 panic(todo("%q", s)) 648 } 649 650 if a[2] == sid { 651 uid, err := strconv.Atoi(a[2]) 652 if err != nil { 653 panic(todo("")) 654 } 655 656 gid, err := strconv.Atoi(a[3]) 657 if err != nil { 658 panic(todo("")) 659 } 660 661 closePasswd(&staticGetpwuid) 662 gecos := a[4] 663 if strings.Contains(gecos, ",") { 664 a := strings.Split(gecos, ",") 665 gecos = a[0] 666 } 667 initPasswd(t, &staticGetpwuid, a[0], a[1], uint32(uid), uint32(gid), gecos, a[5], a[6]) 668 return uintptr(unsafe.Pointer(&staticGetpwuid)) 669 } 670 } 671 672 if sc.Err() != nil { 673 panic(todo("")) 674 } 675 676 return 0 677 } 678 679 func initPasswd(t *TLS, p *pwd.Passwd, name, pwd string, uid, gid uint32, gecos, dir, shell string) { 680 p.Fpw_name = cString(t, name) 681 p.Fpw_passwd = cString(t, pwd) 682 p.Fpw_uid = uid 683 p.Fpw_gid = gid 684 p.Fpw_gecos = cString(t, gecos) 685 p.Fpw_dir = cString(t, dir) 686 p.Fpw_shell = cString(t, shell) 687 } 688 689 // struct group *getgrnam(const char *name); 690 func Xgetgrnam(t *TLS, name uintptr) uintptr { 691 f, err := os.Open("/etc/group") 692 if err != nil { 693 panic(todo("")) 694 } 695 696 defer f.Close() 697 698 sname := GoString(name) 699 sc := bufio.NewScanner(f) 700 for sc.Scan() { 701 s := strings.TrimSpace(sc.Text()) 702 if len(s) == 0 || strings.HasPrefix(s, "#") { 703 continue 704 } 705 706 // eg. "root:x:0:" 707 a := strings.Split(s, ":") 708 if len(a) < 4 { 709 panic(todo("%q", s)) 710 } 711 712 if a[0] == sname { 713 closeGroup(&staticGetgrnam) 714 gid, err := strconv.Atoi(a[2]) 715 if err != nil { 716 panic(todo("")) 717 } 718 719 var names []string 720 if a[3] != "" { 721 names = strings.Split(a[3], ",") 722 } 723 initGroup(t, &staticGetgrnam, a[0], a[1], uint32(gid), names) 724 return uintptr(unsafe.Pointer(&staticGetgrnam)) 725 } 726 } 727 728 if sc.Err() != nil { 729 panic(todo("")) 730 } 731 732 return 0 733 } 734 735 // int getgrnam_r(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result); 736 func Xgetgrnam_r(t *TLS, name, pGrp, buf uintptr, buflen types.Size_t, result uintptr) int32 { 737 f, err := os.Open("/etc/group") 738 if err != nil { 739 panic(todo("")) 740 } 741 742 defer f.Close() 743 744 sname := GoString(name) 745 sc := bufio.NewScanner(f) 746 for sc.Scan() { 747 s := strings.TrimSpace(sc.Text()) 748 if len(s) == 0 || strings.HasPrefix(s, "#") { 749 continue 750 } 751 752 // eg. "root:x:0:" 753 a := strings.Split(s, ":") 754 if len(a) < 4 { 755 panic(todo("%q", s)) 756 } 757 758 if a[0] == sname { 759 gid, err := strconv.Atoi(a[2]) 760 if err != nil { 761 panic(todo("")) 762 } 763 764 var names []string 765 if a[3] != "" { 766 names = strings.Split(a[3], ",") 767 } 768 var x grp.Group 769 if initGroup2(buf, buflen, &x, a[0], a[1], uint32(gid), names) { 770 *(*grp.Group)(unsafe.Pointer(pGrp)) = x 771 *(*uintptr)(unsafe.Pointer(result)) = pGrp 772 return 0 773 } 774 775 *(*uintptr)(unsafe.Pointer(result)) = 0 776 return 0 777 } 778 } 779 780 if sc.Err() != nil { 781 panic(todo("")) 782 } 783 784 *(*uintptr)(unsafe.Pointer(result)) = 0 785 return 0 786 } 787 788 // int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result); 789 func Xgetpwuid_r(t *TLS, uid types.Uid_t, cpwd, buf uintptr, buflen types.Size_t, result uintptr) int32 { 790 f, err := os.Open("/etc/passwd") 791 if err != nil { 792 panic(todo("", err)) 793 } 794 795 defer f.Close() 796 797 sid := strconv.Itoa(int(uid)) 798 sc := bufio.NewScanner(f) 799 for sc.Scan() { 800 s := strings.TrimSpace(sc.Text()) 801 if len(s) == 0 || strings.HasPrefix(s, "#") { 802 continue 803 } 804 805 // eg. "root:x:0:0:root:/root:/bin/bash" 806 a := strings.Split(s, ":") 807 if len(a) < 7 { 808 panic(todo("%q", s)) 809 } 810 811 if a[2] == sid { 812 uid, err := strconv.Atoi(a[2]) 813 if err != nil { 814 panic(todo("")) 815 } 816 817 gid, err := strconv.Atoi(a[3]) 818 if err != nil { 819 panic(todo("")) 820 } 821 822 gecos := a[4] 823 if strings.Contains(gecos, ",") { 824 a := strings.Split(gecos, ",") 825 gecos = a[0] 826 } 827 var v pwd.Passwd 828 if initPasswd2(t, buf, buflen, &v, a[0], a[1], uint32(uid), uint32(gid), gecos, a[5], a[6]) { 829 *(*pwd.Passwd)(unsafe.Pointer(cpwd)) = v 830 *(*uintptr)(unsafe.Pointer(result)) = cpwd 831 return 0 832 } 833 834 *(*uintptr)(unsafe.Pointer(result)) = 0 835 return errno.ERANGE 836 } 837 } 838 839 if sc.Err() != nil { 840 panic(todo("")) 841 } 842 843 *(*uintptr)(unsafe.Pointer(result)) = 0 844 return 0 845 } 846 847 // int mkostemp(char *template, int flags); 848 func Xmkostemp(t *TLS, template uintptr, flags int32) int32 { 849 len := uintptr(Xstrlen(t, template)) 850 x := template + uintptr(len-6) 851 for i := uintptr(0); i < 6; i++ { 852 if *(*byte)(unsafe.Pointer(x + i)) != 'X' { 853 t.setErrno(errno.EINVAL) 854 return -1 855 } 856 } 857 858 fd, err := tempFile(template, x, flags) 859 if err != nil { 860 t.setErrno(err) 861 return -1 862 } 863 864 return int32(fd) 865 } 866 867 // void uuid_generate_random(uuid_t out); 868 func Xuuid_generate_random(t *TLS, out uintptr) { 869 x := guuid.New() 870 copy((*RawMem)(unsafe.Pointer(out))[:], x[:]) 871 } 872 873 // void uuid_unparse(uuid_t uu, char *out); 874 func Xuuid_unparse(t *TLS, uu, out uintptr) { 875 s := (*guuid.UUID)(unsafe.Pointer(uu)).String() 876 copy((*RawMem)(unsafe.Pointer(out))[:], s) 877 *(*byte)(unsafe.Pointer(out + uintptr(len(s)))) = 0 878 } 879 880 var staticRandomData = &rand.Rand{} 881 882 // char *initstate(unsigned seed, char *state, size_t size); 883 func Xinitstate(t *TLS, seed uint32, statebuf uintptr, statelen types.Size_t) uintptr { 884 staticRandomData = rand.New(rand.NewSource(int64(seed))) 885 return 0 886 } 887 888 // char *setstate(const char *state); 889 func Xsetstate(t *TLS, state uintptr) uintptr { 890 t.setErrno(errno.EINVAL) //TODO 891 return 0 892 } 893 894 // The initstate_r() function is like initstate(3) except that it initializes 895 // the state in the object pointed to by buf, rather than initializing the 896 // global state variable. Before calling this function, the buf.state field 897 // must be initialized to NULL. The initstate_r() function records a pointer 898 // to the statebuf argument inside the structure pointed to by buf. Thus, 899 // stateā buf should not be deallocated so long as buf is still in use. (So, 900 // statebuf should typically be allocated as a static variable, or allocated on 901 // the heap using malloc(3) or similar.) 902 // 903 // char *initstate_r(unsigned int seed, char *statebuf, size_t statelen, struct random_data *buf); 904 func Xinitstate_r(t *TLS, seed uint32, statebuf uintptr, statelen types.Size_t, buf uintptr) int32 { 905 if buf == 0 { 906 panic(todo("")) 907 } 908 909 randomDataMu.Lock() 910 911 defer randomDataMu.Unlock() 912 913 randomData[buf] = rand.New(rand.NewSource(int64(seed))) 914 return 0 915 } 916 917 var ( 918 randomData = map[uintptr]*rand.Rand{} 919 randomDataMu sync.Mutex 920 ) 921 922 // int mkstemps(char *template, int suffixlen); 923 func Xmkstemps(t *TLS, template uintptr, suffixlen int32) int32 { 924 return Xmkstemps64(t, template, suffixlen) 925 } 926 927 // int mkstemps(char *template, int suffixlen); 928 func Xmkstemps64(t *TLS, template uintptr, suffixlen int32) int32 { 929 len := uintptr(Xstrlen(t, template)) 930 x := template + uintptr(len-6) - uintptr(suffixlen) 931 for i := uintptr(0); i < 6; i++ { 932 if *(*byte)(unsafe.Pointer(x + i)) != 'X' { 933 t.setErrno(errno.EINVAL) 934 return -1 935 } 936 } 937 938 fd, err := tempFile(template, x, 0) 939 if err != nil { 940 t.setErrno(err) 941 return -1 942 } 943 944 return int32(fd) 945 } 946 947 // int mkstemp(char *template); 948 func Xmkstemp(t *TLS, template uintptr) int32 { 949 return Xmkstemp64(t, template) 950 } 951 952 // int mkstemp(char *template); 953 func Xmkstemp64(t *TLS, template uintptr) int32 { 954 return Xmkstemps64(t, template, 0) 955 } 956 957 // int random_r(struct random_data *buf, int32_t *result); 958 func Xrandom_r(t *TLS, buf, result uintptr) int32 { 959 randomDataMu.Lock() 960 961 defer randomDataMu.Unlock() 962 963 mr := randomData[buf] 964 if stdlib.RAND_MAX != math.MaxInt32 { 965 panic(todo("")) 966 } 967 *(*int32)(unsafe.Pointer(result)) = mr.Int31() 968 return 0 969 } 970 971 // int strerror_r(int errnum, char *buf, size_t buflen); 972 func Xstrerror_r(t *TLS, errnum int32, buf uintptr, buflen size_t) int32 { 973 panic(todo("")) 974 } 975 976 // void endpwent(void); 977 func Xendpwent(t *TLS) { 978 // nop 979 } 980 981 var ctimeStaticBuf [32]byte 982 983 // char *ctime(const time_t *timep); 984 func Xctime(t *TLS, timep uintptr) uintptr { 985 return Xctime_r(t, timep, uintptr(unsafe.Pointer(&ctimeStaticBuf[0]))) 986 } 987 988 // char *ctime_r(const time_t *timep, char *buf); 989 func Xctime_r(t *TLS, timep, buf uintptr) uintptr { 990 ut := *(*ctime.Time_t)(unsafe.Pointer(timep)) 991 tm := time.Unix(int64(ut), 0).Local() 992 s := tm.Format(time.ANSIC) + "\n\x00" 993 copy((*RawMem)(unsafe.Pointer(buf))[:26:26], s) 994 return buf 995 } 996 997 // ssize_t pread(int fd, void *buf, size_t count, off_t offset); 998 func Xpread(t *TLS, fd int32, buf uintptr, count types.Size_t, offset types.Off_t) types.Ssize_t { 999 var n int 1000 var err error 1001 switch { 1002 case count == 0: 1003 n, err = unix.Pread(int(fd), nil, int64(offset)) 1004 default: 1005 n, err = unix.Pread(int(fd), (*RawMem)(unsafe.Pointer(buf))[:count:count], int64(offset)) 1006 if dmesgs && err == nil { 1007 dmesg("%v: fd %v, off %#x, count %#x, n %#x\n%s", origin(1), fd, offset, count, n, hex.Dump((*RawMem)(unsafe.Pointer(buf))[:n:n])) 1008 } 1009 } 1010 if err != nil { 1011 if dmesgs { 1012 dmesg("%v: %v FAIL", origin(1), err) 1013 } 1014 t.setErrno(err) 1015 return -1 1016 } 1017 1018 if dmesgs { 1019 dmesg("%v: ok", origin(1)) 1020 } 1021 return types.Ssize_t(n) 1022 }