mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
58 lines
1.2 KiB
Go
58 lines
1.2 KiB
Go
package ioutils
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
)
|
|
|
|
// CopyCtx copies from src to dst until either EOF is reached on src or a context is cancelled.
|
|
// The writer is not closed when the context is cancelled.
|
|
//
|
|
// After CopyCtx exits due to context cancellation, the goroutine that performed
|
|
// the copy may still be running if either the reader or writer blocks.
|
|
func CopyCtx(ctx context.Context, dst io.Writer, src io.Reader) (n int64, err error) {
|
|
copyDone := make(chan struct{})
|
|
|
|
src = &readerCtx{ctx: ctx, r: src}
|
|
|
|
go func() {
|
|
n, err = io.Copy(dst, src)
|
|
close(copyDone)
|
|
}()
|
|
|
|
select {
|
|
case <-ctx.Done():
|
|
return -1, ctx.Err()
|
|
case <-copyDone:
|
|
}
|
|
|
|
return n, err
|
|
}
|
|
|
|
type readerCtx struct {
|
|
ctx context.Context
|
|
r io.Reader
|
|
}
|
|
|
|
// NewCtxReader wraps the given reader with a reader that doesn't proceed with
|
|
// reading if the context is done.
|
|
//
|
|
// Note: Read will still block if the underlying reader blocks.
|
|
func NewCtxReader(ctx context.Context, r io.Reader) io.Reader {
|
|
return &readerCtx{ctx: ctx, r: r}
|
|
}
|
|
|
|
func (r *readerCtx) Read(p []byte) (n int, err error) {
|
|
if err := r.ctx.Err(); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
n, outErr := r.r.Read(p)
|
|
|
|
if err := r.ctx.Err(); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return n, outErr
|
|
}
|