1 package filesystem
2
3 import (
4 "bufio"
5 "bytes"
6 "io"
7 "os"
8 )
9
10 const defaultBufferSize = 4096
11
12
13
14 func FileEqualsTarget(path string, targetBytes []byte) (bool, error) {
15 fileInfo, err := os.Stat(path)
16 if err != nil {
17 return false, err
18 }
19 if fileInfo.Size() != int64(len(targetBytes)) {
20 return false, nil
21 }
22
23 file, closeFn, err := newReader(path)
24 if err != nil {
25 return false, err
26 }
27 defer closeFn()
28 bytesBuffer := bytes.NewReader(targetBytes)
29 return Equal(file, bytesBuffer, defaultBufferSize)
30 }
31
32
33
34 func FilesEqual(path1, path2 string) (bool, error) {
35 file1Info, err := os.Stat(path1)
36 if err != nil {
37 return false, err
38 }
39
40 file2Info, err := os.Stat(path2)
41 if err != nil {
42 return false, err
43 }
44
45 if file1Info.Size() != file2Info.Size() {
46 return false, nil
47 }
48
49 file1, closeFn1, err := newReader(path1)
50 if err != nil {
51 return false, err
52 }
53 defer closeFn1()
54
55 file2, closeFn2, err := newReader(path2)
56 if err != nil {
57 return false, err
58 }
59 defer closeFn2()
60 return Equal(file1, file2, defaultBufferSize)
61 }
62
63
64
65 func Equal(r1, r2 io.Reader, bufferSize int) (bool, error) {
66 if bufferSize <= 0 {
67 bufferSize = defaultBufferSize
68 }
69 buf1 := make([]byte, bufferSize)
70 buf2 := make([]byte, bufferSize)
71
72 for {
73 n1, err1 := readFull(r1, buf1)
74 n2, err2 := readFull(r2, buf2)
75
76
77 if err1 != nil && err1 != io.EOF {
78 return false, err1
79 }
80 if err2 != nil && err2 != io.EOF {
81 return false, err2
82 }
83
84
85 if n1 != n2 || !bytes.Equal(buf1[:n1], buf2[:n2]) {
86 return false, nil
87 }
88
89
90 if err1 == io.EOF && err2 == io.EOF {
91 return true, nil
92 }
93 if err1 == io.EOF || err2 == io.EOF {
94 return false, nil
95 }
96 }
97 }
98
99
100 func readFull(r io.Reader, buf []byte) (int, error) {
101 n, err := io.ReadFull(r, buf)
102 if err == io.ErrUnexpectedEOF {
103 return n, io.EOF
104 }
105 return n, err
106 }
107
108 func newReader(path string) (io.Reader, func() error, error) {
109 base, err := os.Open(path)
110 if err != nil {
111 return nil, nil, err
112 }
113 baseBuffer := bufio.NewReader(base)
114 return baseBuffer, base.Close, nil
115 }
116
View as plain text