github.com/afumu/libc@v0.0.6/ioutil_freebsd.go (about)

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