Avoid bugs where content can mistakenly be read from extra after an EOF is returned. Signed-off-by: Derek McGowan <derek@mcgstyle.net>
		
			
				
	
	
		
			52 lines
		
	
	
		
			876 B
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			52 lines
		
	
	
		
			876 B
		
	
	
	
		
			Go
		
	
	
	
	
	
package content
 | 
						|
 | 
						|
import (
 | 
						|
	contentapi "github.com/containerd/containerd/api/services/content"
 | 
						|
)
 | 
						|
 | 
						|
type remoteReader struct {
 | 
						|
	client contentapi.Content_ReadClient
 | 
						|
	extra  []byte
 | 
						|
}
 | 
						|
 | 
						|
func (rr *remoteReader) Read(p []byte) (n int, err error) {
 | 
						|
	n += copy(p, rr.extra)
 | 
						|
	if n >= len(p) {
 | 
						|
		if n <= len(rr.extra) {
 | 
						|
			rr.extra = rr.extra[n:]
 | 
						|
		} else {
 | 
						|
			rr.extra = rr.extra[:0]
 | 
						|
		}
 | 
						|
		return
 | 
						|
	}
 | 
						|
	rr.extra = rr.extra[:0]
 | 
						|
 | 
						|
	p = p[n:]
 | 
						|
	for len(p) > 0 {
 | 
						|
		var resp *contentapi.ReadResponse
 | 
						|
		// fill our buffer up until we can fill p.
 | 
						|
		resp, err = rr.client.Recv()
 | 
						|
		if err != nil {
 | 
						|
			return
 | 
						|
		}
 | 
						|
 | 
						|
		copied := copy(p, resp.Data)
 | 
						|
		n += copied
 | 
						|
		p = p[copied:]
 | 
						|
 | 
						|
		if copied < len(p) {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		rr.extra = append(rr.extra, resp.Data[copied:]...)
 | 
						|
	}
 | 
						|
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// TODO(stevvooe): Implemente io.ReaderAt.
 | 
						|
 | 
						|
func (rr *remoteReader) Close() error {
 | 
						|
	return rr.client.CloseSend()
 | 
						|
}
 |