|
- // Copyright 2018 Google LLC
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
-
- 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
- }
|