From 4bf1705a880261a4cebd0766824a5a4548b4a947 Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Fri, 13 Jun 2025 21:34:22 +0000 Subject: [PATCH] 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 --- core/remotes/docker/httpreadseeker.go | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/core/remotes/docker/httpreadseeker.go b/core/remotes/docker/httpreadseeker.go index 6739e7904e..ada95b92ba 100644 --- a/core/remotes/docker/httpreadseeker.go +++ b/core/remotes/docker/httpreadseeker.go @@ -102,6 +102,36 @@ func (hrs *httpReadSeeker) Close() error { return nil } +func (hrs *httpReadSeeker) ReadAt(p []byte, offset int64) (n int, err error) { + if hrs.closed { + return 0, fmt.Errorf("httpReadSeeker.ReadAt: closed: %w", errdefs.ErrUnavailable) + } + + if offset < 0 { + return 0, fmt.Errorf("httpReadSeeker.ReadAt: negative offset: %w", errdefs.ErrInvalidArgument) + } + + if hrs.size != -1 && offset >= hrs.size { + return 0, io.EOF + } + + if hrs.open == nil { + return 0, fmt.Errorf("httpReadSeeker.ReadAt: cannot open: %w", errdefs.ErrNotImplemented) + } + + rc, err := hrs.open(offset) + if err != nil { + return 0, fmt.Errorf("httpReadSeeker.ReadAt: failed to open at offset %d: %w", offset, err) + } + defer func() { + if closeErr := rc.Close(); closeErr != nil { + log.L.WithError(closeErr).Error("httpReadSeeker.ReadAt: failed to close ReadCloser") + } + }() + + return io.ReadFull(rc, p) +} + func (hrs *httpReadSeeker) Seek(offset int64, whence int) (int64, error) { if hrs.closed { return 0, fmt.Errorf("Fetcher.Seek: closed: %w", errdefs.ErrUnavailable)