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 }