gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

io.go (1735B)


      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 }