From 02f35fd01477d0f9262ea43b3c5fc1744b752de8 Mon Sep 17 00:00:00 2001 From: Graham Date: Tue, 30 Nov 2021 19:30:52 +0000 Subject: [PATCH] Fix legacy DiskStore support The archive IDs are offset by one in a legacy main_file_cache.dat cache. Signed-off-by: Graham --- .../kotlin/org/openrs2/cache/DiskStore.kt | 30 ++++++---- .../kotlin/org/openrs2/cache/DiskStoreTest.kt | 56 ++++++++++++++++-- .../main_file_cache.dat | Bin 0 -> 7632 bytes .../main_file_cache.idx0 | Bin 0 -> 12 bytes .../main_file_cache.dat | Bin 0 -> 9324 bytes .../main_file_cache.idx0 | Bin 0 -> 12 bytes .../main_file_cache.dat | Bin 0 -> 7632 bytes .../main_file_cache.idx0 | Bin 0 -> 12 bytes .../main_file_cache.dat | Bin 0 -> 8804 bytes .../main_file_cache.idx0 | Bin 0 -> 12 bytes .../single-block-legacy/main_file_cache.dat | Bin 535 -> 535 bytes ...file_cache.idx255 => main_file_cache.idx0} | Bin 12 files changed, 69 insertions(+), 17 deletions(-) create mode 100644 cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-first-invalid-archive-legacy/main_file_cache.dat create mode 100644 cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-first-invalid-archive-legacy/main_file_cache.idx0 create mode 100644 cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-first-invalid-archive-overwritten-legacy/main_file_cache.dat create mode 100644 cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-first-invalid-archive-overwritten-legacy/main_file_cache.idx0 create mode 100644 cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-second-invalid-archive-legacy/main_file_cache.dat create mode 100644 cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-second-invalid-archive-legacy/main_file_cache.idx0 create mode 100644 cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-second-invalid-archive-overwritten-legacy/main_file_cache.dat create mode 100644 cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-second-invalid-archive-overwritten-legacy/main_file_cache.idx0 rename cache/src/test/resources/org/openrs2/cache/disk-store/single-block-legacy/{main_file_cache.idx255 => main_file_cache.idx0} (100%) diff --git a/cache/src/main/kotlin/org/openrs2/cache/DiskStore.kt b/cache/src/main/kotlin/org/openrs2/cache/DiskStore.kt index 3c43f709..e34028a4 100644 --- a/cache/src/main/kotlin/org/openrs2/cache/DiskStore.kt +++ b/cache/src/main/kotlin/org/openrs2/cache/DiskStore.kt @@ -30,10 +30,13 @@ public class DiskStore private constructor( private val data: BufferedFileChannel, private val musicData: BufferedFileChannel?, private val indexes: Array, - private val alloc: ByteBufAllocator + private val alloc: ByteBufAllocator, + legacyData: Boolean ) : Store { private data class IndexEntry(val size: Int, val block: Int) + private val archiveOffset = if (legacyData) 1 else 0 + init { require(indexes.size == Store.MAX_ARCHIVE + 1) } @@ -194,7 +197,7 @@ public class DiskStore private constructor( } val actualNum = tempBuf.readUnsignedShort() val nextBlock = tempBuf.readUnsignedMedium() - val actualArchive = tempBuf.readUnsignedByte().toInt() + val actualArchive = (tempBuf.readUnsignedByte().toInt() - archiveOffset) and 0xFF // verify header when { @@ -317,7 +320,7 @@ public class DiskStore private constructor( } val actualNum = tempBuf.readUnsignedShort() nextBlock = tempBuf.readUnsignedMedium() - val actualArchive = tempBuf.readUnsignedByte().toInt() + val actualArchive = (tempBuf.readUnsignedByte().toInt() - archiveOffset) and 0xFF if (actualGroup != group || actualNum != num || actualArchive != archive) { block = 0 @@ -371,7 +374,7 @@ public class DiskStore private constructor( } val actualNum = tempBuf.readUnsignedShort() nextNextBlock = tempBuf.readUnsignedMedium() - val actualArchive = tempBuf.readUnsignedByte().toInt() + val actualArchive = (tempBuf.readUnsignedByte().toInt() - archiveOffset) and 0xFF if (actualGroup != group || actualNum != nextNum || actualArchive != archive) { nextBlock = 0 @@ -403,7 +406,7 @@ public class DiskStore private constructor( } tempBuf.writeShort(num) tempBuf.writeMedium(nextBlock) - tempBuf.writeByte(archive) + tempBuf.writeByte(archive + archiveOffset) data.write(blockPos, tempBuf, headerSize) @@ -501,10 +504,13 @@ public class DiskStore private constructor( val js5DataPath = dataPath(root) val legacyDataPath = legacyDataPath(root) - val dataPath = if (Files.exists(js5DataPath)) { - js5DataPath - } else { + // We check for js5DataPath first as it takes precedence. + val legacyDataFile = !Files.exists(js5DataPath) + + val dataPath = if (legacyDataFile) { legacyDataPath + } else { + js5DataPath } val data = BufferedFileChannel( FileChannel.open(dataPath, READ, WRITE), @@ -539,17 +545,17 @@ public class DiskStore private constructor( } } - return DiskStore(root, data, musicData, archives, alloc) + return DiskStore(root, data, musicData, archives, alloc, legacyDataFile) } public fun create( root: Path, alloc: ByteBufAllocator = ByteBufAllocator.DEFAULT, - legacyDataPath: Boolean = false + legacyDataFile: Boolean = false ): Store { Files.createDirectories(root) - val dataPath = if (legacyDataPath) { + val dataPath = if (legacyDataFile) { legacyDataPath(root) } else { dataPath(root) @@ -563,7 +569,7 @@ public class DiskStore private constructor( val archives = Array(Store.MAX_ARCHIVE + 1) { null } - return DiskStore(root, data, null, archives, alloc) + return DiskStore(root, data, null, archives, alloc, legacyDataFile) } } } diff --git a/cache/src/test/kotlin/org/openrs2/cache/DiskStoreTest.kt b/cache/src/test/kotlin/org/openrs2/cache/DiskStoreTest.kt index 208d0dcc..d2bf6b9d 100644 --- a/cache/src/test/kotlin/org/openrs2/cache/DiskStoreTest.kt +++ b/cache/src/test/kotlin/org/openrs2/cache/DiskStoreTest.kt @@ -507,6 +507,12 @@ class DiskStoreTest { } } + readTest("corrupt-first-invalid-archive-legacy") { store -> + assertFailsWith { + store.read(0, 1).release() + } + } + readTest("corrupt-first-invalid-block-number") { store -> assertFailsWith { store.read(255, 1).release() @@ -537,6 +543,12 @@ class DiskStoreTest { } } + readTest("corrupt-second-invalid-archive-legacy") { store -> + assertFailsWith { + store.read(0, 1).release() + } + } + readTest("corrupt-second-invalid-block-number") { store -> assertFailsWith { store.read(255, 1).release() @@ -587,6 +599,15 @@ class DiskStoreTest { } } + overwriteTest( + "corrupt-first-invalid-archive-legacy", + "corrupt-first-invalid-archive-overwritten-legacy" + ) { store -> + copiedBuffer("Hello".repeat(300)).use { buf -> + store.write(0, 1, buf) + } + } + overwriteTest("corrupt-first-invalid-block-number", "corrupt-first-invalid-block-number-overwritten") { store -> copiedBuffer("Hello".repeat(300)).use { buf -> store.write(255, 1, buf) @@ -617,6 +638,15 @@ class DiskStoreTest { } } + overwriteTest( + "corrupt-second-invalid-archive-legacy", + "corrupt-second-invalid-archive-overwritten-legacy" + ) { store -> + copiedBuffer("Hello".repeat(300)).use { buf -> + store.write(0, 1, buf) + } + } + overwriteTest( "corrupt-second-invalid-block-number", "corrupt-second-invalid-block-number-overwritten" @@ -665,6 +695,14 @@ class DiskStoreTest { } } + readTest("corrupt-first-invalid-archive-overwritten-legacy") { store -> + store.read(0, 1).use { actual -> + copiedBuffer("Hello".repeat(300)).use { expected -> + assertEquals(expected, actual) + } + } + } + readTest("corrupt-first-invalid-block-number-overwritten") { store -> store.read(255, 1).use { actual -> copiedBuffer("Hello".repeat(300)).use { expected -> @@ -705,6 +743,14 @@ class DiskStoreTest { } } + readTest("corrupt-second-invalid-archive-overwritten-legacy") { store -> + store.read(0, 1).use { actual -> + copiedBuffer("Hello".repeat(300)).use { expected -> + assertEquals(expected, actual) + } + } + } + readTest("corrupt-second-invalid-block-number-overwritten") { store -> store.read(255, 1).use { actual -> copiedBuffer("Hello".repeat(300)).use { expected -> @@ -762,9 +808,9 @@ class DiskStoreTest { @Test fun testCreateLegacyDataFile() { - writeTest("single-block-legacy", legacyDataPath = true) { store -> + writeTest("single-block-legacy", legacyDataFile = true) { store -> copiedBuffer("OpenRS2").use { buf -> - store.write(255, 1, buf) + store.write(0, 1, buf) } } } @@ -773,7 +819,7 @@ class DiskStoreTest { fun testOpenLegacyDataFile() { readTest("single-block-legacy") { store -> copiedBuffer("OpenRS2").use { expected -> - store.read(255, 1).use { actual -> + store.read(0, 1).use { actual -> assertEquals(expected, actual) } } @@ -786,10 +832,10 @@ class DiskStoreTest { } } - private fun writeTest(name: String, legacyDataPath: Boolean = false, f: (Store) -> Unit) { + private fun writeTest(name: String, legacyDataFile: Boolean = false, f: (Store) -> Unit) { Jimfs.newFileSystem(Configuration.forCurrentPlatform()).use { fs -> val actual = fs.rootDirectories.first().resolve("cache") - DiskStore.create(actual, legacyDataPath = legacyDataPath).use { store -> + DiskStore.create(actual, legacyDataFile = legacyDataFile).use { store -> f(store) } diff --git a/cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-first-invalid-archive-legacy/main_file_cache.dat b/cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-first-invalid-archive-legacy/main_file_cache.dat new file mode 100644 index 0000000000000000000000000000000000000000..7220e157879025110cecec814aea41f8fab9b301 GIT binary patch literal 7632 zcmeI1xeWqA5Cm)Pe+lLiL4p`?5pfYEecmO2)xFO8qnh4oE#zbZnn0aXXukK)>-~5h zxlBhO4n#s*!N7Y3L_q^xB@MhcK^(NuR~`lLO%Mki3>7!<-UM;b!&p&7?@bT~159PA z$=*_Mi9m5M!d%|A?Cl0;5{iQfmh?vRKokcvtm%#BfhZ0Z*wP!#O+g&2u%|bgD}p%K X;FjKaac9RTLLBVpZ8e;LyXRgf_QH8}Iw)J2u(9Jv7kBVBNpYo2u4S-{5%P=QD)WS_@- zUZ1ajl5h=Eplt$D Nz?~OC8>5bkPobrPOw)94GLlg%q?CFi(&j*J%*x;7l Uc*)L=D?%LXzu%_x#{U$CFNYp%H~;_u literal 0 HcmV?d00001 diff --git a/cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-second-invalid-archive-legacy/main_file_cache.idx0 b/cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-second-invalid-archive-legacy/main_file_cache.idx0 new file mode 100644 index 0000000000000000000000000000000000000000..fba8761c34ff5b7e2836fd5b87c9b0a798b56100 GIT binary patch literal 12 PcmZQz00Zd=1_nj|0rUWM literal 0 HcmV?d00001 diff --git a/cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-second-invalid-archive-overwritten-legacy/main_file_cache.dat b/cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-second-invalid-archive-overwritten-legacy/main_file_cache.dat new file mode 100644 index 0000000000000000000000000000000000000000..93ca114646522f52ed4bf1958682e692f8441f1d GIT binary patch literal 8804 zcmeI1y%B<77=sf5`B!Ig3Ony~20Bii%PGxgPs_UA z^Rm5xI1mZd^Re76*W)=K(-Vk-4Nx-}cuPPWR6xVHfwvOGK@Dt~pMtj%#6bhJOg8XV zf;iX$9TO3~l^_mUpr>g}_6`Lf7AOunV4!ze_Ra>y3B^GVjOmT$hA0jOU`lT^H$-tT z0&{w!c~TGu6R=BfG>-`4U@mJ@dgFI`V_ETj;(6~(2WD;b9$V!H+L^#?&i|`~7tvt` ADgXcg literal 0 HcmV?d00001 diff --git a/cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-second-invalid-archive-overwritten-legacy/main_file_cache.idx0 b/cache/src/test/resources/org/openrs2/cache/disk-store/corrupt-second-invalid-archive-overwritten-legacy/main_file_cache.idx0 new file mode 100644 index 0000000000000000000000000000000000000000..6c97b5aaba4205a2a9855883b28bd68625f91cf3 GIT binary patch literal 12 PcmZQz00Y)L3=E6_1C{{e literal 0 HcmV?d00001 diff --git a/cache/src/test/resources/org/openrs2/cache/disk-store/single-block-legacy/main_file_cache.dat b/cache/src/test/resources/org/openrs2/cache/disk-store/single-block-legacy/main_file_cache.dat index 98a426d1d82802721dc2e6fb46fc7600b9db6a2e..c7bc0906917411bc9022c14daf0b664794dd516b 100644 GIT binary patch delta 16 XcmbQvGM!}uKNAO|e?e+qP_PjICBp=2 delta 16 XcmbQvGM!}uKNH7)|AN%KpkN~aEwcq^ diff --git a/cache/src/test/resources/org/openrs2/cache/disk-store/single-block-legacy/main_file_cache.idx255 b/cache/src/test/resources/org/openrs2/cache/disk-store/single-block-legacy/main_file_cache.idx0 similarity index 100% rename from cache/src/test/resources/org/openrs2/cache/disk-store/single-block-legacy/main_file_cache.idx255 rename to cache/src/test/resources/org/openrs2/cache/disk-store/single-block-legacy/main_file_cache.idx0