Skip to content

Instantly share code, notes, and snippets.

@fuzzy
Created July 30, 2015 22:09
Show Gist options
  • Save fuzzy/bb60dbc131978d25c56b to your computer and use it in GitHub Desktop.
Save fuzzy/bb60dbc131978d25c56b to your computer and use it in GitHub Desktop.
package main
import (
// "bufio"
// "io"
"fmt"
"os"
"math"
"path"
"math/rand"
"strings"
"strconv"
)
// the Iobj class
type Config struct {
Input *os.File // File pointer for the input filename
InName string // Gotta record the filename somewhere
InSize int64 // If it's not in /dev record the file size
Output *os.File // output file pointer
OutName string // output file name
BlockSize int64 // our block size, defaults to 1MB
Count int64 // by default: 0, which means no limit.
Sync bool // by default this is false, can be changed with the 'sync' commandline arg
Transfer struct {
Started float64
Moved float64
}
}
// this is just a helper for formatting output to stderr
func (this Config) formatSize(s float64) string {
fmt.Printf("DEBUG: formatSize(%f)\n", s)
if s > 0 {
suffixes := []string{"B","KB","MB","GB","TB","PB","EB","ZB"}
exponent := int64(math.Log(s) / math.Log(1024))
quotient := s / math.Pow(1024, float64(exponent))
return fmt.Sprintf("%3.02f%s", quotient, suffixes[exponent])
} else {
return fmt.Sprintf("0B")
}
}
func (this Config) formatTime(s float64) string {
fmt.Printf("DEBUG: formatTime(%f)\n", s)
mn := math.Floor(s / 60.0)
sc := math.Remainder(s, 60.0)
hr := math.Floor(mn / 60.0)
mn = math.Remainder(mn, 60.0)
//dy := math.Floor(hr / 24.0)
//hr = math.Remainder(hr, 24.0)
return fmt.Sprintf("%02dh%02dm%02ds", int64(hr), int64(mn), int64(sc))
}
func (this Config) progress() {
}
// Reading files requires checking most calls for errors.
// This helper will streamline our error checks below.
func errCheck(e error) {
if e != nil {
if e.Error() != "EOF" {
fmt.Println(e.Error())
panic(e)
} else {
os.Exit(0)
}
}
}
func main() {
var iter int64
var err error
var args = os.Args[1:]
var cfg = Config{}
for _, tval := range args {
sval := strings.Split(tval, "=")
key := sval[0]
val := sval[1]
switch {
case "if" == key:
cfg.Input, err = os.Open(val)
errCheck(err)
cfg.InName = val
if cfg.InName != "/dev" {
tmp, _ := cfg.Input.Stat()
cfg.InSize = tmp.Size()
fmt.Println(cfg.formatSize(float64(cfg.InSize)))
fmt.Println(cfg.formatTime(float64(rand.Int63n(100000))))
errCheck(err)
}
defer cfg.Input.Close()
case "of" == key:
cfg.Output, err = os.Create(val)
errCheck(err)
cfg.OutName = val
defer cfg.Output.Close()
case "bs" == key:
cfg.BlockSize, err = strconv.ParseInt(val, 10, 64)
errCheck(err)
case "count" == key:
cfg.Count, err = strconv.ParseInt(val, 10, 64)
errCheck(err)
}
}
// error check to see if we have both of our input and outputs,
// and set them to their defaults if not.
if cfg.Input == nil {
cfg.Input = os.Stdin
}
fmt.Printf("%s\n", path.Dir(cfg.InName))
if cfg.Output == nil {
cfg.Output = os.Stdout
}
// now lets see if we have a blocksize, default to 1MB
if cfg.BlockSize == 0 {
cfg.BlockSize = 1048576
}
// this is for debug purposes only
fmt.Printf("%s\n", cfg)
// setup our reader/writer
buffer := make([]byte, cfg.BlockSize)
// and fire it off
iter = 0
for err == nil {
buffer = make([]byte, cfg.BlockSize)
// first read a block
_, err = cfg.Input.Read(buffer)
errCheck(err)
if err != nil {
fmt.Println(err.Error())
}
// next write out block out
_, err = cfg.Output.Write(buffer)
errCheck(err)
iter++
// And exit the loop if we need to
if cfg.Count > 0 {
if iter == cfg.Count {
break
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment