| // Copyright 2015 The Go Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style | 
 | // license that can be found in the LICENSE file. | 
 |  | 
 | package elf | 
 |  | 
 | import ( | 
 | 	"io" | 
 | 	"os" | 
 | ) | 
 |  | 
 | // errorReader returns error from all operations. | 
 | type errorReader struct { | 
 | 	error | 
 | } | 
 |  | 
 | func (r errorReader) Read(p []byte) (n int, err error) { | 
 | 	return 0, r.error | 
 | } | 
 |  | 
 | func (r errorReader) ReadAt(p []byte, off int64) (n int, err error) { | 
 | 	return 0, r.error | 
 | } | 
 |  | 
 | func (r errorReader) Seek(offset int64, whence int) (int64, error) { | 
 | 	return 0, r.error | 
 | } | 
 |  | 
 | func (r errorReader) Close() error { | 
 | 	return r.error | 
 | } | 
 |  | 
 | // readSeekerFromReader converts an io.Reader into an io.ReadSeeker. | 
 | // In general Seek may not be efficient, but it is optimized for | 
 | // common cases such as seeking to the end to find the length of the | 
 | // data. | 
 | type readSeekerFromReader struct { | 
 | 	reset  func() (io.Reader, error) | 
 | 	r      io.Reader | 
 | 	size   int64 | 
 | 	offset int64 | 
 | } | 
 |  | 
 | func (r *readSeekerFromReader) start() { | 
 | 	x, err := r.reset() | 
 | 	if err != nil { | 
 | 		r.r = errorReader{err} | 
 | 	} else { | 
 | 		r.r = x | 
 | 	} | 
 | 	r.offset = 0 | 
 | } | 
 |  | 
 | func (r *readSeekerFromReader) Read(p []byte) (n int, err error) { | 
 | 	if r.r == nil { | 
 | 		r.start() | 
 | 	} | 
 | 	n, err = r.r.Read(p) | 
 | 	r.offset += int64(n) | 
 | 	return n, err | 
 | } | 
 |  | 
 | func (r *readSeekerFromReader) Seek(offset int64, whence int) (int64, error) { | 
 | 	var newOffset int64 | 
 | 	switch whence { | 
 | 	case seekStart: | 
 | 		newOffset = offset | 
 | 	case seekCurrent: | 
 | 		newOffset = r.offset + offset | 
 | 	case seekEnd: | 
 | 		newOffset = r.size + offset | 
 | 	default: | 
 | 		return 0, os.ErrInvalid | 
 | 	} | 
 |  | 
 | 	switch { | 
 | 	case newOffset == r.offset: | 
 | 		return newOffset, nil | 
 |  | 
 | 	case newOffset < 0, newOffset > r.size: | 
 | 		return 0, os.ErrInvalid | 
 |  | 
 | 	case newOffset == 0: | 
 | 		r.r = nil | 
 |  | 
 | 	case newOffset == r.size: | 
 | 		r.r = errorReader{io.EOF} | 
 |  | 
 | 	default: | 
 | 		if newOffset < r.offset { | 
 | 			// Restart at the beginning. | 
 | 			r.start() | 
 | 		} | 
 | 		// Read until we reach offset. | 
 | 		var buf [512]byte | 
 | 		for r.offset < newOffset { | 
 | 			b := buf[:] | 
 | 			if newOffset-r.offset < int64(len(buf)) { | 
 | 				b = buf[:newOffset-r.offset] | 
 | 			} | 
 | 			if _, err := r.Read(b); err != nil { | 
 | 				return 0, err | 
 | 			} | 
 | 		} | 
 | 	} | 
 | 	r.offset = newOffset | 
 | 	return r.offset, nil | 
 | } |