main.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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. )
  17. func main() {
  18. dir := flag.String("dir", "~/files", "Directory to generate into")
  19. files := flag.Int("files", 1000, "Number of files to create")
  20. maxExp := flag.Int("maxexp", 20, "Max size exponent")
  21. src := flag.String("src", "/dev/urandom", "Source of file data")
  22. flag.Parse()
  23. if err := generateFiles(*dir, *files, *maxExp, *src); err != nil {
  24. log.Println(err)
  25. }
  26. }
  27. func generateFiles(dir string, files, maxexp int, srcname string) error {
  28. fd, err := os.Open(srcname)
  29. if err != nil {
  30. return err
  31. }
  32. for i := 0; i < files; i++ {
  33. n := randomName()
  34. if rand.Float64() < 0.05 {
  35. // Some files and directories are dotfiles
  36. n = "." + n
  37. }
  38. p0 := filepath.Join(dir, string(n[0]), n[0:2])
  39. err = os.MkdirAll(p0, 0755)
  40. if err != nil {
  41. log.Fatal(err)
  42. }
  43. p1 := filepath.Join(p0, n)
  44. s := int64(1 << uint(rand.Intn(maxexp)))
  45. a := int64(128 * 1024)
  46. if a > s {
  47. a = s
  48. }
  49. s += rand.Int63n(a)
  50. if err := generateOneFile(fd, p1, s); err != nil {
  51. return err
  52. }
  53. }
  54. return nil
  55. }
  56. func generateOneFile(fd io.ReadSeeker, p1 string, s int64) error {
  57. src := io.LimitReader(&inifiteReader{fd}, s)
  58. dst, err := os.Create(p1)
  59. if err != nil {
  60. return err
  61. }
  62. _, err = io.Copy(dst, src)
  63. if err != nil {
  64. return err
  65. }
  66. err = dst.Close()
  67. if err != nil {
  68. return err
  69. }
  70. os.Chmod(p1, os.FileMode(rand.Intn(0777)|0400))
  71. t := time.Now().Add(-time.Duration(rand.Intn(30*86400)) * time.Second)
  72. return os.Chtimes(p1, t, t)
  73. }
  74. func randomName() string {
  75. var b [16]byte
  76. readRand(b[:])
  77. return fmt.Sprintf("%x", b[:])
  78. }
  79. func readRand(bs []byte) (int, error) {
  80. var r uint32
  81. for i := range bs {
  82. if i%4 == 0 {
  83. r = uint32(rand.Int63())
  84. }
  85. bs[i] = byte(r >> uint((i%4)*8))
  86. }
  87. return len(bs), nil
  88. }
  89. type inifiteReader struct {
  90. rd io.ReadSeeker
  91. }
  92. func (i *inifiteReader) Read(bs []byte) (int, error) {
  93. n, err := i.rd.Read(bs)
  94. if err == io.EOF {
  95. err = nil
  96. i.rd.Seek(0, 0)
  97. }
  98. return n, err
  99. }