github.com/cilium/ebpf@v0.10.0/internal/io.go (about)

     1  package internal
     2  
     3  import (
     4  	"bufio"
     5  	"compress/gzip"
     6  	"errors"
     7  	"io"
     8  	"os"
     9  )
    10  
    11  // NewBufferedSectionReader wraps an io.ReaderAt in an appropriately-sized
    12  // buffered reader. It is a convenience function for reading subsections of
    13  // ELF sections while minimizing the amount of read() syscalls made.
    14  //
    15  // Syscall overhead is non-negligible in continuous integration context
    16  // where ELFs might be accessed over virtual filesystems with poor random
    17  // access performance. Buffering reads makes sense because (sub)sections
    18  // end up being read completely anyway.
    19  //
    20  // Use instead of the r.Seek() + io.LimitReader() pattern.
    21  func NewBufferedSectionReader(ra io.ReaderAt, off, n int64) *bufio.Reader {
    22  	// Clamp the size of the buffer to one page to avoid slurping large parts
    23  	// of a file into memory. bufio.NewReader uses a hardcoded default buffer
    24  	// of 4096. Allow arches with larger pages to allocate more, but don't
    25  	// allocate a fixed 4k buffer if we only need to read a small segment.
    26  	buf := n
    27  	if ps := int64(os.Getpagesize()); n > ps {
    28  		buf = ps
    29  	}
    30  
    31  	return bufio.NewReaderSize(io.NewSectionReader(ra, off, n), int(buf))
    32  }
    33  
    34  // DiscardZeroes makes sure that all written bytes are zero
    35  // before discarding them.
    36  type DiscardZeroes struct{}
    37  
    38  func (DiscardZeroes) Write(p []byte) (int, error) {
    39  	for _, b := range p {
    40  		if b != 0 {
    41  			return 0, errors.New("encountered non-zero byte")
    42  		}
    43  	}
    44  	return len(p), nil
    45  }
    46  
    47  // ReadAllCompressed decompresses a gzipped file into memory.
    48  func ReadAllCompressed(file string) ([]byte, error) {
    49  	fh, err := os.Open(file)
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  	defer fh.Close()
    54  
    55  	gz, err := gzip.NewReader(fh)
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  	defer gz.Close()
    60  
    61  	return io.ReadAll(gz)
    62  }