aboutsummaryrefslogtreecommitdiffhomepage
path: root/Spigot-Server-Patches/0363-Detect-and-repair-corrupt-Region-Files.patch
diff options
context:
space:
mode:
Diffstat (limited to 'Spigot-Server-Patches/0363-Detect-and-repair-corrupt-Region-Files.patch')
-rw-r--r--Spigot-Server-Patches/0363-Detect-and-repair-corrupt-Region-Files.patch125
1 files changed, 125 insertions, 0 deletions
diff --git a/Spigot-Server-Patches/0363-Detect-and-repair-corrupt-Region-Files.patch b/Spigot-Server-Patches/0363-Detect-and-repair-corrupt-Region-Files.patch
new file mode 100644
index 0000000000..3be82ad0db
--- /dev/null
+++ b/Spigot-Server-Patches/0363-Detect-and-repair-corrupt-Region-Files.patch
@@ -0,0 +1,125 @@
+From ec510b0b41b7924da4737613c9c10441498eb46f Mon Sep 17 00:00:00 2001
+From: Aikar <[email protected]>
+Date: Sat, 11 Aug 2018 00:49:20 -0400
+Subject: [PATCH] Detect and repair corrupt Region Files
+
+If the file has partial data written but not the full 8192 bytes,
+then the server will be unable to load that region file...
+
+I don't know why mojang only checks for 4096, when anything less than 8192 is a crash.
+
+But to be safe, it will attempt to back up the file.
+
+diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java
+index 2bd85e2d..d334d634 100644
+--- a/src/main/java/net/minecraft/server/RegionFile.java
++++ b/src/main/java/net/minecraft/server/RegionFile.java
+@@ -23,10 +23,10 @@ import javax.annotation.Nullable;
+ public class RegionFile {
+
+ private static final byte[] a = new byte[4096];
+- private final File b;
+- private RandomAccessFile c;
+- private final int[] d = new int[1024];
+- private final int[] e = new int[1024];
++ private final File b;private File getFile() { return b; } // Paper - OBFHELPER
++ private RandomAccessFile c;private RandomAccessFile getDataFile() { return c; } // Paper - OBFHELPER
++ private final int[] d = new int[1024];private int[] offsets = d; // Paper - OBFHELPER
++ private final int[] e = new int[1024];private int[] timestamps = e; // Paper - OBFHELPER
+ private List<Boolean> f;
+ private int g;
+ private long h;
+@@ -40,10 +40,11 @@ public class RegionFile {
+ this.h = file.lastModified();
+ }
+
++
+ this.c = new RandomAccessFile(file, "rw");
+- if (this.c.length() < 4096L) {
+- this.c.write(RegionFile.a);
+- this.c.write(RegionFile.a);
++ if (this.c.length() < 8192L) { // Paper - headers should be 8192
++ this.c.write(a);
++ this.c.write(a);
+ this.g += 8192;
+ }
+
+@@ -81,16 +82,16 @@ public class RegionFile {
+ for (j = 0; j < 1024; ++j) {
+ k = headerAsInts.get(); // Paper
+ this.d[j] = k;
+- if (k != 0 && (k >> 8) + (k & 255) <= this.f.size()) {
++ if (k > 0 && (k >> 8) > 1 && (k >> 8) + (k & 255) <= this.f.size()) { // Paper >= 1 as 0/1 are the headers, and negative isnt valid
+ for (int l = 0; l < (k & 255); ++l) {
+ this.f.set((k >> 8) + l, Boolean.valueOf(false));
+ }
+- }
++ } else if (k != 0) deleteChunk(j); // Paper
+ }
+
+ for (j = 0; j < 1024; ++j) {
+ k = headerAsInts.get(); // Paper
+- this.e[j] = k;
++ if (offsets[j] != 0) this.timestamps[j] = k; // Paper - don't set timestamp if it got 0'd above due to corruption
+ }
+ } catch (IOException ioexception) {
+ ioexception.printStackTrace();
+@@ -264,6 +265,55 @@ public class RegionFile {
+
+ }
+
++ // Paper start
++ public synchronized void deleteChunk(int j1) {
++ backup();
++ int k = offsets[j1];
++ int x = j1 & 1024;
++ int z = j1 >> 2;
++ int offset = (k >> 8);
++ int len = (k & 255);
++ org.apache.logging.log4j.Logger logger = org.apache.logging.log4j.LogManager.getLogger();
++ String debug = "idx:" + + j1 + " - " + x + "," + z + " - offset: " + offset + " - len: " + len;
++ try {
++ RandomAccessFile file = getDataFile();
++ file.seek(j1 * 4);
++ file.writeInt(0);
++ // clear the timestamp
++ file.seek(4096 + j1 * 4);
++ file.writeInt(0);
++ timestamps[j1] = 0;
++ offsets[j1] = 0;
++ logger.error("Deleted corrupt chunk (" + debug + ") " + getFile().getAbsolutePath(), e);
++ } catch (IOException e) {
++
++ logger.error("Error deleting corrupt chunk (" + debug + ") " + getFile().getAbsolutePath(), e);
++ }
++ }
++ private boolean backedUp = false;
++ private synchronized void backup() {
++ if (backedUp) {
++ return;
++ }
++ backedUp = true;
++ File file = this.getFile();
++ java.text.DateFormat formatter = new java.text.SimpleDateFormat("yyyy-MM-dd");
++ java.util.Date today = new java.util.Date();
++ File corrupt = new File(file.getParentFile(), file.getName() + "." + formatter.format(today) + ".corrupt");
++ if (corrupt.exists()) {
++ return;
++ }
++ org.apache.logging.log4j.Logger logger = org.apache.logging.log4j.LogManager.getLogger();
++ logger.error("Region file " + file.getAbsolutePath() + " was corrupt. Backing up to " + corrupt.getAbsolutePath() + " and repairing");
++ try {
++ java.nio.file.Files.copy(file.toPath(), corrupt.toPath());
++
++ } catch (IOException e) {
++ logger.error("Error backing up corrupt file" + file.getAbsolutePath(), e);
++ }
++ }
++ // Paper end
++
+ class ChunkBuffer extends ByteArrayOutputStream {
+
+ private final int b;
+--
+2.19.1
+