Created
December 7, 2023 22:28
-
-
Save ekmillard/9df5d5481b9b4154adcf2e97958c62a7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ps.eden.server.cache.editor.leanbow; | |
import ps.eden.server.ServerConstants; | |
import ps.eden.server.cache.editor.mgi.tools.rseditor.core.cache.*; | |
import ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.ByteBuffer; | |
import ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.Whirlpool; | |
public class CacheRepair { | |
/** | |
* Wheter to generate missing filesystems. | |
*/ | |
private boolean generateMissingFilesystems; | |
/** | |
* Whether to not remove missing folders. | |
*/ | |
private boolean dontRemoveMissingFolders; | |
public static void main(String[] args) { | |
args = new String[] {"-x", ServerConstants.CACHE_530_DIR}; | |
StringBuilder bldArgs = new StringBuilder(); | |
for (int i = 0; i < args.length; i++) { | |
bldArgs.append(args[i]); | |
if ((i + 1) < args.length) | |
bldArgs.append(' '); | |
} | |
try { | |
new CacheRepair().command(bldArgs.toString()); | |
} catch (Throwable t) { | |
if (t.getMessage().contains("startup")) | |
main(new String[0]); // output usage | |
else if (t.getMessage().contains("notfound")) | |
System.err.println("Couldn't find cache."); | |
else if (t.getMessage().contains("error")) { | |
System.err.println("Oops! An error occured:"); | |
t.getCause().printStackTrace(); | |
} | |
} | |
} | |
public Object command(String command) { | |
String path = null; | |
for (int offset = 0; offset < command.length();) { | |
if (command.charAt(offset) == '-') { | |
if ((offset + 1) >= command.length()) { | |
System.err.println("Bad option syntax, required -[option], found -[endofcommand]"); | |
throw new RuntimeException("startup:badoption"); | |
} | |
char option = command.charAt(++offset); | |
if (option == 'x') | |
generateMissingFilesystems = true; | |
else if (option == 'd') | |
dontRemoveMissingFolders = true; | |
else { | |
System.err.println("Unknown option: [-" + option + "]"); | |
throw new RuntimeException("startup:badoption"); | |
} | |
offset++; | |
} else if (command.charAt(offset) == ' ') | |
offset++; | |
else { | |
path = command.substring(offset); | |
break; | |
} | |
} | |
if (path == null) | |
throw new RuntimeException("notfound:"); | |
try { | |
doRecover(path); | |
} catch (Throwable t) { | |
throw new RuntimeException("error:unexpected", t); | |
} | |
return null; | |
} | |
public void doRecover(String path) { | |
Cache cache = Cache.openCache(path); | |
int totalErrors = 0; | |
for (int i = 0; i < cache.getIndicesCount(); i++) { | |
if (i == 6 || i == 14 || i == 5 /* maps */) | |
continue; | |
System.err.println("Verifying information of:" + i); | |
FileSystem system; | |
try { | |
system = cache.getFilesSystem(i); | |
} catch (Throwable t) { | |
totalErrors++; | |
System.err.println("------------------------------"); | |
System.err.println("Failed to load information"); | |
if (generateMissingFilesystems) { | |
System.err.println("Trying to regenerate filesystem"); | |
try { | |
byte[] pdata = Helper.encodeFITContainer(new byte[] { 5, 0, 0, 0 }, 0); // empty | |
// fs | |
// (protocol | |
// 5, | |
// props | |
// 0, | |
// folders | |
// count | |
// - | |
// 0) | |
cache.getInformationStore().put(i, new ByteBuffer(pdata), pdata.length); | |
system = cache.getFilesSystem(i); | |
system.setUseAutomaticVersionsIncremetor(false); | |
int count = cache.getFilesStore(i).getFileCount(); | |
for (int file = 0; file < count; file++) { | |
ByteBuffer data = cache.getFilesStore(i).get(file); | |
if (data == null || !Helper.validFilesContainer(data)) { | |
if (data != null) | |
System.err.println("Failed to recover folder:" + file + ", because data appears corrupt."); | |
continue; | |
} | |
try { | |
ByteBuffer f = Helper.decodeFilesContainer(data); | |
system.addFolder(new Folder(file, -1, Helper.decodeVersion(data), new File[] { new File(0, -1, f) })); | |
System.err.println("Recovered folder:" + file); | |
} catch (Throwable ttt) { | |
System.err.println("Failed to recover folder:" + file); | |
} | |
} | |
System.err.println("Successfully regenerated filesystem"); | |
} catch (Throwable tt) { | |
System.err.println("Failed to regenerate filesystem"); | |
} | |
} | |
System.err.println("------------------------------"); | |
continue; | |
} | |
system.setUseAutomaticVersionsIncremetor(false); | |
System.err.println("------------------------------"); | |
System.err.println("Information loading sucessfull"); | |
System.err.println("Folders count:" + system.getFolders().length); | |
System.err.println("Uses names:" + system.usesNames()); | |
System.err.println("Uses whirlpool:" + system.usesWhirlpool()); | |
System.err.println("Version:" + system.getVersion()); | |
System.err.println("Verifying files of:" + i); | |
Folder[] folders = new Folder[system.getFolders().length]; | |
System.arraycopy(system.getFolders(), 0, folders, 0, folders.length); | |
int errorsCount = 0; | |
for (int a = 0; a < folders.length; a++) { | |
Folder folder = folders[a]; | |
ByteBuffer data = cache.getFilesStore(i).get(folder.getID()); | |
if (data == null) { | |
System.err.println("Missing folder - " + folder.getID()); | |
errorsCount++; | |
if (!dontRemoveMissingFolders) { | |
system.deleteFolder(folder); | |
System.err.println("Deleted folder " + folder.getID() + " entry from fs."); | |
} | |
continue; | |
} | |
if (Helper.decodeVersion(data) != (folder.getVersion() & 0xFFFF)) { | |
System.err.println("Folder " + folder.getID() + " has incorrect version:" + Helper.decodeVersion(data) + ", expected:" + (folder.getVersion() & 0xFFFF)); | |
folder.setVersion(Helper.decodeVersion(data)); | |
errorsCount++; | |
} | |
boolean recalc = false; | |
if (Helper.crc32(data, 0, data.getBuffer().length - 2) != folder.getCRC32()) { | |
System.err.println("Folder " + folder.getID() + " has incorrect crc:" + Helper.crc32(data, 0, data.getBuffer().length - 2) + ", expected:" + folder.getCRC32()); | |
recalc = true; | |
errorsCount++; | |
} | |
if (system.usesWhirlpool()) { | |
byte[] digest = Whirlpool.whirlpool(data.getBuffer(), 0, data.getBuffer().length - 2); | |
for (int d = 0; d < 64; d++) | |
if (digest[d] != folder.getDigest()[d]) { | |
System.err.println("Folder " + folder.getID() + " has incorrect whirlpool digest."); | |
recalc = true; | |
errorsCount++; | |
break; | |
} | |
} | |
if (recalc) | |
folder.recalculate(); | |
} | |
totalErrors += errorsCount; | |
System.err.println("Done verifying files, errors:" + errorsCount); | |
System.err.println("------------------------------"); | |
} | |
cache.close(); | |
System.err.println("Done, total errors count:" + totalErrors); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment