Skip to content

Commit

Permalink
Prevent file system access for WatchService DELETE events
Browse files Browse the repository at this point in the history
Trying to check if deleted files are hidden, are readable or are directories will result in IOExceptions on many file systems, so that no action will be taken for deletions.

Signed-off-by: Arne Seime <[email protected]>
  • Loading branch information
seime committed Feb 10, 2025
1 parent 06f9eea commit 7ff9145
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public Path getLibraryPath() {
@Override
public void processWatchEvent(WatchService.Kind kind, Path path) {
File file = libraryPath.resolve(path).toFile();
if (!file.isHidden() && (kind == DELETE || (file.canRead() && (kind == CREATE || kind == MODIFY)))) {
if (kind == DELETE || (!file.isHidden() && file.canRead() && (kind == CREATE || kind == MODIFY))) {
dependencyChanged(file.toString());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public void processWatchEvent(WatchService.Kind kind, Path path) {
} else if (kind == WatchService.Kind.DELETE) {
// Detect if a service specific configuration file was removed. We want to
// notify the service in this case with an updated empty configuration.
if (Files.isHidden(fullPath) || Files.isDirectory(fullPath) || !fullPath.toString().endsWith(".cfg")) {
if (!fullPath.toString().endsWith(".cfg")) {
return;
}
configDispatcher.fileRemoved(fullPath.toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,38 +135,37 @@ public void deactivate() {
public synchronized void processWatchEvent(Kind kind, Path path) {
Path fullPath = watchPath.resolve(path);
String pathString = path.toString();
if (!Files.isReadable(fullPath) || Files.isDirectory(fullPath) || path.startsWith("automation")
|| !pathString.endsWith(".yaml") || fullPath.toFile().isHidden()) {
if (path.startsWith("automation") || !pathString.endsWith(".yaml")) {
logger.trace("Ignored {}", fullPath);
return;
}

// strip extension for model name
String modelName = pathString.substring(0, pathString.lastIndexOf("."));

if (kind == WatchService.Kind.DELETE) {
logger.info("Removing YAML model {}", modelName);
YamlModelWrapper removedModel = modelCache.remove(modelName);
if (removedModel == null) {
return;
}
for (Map.Entry<String, List<JsonNode>> modelEntry : removedModel.getNodes().entrySet()) {
String elementName = modelEntry.getKey();
List<JsonNode> removedNodes = modelEntry.getValue();
if (!removedNodes.isEmpty()) {
getElementListeners(elementName).forEach(listener -> {
List removedElements = parseJsonNodes(removedNodes, listener.getElementClass());
listener.removedModel(modelName, removedElements);
});
try {
if (kind == WatchService.Kind.DELETE) {
logger.info("Removing YAML model {}", modelName);
YamlModelWrapper removedModel = modelCache.remove(modelName);
if (removedModel == null) {
return;
}
for (Map.Entry<String, List<JsonNode>> modelEntry : removedModel.getNodes().entrySet()) {
String elementName = modelEntry.getKey();
List<JsonNode> removedNodes = modelEntry.getValue();
if (!removedNodes.isEmpty()) {
getElementListeners(elementName).forEach(listener -> {
List removedElements = parseJsonNodes(removedNodes, listener.getElementClass());
listener.removedModel(modelName, removedElements);
});
}
}
} else if (!Files.isHidden(fullPath) && Files.isReadable(fullPath) && !Files.isDirectory(fullPath)) {
if (kind == Kind.CREATE) {
logger.info("Adding YAML model {}", modelName);
} else {
logger.info("Updating YAML model {}", modelName);
}
}
} else {
if (kind == Kind.CREATE) {
logger.info("Adding YAML model {}", modelName);
} else {
logger.info("Updating YAML model {}", modelName);
}
try {
JsonNode fileContent = objectMapper.readTree(fullPath.toFile());

// check version
Expand Down Expand Up @@ -233,9 +232,11 @@ public synchronized void processWatchEvent(Kind kind, Path path) {
// replace cache
model.getNodes().put(elementName, newNodeElements);
}
} catch (IOException e) {
logger.warn("Failed to read {}: {}", modelName, e.getMessage());
} else {
logger.trace("Ignored {}", fullPath);
}
} catch (IOException e) {
logger.warn("Failed to process model {}: {}", modelName, e.getMessage());
}
}

Expand Down

0 comments on commit 7ff9145

Please sign in to comment.