Remove all schollz/* dependencies: fork pake, replicate logger and CLI
- src/pake: trimmed fork of schollz/pake/v3, P256-only (stdlib crypto/elliptic), dropping the tscholl2/siec and filippo.io/edwards25519 transitive deps along with it. - src/logger: minimal in-repo replacement for schollz/logger with the same leveled-logging call surface. - src/cli: replaced schollz/cli (urfave/cli fork) with a small flag-package-based parser for the send/relay/receive commands actually in use; subcommand keyword can appear before or after its flags. - Dropped schollz/progressbar entirely (its show-progress code paths were already unreachable dead code since no CLI flag wired them up). go.mod/go.sum no longer reference any schollz/* module.
This commit is contained in:
@@ -7,23 +7,11 @@ require (
|
||||
github.com/kalafut/imohash v1.1.1
|
||||
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b
|
||||
github.com/minio/highwayhash v1.0.4
|
||||
github.com/schollz/cli/v2 v2.2.1
|
||||
github.com/schollz/logger v1.2.0
|
||||
github.com/schollz/pake/v3 v3.1.1
|
||||
github.com/schollz/progressbar/v3 v3.19.1
|
||||
golang.org/x/crypto v0.53.0
|
||||
golang.org/x/net v0.56.0
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.2.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
github.com/tscholl2/siec v0.0.0-20240310163802-c2c6f6198406 // indirect
|
||||
github.com/twmb/murmur3 v1.1.8 // indirect
|
||||
golang.org/x/sys v0.46.0 // indirect
|
||||
golang.org/x/term v0.44.0 // indirect
|
||||
)
|
||||
|
||||
@@ -1,45 +1,11 @@
|
||||
filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
|
||||
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM=
|
||||
github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/kalafut/imohash v1.1.1 h1:G/HYtKgteQSVU96LidSJEbUGoZOMiBcuXYxbeb2W9e4=
|
||||
github.com/kalafut/imohash v1.1.1/go.mod h1:6cn9lU0Sj8M4eu9UaQm1kR/5y3k/ayB68yntRhGloL4=
|
||||
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b h1:xZ59n7Frzh8CwyfAapUZLSg+gXH5m63YEaFCMpDHhpI=
|
||||
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b/go.mod h1:uDd4sYVYsqcxAB8j+Q7uhL6IJCs/r1kxib1HV4bgOMg=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/minio/highwayhash v1.0.4 h1:asJizugGgchQod2ja9NJlGOWq4s7KsAWr5XUc9Clgl4=
|
||||
github.com/minio/highwayhash v1.0.4/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ=
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/schollz/cli/v2 v2.2.1 h1:ou22Mj7ZPjrKz+8k2iDTWaHskEEV5NiAxGrdsCL36VU=
|
||||
github.com/schollz/cli/v2 v2.2.1/go.mod h1:My6bfphRLZUhZdlFUK8scAxMWHydE7k4s2ed2Dtnn+s=
|
||||
github.com/schollz/logger v1.2.0 h1:5WXfINRs3lEUTCZ7YXhj0uN+qukjizvITLm3Ca2m0Ho=
|
||||
github.com/schollz/logger v1.2.0/go.mod h1:P6F4/dGMGcx8wh+kG1zrNEd4vnNpEBY/mwEMd/vn6AM=
|
||||
github.com/schollz/pake/v3 v3.1.1 h1:lyoU5uNQ3thfjEzrahgxWWBm6+pbI1F2KAZ3gs6LIV8=
|
||||
github.com/schollz/pake/v3 v3.1.1/go.mod h1:420+m3AakXcS0n7Uwc7eRs2CosQ2YfE/vKcIkilvqZc=
|
||||
github.com/schollz/progressbar/v3 v3.19.1 h1:iv8BgwOvdML/S3p84uBpy/IMigv4U9594vPZYa2EdrU=
|
||||
github.com/schollz/progressbar/v3 v3.19.1/go.mod h1:LFL7jqimKxfhero4K1eCkUr/6R39AgQeiPCJtlTWIW8=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/tscholl2/siec v0.0.0-20240310163802-c2c6f6198406 h1:sDWDZkwYqX0jvLWstKzFwh+pYhQNaVg65BgSkCP/f7U=
|
||||
github.com/tscholl2/siec v0.0.0-20240310163802-c2c6f6198406/go.mod h1:KL9+ubr1JZdaKjgAaHr+tCytEncXBa1pR6FjbTsOJnw=
|
||||
github.com/twmb/murmur3 v1.1.5/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
|
||||
github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg=
|
||||
github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
|
||||
@@ -50,9 +16,3 @@ golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
|
||||
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
|
||||
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
+133
-106
@@ -1,33 +1,24 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"time"
|
||||
"strconv"
|
||||
|
||||
"github.com/schollz/cli/v2"
|
||||
log "github.com/tzgyn/share/src/logger"
|
||||
"github.com/tzgyn/share/src/models"
|
||||
"github.com/tzgyn/share/src/swarm"
|
||||
"github.com/tzgyn/share/src/tcp"
|
||||
"github.com/tzgyn/share/src/utils"
|
||||
log "github.com/schollz/logger"
|
||||
)
|
||||
|
||||
var Version string
|
||||
|
||||
func Run() (err error) {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
const usage = `share [GLOBAL OPTIONS] [COMMAND] [COMMAND OPTIONS] [filename(s)]
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Name = "share"
|
||||
if Version == "" {
|
||||
Version = "v0.1.0"
|
||||
}
|
||||
app.Version = Version
|
||||
app.Compiled = time.Now()
|
||||
app.Usage = "a torrent-like swarm: everyone who joins a room can send and receive"
|
||||
app.UsageText = `share [GLOBAL OPTIONS] [COMMAND] [COMMAND OPTIONS] [filename(s)]
|
||||
a torrent-like swarm: everyone who joins a room can send and receive
|
||||
|
||||
USAGE EXAMPLES:
|
||||
Seed a file into a new room (prints a code):
|
||||
@@ -37,129 +28,165 @@ func Run() (err error) {
|
||||
share send --code secret-code file1.txt file2.txt
|
||||
|
||||
Join a room to receive whatever's shared there (and help re-share it):
|
||||
share secret-code`
|
||||
app.Commands = []*cli.Command{
|
||||
{
|
||||
Name: "send",
|
||||
Usage: "seed file(s) into a room (see options with share send -h)",
|
||||
Description: "seed file(s) into a swarm room so others can join and receive them",
|
||||
ArgsUsage: "[filename(s)]",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "code", Aliases: []string{"c"}, Usage: "room codephrase (generated if not given)"},
|
||||
},
|
||||
HelpName: "share send",
|
||||
Action: send,
|
||||
},
|
||||
{
|
||||
Name: "relay",
|
||||
Usage: "start your own relay (optional)",
|
||||
Description: "start relay",
|
||||
HelpName: "share relay",
|
||||
Action: relay,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "host", Usage: "host of the relay"},
|
||||
&cli.IntFlag{Name: "port", Value: 9009, Usage: "port of the relay", EnvVars: []string{"SHARE_PORT"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
app.Flags = []cli.Flag{
|
||||
&cli.BoolFlag{Name: "internal-dns", Usage: "use a built-in DNS stub resolver rather than the host operating system"},
|
||||
&cli.BoolFlag{Name: "classic", Usage: "toggle between the classic mode (insecure due to local attack vector) and new mode (secure)"},
|
||||
&cli.BoolFlag{Name: "remember", Usage: "save these settings to reuse next time"},
|
||||
&cli.BoolFlag{Name: "debug", Usage: "toggle debug mode"},
|
||||
&cli.BoolFlag{Name: "yes", Usage: "automatically agree to all prompts"},
|
||||
&cli.BoolFlag{Name: "stdout", Usage: "redirect file to stdout"},
|
||||
&cli.BoolFlag{Name: "no-compress", Usage: "disable compression"},
|
||||
&cli.BoolFlag{Name: "ask", Usage: "make sure sender and recipient are prompted"},
|
||||
&cli.BoolFlag{Name: "local", Usage: "force to use only local connections"},
|
||||
&cli.BoolFlag{Name: "ignore-stdin", Usage: "ignore piped stdin"},
|
||||
&cli.BoolFlag{Name: "overwrite", Usage: "do not prompt to overwrite or resume"},
|
||||
&cli.BoolFlag{Name: "testing", Usage: "flag for testing purposes"},
|
||||
&cli.BoolFlag{Name: "quiet", Usage: "disable all output"},
|
||||
&cli.BoolFlag{Name: "disable-clipboard", Usage: "disable copy to clipboard"},
|
||||
&cli.BoolFlag{Name: "extended-clipboard", Usage: "copy full command with secret as env variable to clipboard"},
|
||||
&cli.StringFlag{Name: "multicast", Value: "239.255.255.250", Usage: "multicast address to use for local discovery"},
|
||||
&cli.StringFlag{Name: "curve", Value: "p256", Usage: "choose an encryption curve"},
|
||||
&cli.StringFlag{Name: "ip", Value: "", Usage: "set sender ip if known e.g. 10.0.0.1:9009, [::1]:9009"},
|
||||
&cli.StringFlag{Name: "relay", Value: models.DEFAULT_RELAY, Usage: "address of the relay", EnvVars: []string{"SHARE_RELAY"}},
|
||||
&cli.StringFlag{Name: "relay6", Value: models.DEFAULT_RELAY6, Usage: "ipv6 address of the relay", EnvVars: []string{"SHARE_RELAY6"}},
|
||||
&cli.StringFlag{Name: "out", Value: ".", Usage: "specify an output folder to receive the file"},
|
||||
&cli.BoolFlag{Name: "one-time", Usage: "exit once everything currently in the room is downloaded, instead of staying to help reseed it"},
|
||||
&cli.StringFlag{Name: "socks5", Value: "", Usage: "add a socks5 proxy", EnvVars: []string{"SOCKS5_PROXY"}},
|
||||
&cli.StringFlag{Name: "connect", Value: "", Usage: "add a http proxy", EnvVars: []string{"HTTP_PROXY"}},
|
||||
&cli.StringFlag{Name: "throttleUpload", Value: "", Usage: "throttle the upload speed e.g. 500k"},
|
||||
}
|
||||
app.EnableBashCompletion = true
|
||||
app.HideHelp = false
|
||||
app.HideVersion = false
|
||||
app.Action = func(c *cli.Context) error {
|
||||
return receive(c)
|
||||
share secret-code
|
||||
|
||||
COMMANDS:
|
||||
send seed file(s) into a room (see options with: share send -h)
|
||||
relay start your own relay (optional; see options with: share relay -h)
|
||||
|
||||
Run "share [command] -h" for the options of a given command.
|
||||
`
|
||||
|
||||
// Run parses os.Args and dispatches to the send, relay, or default
|
||||
// (receive) command. The subcommand keyword ("send"/"relay") is found
|
||||
// wherever it appears, not just as the very first argument, so flags can
|
||||
// come before or after it (e.g. both "share --relay X send file" and
|
||||
// "share send --code X file" work).
|
||||
func Run() error {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
if Version == "" {
|
||||
Version = "v0.1.0"
|
||||
}
|
||||
|
||||
return app.Run(os.Args)
|
||||
args := os.Args[1:]
|
||||
if len(args) > 0 {
|
||||
switch args[0] {
|
||||
case "-h", "--help", "help":
|
||||
fmt.Print(usage)
|
||||
return nil
|
||||
case "-v", "--version":
|
||||
fmt.Println(Version)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func setDebugLevel(c *cli.Context) {
|
||||
if c.Bool("quiet") {
|
||||
for i, a := range args {
|
||||
switch a {
|
||||
case "send":
|
||||
return runSend(splice(args, i))
|
||||
case "relay":
|
||||
return runRelay(splice(args, i))
|
||||
}
|
||||
}
|
||||
return runReceive(args)
|
||||
}
|
||||
|
||||
// splice removes the subcommand keyword at index i, leaving flags that
|
||||
// appeared before and after it in one list for that subcommand's own
|
||||
// flag.FlagSet to parse.
|
||||
func splice(args []string, i int) []string {
|
||||
out := make([]string, 0, len(args)-1)
|
||||
out = append(out, args[:i]...)
|
||||
out = append(out, args[i+1:]...)
|
||||
return out
|
||||
}
|
||||
|
||||
func setDebugLevel(quiet, debug bool) {
|
||||
switch {
|
||||
case quiet:
|
||||
log.SetLevel("error")
|
||||
} else if c.Bool("debug") {
|
||||
case debug:
|
||||
log.SetLevel("debug")
|
||||
log.Debug("debug mode on")
|
||||
} else {
|
||||
default:
|
||||
log.SetLevel("info")
|
||||
}
|
||||
}
|
||||
|
||||
func send(c *cli.Context) (err error) {
|
||||
setDebugLevel(c)
|
||||
files := c.Args().Slice()
|
||||
func defaultRelay() string {
|
||||
if v := os.Getenv("SHARE_RELAY"); v != "" {
|
||||
return v
|
||||
}
|
||||
return models.DEFAULT_RELAY
|
||||
}
|
||||
|
||||
func runSend(args []string) error {
|
||||
fs := flag.NewFlagSet("send", flag.ExitOnError)
|
||||
fs.Usage = func() {
|
||||
fmt.Fprintln(os.Stderr, "share send [options] file1 [file2 ...]")
|
||||
fs.PrintDefaults()
|
||||
}
|
||||
code := fs.String("code", "", "room codephrase (generated if not given)")
|
||||
relay := fs.String("relay", defaultRelay(), "address of the relay")
|
||||
debug := fs.Bool("debug", false, "toggle debug mode")
|
||||
quiet := fs.Bool("quiet", false, "disable all output")
|
||||
if err := fs.Parse(args); err != nil {
|
||||
return err
|
||||
}
|
||||
setDebugLevel(*quiet, *debug)
|
||||
|
||||
files := fs.Args()
|
||||
if len(files) == 0 {
|
||||
return fmt.Errorf("no files specified; usage: share send file1 [file2 ...]")
|
||||
}
|
||||
code := c.String("code")
|
||||
if code == "" {
|
||||
code = utils.GetRandomName()
|
||||
roomCode := *code
|
||||
if roomCode == "" {
|
||||
roomCode = utils.GetRandomName()
|
||||
}
|
||||
fmt.Printf("Code is: %s\n", code)
|
||||
fmt.Printf("Code is: %s\n", roomCode)
|
||||
fmt.Println("On the other computer, run:")
|
||||
fmt.Printf("\tshare %s\n", code)
|
||||
fmt.Printf("\tshare %s\n", roomCode)
|
||||
|
||||
return swarm.Run(swarm.Options{
|
||||
RelayAddress: c.String("relay"),
|
||||
Code: code,
|
||||
RelayAddress: *relay,
|
||||
Code: roomCode,
|
||||
Files: files,
|
||||
})
|
||||
}
|
||||
|
||||
func receive(c *cli.Context) (err error) {
|
||||
setDebugLevel(c)
|
||||
code := c.Args().First()
|
||||
if code == "" {
|
||||
return cli.ShowAppHelp(c)
|
||||
func runReceive(args []string) error {
|
||||
fs := flag.NewFlagSet("share", flag.ExitOnError)
|
||||
fs.Usage = func() {
|
||||
fmt.Print(usage)
|
||||
fs.PrintDefaults()
|
||||
}
|
||||
outDir := c.String("out")
|
||||
if outDir == "" {
|
||||
outDir = "."
|
||||
relay := fs.String("relay", defaultRelay(), "address of the relay")
|
||||
out := fs.String("out", ".", "specify an output folder to receive the file")
|
||||
oneTime := fs.Bool("one-time", false, "exit once everything currently in the room is downloaded, instead of staying to help reseed it")
|
||||
debug := fs.Bool("debug", false, "toggle debug mode")
|
||||
quiet := fs.Bool("quiet", false, "disable all output")
|
||||
if err := fs.Parse(args); err != nil {
|
||||
return err
|
||||
}
|
||||
setDebugLevel(*quiet, *debug)
|
||||
|
||||
code := fs.Arg(0)
|
||||
if code == "" {
|
||||
fs.Usage()
|
||||
return nil
|
||||
}
|
||||
|
||||
return swarm.Run(swarm.Options{
|
||||
RelayAddress: c.String("relay"),
|
||||
RelayAddress: *relay,
|
||||
Code: code,
|
||||
OutDir: outDir,
|
||||
OneTime: c.Bool("one-time"),
|
||||
OutDir: *out,
|
||||
OneTime: *oneTime,
|
||||
})
|
||||
}
|
||||
|
||||
func relay(c *cli.Context) (err error) {
|
||||
log.Infof("starting share relay version %v", Version)
|
||||
func runRelay(args []string) error {
|
||||
fs := flag.NewFlagSet("relay", flag.ExitOnError)
|
||||
fs.Usage = func() {
|
||||
fmt.Fprintln(os.Stderr, "share relay [options]")
|
||||
fs.PrintDefaults()
|
||||
}
|
||||
defaultPort := 9009
|
||||
if v := os.Getenv("SHARE_PORT"); v != "" {
|
||||
if p, err := strconv.Atoi(v); err == nil {
|
||||
defaultPort = p
|
||||
}
|
||||
}
|
||||
host := fs.String("host", "", "host of the relay")
|
||||
port := fs.Int("port", defaultPort, "port of the relay")
|
||||
debug := fs.Bool("debug", false, "toggle debug mode")
|
||||
if err := fs.Parse(args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
debugString := "info"
|
||||
if c.Bool("debug") {
|
||||
if *debug {
|
||||
debugString = "debug"
|
||||
}
|
||||
host := c.String("host")
|
||||
port := c.Int("port")
|
||||
if port == 0 {
|
||||
port = 9009
|
||||
}
|
||||
return tcp.Run(debugString, host, fmt.Sprintf("%d", port))
|
||||
log.Infof("starting share relay version %v", Version)
|
||||
return tcp.Run(debugString, *host, strconv.Itoa(*port))
|
||||
}
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
"github.com/magisterquis/connectproxy"
|
||||
"github.com/tzgyn/share/src/utils"
|
||||
log "github.com/schollz/logger"
|
||||
log "github.com/tzgyn/share/src/logger"
|
||||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
// Package logger is a minimal leveled logger, replacing the schollz/logger
|
||||
// dependency with an in-repo equivalent covering the same call surface
|
||||
// (SetLevel/SetOutput and Trace/Debug/Info/Warn/Error, each with an -f
|
||||
// variant) used throughout this project.
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
type level int
|
||||
|
||||
const (
|
||||
levelTrace level = iota
|
||||
levelDebug
|
||||
levelInfo
|
||||
levelWarn
|
||||
levelError
|
||||
)
|
||||
|
||||
var (
|
||||
current level = levelInfo
|
||||
loggers = map[level]*log.Logger{
|
||||
levelTrace: log.New(os.Stdout, "[trace]\t", log.Ltime|log.Lmicroseconds|log.Lshortfile),
|
||||
levelDebug: log.New(os.Stdout, "[debug]\t", log.Ltime|log.Lshortfile),
|
||||
levelInfo: log.New(os.Stdout, "[info]\t", log.Ldate|log.Ltime),
|
||||
levelWarn: log.New(os.Stdout, "[warn]\t", log.Ldate|log.Ltime),
|
||||
levelError: log.New(os.Stdout, "[error]\t", log.Ldate|log.Ltime|log.Lshortfile),
|
||||
}
|
||||
)
|
||||
|
||||
// SetOutput redirects all log levels to w.
|
||||
func SetOutput(w io.Writer) {
|
||||
for _, l := range loggers {
|
||||
l.SetOutput(w)
|
||||
}
|
||||
}
|
||||
|
||||
// SetLevel sets the minimum level that will be printed: one of
|
||||
// "trace", "debug", "info", "warn", "error". Unrecognized values are
|
||||
// treated as "trace" (print everything), matching the previous dependency's
|
||||
// behavior.
|
||||
func SetLevel(s string) {
|
||||
switch s {
|
||||
case "debug":
|
||||
current = levelDebug
|
||||
case "info":
|
||||
current = levelInfo
|
||||
case "warn":
|
||||
current = levelWarn
|
||||
case "error":
|
||||
current = levelError
|
||||
default:
|
||||
current = levelTrace
|
||||
}
|
||||
}
|
||||
|
||||
func output(lvl level, s string) {
|
||||
if lvl < current {
|
||||
return
|
||||
}
|
||||
loggers[lvl].Output(3, s)
|
||||
}
|
||||
|
||||
func Tracef(format string, v ...interface{}) { output(levelTrace, fmt.Sprintf(format, v...)) }
|
||||
func Debugf(format string, v ...interface{}) { output(levelDebug, fmt.Sprintf(format, v...)) }
|
||||
func Infof(format string, v ...interface{}) { output(levelInfo, fmt.Sprintf(format, v...)) }
|
||||
func Warnf(format string, v ...interface{}) { output(levelWarn, fmt.Sprintf(format, v...)) }
|
||||
func Errorf(format string, v ...interface{}) { output(levelError, fmt.Sprintf(format, v...)) }
|
||||
|
||||
func Trace(v ...interface{}) { output(levelTrace, fmt.Sprint(v...)) }
|
||||
func Debug(v ...interface{}) { output(levelDebug, fmt.Sprint(v...)) }
|
||||
func Info(v ...interface{}) { output(levelInfo, fmt.Sprint(v...)) }
|
||||
func Warn(v ...interface{}) { output(levelWarn, fmt.Sprint(v...)) }
|
||||
func Error(v ...interface{}) { output(levelError, fmt.Sprint(v...)) }
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/tzgyn/share/src/utils"
|
||||
log "github.com/schollz/logger"
|
||||
log "github.com/tzgyn/share/src/logger"
|
||||
)
|
||||
|
||||
// TCP_BUFFER_SIZE is the maximum packet size
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Zack
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,197 @@
|
||||
// Package pake implements a password-authenticated key exchange (a
|
||||
// SPAKE2-style protocol) over the NIST P256 curve from Go's standard
|
||||
// library. It's a trimmed fork of github.com/schollz/pake/v3, kept only
|
||||
// for the P256 case this project actually uses, so no external module
|
||||
// dependency (and no extra elliptic-curve implementations) are needed for
|
||||
// it. See LICENSE for the original project's MIT license.
|
||||
package pake
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// curve is fixed at P256; every peer link in this project uses the same
|
||||
// curve, so there's no need for the multi-curve selection the original
|
||||
// library offered.
|
||||
var curve = elliptic.P256()
|
||||
|
||||
// generator points U and V, fixed and known to both sides ahead of time
|
||||
// (not sent over the wire). Same values as upstream pake's "p256" curve,
|
||||
// verified below at init to still be valid P256 points.
|
||||
var (
|
||||
Uᵤ, _ = new(big.Int).SetString("793136080485469241208656611513609866400481671852", 10)
|
||||
Uᵥ, _ = new(big.Int).SetString("59748757929350367369315811184980635230185250460108398961713395032485227207304", 10)
|
||||
Vᵤ, _ = new(big.Int).SetString("1086685267857089638167386722555472967068468061489", 10)
|
||||
Vᵥ, _ = new(big.Int).SetString("9157340230202296554417312816309453883742349874205386245733062928888341584123", 10)
|
||||
P = elliptic.P256().Params().P
|
||||
)
|
||||
|
||||
func init() {
|
||||
if !curve.IsOnCurve(Uᵤ, Uᵥ) {
|
||||
panic("pake: U is not on curve")
|
||||
}
|
||||
if !curve.IsOnCurve(Vᵤ, Vᵥ) {
|
||||
panic("pake: V is not on curve")
|
||||
}
|
||||
}
|
||||
|
||||
// Pake keeps public and private variables by only transmitting between
|
||||
// parties after marshaling.
|
||||
//
|
||||
// This method follows
|
||||
// https://crypto.stanford.edu/~dabo/cryptobook/BonehShoup_0_4.pdf
|
||||
// Figure 21/15
|
||||
// http://www.lothar.com/~warner/MagicWormhole-PyCon2016.pdf
|
||||
// Slide 11
|
||||
type Pake struct {
|
||||
// Public variables
|
||||
Role int
|
||||
Xᵤ, Xᵥ *big.Int
|
||||
Yᵤ, Yᵥ *big.Int
|
||||
|
||||
// Private variables
|
||||
Pw []byte
|
||||
Vpwᵤ, Vpwᵥ *big.Int
|
||||
Upwᵤ, Upwᵥ *big.Int
|
||||
Aα []byte
|
||||
Aαᵤ, Aαᵥ *big.Int
|
||||
Zᵤ, Zᵥ *big.Int
|
||||
K []byte
|
||||
}
|
||||
|
||||
// Public returns the public variables of Pake, safe to marshal and send.
|
||||
func (p *Pake) Public() *Pake {
|
||||
return &Pake{
|
||||
Role: p.Role,
|
||||
Xᵤ: p.Xᵤ,
|
||||
Xᵥ: p.Xᵥ,
|
||||
Yᵤ: p.Yᵤ,
|
||||
Yᵥ: p.Yᵥ,
|
||||
}
|
||||
}
|
||||
|
||||
// InitCurve takes the shared weak passphrase (pw) to initialize the points
|
||||
// on the curve. role is 0 for the side that goes first (e.g. the dialer)
|
||||
// and 1 for the other side.
|
||||
func InitCurve(pw []byte, role int) (p *Pake, err error) {
|
||||
p = new(Pake)
|
||||
p.Pw = pw
|
||||
if role == 1 {
|
||||
p.Role = 1
|
||||
return
|
||||
}
|
||||
p.Role = 0
|
||||
|
||||
// STEP: A computes X
|
||||
p.Vpwᵤ, p.Vpwᵥ = curve.ScalarMult(Vᵤ, Vᵥ, p.Pw)
|
||||
p.Upwᵤ, p.Upwᵥ = curve.ScalarMult(Uᵤ, Uᵥ, p.Pw)
|
||||
p.Aα = make([]byte, 32) // randomly generated secret
|
||||
if _, err = rand.Read(p.Aα); err != nil {
|
||||
return
|
||||
}
|
||||
p.Aαᵤ, p.Aαᵥ = curve.ScalarBaseMult(p.Aα)
|
||||
p.Xᵤ, p.Xᵥ = curve.Add(p.Upwᵤ, p.Upwᵥ, p.Aαᵤ, p.Aαᵥ) // "X"
|
||||
// now X should be sent to B
|
||||
return
|
||||
}
|
||||
|
||||
// Bytes marshals the Pake structure so that private variables are hidden.
|
||||
func (p *Pake) Bytes() (b []byte) {
|
||||
if p == nil {
|
||||
panic("pake is not initialized")
|
||||
}
|
||||
b, err := json.Marshal(p.Public())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Update updates itself with the other party's marshaled Pake and
|
||||
// automatically determines what stage it's at and what to generate next.
|
||||
func (p *Pake) Update(qBytes []byte) (err error) {
|
||||
if p == nil {
|
||||
return fmt.Errorf("pake is not initialized")
|
||||
}
|
||||
var q *Pake
|
||||
if err = json.Unmarshal(qBytes, &q); err != nil {
|
||||
return
|
||||
}
|
||||
if p.Role == q.Role {
|
||||
return errors.New("can't have its own role")
|
||||
}
|
||||
|
||||
if p.Role == 1 {
|
||||
// copy over public variables
|
||||
p.Xᵤ, p.Xᵥ = q.Xᵤ, q.Xᵥ
|
||||
if !curve.IsOnCurve(p.Xᵤ, p.Xᵥ) {
|
||||
return errors.New("X values not on curve")
|
||||
}
|
||||
|
||||
// STEP: B computes Y
|
||||
p.Vpwᵤ, p.Vpwᵥ = curve.ScalarMult(Vᵤ, Vᵥ, p.Pw)
|
||||
p.Upwᵤ, p.Upwᵥ = curve.ScalarMult(Uᵤ, Uᵥ, p.Pw)
|
||||
p.Aα = make([]byte, 32) // randomly generated secret
|
||||
if _, err = rand.Read(p.Aα); err != nil {
|
||||
return
|
||||
}
|
||||
p.Aαᵤ, p.Aαᵥ = curve.ScalarBaseMult(p.Aα)
|
||||
p.Yᵤ, p.Yᵥ = curve.Add(p.Vpwᵤ, p.Vpwᵥ, p.Aαᵤ, p.Aαᵥ) // "Y"
|
||||
|
||||
// STEP: B computes Z
|
||||
v := new(big.Int).Neg(p.Upwᵥ)
|
||||
v.Mod(v, P)
|
||||
p.Zᵤ, p.Zᵥ = curve.Add(p.Xᵤ, p.Xᵥ, p.Upwᵤ, v)
|
||||
p.Zᵤ, p.Zᵥ = curve.ScalarMult(p.Zᵤ, p.Zᵥ, p.Aα)
|
||||
|
||||
// STEP: B computes k
|
||||
// H(pw,id_P,id_Q,X,Y,Z)
|
||||
p.K = sessionKey(p.Pw, p.Xᵤ, p.Xᵥ, p.Yᵤ, p.Yᵥ, p.Zᵤ, p.Zᵥ)
|
||||
} else {
|
||||
p.Yᵤ, p.Yᵥ = q.Yᵤ, q.Yᵥ
|
||||
if !curve.IsOnCurve(p.Yᵤ, p.Yᵥ) {
|
||||
return errors.New("Y values not on curve")
|
||||
}
|
||||
|
||||
// STEP: A computes Z
|
||||
v := new(big.Int).Neg(p.Vpwᵥ)
|
||||
v.Mod(v, P)
|
||||
p.Zᵤ, p.Zᵥ = curve.Add(p.Yᵤ, p.Yᵥ, p.Vpwᵤ, v)
|
||||
p.Zᵤ, p.Zᵥ = curve.ScalarMult(p.Zᵤ, p.Zᵥ, p.Aα)
|
||||
|
||||
// STEP: A computes k
|
||||
// H(pw,id_P,id_Q,X,Y,Z)
|
||||
p.K = sessionKey(p.Pw, p.Xᵤ, p.Xᵥ, p.Yᵤ, p.Yᵥ, p.Zᵤ, p.Zᵥ)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func sessionKey(pw []byte, xu, xv, yu, yv, zu, zv *big.Int) []byte {
|
||||
h := sha256.New()
|
||||
h.Write(pw)
|
||||
h.Write(xu.Bytes())
|
||||
h.Write(xv.Bytes())
|
||||
h.Write(yu.Bytes())
|
||||
h.Write(yv.Bytes())
|
||||
h.Write(zu.Bytes())
|
||||
h.Write(zv.Bytes())
|
||||
return h.Sum(nil)
|
||||
}
|
||||
|
||||
// SessionKey returns the derived session key, or an error if one hasn't
|
||||
// been generated yet (i.e. Update hasn't completed the exchange).
|
||||
func (p *Pake) SessionKey() ([]byte, error) {
|
||||
if p == nil {
|
||||
return nil, fmt.Errorf("pake is not initialized")
|
||||
}
|
||||
if p.K == nil {
|
||||
return nil, errors.New("session key not generated")
|
||||
}
|
||||
return p.K, nil
|
||||
}
|
||||
+1
-1
@@ -11,7 +11,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
log "github.com/schollz/logger"
|
||||
log "github.com/tzgyn/share/src/logger"
|
||||
|
||||
"github.com/tzgyn/share/src/comm"
|
||||
"github.com/tzgyn/share/src/tcp"
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package swarm
|
||||
|
||||
import (
|
||||
"github.com/schollz/pake/v3"
|
||||
|
||||
"github.com/tzgyn/share/src/comm"
|
||||
"github.com/tzgyn/share/src/pake"
|
||||
)
|
||||
|
||||
// handshake runs a PAKE key exchange over c using the room's codephrase as
|
||||
@@ -16,7 +15,7 @@ func handshake(c *comm.Comm, codephrase string, initiator bool) (key []byte, err
|
||||
if initiator {
|
||||
role = 0
|
||||
}
|
||||
p, err := pake.InitCurve([]byte(codephrase), role, "siec")
|
||||
p, err := pake.InitCurve([]byte(codephrase), role)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import (
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
log "github.com/schollz/logger"
|
||||
log "github.com/tzgyn/share/src/logger"
|
||||
)
|
||||
|
||||
type stop struct {
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
log "github.com/schollz/logger"
|
||||
log "github.com/tzgyn/share/src/logger"
|
||||
|
||||
"github.com/tzgyn/share/src/comm"
|
||||
)
|
||||
|
||||
+8
-90
@@ -26,8 +26,7 @@ import (
|
||||
"github.com/kalafut/imohash"
|
||||
"github.com/minio/highwayhash"
|
||||
"github.com/tzgyn/share/src/mnemonicode"
|
||||
log "github.com/schollz/logger"
|
||||
"github.com/schollz/progressbar/v3"
|
||||
log "github.com/tzgyn/share/src/logger"
|
||||
)
|
||||
|
||||
const NbPinNumbers = 4
|
||||
@@ -74,11 +73,7 @@ func GetInput(prompt string) string {
|
||||
return strings.TrimSpace(text)
|
||||
}
|
||||
|
||||
func HashFile(fname string, algorithm string, showProgress ...bool) (hash256 []byte, err error) {
|
||||
doShowProgress := false
|
||||
if len(showProgress) > 0 {
|
||||
doShowProgress = showProgress[0]
|
||||
}
|
||||
func HashFile(fname string, algorithm string) (hash256 []byte, err error) {
|
||||
var fstats os.FileInfo
|
||||
fstats, err = os.Lstat(fname)
|
||||
if err != nil {
|
||||
@@ -96,17 +91,17 @@ func HashFile(fname string, algorithm string, showProgress ...bool) (hash256 []b
|
||||
case "imohash":
|
||||
return IMOHashFile(fname)
|
||||
case "md5":
|
||||
return MD5HashFile(fname, doShowProgress)
|
||||
return MD5HashFile(fname)
|
||||
case "xxhash":
|
||||
return XXHashFile(fname, doShowProgress)
|
||||
return XXHashFile(fname)
|
||||
case "highway":
|
||||
return HighwayHashFile(fname, doShowProgress)
|
||||
return HighwayHashFile(fname)
|
||||
}
|
||||
err = fmt.Errorf("unspecified algorithm")
|
||||
return
|
||||
}
|
||||
|
||||
func HighwayHashFile(fname string, doShowProgress bool) (hashHighway []byte, err error) {
|
||||
func HighwayHashFile(fname string) (hashHighway []byte, err error) {
|
||||
f, err := os.Open(fname)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -121,33 +116,15 @@ func HighwayHashFile(fname string, doShowProgress bool) (hashHighway []byte, err
|
||||
err = fmt.Errorf("could not create highwayhash: %s", err.Error())
|
||||
return
|
||||
}
|
||||
if doShowProgress {
|
||||
stat, _ := f.Stat()
|
||||
fnameShort := path.Base(fname)
|
||||
if len(fnameShort) > 20 {
|
||||
fnameShort = fnameShort[:20] + "..."
|
||||
}
|
||||
bar := progressbar.NewOptions64(stat.Size(),
|
||||
progressbar.OptionSetWriter(os.Stderr),
|
||||
progressbar.OptionShowBytes(true),
|
||||
progressbar.OptionSetDescription(fmt.Sprintf("Hashing %s", fnameShort)),
|
||||
progressbar.OptionClearOnFinish(),
|
||||
progressbar.OptionFullWidth(),
|
||||
)
|
||||
if _, err = io.Copy(io.MultiWriter(h, bar), f); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if _, err = io.Copy(h, f); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
hashHighway = h.Sum(nil)
|
||||
return
|
||||
}
|
||||
|
||||
func MD5HashFile(fname string, doShowProgress bool) (hash256 []byte, err error) {
|
||||
func MD5HashFile(fname string) (hash256 []byte, err error) {
|
||||
f, err := os.Open(fname)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -155,27 +132,9 @@ func MD5HashFile(fname string, doShowProgress bool) (hash256 []byte, err error)
|
||||
defer f.Close()
|
||||
|
||||
h := md5.New()
|
||||
if doShowProgress {
|
||||
stat, _ := f.Stat()
|
||||
fnameShort := path.Base(fname)
|
||||
if len(fnameShort) > 20 {
|
||||
fnameShort = fnameShort[:20] + "..."
|
||||
}
|
||||
bar := progressbar.NewOptions64(stat.Size(),
|
||||
progressbar.OptionSetWriter(os.Stderr),
|
||||
progressbar.OptionShowBytes(true),
|
||||
progressbar.OptionSetDescription(fmt.Sprintf("Hashing %s", fnameShort)),
|
||||
progressbar.OptionClearOnFinish(),
|
||||
progressbar.OptionFullWidth(),
|
||||
)
|
||||
if _, err = io.Copy(io.MultiWriter(h, bar), f); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if _, err = io.Copy(h, f); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
hash256 = h.Sum(nil)
|
||||
return
|
||||
@@ -196,7 +155,7 @@ func IMOHashFileFull(fname string) (hash []byte, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func XXHashFile(fname string, doShowProgress bool) (hash256 []byte, err error) {
|
||||
func XXHashFile(fname string) (hash256 []byte, err error) {
|
||||
f, err := os.Open(fname)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -204,27 +163,9 @@ func XXHashFile(fname string, doShowProgress bool) (hash256 []byte, err error) {
|
||||
defer f.Close()
|
||||
|
||||
h := xxhash.New()
|
||||
if doShowProgress {
|
||||
stat, _ := f.Stat()
|
||||
fnameShort := path.Base(fname)
|
||||
if len(fnameShort) > 20 {
|
||||
fnameShort = fnameShort[:20] + "..."
|
||||
}
|
||||
bar := progressbar.NewOptions64(stat.Size(),
|
||||
progressbar.OptionSetWriter(os.Stderr),
|
||||
progressbar.OptionShowBytes(true),
|
||||
progressbar.OptionSetDescription(fmt.Sprintf("Hashing %s", fnameShort)),
|
||||
progressbar.OptionClearOnFinish(),
|
||||
progressbar.OptionFullWidth(),
|
||||
)
|
||||
if _, err = io.Copy(io.MultiWriter(h, bar), f); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if _, err = io.Copy(h, f); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
hash256 = h.Sum(nil)
|
||||
return
|
||||
@@ -310,23 +251,6 @@ func MissingChunks(fname string, fsize int64, chunkSize int) (chunkRanges []int6
|
||||
return
|
||||
}
|
||||
|
||||
var bar *progressbar.ProgressBar
|
||||
showProgress := fsize > 10*1024*1024
|
||||
if showProgress {
|
||||
fnameShort := path.Base(fname)
|
||||
if len(fnameShort) > 20 {
|
||||
fnameShort = fnameShort[:20] + "..."
|
||||
}
|
||||
bar = progressbar.NewOptions64(fsize,
|
||||
progressbar.OptionSetWriter(os.Stderr),
|
||||
progressbar.OptionShowBytes(true),
|
||||
progressbar.OptionSetDescription(fmt.Sprintf("Checking %s", fnameShort)),
|
||||
progressbar.OptionClearOnFinish(),
|
||||
progressbar.OptionFullWidth(),
|
||||
progressbar.OptionThrottle(100*time.Millisecond),
|
||||
)
|
||||
}
|
||||
|
||||
emptyBuffer := make([]byte, chunkSize)
|
||||
chunkNum := 0
|
||||
chunks := make([]int64, int64(math.Ceil(float64(fsize)/float64(chunkSize))))
|
||||
@@ -342,12 +266,6 @@ func MissingChunks(fname string, fsize int64, chunkSize int) (chunkRanges []int6
|
||||
chunkNum++
|
||||
}
|
||||
currentLocation += int64(bytesread)
|
||||
if showProgress && bar != nil {
|
||||
bar.Add(bytesread)
|
||||
}
|
||||
}
|
||||
if showProgress && bar != nil {
|
||||
bar.Finish()
|
||||
}
|
||||
if chunkNum == 0 {
|
||||
chunkRanges = []int64{}
|
||||
|
||||
Reference in New Issue
Block a user