main.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // Copyright (C) 2016 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. package main
  7. import (
  8. "flag"
  9. "fmt"
  10. "io"
  11. "log"
  12. "math/rand"
  13. "os"
  14. "path/filepath"
  15. "time"
  16. _ "github.com/syncthing/syncthing/lib/automaxprocs"
  17. )
  18. func main() {
  19. dir := flag.String("dir", "~/files", "Directory to generate into")
  20. files := flag.Int("files", 1000, "Number of files to create")
  21. maxExp := flag.Int("maxexp", 20, "Max size exponent")
  22. src := flag.String("src", "/dev/urandom", "Source of file data")
  23. flag.Parse()
  24. if err := generateFiles(*dir, *files, *maxExp, *src); err != nil {
  25. log.Println(err)
  26. }
  27. }
  28. func generateFiles(dir string, files, maxexp int, srcname string) error {
  29. fd, err := os.Open(srcname)
  30. if err != nil {
  31. return err
  32. }
  33. for i := 0; i < files; i++ {
  34. n := randomName()
  35. if rand.Float64() < 0.05 {
  36. // Some files and directories are dotfiles
  37. n = "." + n
  38. }
  39. p0 := filepath.Join(dir, string(n[0]), n[0:2])
  40. err = os.MkdirAll(p0, 0o755)
  41. if err != nil {
  42. log.Fatal(err)
  43. }
  44. p1 := filepath.Join(p0, n)
  45. s := int64(1 << uint(rand.Intn(maxexp)))
  46. a := int64(128 * 1024)
  47. if a > s {
  48. a = s
  49. }
  50. s += rand.Int63n(a)
  51. if err := generateOneFile(fd, p1, s); err != nil {
  52. return err
  53. }
  54. }
  55. return nil
  56. }
  57. func generateOneFile(fd io.ReadSeeker, p1 string, s int64) error {
  58. src := io.LimitReader(&infiniteReader{fd}, s)
  59. dst, err := os.Create(p1)
  60. if err != nil {
  61. return err
  62. }
  63. _, err = io.Copy(dst, src)
  64. if err != nil {
  65. return err
  66. }
  67. err = dst.Close()
  68. if err != nil {
  69. return err
  70. }
  71. os.Chmod(p1, os.FileMode(rand.Intn(0o777)|0o400))
  72. t := time.Now().Add(-time.Duration(rand.Intn(30*86400)) * time.Second)
  73. return os.Chtimes(p1, t, t)
  74. }
  75. func randomName() string {
  76. var b [16]byte
  77. readRand(b[:])
  78. return fmt.Sprintf("%x", b[:])
  79. }
  80. func readRand(bs []byte) (int, error) {
  81. var r uint32
  82. for i := range bs {
  83. if i%4 == 0 {
  84. r = uint32(rand.Int63())
  85. }
  86. bs[i] = byte(r >> uint((i%4)*8))
  87. }
  88. return len(bs), nil
  89. }
  90. type infiniteReader struct {
  91. rd io.ReadSeeker
  92. }
  93. func (i *infiniteReader) Read(bs []byte) (int, error) {
  94. n, err := i.rd.Read(bs)
  95. if err == io.EOF {
  96. err = nil
  97. i.rd.Seek(0, 0)
  98. }
  99. return n, err
  100. }