github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/cmd/ipfs/init.go (about) 1 package main 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "os" 8 "path" 9 10 context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" 11 assets "github.com/ipfs/go-ipfs/assets" 12 cmds "github.com/ipfs/go-ipfs/commands" 13 core "github.com/ipfs/go-ipfs/core" 14 namesys "github.com/ipfs/go-ipfs/namesys" 15 config "github.com/ipfs/go-ipfs/repo/config" 16 fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo" 17 ) 18 19 const nBitsForKeypairDefault = 2048 20 21 var initCmd = &cmds.Command{ 22 Helptext: cmds.HelpText{ 23 Tagline: "Initializes IPFS config file", 24 ShortDescription: "Initializes IPFS configuration files and generates a new keypair.", 25 }, 26 27 Options: []cmds.Option{ 28 cmds.IntOption("bits", "b", fmt.Sprintf("Number of bits to use in the generated RSA private key (defaults to %d)", nBitsForKeypairDefault)), 29 cmds.BoolOption("force", "f", "Overwrite existing config (if it exists)"), 30 cmds.BoolOption("empty-repo", "e", "Don't add and pin help files to the local storage"), 31 32 // TODO need to decide whether to expose the override as a file or a 33 // directory. That is: should we allow the user to also specify the 34 // name of the file? 35 // TODO cmds.StringOption("event-logs", "l", "Location for machine-readable event logs"), 36 }, 37 PreRun: func(req cmds.Request) error { 38 daemonLocked, err := fsrepo.LockedByOtherProcess(req.InvocContext().ConfigRoot) 39 if err != nil { 40 return err 41 } 42 43 log.Info("checking if daemon is running...") 44 if daemonLocked { 45 e := "ipfs daemon is running. please stop it to run this command" 46 return cmds.ClientError(e) 47 } 48 49 return nil 50 }, 51 Run: func(req cmds.Request, res cmds.Response) { 52 if req.InvocContext().Online { 53 res.SetError(errors.New("init must be run offline only!"), cmds.ErrNormal) 54 return 55 } 56 57 force, _, err := req.Option("f").Bool() // if !found, it's okay force == false 58 if err != nil { 59 res.SetError(err, cmds.ErrNormal) 60 return 61 } 62 63 empty, _, err := req.Option("e").Bool() // if !empty, it's okay empty == false 64 if err != nil { 65 res.SetError(err, cmds.ErrNormal) 66 return 67 } 68 69 nBitsForKeypair, bitsOptFound, err := req.Option("b").Int() 70 if err != nil { 71 res.SetError(err, cmds.ErrNormal) 72 return 73 } 74 75 if !bitsOptFound { 76 nBitsForKeypair = nBitsForKeypairDefault 77 } 78 79 if err := doInit(os.Stdout, req.InvocContext().ConfigRoot, force, empty, nBitsForKeypair); err != nil { 80 res.SetError(err, cmds.ErrNormal) 81 return 82 } 83 }, 84 } 85 86 var errRepoExists = errors.New(`ipfs configuration file already exists! 87 Reinitializing would overwrite your keys. 88 (use -f to force overwrite) 89 `) 90 91 func initWithDefaults(out io.Writer, repoRoot string) error { 92 return doInit(out, repoRoot, false, false, nBitsForKeypairDefault) 93 } 94 95 func doInit(out io.Writer, repoRoot string, force bool, empty bool, nBitsForKeypair int) error { 96 if _, err := fmt.Fprintf(out, "initializing ipfs node at %s\n", repoRoot); err != nil { 97 return err 98 } 99 100 if err := checkWriteable(repoRoot); err != nil { 101 return err 102 } 103 104 if fsrepo.IsInitialized(repoRoot) && !force { 105 return errRepoExists 106 } 107 108 conf, err := config.Init(out, nBitsForKeypair) 109 if err != nil { 110 return err 111 } 112 113 if fsrepo.IsInitialized(repoRoot) { 114 if err := fsrepo.Remove(repoRoot); err != nil { 115 return err 116 } 117 } 118 119 if err := fsrepo.Init(repoRoot, conf); err != nil { 120 return err 121 } 122 123 if !empty { 124 if err := addDefaultAssets(out, repoRoot); err != nil { 125 return err 126 } 127 } 128 129 return initializeIpnsKeyspace(repoRoot) 130 } 131 132 func checkWriteable(dir string) error { 133 _, err := os.Stat(dir) 134 if err == nil { 135 // dir exists, make sure we can write to it 136 testfile := path.Join(dir, "test") 137 fi, err := os.Create(testfile) 138 if err != nil { 139 if os.IsPermission(err) { 140 return fmt.Errorf("%s is not writeable by the current user", dir) 141 } 142 return fmt.Errorf("unexpected error while checking writeablility of repo root: %s", err) 143 } 144 fi.Close() 145 return os.Remove(testfile) 146 } 147 148 if os.IsNotExist(err) { 149 // dir doesnt exist, check that we can create it 150 return os.Mkdir(dir, 0775) 151 } 152 153 if os.IsPermission(err) { 154 return fmt.Errorf("cannot write to %s, incorrect permissions", err) 155 } 156 157 return err 158 } 159 160 func addDefaultAssets(out io.Writer, repoRoot string) error { 161 ctx, cancel := context.WithCancel(context.Background()) 162 defer cancel() 163 164 r, err := fsrepo.Open(repoRoot) 165 if err != nil { // NB: repo is owned by the node 166 return err 167 } 168 169 nd, err := core.NewNode(ctx, &core.BuildCfg{Repo: r}) 170 if err != nil { 171 return err 172 } 173 defer nd.Close() 174 175 dkey, err := assets.SeedInitDocs(nd) 176 if err != nil { 177 return fmt.Errorf("init: seeding init docs failed: %s", err) 178 } 179 log.Debugf("init: seeded init docs %s", dkey) 180 181 if _, err = fmt.Fprintf(out, "to get started, enter:\n"); err != nil { 182 return err 183 } 184 185 _, err = fmt.Fprintf(out, "\n\tipfs cat /ipfs/%s/readme\n\n", dkey) 186 return err 187 } 188 189 func initializeIpnsKeyspace(repoRoot string) error { 190 ctx, cancel := context.WithCancel(context.Background()) 191 defer cancel() 192 193 r, err := fsrepo.Open(repoRoot) 194 if err != nil { // NB: repo is owned by the node 195 return err 196 } 197 198 nd, err := core.NewNode(ctx, &core.BuildCfg{Repo: r}) 199 if err != nil { 200 return err 201 } 202 defer nd.Close() 203 204 err = nd.SetupOfflineRouting() 205 if err != nil { 206 return err 207 } 208 209 return namesys.InitializeKeyspace(ctx, nd.DAG, nd.Namesys, nd.Pinning, nd.PrivateKey) 210 }