package coreapi import ( "context" "fmt" "github.com/ipfs/go-ipfs/core" "io" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" "github.com/ipfs/go-ipfs/core/coreapi/interface/options" "github.com/ipfs/go-ipfs/core/coreunix" cidutil "gx/ipfs/QmQJSeE3CX4zos9qeaG8EhecEK9zvrTEfTG84J8C5NVRwt/go-cidutil" offline "gx/ipfs/QmR5miWuikPxWyUrzMYJVmFUcD44pGdtc98h9Qsbp4YcJw/go-ipfs-exchange-offline" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit/files" ft "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs" uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" mfs "gx/ipfs/QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2/go-mfs" dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" dagtest "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag/test" blockservice "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" bstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" ) type UnixfsAPI CoreAPI // Add builds a merkledag node from a reader, adds it to the blockstore, // and returns the key representing that node. func (api *UnixfsAPI) Add(ctx context.Context, r io.ReadCloser, opts ...options.UnixfsAddOption) (coreiface.ResolvedPath, error) { settings, prefix, err := options.UnixfsAddOptions(opts...) if err != nil { return nil, err } n := api.node if settings.OnlyHash { nilnode, err := core.NewNode(ctx, &core.BuildCfg{ //TODO: need this to be true or all files // hashed will be stored in memory! NilRepo: true, }) if err != nil { return nil, err } n = nilnode } addblockstore := n.Blockstore //if !(fscache || nocopy) { addblockstore = bstore.NewGCBlockstore(n.BaseBlocks, n.GCLocker) //} exch := n.Exchange if settings.Local { exch = offline.Exchange(addblockstore) } bserv := blockservice.New(addblockstore, exch) // hash security 001 dserv := dag.NewDAGService(bserv) fileAdder, err := coreunix.NewAdder(ctx, n.Pinning, n.Blockstore, dserv) if err != nil { return nil, err } fileAdder.Chunker = settings.Chunker //fileAdder.Progress = progress //fileAdder.Hidden = hidden //fileAdder.Wrap = wrap fileAdder.Pin = settings.Pin fileAdder.Silent = true fileAdder.RawLeaves = settings.RawLeaves //fileAdder.NoCopy = nocopy //fileAdder.Name = pathName fileAdder.CidBuilder = prefix switch settings.Layout { case options.BalancedLayout: // Default case options.TrickleLeyout: fileAdder.Trickle = true default: return nil, fmt.Errorf("unknown layout: %d", settings.Layout) } if settings.InlineLimit > 0 { fileAdder.CidBuilder = cidutil.InlineBuilder{ Builder: fileAdder.CidBuilder, Limit: settings.InlineLimit, } } if settings.OnlyHash { md := dagtest.Mock() emptyDirNode := ft.EmptyDirNode() // Use the same prefix for the "empty" MFS root as for the file adder. emptyDirNode.SetCidBuilder(fileAdder.CidBuilder) mr, err := mfs.NewRoot(ctx, md, emptyDirNode, nil) if err != nil { return nil, err } fileAdder.SetMfsRoot(mr) } err = fileAdder.AddFile(files.NewReaderFile("", "", r, nil)) if err != nil { return nil, err } nd, err := fileAdder.Finalize() if err != nil { return nil, err } if settings.Pin { err = fileAdder.PinRoot() } return coreiface.IpfsPath(nd.Cid()), err } // Cat returns the data contained by an IPFS or IPNS object(s) at path `p`. func (api *UnixfsAPI) Cat(ctx context.Context, p coreiface.Path) (coreiface.Reader, error) { dget := api.node.DAG // TODO: use a session here once routing perf issues are resolved dagnode, err := api.core().ResolveNode(ctx, p) if err != nil { return nil, err } r, err := uio.NewDagReader(ctx, dagnode, dget) if err == uio.ErrIsDir { return nil, coreiface.ErrIsDir } else if err != nil { return nil, err } return r, nil } // Ls returns the contents of an IPFS or IPNS object(s) at path p, with the format: // ` ` func (api *UnixfsAPI) Ls(ctx context.Context, p coreiface.Path) ([]*ipld.Link, error) { dagnode, err := api.core().ResolveNode(ctx, p) if err != nil { return nil, err } var ndlinks []*ipld.Link dir, err := uio.NewDirectoryFromNode(api.node.DAG, dagnode) switch err { case nil: l, err := dir.Links(ctx) if err != nil { return nil, err } ndlinks = l case uio.ErrNotADir: ndlinks = dagnode.Links() default: return nil, err } links := make([]*ipld.Link, len(ndlinks)) for i, l := range ndlinks { links[i] = &ipld.Link{Name: l.Name, Size: l.Size, Cid: l.Cid} } return links, nil } func (api *UnixfsAPI) core() coreiface.CoreAPI { return (*CoreAPI)(api) }