From 3a1eae5b6b77b85ba792f7aec2790cdc0cf5ed3c Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 29 Mar 2021 22:13:06 -0700 Subject: [PATCH] cmd/tailscale/cli: factor out filename selection Signed-off-by: Brad Fitzpatrick --- cmd/tailscale/cli/push.go | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/cmd/tailscale/cli/push.go b/cmd/tailscale/cli/push.go index f6bec389a..98fefe846 100644 --- a/cmd/tailscale/cli/push.go +++ b/cmd/tailscale/cli/push.go @@ -18,6 +18,7 @@ import ( "net/url" "os" "time" + "unicode/utf8" "github.com/peterbourgon/ff/v2/ffcli" "tailscale.com/ipn" @@ -64,16 +65,10 @@ func runPush(ctx context.Context, args []string) error { if fileArg == "-" { fileContents = os.Stdin if name == "" { - sniff, err := io.ReadAll(io.LimitReader(fileContents, 4<<20)) + name, fileContents, err = pickStdinFilename() if err != nil { return err } - if exts, _ := mime.ExtensionsByType(http.DetectContentType(sniff)); len(exts) > 0 { - name = "stdin" + exts[0] - } else { - name = "stdin.txt" - } - fileContents = io.MultiReader(bytes.NewReader(sniff), fileContents) } } else { f, err := os.Open(fileArg) @@ -153,3 +148,26 @@ func discoverPeerAPIPort(ctx context.Context, ip string) (port uint16, err error } } } + +const maxSniff = 4 << 20 + +func ext(b []byte) string { + if len(b) < maxSniff && utf8.Valid(b) { + return ".txt" + } + if exts, _ := mime.ExtensionsByType(http.DetectContentType(b)); len(exts) > 0 { + return exts[0] + } + return "" +} + +// pickStdinFilename reads a bit of stdin to return a good filename +// for its contents. The returned Reader is the concatenation of the +// read and unread bits. +func pickStdinFilename() (name string, r io.Reader, err error) { + sniff, err := io.ReadAll(io.LimitReader(os.Stdin, maxSniff)) + if err != nil { + return "", nil, err + } + return "stdin" + ext(sniff), io.MultiReader(bytes.NewReader(sniff), os.Stdin), nil +}