Skip to content

Commit 4bf1705

Browse files
committed
Implement io.ReaderAt on docker fetch reader
I was working on treating a remote as a content provider and ran into the stream backing the fetch only implementing io.Seeker. I shimmed an io.ReaderAt implementation by calling seek under the hood, but this is of course not a faithful io.ReaderAt implementation. This just implements a correct io.ReaderAt implementation directly. Signed-off-by: Brian Goff <[email protected]>
1 parent 2af24b5 commit 4bf1705

1 file changed

Lines changed: 30 additions & 0 deletions

File tree

core/remotes/docker/httpreadseeker.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,36 @@ func (hrs *httpReadSeeker) Close() error {
102102
return nil
103103
}
104104

105+
func (hrs *httpReadSeeker) ReadAt(p []byte, offset int64) (n int, err error) {
106+
if hrs.closed {
107+
return 0, fmt.Errorf("httpReadSeeker.ReadAt: closed: %w", errdefs.ErrUnavailable)
108+
}
109+
110+
if offset < 0 {
111+
return 0, fmt.Errorf("httpReadSeeker.ReadAt: negative offset: %w", errdefs.ErrInvalidArgument)
112+
}
113+
114+
if hrs.size != -1 && offset >= hrs.size {
115+
return 0, io.EOF
116+
}
117+
118+
if hrs.open == nil {
119+
return 0, fmt.Errorf("httpReadSeeker.ReadAt: cannot open: %w", errdefs.ErrNotImplemented)
120+
}
121+
122+
rc, err := hrs.open(offset)
123+
if err != nil {
124+
return 0, fmt.Errorf("httpReadSeeker.ReadAt: failed to open at offset %d: %w", offset, err)
125+
}
126+
defer func() {
127+
if closeErr := rc.Close(); closeErr != nil {
128+
log.L.WithError(closeErr).Error("httpReadSeeker.ReadAt: failed to close ReadCloser")
129+
}
130+
}()
131+
132+
return io.ReadFull(rc, p)
133+
}
134+
105135
func (hrs *httpReadSeeker) Seek(offset int64, whence int) (int64, error) {
106136
if hrs.closed {
107137
return 0, fmt.Errorf("Fetcher.Seek: closed: %w", errdefs.ErrUnavailable)

0 commit comments

Comments
 (0)