github.com/Finschia/finschia-sdk@v0.48.1/internal/os/file.go (about)

     1  package os
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  )
     8  
     9  // ReadFileWithSizeLimit expanded os.ReadFile for checking the file size before reading it
    10  func ReadFileWithSizeLimit(name string, sizeLimit int64) ([]byte, error) {
    11  	f, err := os.Open(name)
    12  	if err != nil {
    13  		return nil, err
    14  	}
    15  	defer func() {
    16  		err := f.Close()
    17  		if err != nil {
    18  			fmt.Printf("Cannot close the file: %s\n", name)
    19  		}
    20  	}()
    21  
    22  	var size int
    23  	if info, err := f.Stat(); err == nil {
    24  		size64 := info.Size()
    25  		// Check the file size
    26  		if size64 > sizeLimit {
    27  			return nil, fmt.Errorf("the file is too large: %s, size limit over > %d", name, sizeLimit)
    28  		}
    29  		if int64(int(size64)) == size64 {
    30  			size = int(size64)
    31  		}
    32  	}
    33  	size++ // one byte for final read at EOF
    34  
    35  	// If a file claims a small size, read at least 512 bytes.
    36  	// In particular, files in Linux's /proc claim size 0 but
    37  	// then do not work right if read in small pieces,
    38  	// so an initial read of 1 byte would not work correctly.
    39  	if size < 512 {
    40  		size = 512
    41  	}
    42  
    43  	data := make([]byte, 0, size)
    44  	for {
    45  		if len(data) >= cap(data) {
    46  			d := append(data[:cap(data)], 0)
    47  			data = d[:len(data)]
    48  		}
    49  		n, err := f.Read(data[len(data):cap(data)])
    50  		data = data[:len(data)+n]
    51  		if err != nil {
    52  			if err == io.EOF {
    53  				err = nil
    54  			}
    55  			return data, err
    56  		}
    57  	}
    58  }