mirror of https://github.com/containers/podman.git
				
				
				
			
		
			
				
	
	
		
			106 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
| package storage
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"errors"
 | |
| 	"hash/crc64"
 | |
| 	"io"
 | |
| 	"os"
 | |
| 	"path/filepath"
 | |
| )
 | |
| 
 | |
| // FileGetter is the interface for getting a stream of a file payload,
 | |
| // addressed by name/filename. Presumably, the names will be scoped to relative
 | |
| // file paths.
 | |
| type FileGetter interface {
 | |
| 	// Get returns a stream for the provided file path
 | |
| 	Get(filename string) (output io.ReadCloser, err error)
 | |
| }
 | |
| 
 | |
| // FilePutter is the interface for storing a stream of a file payload,
 | |
| // addressed by name/filename.
 | |
| type FilePutter interface {
 | |
| 	// Put returns the size of the stream received, and the crc64 checksum for
 | |
| 	// the provided stream
 | |
| 	Put(filename string, input io.Reader) (size int64, checksum []byte, err error)
 | |
| }
 | |
| 
 | |
| // FileGetPutter is the interface that groups both Getting and Putting file
 | |
| // payloads.
 | |
| type FileGetPutter interface {
 | |
| 	FileGetter
 | |
| 	FilePutter
 | |
| }
 | |
| 
 | |
| // NewPathFileGetter returns a FileGetter that is for files relative to path
 | |
| // relpath.
 | |
| func NewPathFileGetter(relpath string) FileGetter {
 | |
| 	return &pathFileGetter{root: relpath}
 | |
| }
 | |
| 
 | |
| type pathFileGetter struct {
 | |
| 	root string
 | |
| }
 | |
| 
 | |
| func (pfg pathFileGetter) Get(filename string) (io.ReadCloser, error) {
 | |
| 	return os.Open(filepath.Join(pfg.root, filename))
 | |
| }
 | |
| 
 | |
| type bufferFileGetPutter struct {
 | |
| 	files map[string][]byte
 | |
| }
 | |
| 
 | |
| func (bfgp bufferFileGetPutter) Get(name string) (io.ReadCloser, error) {
 | |
| 	if _, ok := bfgp.files[name]; !ok {
 | |
| 		return nil, errors.New("no such file")
 | |
| 	}
 | |
| 	b := bytes.NewBuffer(bfgp.files[name])
 | |
| 	return &readCloserWrapper{b}, nil
 | |
| }
 | |
| 
 | |
| func (bfgp *bufferFileGetPutter) Put(name string, r io.Reader) (int64, []byte, error) {
 | |
| 	crc := crc64.New(CRCTable)
 | |
| 	buf := bytes.NewBuffer(nil)
 | |
| 	cw := io.MultiWriter(crc, buf)
 | |
| 	i, err := io.Copy(cw, r)
 | |
| 	if err != nil {
 | |
| 		return 0, nil, err
 | |
| 	}
 | |
| 	bfgp.files[name] = buf.Bytes()
 | |
| 	return i, crc.Sum(nil), nil
 | |
| }
 | |
| 
 | |
| type readCloserWrapper struct {
 | |
| 	io.Reader
 | |
| }
 | |
| 
 | |
| func (w *readCloserWrapper) Close() error { return nil }
 | |
| 
 | |
| // NewBufferFileGetPutter is a simple in-memory FileGetPutter
 | |
| //
 | |
| // Implication is this is memory intensive...
 | |
| // Probably best for testing or light weight cases.
 | |
| func NewBufferFileGetPutter() FileGetPutter {
 | |
| 	return &bufferFileGetPutter{
 | |
| 		files: map[string][]byte{},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // NewDiscardFilePutter is a bit bucket FilePutter
 | |
| func NewDiscardFilePutter() FilePutter {
 | |
| 	return &bitBucketFilePutter{}
 | |
| }
 | |
| 
 | |
| type bitBucketFilePutter struct {
 | |
| 	buffer [32 * 1024]byte // 32 kB is the buffer size currently used by io.Copy, as of August 2021.
 | |
| }
 | |
| 
 | |
| func (bbfp *bitBucketFilePutter) Put(name string, r io.Reader) (int64, []byte, error) {
 | |
| 	c := crc64.New(CRCTable)
 | |
| 	i, err := io.CopyBuffer(c, r, bbfp.buffer[:])
 | |
| 	return i, c.Sum(nil), err
 | |
| }
 | |
| 
 | |
| // CRCTable is the default table used for crc64 sum calculations
 | |
| var CRCTable = crc64.MakeTable(crc64.ISO)
 |