mirror of
https://github.com/golang/go
synced 2024-11-26 04:58:00 -07:00
io/ioutil: forward TempFile and TempDir to os package
For #42026 Fixes #44311 Change-Id: I3dabcf902d155f95800b4adf1d7578906a194ce6 Reviewed-on: https://go-review.googlesource.com/c/go/+/285378 Trust: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
This commit is contained in:
parent
04edf418d2
commit
07c658316b
@ -1,7 +0,0 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ioutil
|
||||
|
||||
var ErrPatternHasSeparator = errPatternHasSeparator
|
@ -5,38 +5,9 @@
|
||||
package ioutil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Random number state.
|
||||
// We generate random temporary file names so that there's a good
|
||||
// chance the file doesn't exist yet - keeps the number of tries in
|
||||
// TempFile to a minimum.
|
||||
var rand uint32
|
||||
var randmu sync.Mutex
|
||||
|
||||
func reseed() uint32 {
|
||||
return uint32(time.Now().UnixNano() + int64(os.Getpid()))
|
||||
}
|
||||
|
||||
func nextRandom() string {
|
||||
randmu.Lock()
|
||||
r := rand
|
||||
if r == 0 {
|
||||
r = reseed()
|
||||
}
|
||||
r = r*1664525 + 1013904223 // constants from Numerical Recipes
|
||||
rand = r
|
||||
randmu.Unlock()
|
||||
return strconv.Itoa(int(1e9 + r%1e9))[1:]
|
||||
}
|
||||
|
||||
// TempFile creates a new temporary file in the directory dir,
|
||||
// opens the file for reading and writing, and returns the resulting *os.File.
|
||||
// The filename is generated by taking pattern and adding a random
|
||||
@ -48,48 +19,10 @@ func nextRandom() string {
|
||||
// will not choose the same file. The caller can use f.Name()
|
||||
// to find the pathname of the file. It is the caller's responsibility
|
||||
// to remove the file when no longer needed.
|
||||
//
|
||||
// As of Go 1.16, this function simply calls os.CreateTemp.
|
||||
func TempFile(dir, pattern string) (f *os.File, err error) {
|
||||
if dir == "" {
|
||||
dir = os.TempDir()
|
||||
}
|
||||
|
||||
prefix, suffix, err := prefixAndSuffix(pattern)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
nconflict := 0
|
||||
for i := 0; i < 10000; i++ {
|
||||
name := filepath.Join(dir, prefix+nextRandom()+suffix)
|
||||
f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
|
||||
if os.IsExist(err) {
|
||||
if nconflict++; nconflict > 10 {
|
||||
randmu.Lock()
|
||||
rand = reseed()
|
||||
randmu.Unlock()
|
||||
}
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var errPatternHasSeparator = errors.New("pattern contains path separator")
|
||||
|
||||
// prefixAndSuffix splits pattern by the last wildcard "*", if applicable,
|
||||
// returning prefix as the part before "*" and suffix as the part after "*".
|
||||
func prefixAndSuffix(pattern string) (prefix, suffix string, err error) {
|
||||
if strings.ContainsRune(pattern, os.PathSeparator) {
|
||||
err = errPatternHasSeparator
|
||||
return
|
||||
}
|
||||
if pos := strings.LastIndex(pattern, "*"); pos != -1 {
|
||||
prefix, suffix = pattern[:pos], pattern[pos+1:]
|
||||
} else {
|
||||
prefix = pattern
|
||||
}
|
||||
return
|
||||
return os.CreateTemp(dir, pattern)
|
||||
}
|
||||
|
||||
// TempDir creates a new temporary directory in the directory dir.
|
||||
@ -101,37 +34,8 @@ func prefixAndSuffix(pattern string) (prefix, suffix string, err error) {
|
||||
// Multiple programs calling TempDir simultaneously
|
||||
// will not choose the same directory. It is the caller's responsibility
|
||||
// to remove the directory when no longer needed.
|
||||
//
|
||||
// As of Go 1.16, this function simply calls os.MkdirTemp.
|
||||
func TempDir(dir, pattern string) (name string, err error) {
|
||||
if dir == "" {
|
||||
dir = os.TempDir()
|
||||
}
|
||||
|
||||
prefix, suffix, err := prefixAndSuffix(pattern)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
nconflict := 0
|
||||
for i := 0; i < 10000; i++ {
|
||||
try := filepath.Join(dir, prefix+nextRandom()+suffix)
|
||||
err = os.Mkdir(try, 0700)
|
||||
if os.IsExist(err) {
|
||||
if nconflict++; nconflict > 10 {
|
||||
randmu.Lock()
|
||||
rand = reseed()
|
||||
randmu.Unlock()
|
||||
}
|
||||
continue
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
name = try
|
||||
}
|
||||
break
|
||||
}
|
||||
return
|
||||
return os.MkdirTemp(dir, pattern)
|
||||
}
|
||||
|
@ -50,6 +50,9 @@ func TestTempFile_pattern(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// This string is from os.errPatternHasSeparator.
|
||||
const patternHasSeparator = "pattern contains path separator"
|
||||
|
||||
func TestTempFile_BadPattern(t *testing.T) {
|
||||
tmpDir, err := TempDir("", t.Name())
|
||||
if err != nil {
|
||||
@ -81,9 +84,8 @@ func TestTempFile_BadPattern(t *testing.T) {
|
||||
if tt.wantErr {
|
||||
if err == nil {
|
||||
t.Errorf("Expected an error for pattern %q", tt.pattern)
|
||||
}
|
||||
if g, w := err, ErrPatternHasSeparator; g != w {
|
||||
t.Errorf("Error mismatch: got %#v, want %#v for pattern %q", g, w, tt.pattern)
|
||||
} else if !strings.Contains(err.Error(), patternHasSeparator) {
|
||||
t.Errorf("Error mismatch: got %#v, want %q for pattern %q", err, patternHasSeparator, tt.pattern)
|
||||
}
|
||||
} else if err != nil {
|
||||
t.Errorf("Unexpected error %v for pattern %q", err, tt.pattern)
|
||||
@ -183,9 +185,8 @@ func TestTempDir_BadPattern(t *testing.T) {
|
||||
if tt.wantErr {
|
||||
if err == nil {
|
||||
t.Errorf("Expected an error for pattern %q", tt.pattern)
|
||||
}
|
||||
if g, w := err, ErrPatternHasSeparator; g != w {
|
||||
t.Errorf("Error mismatch: got %#v, want %#v for pattern %q", g, w, tt.pattern)
|
||||
} else if !strings.Contains(err.Error(), patternHasSeparator) {
|
||||
t.Errorf("Error mismatch: got %#v, want %q for pattern %q", err, patternHasSeparator, tt.pattern)
|
||||
}
|
||||
} else if err != nil {
|
||||
t.Errorf("Unexpected error %v for pattern %q", err, tt.pattern)
|
||||
|
Loading…
Reference in New Issue
Block a user