github.com/rigado/snapd@v2.42.5-go-mod+incompatible/osutil/cmp.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2014-2015 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package osutil 21 22 import ( 23 "bytes" 24 "io" 25 "os" 26 ) 27 28 const defaultBufsz = 16 * 1024 29 30 var bufsz = defaultBufsz 31 32 // FilesAreEqual compares the two files' contents and returns whether 33 // they are the same. 34 func FilesAreEqual(a, b string) bool { 35 fa, err := os.Open(a) 36 if err != nil { 37 return false 38 } 39 defer fa.Close() 40 41 fb, err := os.Open(b) 42 if err != nil { 43 return false 44 } 45 defer fb.Close() 46 47 fia, err := fa.Stat() 48 if err != nil { 49 return false 50 } 51 52 fib, err := fb.Stat() 53 if err != nil { 54 return false 55 } 56 57 if fia.Size() != fib.Size() { 58 return false 59 } 60 61 return StreamsEqual(fa, fb) 62 } 63 64 // StreamsEqual compares two streams and returns true if both 65 // have the same content. 66 func StreamsEqual(a, b io.Reader) bool { 67 bufa := make([]byte, bufsz) 68 bufb := make([]byte, bufsz) 69 for { 70 ra, erra := io.ReadAtLeast(a, bufa, bufsz) 71 rb, errb := io.ReadAtLeast(b, bufb, bufsz) 72 if erra == io.EOF && errb == io.EOF { 73 return true 74 } 75 if erra != nil || errb != nil { 76 // if both files finished in the middle of a 77 // ReadAtLeast, (returning io.ErrUnexpectedEOF), then we 78 // still need to check what was read to know whether 79 // they're equal. Otherwise, we know they're not equal 80 // (because we count any read error as a being non-equal 81 // also). 82 tailMightBeEqual := erra == io.ErrUnexpectedEOF && errb == io.ErrUnexpectedEOF 83 if !tailMightBeEqual { 84 return false 85 } 86 } 87 if !bytes.Equal(bufa[:ra], bufb[:rb]) { 88 return false 89 } 90 } 91 }