ioutil_darwin.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. // Copyright 2010 The Go 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-GO file.
  4. // Modifications Copyright 2020 The Libc Authors. All rights reserved.
  5. // Use of this source code is governed by a BSD-style
  6. // license that can be found in the LICENSE file.
  7. package libc // import "modernc.org/libc"
  8. import (
  9. "fmt"
  10. "os"
  11. "sync"
  12. "time"
  13. "unsafe"
  14. "golang.org/x/sys/unix"
  15. )
  16. // Random number state.
  17. // We generate random temporary file names so that there's a good
  18. // chance the file doesn't exist yet - keeps the number of tries in
  19. // TempFile to a minimum.
  20. var randState uint32
  21. var randStateMu sync.Mutex
  22. func reseed() uint32 {
  23. return uint32(time.Now().UnixNano() + int64(os.Getpid()))
  24. }
  25. func nextRandom(x uintptr) {
  26. randStateMu.Lock()
  27. r := randState
  28. if r == 0 {
  29. r = reseed()
  30. }
  31. r = r*1664525 + 1013904223 // constants from Numerical Recipes
  32. randState = r
  33. randStateMu.Unlock()
  34. copy((*RawMem)(unsafe.Pointer(x))[:6:6], fmt.Sprintf("%06d", int(1e9+r%1e9)%1e6))
  35. }
  36. func tempFile(s, x uintptr, _ int32) (fd int, err error) {
  37. const maxTry = 10000
  38. nconflict := 0
  39. for i := 0; i < maxTry; i++ {
  40. nextRandom(x)
  41. if fd, err = unix.Open(GoString(s), os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600); err == nil {
  42. return fd, nil
  43. }
  44. if !os.IsExist(err) {
  45. return -1, err
  46. }
  47. if nconflict++; nconflict > 10 {
  48. randStateMu.Lock()
  49. randState = reseed()
  50. nconflict = 0
  51. randStateMu.Unlock()
  52. }
  53. }
  54. return -1, err
  55. }