main.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // Command line utility for the lz4 package.
  2. package main
  3. import (
  4. // "bytes"
  5. "flag"
  6. "fmt"
  7. "io"
  8. "log"
  9. "os"
  10. "path"
  11. "runtime"
  12. "strings"
  13. "github.com/pierrec/lz4"
  14. profile "v/github.com/pkg/profile@v1.2.1"
  15. )
  16. func main() {
  17. // Process command line arguments
  18. var (
  19. blockMaxSizeDefault = 4 << 20
  20. flagStdout = flag.Bool("c", false, "output to stdout")
  21. flagDecompress = flag.Bool("d", false, "decompress flag")
  22. flagBlockMaxSize = flag.Int("B", blockMaxSizeDefault, "block max size [64Kb,256Kb,1Mb,4Mb]")
  23. flagBlockChecksum = flag.Bool("BX", false, "enable block checksum")
  24. flagStreamChecksum = flag.Bool("Sx", false, "disable stream checksum")
  25. flagCompressionLevel = flag.Int("l", 0, "compression level (0=fastest)")
  26. profileName = flag.String("p", "", "path to the profile file")
  27. mode = flag.String("profile.mode", "", "enable profiling mode, one of [cpu, mem, mutex, block]")
  28. )
  29. flag.Usage = func() {
  30. fmt.Fprintf(os.Stderr, "Usage:\n\t%s [arg] [input]...\n\tNo input means [de]compress stdin to stdout\n\n", os.Args[0])
  31. flag.PrintDefaults()
  32. }
  33. flag.Parse()
  34. ppath := profile.ProfilePath(*profileName)
  35. switch *mode {
  36. case "cpu":
  37. defer profile.Start(profile.CPUProfile, ppath).Stop()
  38. case "mem":
  39. defer profile.Start(profile.MemProfile, ppath).Stop()
  40. case "mutex":
  41. defer profile.Start(profile.MutexProfile, ppath).Stop()
  42. case "block":
  43. defer profile.Start(profile.BlockProfile, ppath).Stop()
  44. default:
  45. // do nothing
  46. }
  47. flag.Parse()
  48. // Use all CPUs
  49. runtime.GOMAXPROCS(runtime.NumCPU())
  50. zr := lz4.NewReader(nil)
  51. zw := lz4.NewWriter(nil)
  52. zh := lz4.Header{
  53. BlockChecksum: *flagBlockChecksum,
  54. BlockMaxSize: *flagBlockMaxSize,
  55. NoChecksum: *flagStreamChecksum,
  56. CompressionLevel: *flagCompressionLevel,
  57. }
  58. worker := func(in io.Reader, out io.Writer) {
  59. if *flagDecompress {
  60. zr.Reset(in)
  61. if _, err := io.Copy(out, zr); err != nil {
  62. log.Fatalf("Error while decompressing input: %v", err)
  63. }
  64. } else {
  65. zw.Reset(out)
  66. zw.Header = zh
  67. if _, err := io.Copy(zw, in); err != nil {
  68. log.Fatalf("Error while compressing input: %v", err)
  69. }
  70. if err := zw.Close(); err != nil {
  71. log.Fatalf("Error while closing stream: %v", err)
  72. }
  73. }
  74. }
  75. // No input means [de]compress stdin to stdout
  76. if len(flag.Args()) == 0 {
  77. worker(os.Stdin, os.Stdout)
  78. os.Exit(0)
  79. }
  80. // Compress or decompress all input files
  81. for _, inputFileName := range flag.Args() {
  82. outputFileName := path.Clean(inputFileName)
  83. if !*flagStdout {
  84. if *flagDecompress {
  85. outputFileName = strings.TrimSuffix(outputFileName, lz4.Extension)
  86. if outputFileName == inputFileName {
  87. log.Fatalf("Invalid output file name: same as input: %s", inputFileName)
  88. }
  89. } else {
  90. outputFileName += lz4.Extension
  91. }
  92. }
  93. inputFile, err := os.Open(inputFileName)
  94. if err != nil {
  95. log.Fatalf("Error while opening input: %v", err)
  96. }
  97. outputFile := os.Stdout
  98. if !*flagStdout {
  99. outputFile, err = os.Create(outputFileName)
  100. if err != nil {
  101. log.Fatalf("Error while opening output: %v", err)
  102. }
  103. }
  104. worker(inputFile, outputFile)
  105. inputFile.Close()
  106. if !*flagStdout {
  107. outputFile.Close()
  108. }
  109. }
  110. }