| 1 | /************************************************************************** |
|---|
| 2 | * Copyright (C) 2004-2007 by Michael Medin <michael@medin.name> * |
|---|
| 3 | * * |
|---|
| 4 | * This code is part of NSClient++ - http://trac.nakednuns.org/nscp * |
|---|
| 5 | * * |
|---|
| 6 | * This program is free software; you can redistribute it and/or modify * |
|---|
| 7 | * it under the terms of the GNU General Public License as published by * |
|---|
| 8 | * the Free Software Foundation; either version 2 of the License, or * |
|---|
| 9 | * (at your option) any later version. * |
|---|
| 10 | * * |
|---|
| 11 | * This program is distributed in the hope that it will be useful, * |
|---|
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
|---|
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
|---|
| 14 | * GNU General Public License for more details. * |
|---|
| 15 | * * |
|---|
| 16 | * You should have received a copy of the GNU General Public License * |
|---|
| 17 | * along with this program; if not, write to the * |
|---|
| 18 | * Free Software Foundation, Inc., * |
|---|
| 19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
|---|
| 20 | ***************************************************************************/ |
|---|
| 21 | #include "stdafx.h" |
|---|
| 22 | #include "CheckDisk.h" |
|---|
| 23 | #include <strEx.h> |
|---|
| 24 | #include <time.h> |
|---|
| 25 | #include <filter_framework.hpp> |
|---|
| 26 | #include <error.hpp> |
|---|
| 27 | #include <file_helpers.hpp> |
|---|
| 28 | #include <checkHelpers.hpp> |
|---|
| 29 | |
|---|
| 30 | CheckDisk gCheckDisk; |
|---|
| 31 | |
|---|
| 32 | BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) |
|---|
| 33 | { |
|---|
| 34 | NSCModuleWrapper::wrapDllMain(hModule, ul_reason_for_call); |
|---|
| 35 | return TRUE; |
|---|
| 36 | } |
|---|
| 37 | |
|---|
| 38 | CheckDisk::CheckDisk() { |
|---|
| 39 | } |
|---|
| 40 | CheckDisk::~CheckDisk() { |
|---|
| 41 | } |
|---|
| 42 | |
|---|
| 43 | bool is_directory(DWORD dwAttr) { |
|---|
| 44 | return ((dwAttr != INVALID_FILE_ATTRIBUTES) && ((dwAttr&FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)); |
|---|
| 45 | } |
|---|
| 46 | |
|---|
| 47 | bool CheckDisk::loadModule(NSCAPI::moduleLoadMode mode) { |
|---|
| 48 | |
|---|
| 49 | try { |
|---|
| 50 | NSCModuleHelper::registerCommand(_T("CheckFileSize"), _T("Check or directory a file and verify its size.")); |
|---|
| 51 | NSCModuleHelper::registerCommand(_T("CheckDriveSize"), _T("Check the size (free-space) of a drive or volume.")); |
|---|
| 52 | NSCModuleHelper::registerCommand(_T("CheckFile"), _T("Check various aspects of a file and/or folder.")); |
|---|
| 53 | } catch (NSCModuleHelper::NSCMHExcpetion &e) { |
|---|
| 54 | NSC_LOG_ERROR_STD(_T("Failed to register command: ") + e.msg_); |
|---|
| 55 | } catch (...) { |
|---|
| 56 | NSC_LOG_ERROR_STD(_T("Failed to register command.")); |
|---|
| 57 | } |
|---|
| 58 | return true; |
|---|
| 59 | } |
|---|
| 60 | bool CheckDisk::unloadModule() { |
|---|
| 61 | return true; |
|---|
| 62 | } |
|---|
| 63 | |
|---|
| 64 | bool CheckDisk::hasCommandHandler() { |
|---|
| 65 | return true; |
|---|
| 66 | } |
|---|
| 67 | bool CheckDisk::hasMessageHandler() { |
|---|
| 68 | return false; |
|---|
| 69 | } |
|---|
| 70 | |
|---|
| 71 | class error_reporter { |
|---|
| 72 | public: |
|---|
| 73 | virtual void report_error(std::wstring error) = 0; |
|---|
| 74 | virtual void report_warning(std::wstring error) = 0; |
|---|
| 75 | }; |
|---|
| 76 | |
|---|
| 77 | |
|---|
| 78 | |
|---|
| 79 | struct file_finder_data { |
|---|
| 80 | file_finder_data(const WIN32_FIND_DATA wfd_, const std::wstring path_, error_reporter *errors_) : wfd(wfd_), path(path_), errors(errors_) {} |
|---|
| 81 | const WIN32_FIND_DATA wfd; |
|---|
| 82 | const std::wstring path; |
|---|
| 83 | error_reporter *errors; |
|---|
| 84 | }; |
|---|
| 85 | typedef std::unary_function<const file_finder_data&, bool> baseFinderFunction; |
|---|
| 86 | |
|---|
| 87 | struct get_size : public baseFinderFunction |
|---|
| 88 | { |
|---|
| 89 | bool error; |
|---|
| 90 | get_size() : size(0), error(false) { } |
|---|
| 91 | result_type operator()(argument_type ffd) { |
|---|
| 92 | if (!file_helpers::checks::is_directory(ffd.wfd.dwFileAttributes)) { |
|---|
| 93 | size += (ffd.wfd.nFileSizeHigh * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)ffd.wfd.nFileSizeLow; |
|---|
| 94 | } |
|---|
| 95 | return true; |
|---|
| 96 | } |
|---|
| 97 | inline unsigned long long getSize() { |
|---|
| 98 | return size; |
|---|
| 99 | } |
|---|
| 100 | inline const bool hasError() const { |
|---|
| 101 | return error; |
|---|
| 102 | } |
|---|
| 103 | inline void setError(error_reporter *errors, std::wstring msg) { |
|---|
| 104 | if (errors != NULL) |
|---|
| 105 | errors->report_error(msg); |
|---|
| 106 | error = true; |
|---|
| 107 | } |
|---|
| 108 | private: |
|---|
| 109 | unsigned long long size; |
|---|
| 110 | }; |
|---|
| 111 | |
|---|
| 112 | template <class finder_function> |
|---|
| 113 | void recursive_scan(std::wstring dir, std::wstring pattern, int current_level, int max_level, finder_function & f, error_reporter * errors) { |
|---|
| 114 | if ((max_level != -1) && (current_level > max_level)) |
|---|
| 115 | return; |
|---|
| 116 | WIN32_FIND_DATA wfd; |
|---|
| 117 | |
|---|
| 118 | DWORD fileAttr = GetFileAttributes(dir.c_str()); |
|---|
| 119 | NSC_DEBUG_MSG_STD(_T("Input is: ") + dir + _T(" / ") + strEx::ihextos(fileAttr)); |
|---|
| 120 | |
|---|
| 121 | if (!file_helpers::checks::is_directory(fileAttr)) { |
|---|
| 122 | NSC_DEBUG_MSG_STD(_T("Found a file dont do recursive scan: ") + dir); |
|---|
| 123 | // It is a file check it an return (dont check recursivly) |
|---|
| 124 | pattern_type single_path = split_path_ex(dir); |
|---|
| 125 | NSC_DEBUG_MSG_STD(_T("Path is: ") + single_path.first); |
|---|
| 126 | HANDLE hFind = FindFirstFile(dir.c_str(), &wfd); |
|---|
| 127 | if (hFind != INVALID_HANDLE_VALUE) { |
|---|
| 128 | f(file_finder_data(wfd, single_path.first, errors)); |
|---|
| 129 | FindClose(hFind); |
|---|
| 130 | } |
|---|
| 131 | return; |
|---|
| 132 | } |
|---|
| 133 | std::wstring file_pattern = dir + _T("\\") + pattern; |
|---|
| 134 | NSC_DEBUG_MSG_STD(_T("File pattern: ") + file_pattern); |
|---|
| 135 | HANDLE hFind = FindFirstFile(file_pattern.c_str(), &wfd); |
|---|
| 136 | if (hFind != INVALID_HANDLE_VALUE) { |
|---|
| 137 | do { |
|---|
| 138 | if (!f(file_finder_data(wfd, dir, errors))) |
|---|
| 139 | break; |
|---|
| 140 | } while (FindNextFile(hFind, &wfd)); |
|---|
| 141 | FindClose(hFind); |
|---|
| 142 | } |
|---|
| 143 | std::wstring dir_pattern = dir + _T("\\*.*"); |
|---|
| 144 | NSC_DEBUG_MSG_STD(_T("File pattern: ") + dir_pattern); |
|---|
| 145 | hFind = FindFirstFile(dir_pattern.c_str(), &wfd); |
|---|
| 146 | if (hFind != INVALID_HANDLE_VALUE) { |
|---|
| 147 | do { |
|---|
| 148 | if (file_helpers::checks::is_directory(wfd.dwFileAttributes)) { |
|---|
| 149 | if ( (wcscmp(wfd.cFileName, _T(".")) != 0) && (wcscmp(wfd.cFileName, _T("..")) != 0) ) |
|---|
| 150 | recursive_scan<finder_function>(dir + _T("\\") + wfd.cFileName, pattern, current_level+1, max_level, f, errors, debug); |
|---|
| 151 | } |
|---|
| 152 | } while (FindNextFile(hFind, &wfd)); |
|---|
| 153 | FindClose(hFind); |
|---|
| 154 | } |
|---|
| 155 | } |
|---|
| 156 | |
|---|
| 157 | |
|---|
| 158 | |
|---|
| 159 | NSCAPI::nagiosReturn CheckDisk::CheckDriveSize(const unsigned int argLen, TCHAR **char_args, std::wstring &message, std::wstring &perf) { |
|---|
| 160 | NSCAPI::nagiosReturn returnCode = NSCAPI::returnOK; |
|---|
| 161 | std::list<std::wstring> args = arrayBuffer::arrayBuffer2list(argLen, char_args); |
|---|
| 162 | if (args.empty()) { |
|---|
| 163 | message = _T("Missing argument(s)."); |
|---|
| 164 | return NSCAPI::returnCRIT; |
|---|
| 165 | } |
|---|
| 166 | |
|---|
| 167 | DriveContainer tmpObject; |
|---|
| 168 | bool bFilter = false; |
|---|
| 169 | bool bFilterRemote = false; |
|---|
| 170 | bool bFilterRemovable = false; |
|---|
| 171 | bool bFilterFixed = false; |
|---|
| 172 | bool bFilterCDROM = false; |
|---|
| 173 | bool bFilterNoRootDir = false; |
|---|
| 174 | bool bCheckAllDrives = false; |
|---|
| 175 | bool bCheckAllOthers = false; |
|---|
| 176 | bool bNSClient = false; |
|---|
| 177 | bool bPerfData = true; |
|---|
| 178 | std::list<DriveContainer> drives; |
|---|
| 179 | std::wstring strCheckAll; |
|---|
| 180 | |
|---|
| 181 | MAP_OPTIONS_BEGIN(args) |
|---|
| 182 | MAP_OPTIONS_STR_AND(_T("Drive"), tmpObject.data, drives.push_back(tmpObject)) |
|---|
| 183 | MAP_OPTIONS_DISK_ALL(tmpObject, _T(""), _T("Free"), _T("Used")) |
|---|
| 184 | MAP_OPTIONS_SHOWALL(tmpObject) |
|---|
| 185 | MAP_OPTIONS_BOOL_VALUE(_T("FilterType"), bFilterFixed, _T("FIXED")) |
|---|
| 186 | MAP_OPTIONS_BOOL_VALUE(_T("FilterType"), bFilterCDROM, _T("CDROM")) |
|---|
| 187 | MAP_OPTIONS_BOOL_VALUE(_T("FilterType"), bFilterRemovable, _T("REMOVABLE")) |
|---|
| 188 | MAP_OPTIONS_BOOL_VALUE(_T("FilterType"), bFilterRemote, _T("REMOTE")) |
|---|
| 189 | MAP_OPTIONS_BOOL_VALUE(_T("FilterType"), bFilterNoRootDir, _T("NO_ROOT_DIR")) |
|---|
| 190 | MAP_OPTIONS_BOOL_FALSE(IGNORE_PERFDATA, bPerfData) |
|---|
| 191 | MAP_OPTIONS_BOOL_TRUE(NSCLIENT, bNSClient) |
|---|
| 192 | //MAP_OPTIONS_BOOL_TRUE(CHECK_ALL, bCheckAll) |
|---|
| 193 | MAP_OPTIONS_STR(CHECK_ALL, strCheckAll) |
|---|
| 194 | MAP_OPTIONS_BOOL_TRUE(CHECK_ALL_OTHERS, bCheckAllOthers) |
|---|
| 195 | MAP_OPTIONS_SECONDARY_BEGIN(_T(":"), p2) |
|---|
| 196 | else if (p2.first == _T("Drive")) { |
|---|
| 197 | tmpObject.data = p__.second; |
|---|
| 198 | tmpObject.alias = p2.second; |
|---|
| 199 | drives.push_back(tmpObject); |
|---|
| 200 | } |
|---|
| 201 | MAP_OPTIONS_MISSING_EX(p2, message, _T("Unknown argument: ")) |
|---|
| 202 | MAP_OPTIONS_SECONDARY_END() |
|---|
| 203 | MAP_OPTIONS_FALLBACK_AND(tmpObject.data, drives.push_back(tmpObject)) |
|---|
| 204 | MAP_OPTIONS_END() |
|---|
| 205 | bFilter = bFilterFixed || bFilterCDROM || bFilterRemote || bFilterRemovable; |
|---|
| 206 | |
|---|
| 207 | if ((drives.size() == 0) && strCheckAll.empty()) |
|---|
| 208 | bCheckAllDrives = true; |
|---|
| 209 | |
|---|
| 210 | if (strCheckAll == _T("volumes")) { |
|---|
| 211 | |
|---|
| 212 | DWORD bufSize = GetLogicalDriveStrings(0, NULL)+5; |
|---|
| 213 | TCHAR *buffer = new TCHAR[bufSize+10]; |
|---|
| 214 | if (GetLogicalDriveStrings(bufSize, buffer)>0) { |
|---|
| 215 | while (buffer[0] != 0) { |
|---|
| 216 | std::wstring drv = buffer; |
|---|
| 217 | |
|---|
| 218 | UINT drvType = GetDriveType(drv.c_str()); |
|---|
| 219 | if ( |
|---|
| 220 | ((!bFilter)&&(drvType == DRIVE_FIXED)) || |
|---|
| 221 | ((bFilter)&&(bFilterFixed)&&(drvType==DRIVE_FIXED)) || |
|---|
| 222 | ((bFilter)&&(bFilterCDROM)&&(drvType==DRIVE_CDROM)) || |
|---|
| 223 | ((bFilter)&&(bFilterRemote)&&(drvType==DRIVE_REMOTE)) || |
|---|
| 224 | ((bFilter)&&(bFilterRemovable)&&(drvType==DRIVE_REMOVABLE)) || |
|---|
| 225 | ((bFilter)&&(bFilterNoRootDir)&&(drvType==DRIVE_NO_ROOT_DIR)) |
|---|
| 226 | ) |
|---|
| 227 | drives.push_back(DriveContainer(drv, tmpObject.warn, tmpObject.crit)); |
|---|
| 228 | |
|---|
| 229 | buffer = &buffer[drv.size()]; |
|---|
| 230 | buffer++; |
|---|
| 231 | } |
|---|
| 232 | } else { |
|---|
| 233 | NSC_LOG_ERROR_STD(_T("Failed to get buffer size: ") + error::lookup::last_error()); |
|---|
| 234 | } |
|---|
| 235 | } |
|---|
| 236 | |
|---|
| 237 | if (bCheckAllDrives) { |
|---|
| 238 | DWORD dwDrives = GetLogicalDrives(); |
|---|
| 239 | int idx = 0; |
|---|
| 240 | while (dwDrives != 0) { |
|---|
| 241 | if (dwDrives & 0x1) { |
|---|
| 242 | std::wstring drv; |
|---|
| 243 | drv += static_cast<TCHAR>('A' + idx); drv += _T(":\\"); |
|---|
| 244 | UINT drvType = GetDriveType(drv.c_str()); |
|---|
| 245 | if ( ((!bFilter)&&(drvType == DRIVE_FIXED)) || |
|---|
| 246 | ((bFilter)&&(bFilterFixed)&&(drvType==DRIVE_FIXED)) || |
|---|
| 247 | ((bFilter)&&(bFilterCDROM)&&(drvType==DRIVE_CDROM)) || |
|---|
| 248 | ((bFilter)&&(bFilterRemote)&&(drvType==DRIVE_REMOTE)) || |
|---|
| 249 | ((bFilter)&&(bFilterRemovable)&&(drvType==DRIVE_REMOVABLE)) || |
|---|
| 250 | ((bFilter)&&(bFilterNoRootDir)&&(drvType==DRIVE_NO_ROOT_DIR)) |
|---|
| 251 | ) |
|---|
| 252 | drives.push_back(DriveContainer(drv, tmpObject.warn, tmpObject.crit)); |
|---|
| 253 | } |
|---|
| 254 | idx++; |
|---|
| 255 | dwDrives >>= 1; |
|---|
| 256 | } |
|---|
| 257 | } |
|---|
| 258 | if (bCheckAllOthers) { |
|---|
| 259 | std::list<DriveContainer> checkdrives; |
|---|
| 260 | DWORD dwDrives = GetLogicalDrives(); |
|---|
| 261 | int idx = 0; |
|---|
| 262 | while (dwDrives != 0) { |
|---|
| 263 | if (dwDrives & 0x1) { |
|---|
| 264 | std::wstring drv; |
|---|
| 265 | drv += static_cast<TCHAR>('A' + idx); drv += _T(":\\"); |
|---|
| 266 | UINT drvType = GetDriveType(drv.c_str()); |
|---|
| 267 | if ( ((!bFilter)&&(drvType == DRIVE_FIXED)) || |
|---|
| 268 | ((bFilter)&&(bFilterFixed)&&(drvType==DRIVE_FIXED)) || |
|---|
| 269 | ((bFilter)&&(bFilterCDROM)&&(drvType==DRIVE_CDROM)) || |
|---|
| 270 | ((bFilter)&&(bFilterRemote)&&(drvType==DRIVE_REMOTE)) || |
|---|
| 271 | ((bFilter)&&(bFilterRemovable)&&(drvType==DRIVE_REMOVABLE)) || |
|---|
| 272 | ((bFilter)&&(bFilterNoRootDir)&&(drvType==DRIVE_NO_ROOT_DIR)) |
|---|
| 273 | ) |
|---|
| 274 | { |
|---|
| 275 | bool bFound = false; |
|---|
| 276 | for (std::list<DriveContainer>::const_iterator pit = drives.begin();pit!=drives.end();++pit) { |
|---|
| 277 | DriveContainer drive = (*pit); |
|---|
| 278 | if (_wcsicmp(drive.data.substr(0,1).c_str(), drv.substr(0,1).c_str())==0) |
|---|
| 279 | bFound = true; |
|---|
| 280 | } |
|---|
| 281 | if (!bFound) |
|---|
| 282 | checkdrives.push_back(DriveContainer(drv, tmpObject.warn, tmpObject.crit)); |
|---|
| 283 | } |
|---|
| 284 | } |
|---|
| 285 | idx++; |
|---|
| 286 | dwDrives >>= 1; |
|---|
| 287 | } |
|---|
| 288 | drives = checkdrives; |
|---|
| 289 | } |
|---|
| 290 | |
|---|
| 291 | |
|---|
| 292 | for (std::list<DriveContainer>::const_iterator pit = drives.begin();pit!=drives.end();++pit) { |
|---|
| 293 | DriveContainer drive = (*pit); |
|---|
| 294 | if (drive.data.length() == 1) |
|---|
| 295 | drive.data += _T(":"); |
|---|
| 296 | drive.perfData = bPerfData; |
|---|
| 297 | UINT drvType = GetDriveType(drive.data.c_str()); |
|---|
| 298 | |
|---|
| 299 | if ((!bFilter)&&!((drvType == DRIVE_FIXED)||(drvType == DRIVE_NO_ROOT_DIR))) { |
|---|
| 300 | message = _T("UNKNOWN: Drive is not a fixed drive: ") + drive.getAlias() + _T(" (it is a ") + get_filter(drvType) + _T(" drive)"); |
|---|
| 301 | return NSCAPI::returnUNKNOWN; |
|---|
| 302 | } else if ( (bFilter)&& |
|---|
| 303 | ( |
|---|
| 304 | ((!bFilterFixed)&&((drvType==DRIVE_FIXED)||(drvType==DRIVE_NO_ROOT_DIR))) || |
|---|
| 305 | ((!bFilterCDROM)&&(drvType==DRIVE_CDROM)) || |
|---|
| 306 | ((!bFilterRemote)&&(drvType==DRIVE_REMOTE)) || |
|---|
| 307 | ((!bFilterRemovable)&&(drvType==DRIVE_REMOVABLE)) |
|---|
| 308 | )) { |
|---|
| 309 | message = _T("UNKNOWN: Drive does not match the current filter: ") + drive.getAlias() + _T(" (add FilterType=") + get_filter(drvType) + _T(" to check this drive)"); |
|---|
| 310 | return NSCAPI::returnUNKNOWN; |
|---|
| 311 | } |
|---|
| 312 | |
|---|
| 313 | ULARGE_INTEGER freeBytesAvailableToCaller; |
|---|
| 314 | ULARGE_INTEGER totalNumberOfBytes; |
|---|
| 315 | ULARGE_INTEGER totalNumberOfFreeBytes; |
|---|
| 316 | if (!GetDiskFreeSpaceEx(drive.data.c_str(), &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes)) { |
|---|
| 317 | message = _T("CRITICAL: Could not get free space for: ") + drive.getAlias() + _T(" ") + drive.data + _T(" reason: ") + error::lookup::last_error(); |
|---|
| 318 | return NSCAPI::returnCRIT; |
|---|
| 319 | } |
|---|
| 320 | |
|---|
| 321 | if (bNSClient) { |
|---|
| 322 | if (!message.empty()) |
|---|
| 323 | message += _T("&"); |
|---|
| 324 | message += strEx::itos(totalNumberOfFreeBytes.QuadPart); |
|---|
| 325 | message += _T("&"); |
|---|
| 326 | message += strEx::itos(totalNumberOfBytes.QuadPart); |
|---|
| 327 | } else { |
|---|
| 328 | checkHolders::PercentageValueType<checkHolders::disk_size_type, checkHolders::disk_size_type> value; |
|---|
| 329 | std::wstring tstr; |
|---|
| 330 | value.value = totalNumberOfBytes.QuadPart-totalNumberOfFreeBytes.QuadPart; |
|---|
| 331 | value.total = totalNumberOfBytes.QuadPart; |
|---|
| 332 | drive.setDefault(tmpObject); |
|---|
| 333 | drive.runCheck(value, returnCode, message, perf); |
|---|
| 334 | } |
|---|
| 335 | } |
|---|
| 336 | if (message.empty()) |
|---|
| 337 | message = _T("OK: All drives within bounds."); |
|---|
| 338 | else if (!bNSClient) |
|---|
| 339 | message = NSCHelper::translateReturn(returnCode) + _T(": ") + message; |
|---|
| 340 | return returnCode; |
|---|
| 341 | } |
|---|
| 342 | |
|---|
| 343 | std::wstring CheckDisk::get_filter(unsigned int drvType) { |
|---|
| 344 | if (drvType==DRIVE_FIXED) |
|---|
| 345 | return _T("FIXED"); |
|---|
| 346 | if (drvType==DRIVE_NO_ROOT_DIR) |
|---|
| 347 | return _T("NO_ROOT_DIR"); |
|---|
| 348 | if (drvType==DRIVE_CDROM) |
|---|
| 349 | return _T("CDROM"); |
|---|
| 350 | if (drvType==DRIVE_REMOTE) |
|---|
| 351 | return _T("REMOTE"); |
|---|
| 352 | if (drvType==DRIVE_REMOVABLE) |
|---|
| 353 | return _T("REMOVABLE"); |
|---|
| 354 | return _T("unknown: ") + strEx::itos(drvType); |
|---|
| 355 | } |
|---|
| 356 | |
|---|
| 357 | class NSC_error : public error_reporter { |
|---|
| 358 | void report_error(std::wstring error) { |
|---|
| 359 | NSC_LOG_ERROR(error); |
|---|
| 360 | } |
|---|
| 361 | void report_warning(std::wstring error) { |
|---|
| 362 | NSC_LOG_MESSAGE(error); |
|---|
| 363 | } |
|---|
| 364 | }; |
|---|
| 365 | typedef std::pair<std::wstring,std::wstring> pattern_type; |
|---|
| 366 | pattern_type split_path_ex(std::wstring path) { |
|---|
| 367 | std::wstring baseDir; |
|---|
| 368 | if (file_helpers::checks::is_directory(path)) { |
|---|
| 369 | return pattern_type(path, _T("")); |
|---|
| 370 | } |
|---|
| 371 | std::wstring::size_type pos = path.find_last_of('\\'); |
|---|
| 372 | if (pos == std::wstring::npos) { |
|---|
| 373 | pattern_type(path, _T("*.*")); |
|---|
| 374 | } |
|---|
| 375 | NSC_DEBUG_MSG_STD(_T("Looking for: path: ") + path.substr(0, pos) + _T(", pattern: ") + path.substr(pos+1)); |
|---|
| 376 | return pattern_type(path.substr(0, pos), path.substr(pos+1)); |
|---|
| 377 | } |
|---|
| 378 | |
|---|
| 379 | typedef std::pair<std::wstring,std::wstring> pattern_type; |
|---|
| 380 | pattern_type split_pattern(std::wstring path) { |
|---|
| 381 | std::wstring baseDir; |
|---|
| 382 | if (file_helpers::checks::exists(path)) { |
|---|
| 383 | return pattern_type(path, _T("")); |
|---|
| 384 | } |
|---|
| 385 | std::wstring::size_type pos = path.find_last_of('\\'); |
|---|
| 386 | if (pos == std::wstring::npos) { |
|---|
| 387 | pattern_type(path, _T("*.*")); |
|---|
| 388 | } |
|---|
| 389 | NSC_DEBUG_MSG_STD(_T("Looking for: pattern: ") + path.substr(0, pos) + _T(", pattern: ") + path.substr(pos+1)); |
|---|
| 390 | return pattern_type(path.substr(0, pos), path.substr(pos+1)); |
|---|
| 391 | } |
|---|
| 392 | |
|---|
| 393 | |
|---|
| 394 | NSCAPI::nagiosReturn CheckDisk::CheckFileSize(const unsigned int argLen, TCHAR **char_args, std::wstring &message, std::wstring &perf) { |
|---|
| 395 | NSCAPI::nagiosReturn returnCode = NSCAPI::returnOK; |
|---|
| 396 | std::list<std::wstring> args = arrayBuffer::arrayBuffer2list(argLen, char_args); |
|---|
| 397 | bool bPerfData = true; |
|---|
| 398 | bool debug = false; |
|---|
| 399 | if (args.empty()) { |
|---|
| 400 | message = _T("Missing argument(s)."); |
|---|
| 401 | return NSCAPI::returnUNKNOWN; |
|---|
| 402 | } |
|---|
| 403 | PathContainer tmpObject; |
|---|
| 404 | std::list<PathContainer> paths; |
|---|
| 405 | |
|---|
| 406 | MAP_OPTIONS_BEGIN(args) |
|---|
| 407 | MAP_OPTIONS_STR_AND(_T("File"), tmpObject.data, paths.push_back(tmpObject)) |
|---|
| 408 | MAP_OPTIONS_SHOWALL(tmpObject) |
|---|
| 409 | MAP_OPTIONS_STR(_T("MaxWarn"), tmpObject.warn.max) |
|---|
| 410 | MAP_OPTIONS_STR(_T("MinWarn"), tmpObject.warn.min) |
|---|
| 411 | MAP_OPTIONS_STR(_T("MaxCrit"), tmpObject.crit.max) |
|---|
| 412 | MAP_OPTIONS_STR(_T("MinCrit"), tmpObject.crit.min) |
|---|
| 413 | MAP_OPTIONS_BOOL_TRUE(_T("debug"), debug) |
|---|
| 414 | MAP_OPTIONS_BOOL_FALSE(IGNORE_PERFDATA, bPerfData) |
|---|
| 415 | MAP_OPTIONS_SECONDARY_BEGIN(_T(":"), p2) |
|---|
| 416 | else if (p2.first == _T("File")) { |
|---|
| 417 | tmpObject.data = p__.second; |
|---|
| 418 | tmpObject.alias = p2.second; |
|---|
| 419 | paths.push_back(tmpObject); |
|---|
| 420 | } |
|---|
| 421 | MAP_OPTIONS_MISSING_EX(p2, message, _T("Unknown argument: ")) |
|---|
| 422 | MAP_OPTIONS_SECONDARY_END() |
|---|
| 423 | MAP_OPTIONS_MISSING(message, _T("Unknown argument: ")) |
|---|
| 424 | MAP_OPTIONS_END() |
|---|
| 425 | |
|---|
| 426 | for (std::list<PathContainer>::const_iterator pit = paths.begin(); pit != paths.end(); ++pit) { |
|---|
| 427 | PathContainer path = (*pit); |
|---|
| 428 | std::wstring tstr; |
|---|
| 429 | std::wstring sName = path.getAlias(); |
|---|
| 430 | get_size sizeFinder; |
|---|
| 431 | NSC_error errors; |
|---|
| 432 | pattern_type splitpath = split_pattern(path.data); |
|---|
| 433 | recursive_scan<get_size>(splitpath.first, splitpath.second, -1, -1, sizeFinder, &errors, debug); |
|---|
| 434 | if (sizeFinder.hasError()) { |
|---|
| 435 | message = _T("File not found check log for details"); |
|---|
| 436 | return NSCAPI::returnUNKNOWN; |
|---|
| 437 | } |
|---|
| 438 | path.setDefault(tmpObject); |
|---|
| 439 | path.perfData = bPerfData; |
|---|
| 440 | |
|---|
| 441 | checkHolders::disk_size_type size = sizeFinder.getSize(); |
|---|
| 442 | path.runCheck(size, returnCode, message, perf); |
|---|
| 443 | } |
|---|
| 444 | if (message.empty()) |
|---|
| 445 | message = _T("OK all file sizes are within bounds."); |
|---|
| 446 | else |
|---|
| 447 | message = NSCHelper::translateReturn(returnCode) + _T(": ") + message; |
|---|
| 448 | return returnCode; |
|---|
| 449 | } |
|---|
| 450 | |
|---|
| 451 | |
|---|
| 452 | struct file_info { |
|---|
| 453 | |
|---|
| 454 | std::wstring error; |
|---|
| 455 | bool has_error; |
|---|
| 456 | |
|---|
| 457 | static file_info get(std::wstring path, std::wstring file) { |
|---|
| 458 | return get_2(path, file); |
|---|
| 459 | } |
|---|
| 460 | static file_info get(file_finder_data data) { |
|---|
| 461 | return file_info(data.wfd, data.path, data.wfd.cFileName); |
|---|
| 462 | } |
|---|
| 463 | |
|---|
| 464 | static file_info get_2(std::wstring path, std::wstring file) { |
|---|
| 465 | WIN32_FILE_ATTRIBUTE_DATA data; |
|---|
| 466 | if (!GetFileAttributesEx((path + _T("\\") + file).c_str(), GetFileExInfoStandard, reinterpret_cast<LPVOID>(&data))) { |
|---|
| 467 | file_info ret; |
|---|
| 468 | ret.error = _T("Could not open file (2) ") + path + _T("\\") + file + _T(": ") + error::lookup::last_error(); |
|---|
| 469 | return ret; |
|---|
| 470 | } |
|---|
| 471 | return file_info(data, path, file); |
|---|
| 472 | } |
|---|
| 473 | static file_info get_1(std::wstring path, std::wstring file) { |
|---|
| 474 | HANDLE hFile = CreateFile((path + _T("\\") + file).c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); |
|---|
| 475 | if (hFile == INVALID_HANDLE_VALUE) { |
|---|
| 476 | file_info ret; |
|---|
| 477 | ret.error = _T("Could not open file (1) ") + path + _T("\\") + file + _T(": ") + error::lookup::last_error(); |
|---|
| 478 | return ret; |
|---|
| 479 | } |
|---|
| 480 | BY_HANDLE_FILE_INFORMATION _info; |
|---|
| 481 | GetFileInformationByHandle(hFile, &_info); |
|---|
| 482 | CloseHandle(hFile); |
|---|
| 483 | return file_info(_info, path, file); |
|---|
| 484 | } |
|---|
| 485 | |
|---|
| 486 | file_info() |
|---|
| 487 | : ullCreationTime(0) |
|---|
| 488 | , ullLastAccessTime(0) |
|---|
| 489 | , ullLastWriteTime(0) |
|---|
| 490 | , ullSize(0) |
|---|
| 491 | , cached_version(false, _T("")) |
|---|
| 492 | , cached_count(false, 0) |
|---|
| 493 | {} |
|---|
| 494 | file_info(const WIN32_FILE_ATTRIBUTE_DATA info, std::wstring path_, std::wstring filename_) |
|---|
| 495 | : path(path_) |
|---|
| 496 | , filename(filename_) |
|---|
| 497 | , ullCreationTime(0) |
|---|
| 498 | , ullLastAccessTime(0) |
|---|
| 499 | , ullLastWriteTime(0) |
|---|
| 500 | , ullSize(0) |
|---|
| 501 | , cached_version(false, _T("")) |
|---|
| 502 | , cached_count(false, 0) |
|---|
| 503 | { |
|---|
| 504 | ullSize = ((info.nFileSizeHigh * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.nFileSizeLow); |
|---|
| 505 | ullCreationTime = ((info.ftCreationTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftCreationTime.dwLowDateTime); |
|---|
| 506 | ullLastAccessTime = ((info.ftLastAccessTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftLastAccessTime.dwLowDateTime); |
|---|
| 507 | ullLastWriteTime = ((info.ftLastWriteTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftLastWriteTime.dwLowDateTime); |
|---|
| 508 | }; |
|---|
| 509 | file_info(const BY_HANDLE_FILE_INFORMATION info, std::wstring path_, std::wstring filename_) |
|---|
| 510 | : path(path_) |
|---|
| 511 | , filename(filename_) |
|---|
| 512 | , ullCreationTime(0) |
|---|
| 513 | , ullLastAccessTime(0) |
|---|
| 514 | , ullLastWriteTime(0) |
|---|
| 515 | , ullSize(0) |
|---|
| 516 | , cached_version(false, _T("")) |
|---|
| 517 | , cached_count(false, 0) |
|---|
| 518 | { |
|---|
| 519 | ullSize = ((info.nFileSizeHigh * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.nFileSizeLow); |
|---|
| 520 | ullCreationTime = ((info.ftCreationTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftCreationTime.dwLowDateTime); |
|---|
| 521 | ullLastAccessTime = ((info.ftLastAccessTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftLastAccessTime.dwLowDateTime); |
|---|
| 522 | ullLastWriteTime = ((info.ftLastWriteTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftLastWriteTime.dwLowDateTime); |
|---|
| 523 | }; |
|---|
| 524 | file_info(const WIN32_FIND_DATA info, std::wstring path_, std::wstring filename_) |
|---|
| 525 | : path(path_) |
|---|
| 526 | , filename(filename_) |
|---|
| 527 | , ullCreationTime(0) |
|---|
| 528 | , ullLastAccessTime(0) |
|---|
| 529 | , ullLastWriteTime(0) |
|---|
| 530 | , ullSize(0) |
|---|
| 531 | , cached_version(false, _T("")) |
|---|
| 532 | , cached_count(false, 0) |
|---|
| 533 | { |
|---|
| 534 | ullSize = ((info.nFileSizeHigh * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.nFileSizeLow); |
|---|
| 535 | ullCreationTime = ((info.ftCreationTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftCreationTime.dwLowDateTime); |
|---|
| 536 | ullLastAccessTime = ((info.ftLastAccessTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftLastAccessTime.dwLowDateTime); |
|---|
| 537 | ullLastWriteTime = ((info.ftLastWriteTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftLastWriteTime.dwLowDateTime); |
|---|
| 538 | }; |
|---|
| 539 | file_info(std::wstring path_, std::wstring filename_) |
|---|
| 540 | : path(path_) |
|---|
| 541 | , filename(filename_) |
|---|
| 542 | , ullCreationTime(0) |
|---|
| 543 | , ullLastAccessTime(0) |
|---|
| 544 | , ullLastWriteTime(0) |
|---|
| 545 | , ullSize(0) |
|---|
| 546 | , cached_version(false, _T("")) |
|---|
| 547 | , cached_count(false, 0) |
|---|
| 548 | { |
|---|
| 549 | }; |
|---|
| 550 | |
|---|
| 551 | unsigned long long ullSize; |
|---|
| 552 | __int64 ullCreationTime; |
|---|
| 553 | __int64 ullLastAccessTime; |
|---|
| 554 | __int64 ullLastWriteTime; |
|---|
| 555 | __int64 ullNow; |
|---|
| 556 | std::wstring filename; |
|---|
| 557 | std::wstring path; |
|---|
| 558 | std::pair<bool,std::wstring> cached_version; |
|---|
| 559 | std::pair<bool,unsigned long> cached_count; |
|---|
| 560 | |
|---|
| 561 | static const __int64 MSECS_TO_100NS = 10000; |
|---|
| 562 | |
|---|
| 563 | __int64 get_creation() { |
|---|
| 564 | return (ullNow-ullCreationTime)/MSECS_TO_100NS; |
|---|
| 565 | } |
|---|
| 566 | __int64 get_access() { |
|---|
| 567 | return (ullNow-ullLastAccessTime)/MSECS_TO_100NS; |
|---|
| 568 | } |
|---|
| 569 | __int64 get_write() { |
|---|
| 570 | return (ullNow-ullLastWriteTime)/MSECS_TO_100NS; |
|---|
| 571 | } |
|---|
| 572 | std::wstring render(std::wstring syntax) { |
|---|
| 573 | strEx::replace(syntax, _T("%path%"), path); |
|---|
| 574 | strEx::replace(syntax, _T("%filename%"), filename); |
|---|
| 575 | strEx::replace(syntax, _T("%creation%"), strEx::format_filetime(ullCreationTime, DATE_FORMAT)); |
|---|
| 576 | strEx::replace(syntax, _T("%access%"), strEx::format_filetime(ullLastAccessTime, DATE_FORMAT)); |
|---|
| 577 | strEx::replace(syntax, _T("%write%"), strEx::format_filetime(ullLastWriteTime, DATE_FORMAT)); |
|---|
| 578 | /* |
|---|
| 579 | strEx::replace(syntax, _T("%creation-d%"), strEx::format_filetime(ullCreationTime, DATE_FORMAT)); |
|---|
| 580 | strEx::replace(syntax, _T("%access-d%"), strEx::format_filetime(ullLastAccessTime, DATE_FORMAT)); |
|---|
| 581 | strEx::replace(syntax, _T("%write-d%"), strEx::format_filetime(ullLastWriteTime, DATE_FORMAT)); |
|---|
| 582 | */ |
|---|
| 583 | strEx::replace(syntax, _T("%size%"), strEx::itos_as_BKMG(ullSize)); |
|---|
| 584 | if (cached_version.first) |
|---|
| 585 | strEx::replace(syntax, _T("%version%"), cached_version.second); |
|---|
| 586 | if (cached_count.first) |
|---|
| 587 | strEx::replace(syntax, _T("%line-count%"), strEx::itos(cached_count.second)); |
|---|
| 588 | return syntax; |
|---|
| 589 | } |
|---|
| 590 | |
|---|
| 591 | std::wstring get_version() { |
|---|
| 592 | if (cached_version.first) |
|---|
| 593 | return cached_version.second; |
|---|
| 594 | std::wstring fullpath = path+_T("\\")+filename; |
|---|
| 595 | |
|---|
| 596 | DWORD dwDummy; |
|---|
| 597 | DWORD dwFVISize = GetFileVersionInfoSize(fullpath.c_str(),&dwDummy); |
|---|
| 598 | LPBYTE lpVersionInfo = new BYTE[dwFVISize+1]; |
|---|
| 599 | GetFileVersionInfo(fullpath.c_str(),0,dwFVISize,lpVersionInfo); |
|---|
| 600 | UINT uLen; |
|---|
| 601 | VS_FIXEDFILEINFO *lpFfi; |
|---|
| 602 | VerQueryValue( lpVersionInfo , _T("\\") , (LPVOID *)&lpFfi , &uLen ); |
|---|
| 603 | DWORD dwFileVersionMS = lpFfi->dwFileVersionMS; |
|---|
| 604 | DWORD dwFileVersionLS = lpFfi->dwFileVersionLS; |
|---|
| 605 | delete [] lpVersionInfo; |
|---|
| 606 | DWORD dwLeftMost = HIWORD(dwFileVersionMS); |
|---|
| 607 | DWORD dwSecondLeft = LOWORD(dwFileVersionMS); |
|---|
| 608 | DWORD dwSecondRight = HIWORD(dwFileVersionLS); |
|---|
| 609 | DWORD dwRightMost = LOWORD(dwFileVersionLS); |
|---|
| 610 | cached_version.second = strEx::itos(dwLeftMost) + _T(".") + |
|---|
| 611 | strEx::itos(dwSecondLeft) + _T(".") + |
|---|
| 612 | strEx::itos(dwSecondRight) + _T(".") + |
|---|
| 613 | strEx::itos(dwRightMost); |
|---|
| 614 | cached_version.first = true; |
|---|
| 615 | return cached_version.second; |
|---|
| 616 | } |
|---|
| 617 | |
|---|
| 618 | unsigned long get_line_count() { |
|---|
| 619 | if (cached_count.first) |
|---|
| 620 | return cached_count.second; |
|---|
| 621 | |
|---|
| 622 | unsigned long count = 0; |
|---|
| 623 | std::wstring fullpath = path+_T("\\")+filename; |
|---|
| 624 | FILE * pFile = fopen(strEx::wstring_to_string(fullpath).c_str(),"r");; |
|---|
| 625 | if (pFile==NULL) |
|---|
| 626 | return 0; |
|---|
| 627 | char c; |
|---|
| 628 | do { |
|---|
| 629 | c = fgetc (pFile); |
|---|
| 630 | if (c == '\r') { |
|---|
| 631 | c = fgetc (pFile); |
|---|
| 632 | count++; |
|---|
| 633 | } else if (c == '\n') { |
|---|
| 634 | c = fgetc (pFile); |
|---|
| 635 | count++; |
|---|
| 636 | } |
|---|
| 637 | } while (c != EOF); |
|---|
| 638 | fclose (pFile); |
|---|
| 639 | cached_count.second = count; |
|---|
| 640 | cached_count.first = true; |
|---|
| 641 | return cached_count.second; |
|---|
| 642 | } |
|---|
| 643 | }; |
|---|
| 644 | |
|---|
| 645 | struct file_filter { |
|---|
| 646 | filters::filter_all_numeric<unsigned long long, checkHolders::disk_size_handler<checkHolders::disk_size_type> > size; |
|---|
| 647 | filters::filter_all_times creation; |
|---|
| 648 | filters::filter_all_times accessed; |
|---|
| 649 | filters::filter_all_times written; |
|---|
| 650 | filters::filter_all_strings version; |
|---|
| 651 | filters::filter_all_num_ul line_count; |
|---|
| 652 | |
|---|
| 653 | inline bool hasFilter() { |
|---|
| 654 | return size.hasFilter() || creation.hasFilter() || |
|---|
| 655 | accessed.hasFilter() || written.hasFilter(); |
|---|
| 656 | } |
|---|
| 657 | bool matchFilter(file_info &value) const { |
|---|
| 658 | if ((size.hasFilter())&&(size.matchFilter(value.ullSize))) |
|---|
| 659 | return true; |
|---|
| 660 | else if (creation.hasFilter()&&creation.matchFilter(value.get_creation())) |
|---|
| 661 | return true; |
|---|
| 662 | else if (accessed.hasFilter()&&accessed.matchFilter(value.get_access())) |
|---|
| 663 | return true; |
|---|
| 664 | else if (written.hasFilter()&&written.matchFilter(value.get_write())) |
|---|
| 665 | return true; |
|---|
| 666 | else if ((version.hasFilter())&&(version.matchFilter(value.get_version()))) |
|---|
| 667 | return true; |
|---|
| 668 | else if ((line_count.hasFilter())&&(line_count.matchFilter(value.get_line_count()))) |
|---|
| 669 | return true; |
|---|
| 670 | return false; |
|---|
| 671 | } |
|---|
| 672 | |
|---|
| 673 | std::wstring getValue() const { |
|---|
| 674 | if (size.hasFilter()) |
|---|
| 675 | return _T("size: ") + size.getValue(); |
|---|
| 676 | if (creation.hasFilter()) |
|---|
| 677 | return _T("creation: ") + creation.getValue(); |
|---|
| 678 | if (accessed.hasFilter()) |
|---|
| 679 | return _T("accessed: ") + accessed.getValue(); |
|---|
| 680 | if (written.hasFilter()) |
|---|
| 681 | return _T("written: ") + written.getValue(); |
|---|
| 682 | if (version.hasFilter()) |
|---|
| 683 | return _T("written: ") + version.getValue(); |
|---|
| 684 | if (line_count.hasFilter()) |
|---|
| 685 | return _T("written: ") + line_count.getValue(); |
|---|
| 686 | return _T("UNknown..."); |
|---|
| 687 | } |
|---|
| 688 | |
|---|
| 689 | }; |
|---|
| 690 | |
|---|
| 691 | |
|---|
| 692 | struct find_first_file_info : public baseFinderFunction |
|---|
| 693 | { |
|---|
| 694 | file_info info; |
|---|
| 695 | bool error; |
|---|
| 696 | // std::wstring message; |
|---|
| 697 | find_first_file_info() : error(false) {} |
|---|
| 698 | result_type operator()(argument_type ffd) { |
|---|
| 699 | if (file_helpers::checks::is_directory(ffd.wfd.dwFileAttributes)) |
|---|
| 700 | return true; |
|---|
| 701 | |
|---|
| 702 | file_info info = file_info::get(ffd); |
|---|
| 703 | if (!info.error.empty()) { |
|---|
| 704 | setError(ffd.errors, info.error); |
|---|
| 705 | return false; |
|---|
| 706 | } |
|---|
| 707 | return false; |
|---|
| 708 | /* |
|---|
| 709 | BY_HANDLE_FILE_INFORMATION _info; |
|---|
| 710 | |
|---|
| 711 | HANDLE hFile = CreateFile((ffd.path + _T("\\") + ffd.wfd.cFileName).c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, |
|---|
| 712 | 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); |
|---|
| 713 | if (hFile == INVALID_HANDLE_VALUE) { |
|---|
| 714 | setError(ffd.errors, _T("Could not open file: ") + ffd.path + _T("\\") + ffd.wfd.cFileName + _T(": ") + error::lookup::last_error()); |
|---|
| 715 | return false; |
|---|
| 716 | } |
|---|
| 717 | GetFileInformationByHandle(hFile, &_info); |
|---|
| 718 | CloseHandle(hFile); |
|---|
| 719 | info = file_info(_info, ffd.path, ffd.wfd.cFileName); |
|---|
| 720 | return false; |
|---|
| 721 | */ |
|---|
| 722 | } |
|---|
| 723 | inline const bool hasError() const { |
|---|
| 724 | return error; |
|---|
| 725 | } |
|---|
| 726 | inline void setError(error_reporter *errors, std::wstring msg) { |
|---|
| 727 | if (errors != NULL) |
|---|
| 728 | errors->report_error(msg); |
|---|
| 729 | error = true; |
|---|
| 730 | } |
|---|
| 731 | }; |
|---|
| 732 | |
|---|
| 733 | struct file_filter_function : public baseFinderFunction |
|---|
| 734 | { |
|---|
| 735 | std::list<file_filter> filter_chain; |
|---|
| 736 | bool bFilterAll; |
|---|
| 737 | bool bFilterIn; |
|---|
| 738 | bool error; |
|---|
| 739 | std::wstring message; |
|---|
| 740 | std::wstring syntax; |
|---|
| 741 | std::wstring alias; |
|---|
| 742 | unsigned long long now; |
|---|
| 743 | unsigned int hit_count; |
|---|
| 744 | |
|---|
| 745 | file_filter_function() : hit_count(0), error(false), bFilterIn(true), bFilterAll(true) {} |
|---|
| 746 | result_type operator()(argument_type ffd) { |
|---|
| 747 | if (file_helpers::checks::is_directory(ffd.wfd.dwFileAttributes)) |
|---|
| 748 | return true; |
|---|
| 749 | |
|---|
| 750 | file_info info = file_info::get(ffd); |
|---|
| 751 | if (!info.error.empty()) { |
|---|
| 752 | setError(ffd.errors, info.error); |
|---|
| 753 | return true; |
|---|
| 754 | } |
|---|
| 755 | /* |
|---|
| 756 | BY_HANDLE_FILE_INFORMATION _info; |
|---|
| 757 | |
|---|
| 758 | HANDLE hFile = CreateFile((ffd.path + _T("\\") + ffd.wfd.cFileName).c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, |
|---|
| 759 | 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); |
|---|
| 760 | if (hFile == INVALID_HANDLE_VALUE) { |
|---|
| 761 | setError(ffd.errors, _T("Could not open file: ") + ffd.path + _T("\\") + ffd.wfd.cFileName + _T(": ") + error::lookup::last_error()); |
|---|
| 762 | return true; |
|---|
| 763 | } |
|---|
| 764 | GetFileInformationByHandle(hFile, &_info); |
|---|
| 765 | CloseHandle(hFile); |
|---|
| 766 | file_info info(_info, ffd.path, ffd.wfd.cFileName); |
|---|
| 767 | info.ullNow = now; |
|---|
| 768 | */ |
|---|
| 769 | |
|---|
| 770 | for (std::list<file_filter>::const_iterator cit3 = filter_chain.begin(); cit3 != filter_chain.end(); ++cit3 ) { |
|---|
| 771 | bool bMatch = bFilterAll; |
|---|
| 772 | bool bTmpMatched = (*cit3).matchFilter(info); |
|---|
| 773 | if (bFilterAll) { |
|---|
| 774 | if (!bTmpMatched) { |
|---|
| 775 | bMatch = false; |
|---|
| 776 | break; |
|---|
| 777 | } |
|---|
| 778 | } else { |
|---|
| 779 | if (bTmpMatched) { |
|---|
| 780 | bMatch = true; |
|---|
| 781 | break; |
|---|
| 782 | } |
|---|
| 783 | } |
|---|
| 784 | if ((bFilterIn&&bMatch)||(!bFilterIn&&!bMatch)) { |
|---|
| 785 | strEx::append_list(message, info.render(syntax)); |
|---|
| 786 | if (alias.length() < 16) |
|---|
| 787 | strEx::append_list(alias, info.filename); |
|---|
| 788 | else |
|---|
| 789 | strEx::append_list(alias, std::wstring(_T("..."))); |
|---|
| 790 | hit_count++; |
|---|
| 791 | } |
|---|
| 792 | } |
|---|
| 793 | return true; |
|---|
| 794 | } |
|---|
| 795 | inline const bool hasError() const { |
|---|
| 796 | return error; |
|---|
| 797 | } |
|---|
| 798 | inline void setError(error_reporter *errors, std::wstring msg) { |
|---|
| 799 | if (errors != NULL) |
|---|
| 800 | errors->report_error(msg); |
|---|
| 801 | error = true; |
|---|
| 802 | } |
|---|
| 803 | }; |
|---|
| 804 | |
|---|
| 805 | |
|---|
| 806 | |
|---|
| 807 | struct file_filter_function_ex : public baseFinderFunction |
|---|
| 808 | { |
|---|
| 809 | static const int filter_plus = 1; |
|---|
| 810 | static const int filter_minus = 2; |
|---|
| 811 | static const int filter_normal = 3; |
|---|
| 812 | |
|---|
| 813 | typedef std::pair<int,file_filter> filteritem_type; |
|---|
| 814 | typedef std::list<filteritem_type > filterlist_type; |
|---|
| 815 | filterlist_type filter_chain; |
|---|
| 816 | bool bFilterAll; |
|---|
| 817 | bool bFilterIn; |
|---|
| 818 | bool error; |
|---|
| 819 | bool debug_; |
|---|
| 820 | std::wstring message; |
|---|
| 821 | std::wstring syntax; |
|---|
| 822 | //std::wstring alias; |
|---|
| 823 | unsigned long long now; |
|---|
| 824 | unsigned int hit_count; |
|---|
| 825 | unsigned int file_count; |
|---|
| 826 | std::wstring last_error; |
|---|
| 827 | unsigned int error_count; |
|---|
| 828 | |
|---|
| 829 | file_filter_function_ex() : hit_count(0), file_count(0), error(false), debug_(false), bFilterIn(true), bFilterAll(true), error_count(0) {} |
|---|
| 830 | result_type operator()(argument_type ffd) { |
|---|
| 831 | if (is_directory(ffd.wfd.dwFileAttributes)) |
|---|
| 832 | return true; |
|---|
| 833 | |
|---|
| 834 | file_info info = file_info::get(ffd); |
|---|
| 835 | if (!info.error.empty()) { |
|---|
| 836 | setError(ffd.errors, info.error); |
|---|
| 837 | return true; |
|---|
| 838 | } |
|---|
| 839 | /* |
|---|
| 840 | BY_HANDLE_FILE_INFORMATION _info; |
|---|
| 841 | |
|---|
| 842 | HANDLE hFile = CreateFile((ffd.path + _T("\\") + ffd.wfd.cFileName).c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, |
|---|
| 843 | 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); |
|---|
| 844 | if (hFile == INVALID_HANDLE_VALUE) { |
|---|
| 845 | setError(ffd.errors, _T("Could not open file: ") + ffd.path + _T("\\") + ffd.wfd.cFileName + _T(": ") + error::lookup::last_error()); |
|---|
| 846 | return true; |
|---|
| 847 | } |
|---|
| 848 | GetFileInformationByHandle(hFile, &_info); |
|---|
| 849 | CloseHandle(hFile); |
|---|
| 850 | file_info info(_info, ffd.path, ffd.wfd.cFileName); |
|---|
| 851 | info.ullNow = now; |
|---|
| 852 | */ |
|---|
| 853 | |
|---|
| 854 | bool bMatch = !bFilterIn; |
|---|
| 855 | for (filterlist_type::const_iterator cit3 = filter_chain.begin(); cit3 != filter_chain.end(); ++cit3 ) { |
|---|
| 856 | bool bTmpMatched = (*cit3).second.matchFilter(info); |
|---|
| 857 | int mode = (*cit3).first; |
|---|
| 858 | |
|---|
| 859 | if ((mode == filter_minus)&&(bTmpMatched)) { |
|---|
| 860 | // a -<filter> hit so thrash item and bail out! |
|---|
| 861 | if (debug_) |
|---|
| 862 | NSC_DEBUG_MSG_STD(_T("Matched: - ") + (*cit3).second.getValue() + _T(" for: ") + info.render(syntax)); |
|---|
| 863 | bMatch = false; |
|---|
| 864 | break; |
|---|
| 865 | } else if ((mode == filter_plus)&&(!bTmpMatched)) { |
|---|
| 866 | // a +<filter> missed hit so thrash item and bail out! |
|---|
| 867 | if (debug_) |
|---|
| 868 | NSC_DEBUG_MSG_STD(_T("Matched (missed): + ") + (*cit3).second.getValue() + _T(" for: ") + info.render(syntax)); |
|---|
| 869 | bMatch = false; |
|---|
| 870 | break; |
|---|
| 871 | } else if (bTmpMatched) { |
|---|
| 872 | if (debug_) |
|---|
| 873 | NSC_DEBUG_MSG_STD(_T("Matched: . (contiunue): ") + (*cit3).second.getValue() + _T(" for: ") + info.render(syntax)); |
|---|
| 874 | bMatch = true; |
|---|
| 875 | } |
|---|
| 876 | } |
|---|
| 877 | |
|---|
| 878 | //NSC_DEBUG_MSG_STD(_T("result: ") + strEx::itos(bFilterIn) + _T(" -- ") + strEx::itos(bMatch)); |
|---|
| 879 | if ((bFilterIn&&bMatch)||(!bFilterIn&&!bMatch)) { |
|---|
| 880 | strEx::append_list(message, info.render(syntax)); |
|---|
| 881 | /* |
|---|
| 882 | if (alias.length() < 16) |
|---|
| 883 | strEx::append_list(alias, info.filename); |
|---|
| 884 | else |
|---|
| 885 | strEx::append_list(alias, std::wstring(_T("..."))); |
|---|
| 886 | */ |
|---|
| 887 | hit_count++; |
|---|
| 888 | } |
|---|
| 889 | file_count++; |
|---|
| 890 | return true; |
|---|
| 891 | } |
|---|
| 892 | inline const bool hasError() const { |
|---|
| 893 | return error; |
|---|
| 894 | } |
|---|
| 895 | inline void setError(error_reporter *errors, std::wstring msg) { |
|---|
| 896 | if (errors != NULL) |
|---|
| 897 | errors->report_error(msg); |
|---|
| 898 | last_error = msg; |
|---|
| 899 | error_count++; |
|---|
| 900 | error = true; |
|---|
| 901 | } |
|---|
| 902 | |
|---|
| 903 | std::wstring render(std::wstring syntax) { |
|---|
| 904 | strEx::replace(syntax, _T("%list%"), message); |
|---|
| 905 | strEx::replace(syntax, _T("%matches%"), strEx::itos(hit_count)); |
|---|
| 906 | strEx::replace(syntax, _T("%files%"), strEx::itos(file_count)); |
|---|
| 907 | return syntax; |
|---|
| 908 | } |
|---|
| 909 | |
|---|
| 910 | bool has_filter() { |
|---|
| 911 | return !filter_chain.empty(); |
|---|
| 912 | } |
|---|
| 913 | |
|---|
| 914 | }; |
|---|
| 915 | |
|---|
| 916 | |
|---|
| 917 | NSCAPI::nagiosReturn CheckDisk::getFileAge(const unsigned int argLen, TCHAR **char_args, std::wstring &message, std::wstring &perf) { |
|---|
| 918 | NSCAPI::nagiosReturn returnCode = NSCAPI::returnOK; |
|---|
| 919 | std::list<std::wstring> stl_args = arrayBuffer::arrayBuffer2list(argLen, char_args); |
|---|
| 920 | typedef checkHolders::CheckContainer<checkHolders::MaxMinBoundsUInteger> CheckFileContainer; |
|---|
| 921 | if (stl_args.empty()) { |
|---|
| 922 | message = _T("Missing argument(s)."); |
|---|
| 923 | return NSCAPI::returnUNKNOWN; |
|---|
| 924 | } |
|---|
| 925 | std::wstring format = _T("%Y years %m mon %d days %H hours %M min %S sec"); |
|---|
| 926 | std::wstring path; |
|---|
| 927 | bool debug = false; |
|---|
| 928 | find_first_file_info finder; |
|---|
| 929 | MAP_OPTIONS_BEGIN(stl_args) |
|---|
| 930 | MAP_OPTIONS_STR(_T("path"), path) |
|---|
| 931 | MAP_OPTIONS_STR(_T("date"), format) |
|---|
| 932 | MAP_OPTIONS_BOOL_TRUE(_T("debug"), debug) |
|---|
| 933 | MAP_OPTIONS_FALLBACK(format) |
|---|
| 934 | MAP_OPTIONS_END() |
|---|
| 935 | |
|---|
| 936 | if (path.empty()) { |
|---|
| 937 | message = _T("ERROR: no file specified."); |
|---|
| 938 | return NSCAPI::returnUNKNOWN; |
|---|
| 939 | } |
|---|
| 940 | |
|---|
| 941 | NSC_error errors; |
|---|
| 942 | pattern_type splitpath = split_pattern(path); |
|---|
| 943 | recursive_scan<find_first_file_info>(splitpath.first, splitpath.second, -1, -1, finder, &errors, debug); |
|---|
| 944 | if (finder.hasError()) { |
|---|
| 945 | message = _T("File not found (check log for details)"); |
|---|
| 946 | return NSCAPI::returnUNKNOWN; |
|---|
| 947 | } |
|---|
| 948 | FILETIME now_; |
|---|
| 949 | GetSystemTimeAsFileTime(&now_); |
|---|
| 950 | unsigned long long now = ((now_.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)now_.dwLowDateTime); |
|---|
| 951 | time_t value = (now-finder.info.ullLastWriteTime)/10000000; |
|---|
| 952 | message = to_wstring(value/60) + _T("&") + strEx::format_time_delta(gmtime(&value), format); |
|---|
| 953 | return NSCAPI::returnOK; |
|---|
| 954 | } |
|---|
| 955 | |
|---|
| 956 | |
|---|
| 957 | NSCAPI::nagiosReturn CheckDisk::CheckFile(const unsigned int argLen, TCHAR **char_args, std::wstring &message, std::wstring &perf) { |
|---|
| 958 | NSCAPI::nagiosReturn returnCode = NSCAPI::returnOK; |
|---|
| 959 | std::list<std::wstring> stl_args = arrayBuffer::arrayBuffer2list(argLen, char_args); |
|---|
| 960 | typedef checkHolders::CheckContainer<checkHolders::MaxMinBoundsUInteger> CheckFileContainer; |
|---|
| 961 | if (stl_args.empty()) { |
|---|
| 962 | message = _T("Missing argument(s)."); |
|---|
| 963 | return NSCAPI::returnUNKNOWN; |
|---|
| 964 | } |
|---|
| 965 | file_filter_function finder; |
|---|
| 966 | PathContainer tmpObject; |
|---|
| 967 | std::list<std::wstring> paths; |
|---|
| 968 | unsigned int truncate = 0; |
|---|
| 969 | CheckFileContainer query; |
|---|
| 970 | std::wstring syntax = _T("%filename%"); |
|---|
| 971 | std::wstring alias; |
|---|
| 972 | bool bPerfData = true; |
|---|
| 973 | unsigned int max_dir_depth = -1; |
|---|
| 974 | bool debug = false; |
|---|
| 975 | |
|---|
| 976 | try { |
|---|
| 977 | MAP_OPTIONS_BEGIN(stl_args) |
|---|
| 978 | MAP_OPTIONS_NUMERIC_ALL(query, _T("")) |
|---|
| 979 | MAP_OPTIONS_STR2INT(_T("truncate"), truncate) |
|---|
| 980 | MAP_OPTIONS_BOOL_FALSE(IGNORE_PERFDATA, bPerfData) |
|---|
| 981 | MAP_OPTIONS_STR(_T("syntax"), syntax) |
|---|
| 982 | MAP_OPTIONS_PUSH(_T("path"), paths) |
|---|
| 983 | MAP_OPTIONS_STR(_T("alias"), alias) |
|---|
| 984 | MAP_OPTIONS_STR2INT(_T("max-dir-depth"), max_dir_depth) |
|---|
| 985 | MAP_OPTIONS_PUSH(_T("file"), paths) |
|---|
| 986 | MAP_OPTIONS_BOOL_TRUE(_T("debug"), debug) |
|---|
| 987 | MAP_OPTIONS_BOOL_EX(_T("filter"), finder.bFilterIn, _T("in"), _T("out")) |
|---|
| 988 | MAP_OPTIONS_BOOL_EX(_T("filter"), finder.bFilterAll, _T("all"), _T("any")) |
|---|
| 989 | MAP_OPTIONS_PUSH_WTYPE(file_filter, _T("filter-size"), size, finder.filter_chain) |
|---|
| 990 | MAP_OPTIONS_PUSH_WTYPE(file_filter, _T("filter-creation"), creation, finder.filter_chain) |
|---|
| 991 | MAP_OPTIONS_PUSH_WTYPE(file_filter, _T("filter-written"), written, finder.filter_chain) |
|---|
| 992 | MAP_OPTIONS_PUSH_WTYPE(file_filter, _T("filter-accessed"), accessed, finder.filter_chain) |
|---|
| 993 | MAP_OPTIONS_MISSING(message, _T("Unknown argument: ")) |
|---|
| 994 | MAP_OPTIONS_END() |
|---|
| 995 | } catch (filters::parse_exception e) { |
|---|
| 996 | message = e.getMessage(); |
|---|
| 997 | return NSCAPI::returnUNKNOWN; |
|---|
| 998 | } catch (filters::filter_exception e) { |
|---|
| 999 | message = e.getMessage(); |
|---|
| 1000 | return NSCAPI::returnUNKNOWN; |
|---|
| 1001 | } |
|---|
| 1002 | FILETIME now; |
|---|
| 1003 | GetSystemTimeAsFileTime(&now); |
|---|
| 1004 | finder.now = ((now.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)now.dwLowDateTime); |
|---|
| 1005 | finder.syntax = syntax; |
|---|
| 1006 | NSC_error errors; |
|---|
| 1007 | for (std::list<std::wstring>::const_iterator pit = paths.begin(); pit != paths.end(); ++pit) { |
|---|
| 1008 | pattern_type path = split_pattern(*pit); |
|---|
| 1009 | recursive_scan<file_filter_function>(path.first, path.second, 0, max_dir_depth, finder, &errors, debug); |
|---|
| 1010 | if (finder.hasError()) { |
|---|
| 1011 | message = _T("File not found: ") + (*pit) + _T(" check log for details."); |
|---|
| 1012 | return NSCAPI::returnUNKNOWN; |
|---|
| 1013 | } |
|---|
| 1014 | } |
|---|
| 1015 | message = finder.message; |
|---|
| 1016 | if (finder.error) |
|---|
| 1017 | return NSCAPI::returnUNKNOWN; |
|---|
| 1018 | if (!alias.empty()) |
|---|
| 1019 | query.alias = alias; |
|---|
| 1020 | else |
|---|
| 1021 | query.alias = finder.alias; |
|---|
| 1022 | if (query.alias.empty()) |
|---|
| 1023 | query.alias = _T("no files found"); |
|---|
| 1024 | query.runCheck(finder.hit_count, returnCode, message, perf); |
|---|
| 1025 | if ((truncate > 0) && (message.length() > (truncate-4))) |
|---|
| 1026 | message = message.substr(0, truncate-4) + _T("..."); |
|---|
| 1027 | if (message.empty()) |
|---|
| 1028 | message = _T("CheckFile ok"); |
|---|
| 1029 | return returnCode; |
|---|
| 1030 | } |
|---|
| 1031 | |
|---|
| 1032 | #define MAP_FILTER(value, obj) \ |
|---|
| 1033 | else if (p__.first == _T("filter+"##value)) { file_filter filter; filter.obj = p__.second; \ |
|---|
| 1034 | finder.filter_chain.push_back(filteritem_type(file_filter_function_ex::filter_plus, filter)); } \ |
|---|
| 1035 | else if (p__.first == _T("filter-"##value)) { file_filter filter; filter.obj = p__.second; \ |
|---|
| 1036 | finder.filter_chain.push_back(filteritem_type(file_filter_function_ex::filter_minus, filter)); } \ |
|---|
| 1037 | else if (p__.first == _T("filter."##value)) { file_filter filter; filter.obj = p__.second; \ |
|---|
| 1038 | finder.filter_chain.push_back(filteritem_type(file_filter_function_ex::filter_normal, filter)); } |
|---|
| 1039 | |
|---|
| 1040 | NSCAPI::nagiosReturn CheckDisk::CheckFile2(const unsigned int argLen, TCHAR **char_args, std::wstring &message, std::wstring &perf) { |
|---|
| 1041 | NSCAPI::nagiosReturn returnCode = NSCAPI::returnOK; |
|---|
| 1042 | std::list<std::wstring> stl_args = arrayBuffer::arrayBuffer2list(argLen, char_args); |
|---|
| 1043 | typedef checkHolders::CheckContainer<checkHolders::MaxMinBoundsUInteger> CheckFileContainer; |
|---|
| 1044 | typedef std::pair<int,file_filter> filteritem_type; |
|---|
| 1045 | typedef std::list<filteritem_type > filterlist_type; |
|---|
| 1046 | if (stl_args.empty()) { |
|---|
| 1047 | message = _T("Missing argument(s)."); |
|---|
| 1048 | return NSCAPI::returnUNKNOWN; |
|---|
| 1049 | } |
|---|
| 1050 | file_filter_function_ex finder; |
|---|
| 1051 | PathContainer tmpObject; |
|---|
| 1052 | std::list<std::wstring> paths; |
|---|
| 1053 | unsigned int truncate = 0; |
|---|
| 1054 | CheckFileContainer query; |
|---|
| 1055 | std::wstring syntax = _T("%filename%"); |
|---|
| 1056 | std::wstring masterSyntax = _T("%list%"); |
|---|
| 1057 | std::wstring alias; |
|---|
| 1058 | std::wstring pattern = _T("*.*"); |
|---|
| 1059 | bool bPerfData = true; |
|---|
| 1060 | int max_dir_depth = -1; |
|---|
| 1061 | bool debug = false; |
|---|
| 1062 | bool ignoreError = false; |
|---|
| 1063 | |
|---|
| 1064 | try { |
|---|
| 1065 | MAP_OPTIONS_BEGIN(stl_args) |
|---|
| 1066 | MAP_OPTIONS_NUMERIC_ALL(query, _T("")) |
|---|
| 1067 | MAP_OPTIONS_STR2INT(_T("truncate"), truncate) |
|---|
| 1068 | MAP_OPTIONS_BOOL_FALSE(IGNORE_PERFDATA, bPerfData) |
|---|
| 1069 | MAP_OPTIONS_STR(_T("syntax"), syntax) |
|---|
| 1070 | MAP_OPTIONS_STR(_T("master-syntax"), masterSyntax) |
|---|
| 1071 | MAP_OPTIONS_PUSH(_T("path"), paths) |
|---|
| 1072 | MAP_OPTIONS_STR(_T("pattern"), pattern) |
|---|
| 1073 | MAP_OPTIONS_STR(_T("alias"), alias) |
|---|
| 1074 | MAP_OPTIONS_PUSH(_T("file"), paths) |
|---|
| 1075 | MAP_OPTIONS_BOOL_TRUE(_T("debug"), debug) |
|---|
| 1076 | MAP_OPTIONS_BOOL_TRUE(_T("ignore-errors"), ignoreError) |
|---|
| 1077 | MAP_OPTIONS_STR2INT(_T("max-dir-depth"), max_dir_depth) |
|---|
| 1078 | MAP_OPTIONS_BOOL_EX(_T("filter"), finder.bFilterIn, _T("in"), _T("out")) |
|---|
| 1079 | MAP_OPTIONS_BOOL_EX(_T("filter"), finder.bFilterAll, _T("all"), _T("any")) |
|---|
| 1080 | /* |
|---|
| 1081 | MAP_OPTIONS_PUSH_WTYPE(file_filter, _T("filter-size"), fileSize, finder.filter_chain) |
|---|
| 1082 | MAP_OPTIONS_PUSH_WTYPE(file_filter, _T("filter-creation"), fileCreation, finder.filter_chain) |
|---|
| 1083 | MAP_OPTIONS_PUSH_WTYPE(file_filter, _T("filter-written"), fileWritten, finder.filter_chain) |
|---|
| 1084 | MAP_OPTIONS_PUSH_WTYPE(file_filter, _T("filter-accessed"), fileAccessed, finder.filter_chain) |
|---|
| 1085 | */ |
|---|
| 1086 | |
|---|
| 1087 | MAP_FILTER(_T("size"), size) |
|---|
| 1088 | MAP_FILTER(_T("creation"), creation) |
|---|
| 1089 | MAP_FILTER(_T("written"), written) |
|---|
| 1090 | MAP_FILTER(_T("accessed"), accessed) |
|---|
| 1091 | MAP_FILTER(_T("version"), version) |
|---|
| 1092 | MAP_FILTER(_T("line-count"), line_count) |
|---|
| 1093 | /* |
|---|
| 1094 | MAP_FILTER(_T("filter.size"), size, filter_normal) |
|---|
| 1095 | MAP_FILTER(_T("filter.creation"), creation, filter_normal) |
|---|
| 1096 | MAP_FILTER(_T("filter.written"), written, filter_normal) |
|---|
| 1097 | MAP_FILTER(_T("filter.accessed"), accessed, filter_normal) |
|---|
| 1098 | MAP_FILTER(_T("filter.version"), version, filter_normal) |
|---|
| 1099 | |
|---|
| 1100 | MAP_FILTER(_T("filter-size"), size, filter_minus) |
|---|
| 1101 | MAP_FILTER(_T("filter-creation"), creation, filter_minus) |
|---|
| 1102 | MAP_FILTER(_T("filter-written"), written, filter_minus) |
|---|
| 1103 | MAP_FILTER(_T("filter-accessed"), accessed, filter_minus) |
|---|
| 1104 | MAP_FILTER(_T("filter-version"), version, filter_minus) |
|---|
| 1105 | */ |
|---|
| 1106 | MAP_OPTIONS_MISSING(message, _T("Unknown argument: ")) |
|---|
| 1107 | MAP_OPTIONS_END() |
|---|
| 1108 | } catch (filters::parse_exception e) { |
|---|
| 1109 | message = e.getMessage(); |
|---|
| 1110 | return NSCAPI::returnUNKNOWN; |
|---|
| 1111 | } catch (filters::filter_exception e) { |
|---|
| 1112 | message = e.getMessage(); |
|---|
| 1113 | return NSCAPI::returnUNKNOWN; |
|---|
| 1114 | } |
|---|
| 1115 | if (paths.empty()) { |
|---|
| 1116 | message = _T("Missing path argument"); |
|---|
| 1117 | return NSCAPI::returnUNKNOWN; |
|---|
| 1118 | } |
|---|
| 1119 | if (!finder.has_filter()) { |
|---|
| 1120 | message = _T("Missing filter argument"); |
|---|
| 1121 | return NSCAPI::returnUNKNOWN; |
|---|
| 1122 | } |
|---|
| 1123 | FILETIME now; |
|---|
| 1124 | GetSystemTimeAsFileTime(&now); |
|---|
| 1125 | finder.debug_ = debug; |
|---|
| 1126 | finder.now = ((now.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)now.dwLowDateTime); |
|---|
| 1127 | if (debug) |
|---|
| 1128 | NSC_DEBUG_MSG_STD(_T("NOW: ") + strEx::format_filetime(finder.now)); |
|---|
| 1129 | finder.syntax = syntax; |
|---|
| 1130 | NSC_error errors; |
|---|
| 1131 | for (std::list<std::wstring>::const_iterator pit = paths.begin(); pit != paths.end(); ++pit) { |
|---|
| 1132 | recursive_scan<file_filter_function_ex>(*pit, pattern, 0, max_dir_depth, finder, &errors, debug); |
|---|
| 1133 | if (!ignoreError && finder.hasError()) { |
|---|
| 1134 | message = _T("Error when scanning: ") + (*pit) + _T(" check log for details (") + strEx::itos(finder.error_count) + _T(": ") + finder.last_error + _T(")"); |
|---|
| 1135 | return NSCAPI::returnUNKNOWN; |
|---|
| 1136 | } |
|---|
| 1137 | } |
|---|
| 1138 | message = finder.render(masterSyntax); |
|---|
| 1139 | if (!alias.empty()) |
|---|
| 1140 | query.alias = alias; |
|---|
| 1141 | else |
|---|
| 1142 | query.alias = _T("found files"); |
|---|
| 1143 | query.runCheck(finder.hit_count, returnCode, message, perf); |
|---|
| 1144 | if ((truncate > 0) && (message.length() > (truncate-4))) { |
|---|
| 1145 | message = message.substr(0, truncate-4) + _T("..."); |
|---|
| 1146 | //perf = _T(""); |
|---|
| 1147 | } |
|---|
| 1148 | if (message.empty()) |
|---|
| 1149 | message = _T("CheckFile ok"); |
|---|
| 1150 | return returnCode; |
|---|
| 1151 | } |
|---|
| 1152 | struct file_container : public file_info { |
|---|
| 1153 | std::wstring error_; |
|---|
| 1154 | |
|---|
| 1155 | static file_container get(std::wstring file, unsigned long long now) { |
|---|
| 1156 | |
|---|
| 1157 | BY_HANDLE_FILE_INFORMATION _info; |
|---|
| 1158 | |
|---|
| 1159 | HANDLE hFile = CreateFile(file.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, |
|---|
| 1160 | 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); |
|---|
| 1161 | if (hFile == INVALID_HANDLE_VALUE) { |
|---|
| 1162 | return file_container(file, _T("Could not open file: ") + file); |
|---|
| 1163 | } |
|---|
| 1164 | GetFileInformationByHandle(hFile, &_info); |
|---|
| 1165 | CloseHandle(hFile); |
|---|
| 1166 | file_container info(_info, file); |
|---|
| 1167 | info.ullNow = now; |
|---|
| 1168 | return info; |
|---|
| 1169 | } |
|---|
| 1170 | |
|---|
| 1171 | |
|---|
| 1172 | file_container(const BY_HANDLE_FILE_INFORMATION info, std::wstring file) : file_info(info, file_helpers::meta::get_path(file), file_helpers::meta::get_filename(file)) {} |
|---|
| 1173 | file_container(std::wstring file, std::wstring error) : error_(error), file_info(file_helpers::meta::get_path(file), file_helpers::meta::get_filename(file)) {} |
|---|
| 1174 | |
|---|
| 1175 | bool has_errors() { |
|---|
| 1176 | return !error_.empty(); |
|---|
| 1177 | } |
|---|
| 1178 | std::wstring get_error() { |
|---|
| 1179 | return error_; |
|---|
| 1180 | } |
|---|
| 1181 | |
|---|
| 1182 | }; |
|---|
| 1183 | |
|---|
| 1184 | typedef checkHolders::ExactBounds<checkHolders::NumericBounds<checkHolders::disk_size_type, checkHolders::disk_size_handler<checkHolders::disk_size_type> > > ExactBoundsDiscSize; |
|---|
| 1185 | |
|---|
| 1186 | |
|---|
| 1187 | typedef checkHolders::CheckContainer<checkHolders::ExactBoundsULong> ExactULongContainer; |
|---|
| 1188 | typedef checkHolders::CheckContainer<ExactBoundsDiscSize> DiscSizeContainer; |
|---|
| 1189 | typedef checkHolders::CheckContainer<checkHolders::ExactBoundsTime> DateTimeContainer; |
|---|
| 1190 | |
|---|
| 1191 | struct check_file_size : public checkHolders::check_proxy_container<file_container, DiscSizeContainer> { |
|---|
| 1192 | check_file_size() { set_alias(_T("size")); } |
|---|
| 1193 | checkHolders::disk_size_type get_value(file_container &value) { |
|---|
| 1194 | return value.ullSize; |
|---|
| 1195 | } |
|---|
| 1196 | }; |
|---|
| 1197 | struct check_file_line_count : public checkHolders::check_proxy_container<file_container, ExactULongContainer> { |
|---|
| 1198 | check_file_line_count() { set_alias(_T("line-count")); } |
|---|
| 1199 | unsigned long get_value(file_container &value) { |
|---|
| 1200 | return value.get_line_count(); |
|---|
| 1201 | } |
|---|
| 1202 | }; |
|---|
| 1203 | struct check_file_dates : public checkHolders::check_proxy_container<file_container, DateTimeContainer> { |
|---|
| 1204 | enum type_type { |
|---|
| 1205 | date_access, date_creation, date_written |
|---|
| 1206 | } ; |
|---|
| 1207 | type_type type_; |
|---|
| 1208 | check_file_dates(type_type type) : type_(type) |
|---|
| 1209 | { |
|---|
| 1210 | if (type_ == date_creation) |
|---|
| 1211 | set_alias(_T("creation")); |
|---|
| 1212 | else if (type_ == date_access) |
|---|
| 1213 | set_alias(_T("access")); |
|---|
| 1214 | else if (type_ == date_written) |
|---|
| 1215 | set_alias(_T("written")); |
|---|
| 1216 | else |
|---|
| 1217 | set_alias(_T("unknown date type")); |
|---|
| 1218 | } |
|---|
| 1219 | unsigned long long get_value(file_container &value) { |
|---|
| 1220 | if (type_ == date_creation) |
|---|
| 1221 | return value.ullCreationTime; |
|---|
| 1222 | if (type_ == date_access) |
|---|
| 1223 | return value.ullLastAccessTime; |
|---|
| 1224 | if (type_ == date_written) |
|---|
| 1225 | return value.ullLastWriteTime; |
|---|
| 1226 | return -1; |
|---|
| 1227 | } |
|---|
| 1228 | }; |
|---|
| 1229 | |
|---|
| 1230 | typedef checkHolders::check_multi_container<file_container> check_file_multi; |
|---|
| 1231 | struct check_file_factories { |
|---|
| 1232 | static checkHolders::check_proxy_interface<file_container>* size() { |
|---|
| 1233 | return new check_file_size(); |
|---|
| 1234 | } |
|---|
| 1235 | static checkHolders::check_proxy_interface<file_container>* line_count() { |
|---|
| 1236 | return new check_file_line_count(); |
|---|
| 1237 | } |
|---|
| 1238 | static checkHolders::check_proxy_interface<file_container>* access() { |
|---|
| 1239 | return new check_file_dates(check_file_dates::date_access); |
|---|
| 1240 | } |
|---|
| 1241 | static checkHolders::check_proxy_interface<file_container>* creation() { |
|---|
| 1242 | return new check_file_dates(check_file_dates::date_creation); |
|---|
| 1243 | } |
|---|
| 1244 | static checkHolders::check_proxy_interface<file_container>* written() { |
|---|
| 1245 | return new check_file_dates(check_file_dates::date_written); |
|---|
| 1246 | } |
|---|
| 1247 | }; |
|---|
| 1248 | |
|---|
| 1249 | #define MAP_FACTORY_PB(value, obj) \ |
|---|
| 1250 | else if ((p__.first == _T("check")) && (p__.second == ##value)) { checker.add_check(check_file_factories::obj()); } |
|---|
| 1251 | |
|---|
| 1252 | |
|---|
| 1253 | NSCAPI::nagiosReturn CheckDisk::CheckSingleFile(const unsigned int argLen, TCHAR **char_args, std::wstring &message, std::wstring &perf) { |
|---|
| 1254 | NSCAPI::nagiosReturn returnCode = NSCAPI::returnOK; |
|---|
| 1255 | std::list<std::wstring> stl_args = arrayBuffer::arrayBuffer2list(argLen, char_args); |
|---|
| 1256 | check_file_multi checker; |
|---|
| 1257 | typedef std::pair<int,file_filter> filteritem_type; |
|---|
| 1258 | typedef std::list<filteritem_type > filterlist_type; |
|---|
| 1259 | if (stl_args.empty()) { |
|---|
| 1260 | message = _T("Missing argument(s)."); |
|---|
| 1261 | return NSCAPI::returnUNKNOWN; |
|---|
| 1262 | } |
|---|
| 1263 | std::list<std::wstring> files; |
|---|
| 1264 | unsigned int truncate = 0; |
|---|
| 1265 | std::wstring syntax = _T("%filename%"); |
|---|
| 1266 | std::wstring alias; |
|---|
| 1267 | bool bPerfData = true; |
|---|
| 1268 | |
|---|
| 1269 | try { |
|---|
| 1270 | MAP_OPTIONS_BEGIN(stl_args) |
|---|
| 1271 | //MAP_OPTIONS_NUMERIC_ALL(query, _T("")) |
|---|
| 1272 | MAP_OPTIONS_STR2INT(_T("truncate"), truncate) |
|---|
| 1273 | MAP_OPTIONS_BOOL_FALSE(IGNORE_PERFDATA, bPerfData) |
|---|
| 1274 | MAP_OPTIONS_STR(_T("syntax"), syntax) |
|---|
| 1275 | MAP_OPTIONS_STR(_T("alias"), alias) |
|---|
| 1276 | MAP_OPTIONS_PUSH(_T("file"), files) |
|---|
| 1277 | MAP_OPTIONS_EXACT_NUMERIC_ALL_MULTI(checker, _T("")) |
|---|
| 1278 | MAP_FACTORY_PB(_T("size"), size) |
|---|
| 1279 | MAP_FACTORY_PB(_T("line-count"), line_count) |
|---|
| 1280 | MAP_FACTORY_PB(_T("creation"), creation) |
|---|
| 1281 | MAP_FACTORY_PB(_T("access"), access) |
|---|
| 1282 | MAP_FACTORY_PB(_T("written"), written) |
|---|
| 1283 | /* |
|---|
| 1284 | MAP_FILTER(_T("creation"), creation) |
|---|
| 1285 | MAP_FILTER(_T("written"), written) |
|---|
| 1286 | MAP_FILTER(_T("accessed"), accessed) |
|---|
| 1287 | MAP_FILTER(_T("version"), version) |
|---|
| 1288 | MAP_FILTER(_T("line-count"), line_count) |
|---|
| 1289 | */ |
|---|
| 1290 | MAP_OPTIONS_MISSING(message, _T("Unknown argument: ")) |
|---|
| 1291 | MAP_OPTIONS_END() |
|---|
| 1292 | } catch (filters::parse_exception e) { |
|---|
| 1293 | message = e.getMessage(); |
|---|
| 1294 | return NSCAPI::returnUNKNOWN; |
|---|
| 1295 | } catch (filters::filter_exception e) { |
|---|
| 1296 | message = e.getMessage(); |
|---|
| 1297 | return NSCAPI::returnUNKNOWN; |
|---|
| 1298 | } |
|---|
| 1299 | FILETIME now; |
|---|
| 1300 | GetSystemTimeAsFileTime(&now); |
|---|
| 1301 | unsigned __int64 nowi64 = ((now.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)now.dwLowDateTime); |
|---|
| 1302 | //finder.syntax = syntax; |
|---|
| 1303 | for (std::list<std::wstring>::const_iterator pit = files.begin(); pit != files.end(); ++pit) { |
|---|
| 1304 | file_container info = file_container::get(*pit, nowi64); |
|---|
| 1305 | checker.alias = info.render(syntax); |
|---|
| 1306 | checker.runCheck(info, returnCode, message, perf); |
|---|
| 1307 | } |
|---|
| 1308 | if ((truncate > 0) && (message.length() > (truncate-4))) { |
|---|
| 1309 | message = message.substr(0, truncate-4) + _T("..."); |
|---|
| 1310 | perf = _T(""); |
|---|
| 1311 | } |
|---|
| 1312 | if (message.empty()) |
|---|
| 1313 | message = _T("CheckSingleFile ok"); |
|---|
| 1314 | return returnCode; |
|---|
| 1315 | } |
|---|
| 1316 | NSCAPI::nagiosReturn CheckDisk::handleCommand(const strEx::blindstr command, const unsigned int argLen, TCHAR **char_args, std::wstring &msg, std::wstring &perf) { |
|---|
| 1317 | if (command == _T("CheckFileSize")) { |
|---|
| 1318 | return CheckFileSize(argLen, char_args, msg, perf); |
|---|
| 1319 | } else if (command == _T("CheckDriveSize")) { |
|---|
| 1320 | return CheckDriveSize(argLen, char_args, msg, perf); |
|---|
| 1321 | } else if (command == _T("CheckFile")) { |
|---|
| 1322 | return CheckFile(argLen, char_args, msg, perf); |
|---|
| 1323 | } else if (command == _T("CheckFile2")) { |
|---|
| 1324 | return CheckFile2(argLen, char_args, msg, perf); |
|---|
| 1325 | } else if (command == _T("CheckSingleFile")) { |
|---|
| 1326 | return CheckSingleFile(argLen, char_args, msg, perf); |
|---|
| 1327 | } else if (command == _T("getFileAge")) { |
|---|
| 1328 | return getFileAge(argLen, char_args, msg, perf); |
|---|
| 1329 | } |
|---|
| 1330 | return NSCAPI::returnIgnored; |
|---|
| 1331 | } |
|---|
| 1332 | |
|---|
| 1333 | |
|---|
| 1334 | NSC_WRAPPERS_MAIN_DEF(gCheckDisk); |
|---|
| 1335 | NSC_WRAPPERS_IGNORE_MSG_DEF(); |
|---|
| 1336 | NSC_WRAPPERS_HANDLE_CMD_DEF(gCheckDisk); |
|---|