github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/core/commands/object.go (about)

     1  package commands
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  	"io/ioutil"
    10  	"os"
    11  
    12  	"github.com/jbenet/go-ipfs/core"
    13  	dag "github.com/jbenet/go-ipfs/merkledag"
    14  )
    15  
    16  // ObjectData takes a key string from args and writes out the raw bytes of that node (if there is one)
    17  func ObjectData(n *core.IpfsNode, args []string, opts map[string]interface{}, out io.Writer) error {
    18  	dagnode, err := n.Resolver.ResolvePath(args[0])
    19  	if err != nil {
    20  		return fmt.Errorf("objectData error: %v", err)
    21  	}
    22  	log.Debugf("objectData: found dagnode %q (# of bytes: %d - # links: %d)", args[0], len(dagnode.Data), len(dagnode.Links))
    23  
    24  	_, err = io.Copy(out, bytes.NewReader(dagnode.Data))
    25  	return err
    26  }
    27  
    28  // ObjectLinks takes a key string from args and lists the links it points to
    29  func ObjectLinks(n *core.IpfsNode, args []string, opts map[string]interface{}, out io.Writer) error {
    30  	dagnode, err := n.Resolver.ResolvePath(args[0])
    31  	if err != nil {
    32  		return fmt.Errorf("objectLinks error: %v", err)
    33  	}
    34  	log.Debugf("ObjectLinks: found dagnode %q (# of bytes: %d - # links: %d)", args[0], len(dagnode.Data), len(dagnode.Links))
    35  
    36  	for _, link := range dagnode.Links {
    37  		_, err = fmt.Fprintf(out, "%s %d %q\n", link.Hash.B58String(), link.Size, link.Name)
    38  		if err != nil {
    39  			break
    40  		}
    41  	}
    42  
    43  	return err
    44  }
    45  
    46  // ErrUnknownObjectEnc is returned if a invalid encoding is supplied
    47  var ErrUnknownObjectEnc = errors.New("unknown object encoding")
    48  
    49  type objectEncoding string
    50  
    51  const (
    52  	objectEncodingJSON     objectEncoding = "json"
    53  	objectEncodingProtobuf                = "protobuf"
    54  )
    55  
    56  func getObjectEnc(o interface{}) objectEncoding {
    57  	v, ok := o.(string)
    58  	if !ok {
    59  		// chosen as default because it's human readable
    60  		log.Warning("option is not a string - falling back to json")
    61  		return objectEncodingJSON
    62  	}
    63  
    64  	return objectEncoding(v)
    65  }
    66  
    67  // ObjectGet takes a key string from args and a format option and serializes the dagnode to that format
    68  func ObjectGet(n *core.IpfsNode, args []string, opts map[string]interface{}, out io.Writer) error {
    69  	dagnode, err := n.Resolver.ResolvePath(args[0])
    70  	if err != nil {
    71  		return fmt.Errorf("ObjectGet error: %v", err)
    72  	}
    73  	log.Debugf("objectGet: found dagnode %q (# of bytes: %d - # links: %d)", args[0], len(dagnode.Data), len(dagnode.Links))
    74  
    75  	// sadly all encodings dont implement a common interface
    76  	var data []byte
    77  	switch getObjectEnc(opts["encoding"]) {
    78  	case objectEncodingJSON:
    79  		data, err = json.MarshalIndent(dagnode, "", "  ")
    80  
    81  	case objectEncodingProtobuf:
    82  		data, err = dagnode.Marshal()
    83  
    84  	default:
    85  		return ErrUnknownObjectEnc
    86  	}
    87  
    88  	if err != nil {
    89  		return fmt.Errorf("ObjectGet error: %v", err)
    90  	}
    91  
    92  	_, err = io.Copy(out, bytes.NewReader(data))
    93  	return err
    94  }
    95  
    96  // ErrObjectTooLarge is returned when too much data was read from stdin. current limit 512k
    97  var ErrObjectTooLarge = errors.New("input object was too large. limit is 512kbytes")
    98  
    99  const inputLimit = 512 * 1024
   100  
   101  // ObjectPut takes a format option, serilizes bytes from stdin and updates the dag with that data
   102  func ObjectPut(n *core.IpfsNode, args []string, opts map[string]interface{}, out io.Writer) error {
   103  	var (
   104  		dagnode *dag.Node
   105  		data    []byte
   106  		err     error
   107  	)
   108  
   109  	data, err = ioutil.ReadAll(io.LimitReader(os.Stdin, inputLimit+10))
   110  	if err != nil {
   111  		return fmt.Errorf("ObjectPut error: %v", err)
   112  	}
   113  
   114  	if len(data) >= inputLimit {
   115  		return ErrObjectTooLarge
   116  	}
   117  
   118  	switch getObjectEnc(opts["encoding"]) {
   119  	case objectEncodingJSON:
   120  		dagnode = new(dag.Node)
   121  		err = json.Unmarshal(data, dagnode)
   122  
   123  	case objectEncodingProtobuf:
   124  		dagnode, err = dag.Decoded(data)
   125  
   126  	default:
   127  		return ErrUnknownObjectEnc
   128  	}
   129  
   130  	if err != nil {
   131  		return fmt.Errorf("ObjectPut error: %v", err)
   132  	}
   133  
   134  	return addNode(n, dagnode, "stdin", out)
   135  }