Fix application crash in --monitor mode due to 'Failed to stat file' when setgid is used on a directory (#1157)

* Add debugging output when adding paths and items to an inotify watch
* Only if a path is a directory, perform a path walk
* Catch Exception as error when permissions cause access exception
This commit is contained in:
abraunegg 2020-11-26 06:35:20 +11:00 committed by GitHub
parent 48fc64a247
commit 88f78c163f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 9 deletions

View file

@ -1,7 +1,8 @@
import core.sys.linux.sys.inotify;
import core.stdc.errno;
import core.sys.posix.poll, core.sys.posix.unistd;
import std.exception, std.file, std.path, std.regex, std.stdio, std.string, std.algorithm.mutation;
import std.exception, std.file, std.path, std.regex, std.stdio, std.string, std.algorithm;
import core.stdc.stdlib;
import config;
import selective;
import util;
@ -132,17 +133,43 @@ final class Monitor
}
// passed all potential exclusions
// add inotify watch for this path / directory / file
log.vdebug("Calling add() for this dirname: ", dirname);
add(dirname);
try {
auto pathList = dirEntries(dirname, SpanMode.shallow, false);
foreach(DirEntry entry; pathList) {
if (entry.isDir) {
addRecursive(entry.name);
// if this is a directory, recursivly add this path
if (isDir(dirname)) {
// try and get all the directory entities for this path
try {
auto pathList = dirEntries(dirname, SpanMode.shallow, false);
foreach(DirEntry entry; pathList) {
if (entry.isDir) {
log.vdebug("Calling addRecursive() for this directory: ", entry.name);
addRecursive(entry.name);
}
}
// catch any error which is generated
} catch (std.file.FileException e) {
// Standard filesystem error
displayFileSystemErrorMessage(e.msg);
return;
} catch (Exception e) {
// Issue #1154 handling
// Need to check for: Failed to stat file in error message
if (canFind(e.msg, "Failed to stat file")) {
// File system access issue
log.error("ERROR: The local file system returned an error with the following message:");
log.error(" Error Message: ", e.msg);
log.error("ACCESS ERROR: Please check your UID and GID access to this file, as the permissions on this file is preventing this application to read it");
log.error("\nFATAL: Exiting application to avoid deleting data due to local file system access issues\n");
// Must exit here
exit(-1);
} else {
// some other error
displayFileSystemErrorMessage(e.msg);
return;
}
}
} catch (std.file.FileException e) {
log.vdebug("ERROR: ", e.msg);
return;
}
}
@ -173,6 +200,7 @@ final class Monitor
// Add path to inotify watch - required regardless if a '.folder' or 'folder'
wdToDirName[wd] = buildNormalizedPath(pathname) ~ "/";
log.vdebug("inotify_add_watch successfully added for: ", pathname);
// Do we log that we are monitoring this directory?
if (isDir(pathname)) {
@ -360,4 +388,12 @@ final class Monitor
}
}
}
// Parse and display error message received from the local file system
private void displayFileSystemErrorMessage(string message)
{
log.error("ERROR: The local file system returned an error with the following message:");
auto errorArray = splitLines(message);
log.error(" Error Message: ", errorArray[0]);
}
}

View file

@ -2507,6 +2507,7 @@ final class SyncEngine
// handle changed time
if (newItem.type == ItemType.file && oldItem.mtime != newItem.mtime) {
try {
log.vdebug("Calling setTimes() for this file: ", newPath);
setTimes(newPath, newItem.mtime, newItem.mtime);
} catch (FileException e) {
// display the error message
@ -2687,6 +2688,7 @@ final class SyncEngine
// downloaded matches either size or hash
log.vdebug("Downloaded file matches reported size and or reported file hash");
try {
log.vdebug("Calling setTimes() for this file: ", path);
setTimes(path, item.mtime, item.mtime);
} catch (FileException e) {
// display the error message