1// Copyright 2018 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package elf 16 17import ( 18 "io" 19 "os" 20) 21 22// errorReader returns error from all operations. 23type errorReader struct { 24 error 25} 26 27func (r errorReader) Read(p []byte) (n int, err error) { 28 return 0, r.error 29} 30 31func (r errorReader) ReadAt(p []byte, off int64) (n int, err error) { 32 return 0, r.error 33} 34 35func (r errorReader) Seek(offset int64, whence int) (int64, error) { 36 return 0, r.error 37} 38 39func (r errorReader) Close() error { 40 return r.error 41} 42 43// readSeekerFromReader converts an io.Reader into an io.ReadSeeker. 44// In general Seek may not be efficient, but it is optimized for 45// common cases such as seeking to the end to find the length of the 46// data. 47type readSeekerFromReader struct { 48 reset func() (io.Reader, error) 49 r io.Reader 50 size int64 51 offset int64 52} 53 54func (r *readSeekerFromReader) start() { 55 x, err := r.reset() 56 if err != nil { 57 r.r = errorReader{err} 58 } else { 59 r.r = x 60 } 61 r.offset = 0 62} 63 64func (r *readSeekerFromReader) Read(p []byte) (n int, err error) { 65 if r.r == nil { 66 r.start() 67 } 68 n, err = r.r.Read(p) 69 r.offset += int64(n) 70 return n, err 71} 72 73func (r *readSeekerFromReader) Seek(offset int64, whence int) (int64, error) { 74 var newOffset int64 75 switch whence { 76 case seekStart: 77 newOffset = offset 78 case seekCurrent: 79 newOffset = r.offset + offset 80 case seekEnd: 81 newOffset = r.size + offset 82 default: 83 return 0, os.ErrInvalid 84 } 85 86 switch { 87 case newOffset == r.offset: 88 return newOffset, nil 89 90 case newOffset < 0, newOffset > r.size: 91 return 0, os.ErrInvalid 92 93 case newOffset == 0: 94 r.r = nil 95 96 case newOffset == r.size: 97 r.r = errorReader{io.EOF} 98 99 default: 100 if newOffset < r.offset { 101 // Restart at the beginning. 102 r.start() 103 } 104 // Read until we reach offset. 105 var buf [512]byte 106 for r.offset < newOffset { 107 b := buf[:] 108 if newOffset-r.offset < int64(len(buf)) { 109 b = buf[:newOffset-r.offset] 110 } 111 if _, err := r.Read(b); err != nil { 112 return 0, err 113 } 114 } 115 } 116 r.offset = newOffset 117 return r.offset, nil 118} 119