source: nscp/modules/CheckDisk/CheckDisk.cpp @ b4110d8

0.4.00.4.10.4.2
Last change on this file since b4110d8 was b4110d8, checked in by Michael Medin <michael@…>, 3 years ago

Reintegrated stable branch and removed some project files (no longer needed) (part x of many)

  • Property mode set to 100644
File size: 47.8 KB
Line 
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
30CheckDisk gCheckDisk;
31
32BOOL 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
38CheckDisk::CheckDisk() {
39}
40CheckDisk::~CheckDisk() {
41}
42
43bool is_directory(DWORD dwAttr) {
44        return ((dwAttr != INVALID_FILE_ATTRIBUTES) && ((dwAttr&FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY));
45}
46
47bool 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}
60bool CheckDisk::unloadModule() {
61        return true;
62}
63
64bool CheckDisk::hasCommandHandler() {
65        return true;
66}
67bool CheckDisk::hasMessageHandler() {
68        return false;
69}
70
71class error_reporter {
72public:
73        virtual void report_error(std::wstring error) = 0;
74        virtual void report_warning(std::wstring error) = 0;
75};
76
77
78
79struct 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};
85typedef std::unary_function<const file_finder_data&, bool> baseFinderFunction;
86
87struct 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        }
108private: 
109        unsigned long long size;
110};
111
112template <class finder_function>
113void 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
159NSCAPI::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
343std::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
357class 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};
365typedef std::pair<std::wstring,std::wstring> pattern_type;
366pattern_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
379typedef std::pair<std::wstring,std::wstring> pattern_type;
380pattern_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
394NSCAPI::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
452struct 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
645struct 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
692struct 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
733struct 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
807struct 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
917NSCAPI::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
957NSCAPI::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
1040NSCAPI::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}
1152struct 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
1184typedef checkHolders::ExactBounds<checkHolders::NumericBounds<checkHolders::disk_size_type, checkHolders::disk_size_handler<checkHolders::disk_size_type> > > ExactBoundsDiscSize;
1185
1186
1187typedef checkHolders::CheckContainer<checkHolders::ExactBoundsULong> ExactULongContainer;
1188typedef checkHolders::CheckContainer<ExactBoundsDiscSize> DiscSizeContainer;
1189typedef checkHolders::CheckContainer<checkHolders::ExactBoundsTime> DateTimeContainer;
1190
1191struct 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};
1197struct 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};
1203struct 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
1230typedef checkHolders::check_multi_container<file_container> check_file_multi;
1231struct 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
1253NSCAPI::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}
1316NSCAPI::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
1334NSC_WRAPPERS_MAIN_DEF(gCheckDisk);
1335NSC_WRAPPERS_IGNORE_MSG_DEF();
1336NSC_WRAPPERS_HANDLE_CMD_DEF(gCheckDisk);
Note: See TracBrowser for help on using the repository browser.