graceful_copy.go (1133B)
1 package rifs 2 3 import ( 4 "fmt" 5 "io" 6 ) 7 8 const ( 9 defaultCopyBufferSize = 1024 * 1024 10 ) 11 12 // GracefulCopy willcopy while enduring lesser normal issues. 13 // 14 // - We'll ignore EOF if the read byte-count is more than zero. Only an EOF when 15 // zero bytes were read will terminate the loop. 16 // 17 // - Ignore short-writes. If less bytes were written than the bytes that were 18 // given, we'll keep trying until done. 19 func GracefulCopy(w io.Writer, r io.Reader, buffer []byte) (copyCount int, err error) { 20 if buffer == nil { 21 buffer = make([]byte, defaultCopyBufferSize) 22 } 23 24 for { 25 readCount, err := r.Read(buffer) 26 if err != nil { 27 if err != io.EOF { 28 err = fmt.Errorf("read error: %s", err.Error()) 29 return 0, err 30 } 31 32 // Only break on EOF if no bytes were actually read. 33 if readCount == 0 { 34 break 35 } 36 } 37 38 writeBuffer := buffer[:readCount] 39 40 for len(writeBuffer) > 0 { 41 writtenCount, err := w.Write(writeBuffer) 42 if err != nil { 43 err = fmt.Errorf("write error: %s", err.Error()) 44 return 0, err 45 } 46 47 writeBuffer = writeBuffer[writtenCount:] 48 } 49 50 copyCount += readCount 51 } 52 53 return copyCount, nil 54 }