github.com/slspeek/camlistore_namedsearch@v0.0.0-20140519202248-ed6f70f7721a/cmd/camput/blobs.go (about)

     1  /*
     2  Copyright 2011 Google Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8       http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package main
    18  
    19  import (
    20  	"bytes"
    21  	"crypto/sha1"
    22  	"errors"
    23  	"flag"
    24  	"fmt"
    25  	"io"
    26  	"os"
    27  
    28  	"camlistore.org/pkg/blob"
    29  	"camlistore.org/pkg/client"
    30  	"camlistore.org/pkg/cmdmain"
    31  	"camlistore.org/pkg/constants"
    32  )
    33  
    34  type blobCmd struct{}
    35  
    36  func init() {
    37  	cmdmain.RegisterCommand("blob", func(flags *flag.FlagSet) cmdmain.CommandRunner {
    38  		return new(blobCmd)
    39  	})
    40  }
    41  
    42  func (c *blobCmd) Describe() string {
    43  	return "Upload raw blob(s)."
    44  }
    45  
    46  func (c *blobCmd) Usage() {
    47  	fmt.Fprintf(cmdmain.Stderr, "Usage: camput [globalopts] blob <files>\n	camput [globalopts] blob -\n")
    48  }
    49  
    50  func (c *blobCmd) Examples() []string {
    51  	return []string{
    52  		"<files>     (raw, without any metadata)",
    53  		"-           (read from stdin)",
    54  	}
    55  }
    56  
    57  func (c *blobCmd) RunCommand(args []string) error {
    58  	if len(args) == 0 {
    59  		return errors.New("No files given.")
    60  	}
    61  
    62  	up := getUploader()
    63  	for _, arg := range args {
    64  		var (
    65  			handle *client.UploadHandle
    66  			err    error
    67  		)
    68  		if arg == "-" {
    69  			handle, err = stdinBlobHandle()
    70  		} else {
    71  			handle, err = fileBlobHandle(up, arg)
    72  		}
    73  		if err != nil {
    74  			return err
    75  		}
    76  		put, err := up.Upload(handle)
    77  		handleResult("blob", put, err)
    78  		continue
    79  	}
    80  	return nil
    81  }
    82  
    83  func stdinBlobHandle() (uh *client.UploadHandle, err error) {
    84  	var buf bytes.Buffer
    85  	size, err := io.CopyN(&buf, cmdmain.Stdin, constants.MaxBlobSize+1)
    86  	if err == io.EOF {
    87  		err = nil
    88  	}
    89  	if err != nil {
    90  		return
    91  	}
    92  	if size > constants.MaxBlobSize {
    93  		err = fmt.Errorf("blob size cannot be bigger than %d", constants.MaxBlobSize)
    94  	}
    95  	file := buf.Bytes()
    96  	h := blob.NewHash()
    97  	size, err = io.Copy(h, bytes.NewReader(file))
    98  	if err != nil {
    99  		return
   100  	}
   101  	return &client.UploadHandle{
   102  		BlobRef:  blob.RefFromHash(h),
   103  		Size:     uint32(size),
   104  		Contents: io.LimitReader(bytes.NewReader(file), size),
   105  	}, nil
   106  }
   107  
   108  func fileBlobHandle(up *Uploader, path string) (uh *client.UploadHandle, err error) {
   109  	fi, err := up.stat(path)
   110  	if err != nil {
   111  		return
   112  	}
   113  	if fi.Mode()&os.ModeType != 0 {
   114  		return nil, fmt.Errorf("%q is not a regular file", path)
   115  	}
   116  	file, err := up.open(path)
   117  	if err != nil {
   118  		return
   119  	}
   120  	ref, size, err := blobDetails(file)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  	return &client.UploadHandle{
   125  		BlobRef:  ref,
   126  		Size:     size,
   127  		Contents: io.LimitReader(file, int64(size)),
   128  	}, nil
   129  }
   130  
   131  func blobDetails(contents io.ReadSeeker) (bref blob.Ref, size uint32, err error) {
   132  	s1 := sha1.New()
   133  	if _, err = contents.Seek(0, 0); err != nil {
   134  		return
   135  	}
   136  	defer func() {
   137  		if _, seekErr := contents.Seek(0, 0); seekErr != nil {
   138  			if err == nil {
   139  				err = seekErr
   140  			} else {
   141  				err = fmt.Errorf("%s, cannot seek back: %v", err, seekErr)
   142  			}
   143  		}
   144  	}()
   145  	sz, err := io.CopyN(s1, contents, constants.MaxBlobSize+1)
   146  	if err == nil || err == io.EOF {
   147  		bref, err = blob.RefFromHash(s1), nil
   148  	} else {
   149  		err = fmt.Errorf("error reading contents: %v", err)
   150  		return
   151  	}
   152  	if sz > constants.MaxBlobSize {
   153  		err = fmt.Errorf("blob size cannot be bigger than %d", constants.MaxBlobSize)
   154  	}
   155  	size = uint32(sz)
   156  	return
   157  }