Command line client for Write.as https://write.as/apps/cli
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

68 lines
1.7 KiB

  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 file.
  4. package fileutils
  5. import (
  6. "os"
  7. "path/filepath"
  8. "strconv"
  9. "sync"
  10. "time"
  11. )
  12. // Random number state.
  13. // We generate random temporary file names so that there's a good
  14. // chance the file doesn't exist yet - keeps the number of tries in
  15. // TempFile to a minimum.
  16. var rand uint32
  17. var randmu sync.Mutex
  18. func reseed() uint32 {
  19. return uint32(time.Now().UnixNano() + int64(os.Getpid()))
  20. }
  21. func nextSuffix() string {
  22. randmu.Lock()
  23. r := rand
  24. if r == 0 {
  25. r = reseed()
  26. }
  27. r = r*1664525 + 1013904223 // constants from Numerical Recipes
  28. rand = r
  29. randmu.Unlock()
  30. return strconv.Itoa(int(1e9 + r%1e9))[1:]
  31. }
  32. // TempFile creates a new temporary file in the directory dir
  33. // with a name beginning with prefix and ending with ext, opens the
  34. // file for reading and writing, and returns the resulting *os.File.
  35. // If dir is the empty string, TempFile uses the default directory
  36. // for temporary files (see os.TempDir).
  37. // Multiple programs calling TempFile simultaneously
  38. // will not choose the same file. The caller can use f.Name()
  39. // to find the pathname of the file. It is the caller's responsibility
  40. // to remove the file when no longer needed.
  41. func TempFile(dir, prefix, ext string) (f *os.File, err error) {
  42. if dir == "" {
  43. dir = os.TempDir()
  44. }
  45. nconflict := 0
  46. for i := 0; i < 10000; i++ {
  47. name := filepath.Join(dir, prefix+nextSuffix()+"."+ext)
  48. f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
  49. if os.IsExist(err) {
  50. if nconflict++; nconflict > 10 {
  51. randmu.Lock()
  52. rand = reseed()
  53. randmu.Unlock()
  54. }
  55. continue
  56. }
  57. break
  58. }
  59. return
  60. }