...
1 package storage
2
3 import (
4 "bufio"
5 "bytes"
6 "context"
7 "fmt"
8 "io"
9 "io/ioutil"
10
11 storagedriver "github.com/docker/distribution/registry/storage/driver"
12 )
13
14
15
16
17
18
19 const fileReaderBufferSize = 4 << 20
20
21
22
23
24 type fileReader struct {
25 driver storagedriver.StorageDriver
26
27 ctx context.Context
28
29
30 path string
31 size int64
32
33
34 rc io.ReadCloser
35 brd *bufio.Reader
36 offset int64
37 err error
38 }
39
40
41
42
43
44 func newFileReader(ctx context.Context, driver storagedriver.StorageDriver, path string, size int64) (*fileReader, error) {
45 return &fileReader{
46 ctx: ctx,
47 driver: driver,
48 path: path,
49 size: size,
50 }, nil
51 }
52
53 func (fr *fileReader) Read(p []byte) (n int, err error) {
54 if fr.err != nil {
55 return 0, fr.err
56 }
57
58 rd, err := fr.reader()
59 if err != nil {
60 return 0, err
61 }
62
63 n, err = rd.Read(p)
64 fr.offset += int64(n)
65
66
67 if err == nil && fr.offset >= fr.size {
68 err = io.EOF
69 }
70
71 return n, err
72 }
73
74 func (fr *fileReader) Seek(offset int64, whence int) (int64, error) {
75 if fr.err != nil {
76 return 0, fr.err
77 }
78
79 var err error
80 newOffset := fr.offset
81
82 switch whence {
83 case io.SeekCurrent:
84 newOffset += offset
85 case io.SeekEnd:
86 newOffset = fr.size + offset
87 case io.SeekStart:
88 newOffset = offset
89 }
90
91 if newOffset < 0 {
92 err = fmt.Errorf("cannot seek to negative position")
93 } else {
94 if fr.offset != newOffset {
95 fr.reset()
96 }
97
98
99 fr.offset = newOffset
100 }
101
102 return fr.offset, err
103 }
104
105 func (fr *fileReader) Close() error {
106 return fr.closeWithErr(fmt.Errorf("fileReader: closed"))
107 }
108
109
110
111 func (fr *fileReader) reader() (io.Reader, error) {
112 if fr.err != nil {
113 return nil, fr.err
114 }
115
116 if fr.rc != nil {
117 return fr.brd, nil
118 }
119
120
121 rc, err := fr.driver.Reader(fr.ctx, fr.path, fr.offset)
122 if err != nil {
123 switch err := err.(type) {
124 case storagedriver.PathNotFoundError:
125
126
127
128
129 return ioutil.NopCloser(bytes.NewReader([]byte{})), nil
130 default:
131 return nil, err
132 }
133 }
134
135 fr.rc = rc
136
137 if fr.brd == nil {
138 fr.brd = bufio.NewReaderSize(fr.rc, fileReaderBufferSize)
139 } else {
140 fr.brd.Reset(fr.rc)
141 }
142
143 return fr.brd, nil
144 }
145
146
147
148
149
150 func (fr *fileReader) reset() {
151 if fr.err != nil {
152 return
153 }
154 if fr.rc != nil {
155 fr.rc.Close()
156 fr.rc = nil
157 }
158 }
159
160 func (fr *fileReader) closeWithErr(err error) error {
161 if fr.err != nil {
162 return fr.err
163 }
164
165 fr.err = err
166
167
168 if fr.rc != nil {
169 fr.rc.Close()
170 }
171
172 fr.rc = nil
173 fr.brd = nil
174
175 return fr.err
176 }
177
View as plain text