github.com/weiwenhao/getter@v1.30.1/get_file_copy.go (about)

     1  package getter
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"os"
     7  )
     8  
     9  // readerFunc is syntactic sugar for read interface.
    10  type readerFunc func(p []byte) (n int, err error)
    11  
    12  func (rf readerFunc) Read(p []byte) (n int, err error) { return rf(p) }
    13  
    14  // Copy is a io.Copy cancellable by context
    15  func Copy(ctx context.Context, dst io.Writer, src io.Reader) (int64, error) {
    16  	// Copy will call the Reader and Writer interface multiple time, in order
    17  	// to copy by chunk (avoiding loading the whole file in memory).
    18  	return io.Copy(dst, readerFunc(func(p []byte) (int, error) {
    19  
    20  		select {
    21  		case <-ctx.Done():
    22  			// context has been canceled
    23  			// stop process and propagate "context canceled" error
    24  			return 0, ctx.Err()
    25  		default:
    26  			// otherwise just run default io.Reader implementation
    27  			return src.Read(p)
    28  		}
    29  	}))
    30  }
    31  
    32  // copyReader copies from an io.Reader into a file, using umask to create the dst file
    33  func copyReader(dst string, src io.Reader, fmode, umask os.FileMode) error {
    34  	dstF, err := os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, fmode)
    35  	if err != nil {
    36  		return err
    37  	}
    38  	defer dstF.Close()
    39  
    40  	_, err = io.Copy(dstF, src)
    41  	if err != nil {
    42  		return err
    43  	}
    44  
    45  	// Explicitly chmod; the process umask is unconditionally applied otherwise.
    46  	// We'll mask the mode with our own umask, but that may be different than
    47  	// the process umask
    48  	return os.Chmod(dst, mode(fmode, umask))
    49  }
    50  
    51  // copyFile copies a file in chunks from src path to dst path, using umask to create the dst file
    52  func copyFile(ctx context.Context, dst, src string, fmode, umask os.FileMode) (int64, error) {
    53  	srcF, err := os.Open(src)
    54  	if err != nil {
    55  		return 0, err
    56  	}
    57  	defer srcF.Close()
    58  
    59  	dstF, err := os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, fmode)
    60  	if err != nil {
    61  		return 0, err
    62  	}
    63  	defer dstF.Close()
    64  
    65  	count, err := Copy(ctx, dstF, srcF)
    66  	if err != nil {
    67  		return 0, err
    68  	}
    69  
    70  	// Explicitly chmod; the process umask is unconditionally applied otherwise.
    71  	// We'll mask the mode with our own umask, but that may be different than
    72  	// the process umask
    73  	err = os.Chmod(dst, mode(fmode, umask))
    74  	return count, err
    75  }