1package s3crypto
2
3import (
4	"errors"
5	"io"
6	"io/ioutil"
7	"os"
8
9	"github.com/aws/aws-sdk-go/aws/request"
10)
11
12func getWriterStore(req *request.Request, path string, useTempFile bool) (io.ReadWriteSeeker, error) {
13	if !useTempFile {
14		return &bytesReadWriteSeeker{}, nil
15	}
16	// Create temp file to be used later for calculating the SHA256 header
17	f, err := ioutil.TempFile(path, "")
18	if err != nil {
19		return nil, err
20	}
21
22	req.Handlers.Complete.PushBack(func(r *request.Request) {
23		// Close the temp file and cleanup
24		f.Close()
25		os.Remove(f.Name())
26	})
27	return f, nil
28}
29
30type bytesReadWriteSeeker struct {
31	buf []byte
32	i   int64
33}
34
35// Copied from Go stdlib bytes.Reader
36func (ws *bytesReadWriteSeeker) Read(b []byte) (int, error) {
37	if ws.i >= int64(len(ws.buf)) {
38		return 0, io.EOF
39	}
40	n := copy(b, ws.buf[ws.i:])
41	ws.i += int64(n)
42	return n, nil
43}
44
45func (ws *bytesReadWriteSeeker) Write(b []byte) (int, error) {
46	ws.buf = append(ws.buf, b...)
47	return len(b), nil
48}
49
50// Copied from Go stdlib bytes.Reader
51func (ws *bytesReadWriteSeeker) Seek(offset int64, whence int) (int64, error) {
52	var abs int64
53	switch whence {
54	case 0:
55		abs = offset
56	case 1:
57		abs = int64(ws.i) + offset
58	case 2:
59		abs = int64(len(ws.buf)) + offset
60	default:
61		return 0, errors.New("bytes.Reader.Seek: invalid whence")
62	}
63	if abs < 0 {
64		return 0, errors.New("bytes.Reader.Seek: negative position")
65	}
66	ws.i = abs
67	return abs, nil
68}
69