From 7a79fbe73552e4450a7c237c6bd8dfc637a1ed4b Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Mon, 12 Jan 2026 11:02:07 -0500 Subject: [PATCH] GP-6321 Force project filesystem index rebuild if index file is empty --- .../store/local/IndexedLocalFileSystem.java | 50 ++++++++----------- .../store/local/IndexedV1LocalFileSystem.java | 1 + .../store/local/LocalFileSystem.java | 2 - 3 files changed, 22 insertions(+), 31 deletions(-) diff --git a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/IndexedLocalFileSystem.java b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/IndexedLocalFileSystem.java index 3533d45866..33d56875e9 100644 --- a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/IndexedLocalFileSystem.java +++ b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/IndexedLocalFileSystem.java @@ -89,6 +89,7 @@ public class IndexedLocalFileSystem extends LocalFileSystem { * to notify listeners. If false, blocking notification will be performed. * @param create if true a new folder will be created. * @throws FileNotFoundException if specified rootPath does not exist + * @throws IndexReadException failure occured reading index file * @throws IOException if error occurs while reading/writing index files */ IndexedLocalFileSystem(String rootPath, boolean isVersioned, boolean readOnly, @@ -440,11 +441,21 @@ public class IndexedLocalFileSystem extends LocalFileSystem { public static int readIndexVersion(String rootPath) throws IOException { File indexFile = new File(rootPath, INDEX_FILE); + + if (indexFile.exists() && indexFile.length() == 0) { + return 0; // will trigger index rebuild + } + BufferedReader indexReader = null; try { indexReader = new BufferedReader(new InputStreamReader( new BufferedInputStream(new FileInputStream(indexFile)), "UTF8")); - return getIndexVersion(indexReader.readLine()); + int ver = getIndexVersion(indexReader.readLine()); + if (ver >= 0 && ver < LATEST_INDEX_VERSION) { + Msg.warn(LocalFileSystem.class, + "Using deprecated Indexed filesystem (V0): " + rootPath); + } + return ver; } finally { if (indexReader != null) { @@ -463,6 +474,10 @@ public class IndexedLocalFileSystem extends LocalFileSystem { // TODO: current implementation does not attempt to avoid concurrent read/write // access to index/journal files + if (indexFile.length() == 0) { + throw new IndexReadException("empty index: " + indexFile); + } + MessageDigest messageDigest = null; try { messageDigest = MessageDigest.getInstance("MD5"); @@ -485,7 +500,7 @@ public class IndexedLocalFileSystem extends LocalFileSystem { new BufferedInputStream(new FileInputStream(indexFile)), "UTF8")); String line = indexReader.readLine(); if (checkIndexVersion(line)) { - // version line consumed - read next line + // version line consumed - read next line - Version-0 lacked VERSION line line = indexReader.readLine(); } Folder currentFolder = null; @@ -1714,6 +1729,8 @@ public class IndexedLocalFileSystem extends LocalFileSystem { /** * Get the V0 indexed-file-system instance. File system storage should first be * pre-qualified as an having indexed storage using the {@link #isIndexed(String)} method. + *

+ * NOTE: If there is a index read error a forced migration to V1 may occur * @param rootPath * @param isVersioned * @param readOnly @@ -1735,41 +1752,16 @@ public class IndexedLocalFileSystem extends LocalFileSystem { Msg.error(LocalFileSystem.class, "Indexed filesystem error: " + e.getMessage()); Msg.info(LocalFileSystem.class, "Attempting index rebuild: " + rootPath); - if (!IndexedLocalFileSystem.rebuild(new File(rootPath))) { + if (!IndexedV1LocalFileSystem.rebuild(new File(rootPath))) { throw e; } // retry after index rebuild - return new IndexedLocalFileSystem(rootPath, isVersioned, readOnly, + return new IndexedV1LocalFileSystem(rootPath, isVersioned, readOnly, enableAsyncronousDispatching, false); } } - /** - * Completely rebuild filesystem index using item information contained - * within indexed property files. Empty folders will be lost. - * @param rootDir - * @throws IOException - */ - public static boolean rebuild(File rootDir) throws IOException { - - verifyIndexedFileStructure(rootDir); - - IndexedLocalFileSystem fs = new IndexedLocalFileSystem(rootDir.getAbsolutePath()); - fs.rebuildIndex(); - fs.cleanupAfterConstruction(); - fs.dispose(); - - File errorFile = new File(rootDir, REBUILD_ERROR_FILE); - if (errorFile.exists()) { - Msg.error(LocalFileSystem.class, - "Indexed filesystem rebuild failed, see log for details: " + errorFile); - return false; - } - Msg.info(LocalFileSystem.class, "Index rebuild completed: " + rootDir); - return true; - } - static class IndexedItemStorage extends ItemStorage { IndexedItemStorage(File dir, String storageName, String folderPath, String itemName) { diff --git a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/IndexedV1LocalFileSystem.java b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/IndexedV1LocalFileSystem.java index 125f690ae4..1fa6ffe514 100644 --- a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/IndexedV1LocalFileSystem.java +++ b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/IndexedV1LocalFileSystem.java @@ -43,6 +43,7 @@ public class IndexedV1LocalFileSystem extends IndexedLocalFileSystem { * to notify listeners. If false, blocking notification will be performed. * @param create if true a new folder will be created. * @throws FileNotFoundException if specified rootPath does not exist + * @throws IndexReadException failure occured reading index file * @throws IOException if error occurs while reading/writing index files */ protected IndexedV1LocalFileSystem(String rootPath, boolean isVersioned, boolean readOnly, diff --git a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/LocalFileSystem.java b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/LocalFileSystem.java index 4975931845..dd71437d6f 100644 --- a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/LocalFileSystem.java +++ b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/LocalFileSystem.java @@ -130,8 +130,6 @@ public abstract class LocalFileSystem implements FileSystem { return new MangledLocalFileSystem(rootPath, isVersioned, readOnly, enableAsyncronousDispatching); case 0: - Msg.warn(LocalFileSystem.class, - "Using deprecated Indexed filesystem (V0): " + rootPath); return IndexedLocalFileSystem.getFileSystem(rootPath, isVersioned, readOnly, enableAsyncronousDispatching); case 1: