package coreapi import ( "bytes" "context" "errors" "fmt" "io" "io/ioutil" util "github.com/ipfs/go-ipfs/blocks/blockstoreutil" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options" mh "gx/ipfs/QmZyZDi491cCNTLfAhwcaDii2Kg4pwKRkhqQzURGDvY6ua/go-multihash" cid "gx/ipfs/QmcZfnkapfECQGcLZaf9B79NRg7cRa9EnZh4LSbkCzwNvY/go-cid" blocks "gx/ipfs/Qmej7nf81hi2x2tvjRBF3mcp74sQyuDH4VMYDGd1YtXjb2/go-block-format" ) type BlockAPI struct { *CoreAPI *caopts.BlockOptions } type BlockStat struct { path coreiface.Path size int } func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.BlockPutOption) (coreiface.Path, error) { settings, err := caopts.BlockPutOptions(opts...) if err != nil { return nil, err } data, err := ioutil.ReadAll(src) if err != nil { return nil, err } var pref cid.Prefix pref.Version = 1 formatval, ok := cid.Codecs[settings.Codec] if !ok { return nil, fmt.Errorf("unrecognized format: %s", settings.Codec) } if settings.Codec == "v0" && settings.MhType == mh.SHA2_256 { pref.Version = 0 } pref.Codec = formatval pref.MhType = settings.MhType pref.MhLength = settings.MhLength bcid, err := pref.Sum(data) if err != nil { return nil, err } b, err := blocks.NewBlockWithCid(data, bcid) if err != nil { return nil, err } err = api.node.Blocks.AddBlock(b) if err != nil { return nil, err } return ParseCid(b.Cid()), nil } func (api *BlockAPI) Get(ctx context.Context, p coreiface.Path) (io.Reader, error) { b, err := api.node.Blocks.GetBlock(ctx, p.Cid()) if err != nil { return nil, err } return bytes.NewReader(b.RawData()), nil } func (api *BlockAPI) Rm(ctx context.Context, p coreiface.Path, opts ...caopts.BlockRmOption) error { settings, err := caopts.BlockRmOptions(opts...) if err != nil { return err } cids := []*cid.Cid{p.Cid()} o := util.RmBlocksOpts{Force: settings.Force} out, err := util.RmBlocks(api.node.Blockstore, api.node.Pinning, cids, o) if err != nil { return err } select { case res, ok := <-out: if !ok { return nil } remBlock, ok := res.(*util.RemovedBlock) if !ok { return errors.New("got unexpected output from util.RmBlocks") } if remBlock.Error != "" { return errors.New(remBlock.Error) } return nil case <-ctx.Done(): return ctx.Err() } } func (api *BlockAPI) Stat(ctx context.Context, p coreiface.Path) (coreiface.BlockStat, error) { b, err := api.node.Blocks.GetBlock(ctx, p.Cid()) if err != nil { return nil, err } return &BlockStat{ path: ParseCid(b.Cid()), size: len(b.RawData()), }, nil } func (bs *BlockStat) Size() int { return bs.size } func (bs *BlockStat) Path() coreiface.Path { return bs.path }