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 }