4
4
*/
5
5
6
6
@file:OptIn(ExperimentalForeignApi ::class , UnsafeNumber ::class )
7
+
7
8
package kotlinx.datetime.internal
8
9
9
10
import kotlinx.cinterop.*
@@ -43,3 +44,41 @@ internal fun Path.tryTraverseDirectory(
43
44
}
44
45
return true
45
46
}
47
+
48
+ internal fun compareFiles (file1 : String , file2 : String ): Boolean = memScoped {
49
+ try {
50
+ val stat1 = alloc< stat> ()
51
+ val stat2 = alloc< stat> ()
52
+
53
+ if (stat(file1, stat1.ptr) != 0 || stat(file2, stat2.ptr) != 0 ) return false
54
+ if (stat1.st_size != stat2.st_size) return false
55
+
56
+ val f1 = fopen(file1, " rb" ) ? : return false
57
+ val f2 = fopen(file2, " rb" ) ? : run { fclose(f1); return false }
58
+
59
+ try {
60
+ val bufferSize = 4096
61
+ val buffer1 = allocArray<ByteVar >(bufferSize)
62
+ val buffer2 = allocArray<ByteVar >(bufferSize)
63
+
64
+ while (true ) {
65
+ val read1 = fread(buffer1, 1u , bufferSize.toULong(), f1).toInt()
66
+ val read2 = fread(buffer2, 1u , bufferSize.toULong(), f2).toInt()
67
+
68
+ if (read1 != read2) return false
69
+ if (read1 == 0 ) break // EOF
70
+
71
+ for (i in 0 .. < read1.toInt()) {
72
+ if (buffer1[i] != buffer2[i]) return false
73
+ }
74
+ }
75
+
76
+ return true
77
+ } finally {
78
+ fclose(f1)
79
+ fclose(f2)
80
+ }
81
+ } catch (_: Throwable ) {
82
+ return false
83
+ }
84
+ }
0 commit comments