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