gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

ioutil_linux.go (1712B)


      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 "modernc.org/libc"
     10 
     11 import (
     12 	"fmt"
     13 	"os"
     14 	"sync"
     15 	"time"
     16 	"unsafe"
     17 
     18 	"golang.org/x/sys/unix"
     19 	"modernc.org/libc/errno"
     20 	"modernc.org/libc/fcntl"
     21 )
     22 
     23 // Random number state.
     24 // We generate random temporary file names so that there's a good
     25 // chance the file doesn't exist yet - keeps the number of tries in
     26 // TempFile to a minimum.
     27 var randState uint32
     28 var randStateMu sync.Mutex
     29 
     30 func reseed() uint32 {
     31 	return uint32(time.Now().UnixNano() + int64(os.Getpid()))
     32 }
     33 
     34 func nextRandom(x uintptr) {
     35 	randStateMu.Lock()
     36 	r := randState
     37 	if r == 0 {
     38 		r = reseed()
     39 	}
     40 	r = r*1664525 + 1013904223 // constants from Numerical Recipes
     41 	randState = r
     42 	randStateMu.Unlock()
     43 	copy((*RawMem)(unsafe.Pointer(x))[:6:6], fmt.Sprintf("%06d", int(1e9+r%1e9)%1e6))
     44 }
     45 
     46 func tempFile(s, x uintptr, flags int32) (fd int, err error) {
     47 	const maxTry = 10000
     48 	nconflict := 0
     49 	flags |= int32(os.O_RDWR | os.O_CREATE | os.O_EXCL | unix.O_LARGEFILE)
     50 	for i := 0; i < maxTry; i++ {
     51 		nextRandom(x)
     52 		fdcwd := fcntl.AT_FDCWD
     53 		n, _, err := unix.Syscall6(unix.SYS_OPENAT, uintptr(fdcwd), s, uintptr(flags), 0600, 0, 0)
     54 		if err == 0 {
     55 			return int(n), nil
     56 		}
     57 
     58 		if err != errno.EEXIST {
     59 			return -1, err
     60 		}
     61 
     62 		if nconflict++; nconflict > 10 {
     63 			randStateMu.Lock()
     64 			randState = reseed()
     65 			nconflict = 0
     66 			randStateMu.Unlock()
     67 		}
     68 	}
     69 	return -1, unix.Errno(errno.EEXIST)
     70 }