github.com/oskarth/go-ethereum@v1.6.8-0.20191013093314-dac24a9d3494/cmd/swarm/upload.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 // Command bzzup uploads files to the swarm HTTP API. 18 package main 19 20 import ( 21 "errors" 22 "fmt" 23 "io" 24 "io/ioutil" 25 "os" 26 "os/user" 27 "path" 28 "path/filepath" 29 "strings" 30 31 swarm "github.com/ethereum/go-ethereum/swarm/api/client" 32 33 "github.com/ethereum/go-ethereum/cmd/utils" 34 "gopkg.in/urfave/cli.v1" 35 ) 36 37 var upCommand = cli.Command{ 38 Action: upload, 39 CustomHelpTemplate: helpTemplate, 40 Name: "up", 41 Usage: "uploads a file or directory to swarm using the HTTP API", 42 ArgsUsage: "<file>", 43 Flags: []cli.Flag{SwarmEncryptedFlag}, 44 Description: "uploads a file or directory to swarm using the HTTP API and prints the root hash", 45 } 46 47 func upload(ctx *cli.Context) { 48 args := ctx.Args() 49 var ( 50 bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/") 51 recursive = ctx.GlobalBool(SwarmRecursiveFlag.Name) 52 wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name) 53 defaultPath = ctx.GlobalString(SwarmUploadDefaultPath.Name) 54 fromStdin = ctx.GlobalBool(SwarmUpFromStdinFlag.Name) 55 mimeType = ctx.GlobalString(SwarmUploadMimeType.Name) 56 client = swarm.NewClient(bzzapi) 57 toEncrypt = ctx.Bool(SwarmEncryptedFlag.Name) 58 file string 59 ) 60 61 if len(args) != 1 { 62 if fromStdin { 63 tmp, err := ioutil.TempFile("", "swarm-stdin") 64 if err != nil { 65 utils.Fatalf("error create tempfile: %s", err) 66 } 67 defer os.Remove(tmp.Name()) 68 n, err := io.Copy(tmp, os.Stdin) 69 if err != nil { 70 utils.Fatalf("error copying stdin to tempfile: %s", err) 71 } else if n == 0 { 72 utils.Fatalf("error reading from stdin: zero length") 73 } 74 file = tmp.Name() 75 } else { 76 utils.Fatalf("Need filename as the first and only argument") 77 } 78 } else { 79 file = expandPath(args[0]) 80 } 81 82 if !wantManifest { 83 f, err := swarm.Open(file) 84 if err != nil { 85 utils.Fatalf("Error opening file: %s", err) 86 } 87 defer f.Close() 88 hash, err := client.UploadRaw(f, f.Size, toEncrypt) 89 if err != nil { 90 utils.Fatalf("Upload failed: %s", err) 91 } 92 fmt.Println(hash) 93 return 94 } 95 96 stat, err := os.Stat(file) 97 if err != nil { 98 utils.Fatalf("Error opening file: %s", err) 99 } 100 101 // define a function which either uploads a directory or single file 102 // based on the type of the file being uploaded 103 var doUpload func() (hash string, err error) 104 if stat.IsDir() { 105 doUpload = func() (string, error) { 106 if !recursive { 107 return "", errors.New("Argument is a directory and recursive upload is disabled") 108 } 109 if defaultPath != "" { 110 // construct absolute default path 111 absDefaultPath, _ := filepath.Abs(defaultPath) 112 absFile, _ := filepath.Abs(file) 113 // make sure absolute directory ends with only one "/" 114 // to trim it from absolute default path and get relative default path 115 absFile = strings.TrimRight(absFile, "/") + "/" 116 if absDefaultPath != "" && absFile != "" && strings.HasPrefix(absDefaultPath, absFile) { 117 defaultPath = strings.TrimPrefix(absDefaultPath, absFile) 118 } 119 } 120 return client.UploadDirectory(file, defaultPath, "", toEncrypt) 121 } 122 } else { 123 doUpload = func() (string, error) { 124 f, err := swarm.Open(file) 125 if err != nil { 126 return "", fmt.Errorf("error opening file: %s", err) 127 } 128 defer f.Close() 129 if mimeType != "" { 130 f.ContentType = mimeType 131 } 132 return client.Upload(f, "", toEncrypt) 133 } 134 } 135 hash, err := doUpload() 136 if err != nil { 137 utils.Fatalf("Upload failed: %s", err) 138 } 139 fmt.Println(hash) 140 } 141 142 // Expands a file path 143 // 1. replace tilde with users home dir 144 // 2. expands embedded environment variables 145 // 3. cleans the path, e.g. /a/b/../c -> /a/c 146 // Note, it has limitations, e.g. ~someuser/tmp will not be expanded 147 func expandPath(p string) string { 148 if i := strings.Index(p, ":"); i > 0 { 149 return p 150 } 151 if i := strings.Index(p, "@"); i > 0 { 152 return p 153 } 154 if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") { 155 if home := homeDir(); home != "" { 156 p = home + p[1:] 157 } 158 } 159 return path.Clean(os.ExpandEnv(p)) 160 } 161 162 func homeDir() string { 163 if home := os.Getenv("HOME"); home != "" { 164 return home 165 } 166 if usr, err := user.Current(); err == nil { 167 return usr.HomeDir 168 } 169 return "" 170 }