Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix] Bug 34: Monitor files at Windows root directory #154

Merged
merged 1 commit into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ bld/

# Visual Studio 2015/2017 cache/options directory
.vs/
.vscode/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

Expand Down
75 changes: 59 additions & 16 deletions LogMonitor/LogMonitorTests/ConfigFileParserTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,65 @@ namespace LogMonitorTests
}
}

TEST_METHOD(TestRootDirectoryConfigurations)
{

const std::wstring directory = L"C:\\";
bool includeSubdirectories = false;

std::wstring configFileStr;
std::wstring configFileStrFormat =
L"{ \
\"LogConfig\": { \
\"sources\": [ \
{\
\"type\": \"File\",\
\"directory\": \"%s\",\
\"includeSubdirectories\": %s\
}\
]\
}\
}";

// Valid: Root dir and includeSubdirectories = false
{
configFileStr = Utility::FormatString(
configFileStrFormat.c_str(),
Utility::ReplaceAll(directory, L"\\", L"\\\\").c_str(),
includeSubdirectories ? L"true" : L"false");

JsonFileParser jsonParser(configFileStr);
LoggerSettings settings;

bool success = ReadConfigFile(jsonParser, settings);
Assert::IsTrue(success);

std::wstring output = RecoverOuput();
Assert::AreEqual(L"", output.c_str());
}

// Invalid: Root dir and includeSubdirectories = true
{
includeSubdirectories = true;
configFileStr = Utility::FormatString(
configFileStrFormat.c_str(),
Utility::ReplaceAll(directory, L"\\", L"\\\\").c_str(),
includeSubdirectories ? L"true" : L"false");

fflush(stdout);
ZeroMemory(bigOutBuf, sizeof(bigOutBuf));

JsonFileParser jsonParser(configFileStr);
LoggerSettings settings;

bool success = ReadConfigFile(jsonParser, settings);
Assert::IsTrue(success);

std::wstring output = RecoverOuput();
Assert::IsTrue(output.find(L"WARNING") != std::wstring::npos);
}
}

///
/// Check that invalid ETW sources are not returned by ReadConfigFile.
///
Expand Down Expand Up @@ -1557,28 +1616,12 @@ namespace LogMonitorTests

TEST_METHOD(TestInvalidWaitInSeconds) {
std::wstring directory = L"C:\\LogMonitor\\logs";

std::wstring configFileStrFormat =
L"{ \
\"LogConfig\": { \
\"sources\": [ \
{\
\"type\": \"File\",\
\"directory\": \"%s\",\
\"waitInSeconds\": %f\
}\
]\
}\
}";

TestInvalidWaitInSecondsValues(L"-10", false);
TestInvalidWaitInSecondsValues(L"-Inf", true);
}

private:

void TestWaitInSecondsValues(std::wstring waitInSeconds, bool asString = false) {
std::wstring configFileStrFormat;
std::wstring directory = L"C:\\LogMonitor\\logs";
std::wstring configFileStr = GetConfigFileStrFormat(directory, waitInSeconds, asString);

Expand Down
2 changes: 1 addition & 1 deletion LogMonitor/LogMonitorTests/LogMonitorTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include "../src/LogMonitor/EtwMonitor.cpp"
#include "../src/LogMonitor/EventMonitor.cpp"
#include "../src/LogMonitor/JsonFileParser.cpp"
#include "../src/LogMonitor/FileMonitor/Utilities.cpp"
#include "../src/LogMonitor/FileMonitor/FileMonitorUtilities.cpp"
TinaMor marked this conversation as resolved.
Show resolved Hide resolved
#include "../src/LogMonitor/LogFileMonitor.cpp"
#include "../src/LogMonitor/ProcessMonitor.cpp"
#include "../src/LogMonitor/Utility.cpp"
Expand Down
2 changes: 1 addition & 1 deletion LogMonitor/LogMonitorTests/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
#include "../src/LogMonitor/LogWriter.h"
#include "../src/LogMonitor/EtwMonitor.h"
#include "../src/LogMonitor/EventMonitor.h"
#include "../src/LogMonitor/FileMonitor/Utilities.h"
#include "../src/LogMonitor/FileMonitor/FileMonitorUtilities.h"
#include "../src/LogMonitor/LogFileMonitor.h"
#include "../src/LogMonitor/ProcessMonitor.h"
#include "Utility.h"
Expand Down
22 changes: 22 additions & 0 deletions LogMonitor/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,28 @@ This will monitor any changes in log files matching a specified filter, given th
}
```

**Note:** When the directory is the root directory (e.g. C:\\ ) we can only monitor a file that is in the root directory, not a subfolder. This is due to access issues (even when running LogMonitor as an Admin) for some of the folders in the root directory. Therefore, `includeSubdirectories` must be `false` for the root directory. See example below:

```json
{
"LogConfig": {
"sources": [
{
"type": "File",
"directory": "C:",
"filter": "*.log",
"includeSubdirectories": false
}
]
}
}
```
When the root directory is passed and `includeSubdirectories = true`, we get an error:
```
ERROR: LoggerSettings: Invalid Source File atrribute 'directory' (C:) and 'includeSubdirectories' (true).'includeSubdirectories' attribute cannot be 'true' for the root directory
WARNING: Failed to parse configuration file. Error retrieving source attributes. Invalid source
```

## Process Monitoring

### Description
Expand Down
46 changes: 44 additions & 2 deletions LogMonitor/src/LogMonitor/ConfigFileParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "pch.h"
#include "./Parser/ConfigFileParser.h"
#include "./LogWriter.h"
#include "./FileMonitor/FileMonitorUtilities.h"

/// ConfigFileParser.cpp
///
Expand Down Expand Up @@ -306,8 +307,13 @@ ReadSourceAttributes(
// * directory
// * filter
//
else if (_wcsnicmp(key.c_str(), JSON_TAG_DIRECTORY, _countof(JSON_TAG_DIRECTORY)) == 0
|| _wcsnicmp(key.c_str(), JSON_TAG_FILTER, _countof(JSON_TAG_FILTER)) == 0)
else if (_wcsnicmp(key.c_str(), JSON_TAG_DIRECTORY, _countof(JSON_TAG_DIRECTORY)) == 0)
{
std::wstring directory = Parser.ParseStringValue();
FileMonitorUtilities::ParseDirectoryValue(directory);
Attributes[key] = new std::wstring(directory);
}
else if (_wcsnicmp(key.c_str(), JSON_TAG_FILTER, _countof(JSON_TAG_FILTER)) == 0)
{
Attributes[key] = new std::wstring(Parser.ParseStringValue());
}
Expand Down Expand Up @@ -396,6 +402,12 @@ ReadSourceAttributes(
} while (Parser.ParseNextObjectElement());
}

bool isSourceFileValid = ValidateDirectoryAttributes(Attributes);
if (!isSourceFileValid)
{
success = false;
}

return success;
}

Expand Down Expand Up @@ -640,6 +652,36 @@ AddNewSource(
return true;
}

///
/// Validates that when root directory is passed, includeSubdirectories is false
///
/// \param Attributes An AttributesMap that contains the attributes of the new source objet.
/// \return false when root directory is passed, includeSubdirectories = true. Otherwise, true </returns>
bool ValidateDirectoryAttributes(_In_ AttributesMap &Attributes)
{
if (!Utility::ConfigAttributeExists(Attributes, JSON_TAG_DIRECTORY) ||
!Utility::ConfigAttributeExists(Attributes, JSON_TAG_INCLUDE_SUBDIRECTORIES))
{
return true;
}

std::wstring directory = *(std::wstring *)Attributes[JSON_TAG_DIRECTORY];
const bool includeSubdirectories = *(bool *)Attributes[JSON_TAG_INCLUDE_SUBDIRECTORIES];
TinaMor marked this conversation as resolved.
Show resolved Hide resolved

// Check if Log file monitor config is valid
const bool isValid = FileMonitorUtilities::IsValidSourceFile(directory, includeSubdirectories);
if (!isValid)
{
logWriter.TraceError(
Utility::FormatString(
L"LoggerSettings: Invalid Source File atrribute 'directory' (%s) and 'includeSubdirectories' (%s)."
L"'includeSubdirectories' attribute cannot be 'true' for the root directory",
directory.c_str(), includeSubdirectories ? L"true" : L"false")
.c_str());
}
return isValid;
}

///
/// Debug function
///
Expand Down
Loading
Loading