From 88f78c163fd8226b41a0e7050cafac7b7f0b5b40 Mon Sep 17 00:00:00 2001 From: abraunegg Date: Thu, 26 Nov 2020 06:35:20 +1100 Subject: [PATCH] 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 --- src/monitor.d | 54 ++++++++++++++++++++++++++++++++++++++++++--------- src/sync.d | 2 ++ 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/monitor.d b/src/monitor.d index 69f80d74..1dceea9e 100644 --- a/src/monitor.d +++ b/src/monitor.d @@ -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]); + } } diff --git a/src/sync.d b/src/sync.d index 646072ac..704039b1 100644 --- a/src/sync.d +++ b/src/sync.d @@ -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