gopkg.in/hugelgupf/u-root.v7@v7.0.0-20180831062900-6a07824681b2/cmds/scp/scp.go (about) 1 // Copyright 2012-2018 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Scp copies files between hosts on a network. 6 // 7 // Synopsis: 8 // scp [-t|-f] [FILE] 9 // 10 // Description: 11 // If -t is given, decode SCP protocol from stdin and write to FILE. 12 // If -f is given, stream FILE over SCP protocol to stdout. 13 // 14 // Options: 15 // -t: Act as the target 16 // -f: Act as the source 17 // -v: Passed if SCP is verbose, ignored 18 package main 19 20 import ( 21 "flag" 22 "fmt" 23 "io" 24 "log" 25 "os" 26 ) 27 28 const ( 29 SUCCESS = 0 30 ) 31 32 var ( 33 isTarget = flag.Bool("t", false, "Act as the target") 34 isSource = flag.Bool("f", false, "Act as the source") 35 _ = flag.Bool("v", false, "Ignored") 36 ) 37 38 func scpSource(w io.Writer, path string) error { 39 f, err := os.Open(path) 40 if err != nil { 41 return err 42 } 43 defer f.Close() 44 s, err := f.Stat() 45 if err != nil { 46 return err 47 } 48 w.Write([]byte(fmt.Sprintf("C0%o %d %s\n", s.Mode(), s.Size(), path))) 49 if response() != SUCCESS { 50 log.Fatalf("response was not success") 51 } 52 _, err = io.Copy(w, f) 53 if err != nil { 54 log.Fatalf("copy error: %v", err) 55 } 56 reply(SUCCESS) 57 58 if response() != SUCCESS { 59 log.Fatalf("response was not success") 60 } 61 return nil 62 } 63 64 func scpSink(r io.Reader, path string) error { 65 var mode os.FileMode 66 var size int64 67 filename := "" 68 69 if _, err := fmt.Fscanf(r, "C0%o %d %s\n", &mode, &size, &filename); err != nil { 70 return err 71 } 72 f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, mode) 73 if err != nil { 74 log.Fatalf("open error: %v", err) 75 } 76 reply(SUCCESS) 77 defer f.Close() 78 79 _, err = io.CopyN(f, r, size) 80 if err != nil { 81 log.Fatalf("copy error: %v", err) 82 } 83 reply(SUCCESS) 84 return nil 85 } 86 87 func reply(r byte) { 88 os.Stdout.Write([]byte{r}) 89 } 90 91 func response() byte { 92 b := make([]byte, 1) 93 os.Stdout.Read(b) 94 return b[0] 95 } 96 97 func main() { 98 flag.Parse() 99 100 if flag.NArg() == 0 { 101 log.Fatalf("no file provided") 102 } 103 104 if *isSource == *isTarget { 105 log.Fatalf("-t or -f needs to be supplied, and not both") 106 } 107 108 if *isSource { 109 // Sink->Source is started with a response 110 if response() != SUCCESS { 111 log.Fatalf("response was not success") 112 } 113 if err := scpSource(os.Stdout, flag.Args()[0]); err != nil { 114 log.Fatalf("scp: %v", err) 115 } 116 } else if *isTarget { 117 // Sink->Source starts with a response 118 reply(SUCCESS) 119 for { 120 if err := scpSink(os.Stdin, flag.Args()[0]); err != nil { 121 log.Fatalf("scp: %v", err) 122 } 123 } 124 } 125 }