From: Hamatoma Date: Wed, 25 Feb 2015 23:24:18 +0000 (+0100) Subject: ReDirMD5, fix: sync tool (target name), intrinsic logger X-Git-Url: https://gitweb.hamatoma.de/?a=commitdiff_plain;h=a912daefbedf370519d92b2da81363e91c3b02c6;p=crepublib ReDirMD5, fix: sync tool (target name), intrinsic logger --- diff --git a/base/ReByteBuffer.cpp b/base/ReByteBuffer.cpp index 4f28020..72618c5 100644 --- a/base/ReByteBuffer.cpp +++ b/base/ReByteBuffer.cpp @@ -186,14 +186,14 @@ ReByteBuffer& ReByteBuffer::appendFix(const char* data, size_t length, int maxLe int minLength, const char* separator, char padding){ if (length == (size_t) -1) length = strlen(data); - if (length < abs(minLength)){ + if ((int) length < abs(minLength)){ ensureSize(m_length + abs(minLength)); if (minLength < 0) appendChar(padding, - minLength - length); append(data, length); if (minLength > 0) appendChar(padding, minLength - length); - } else if (length > maxLength){ + } else if ((int) length > maxLength){ ensureSize(m_length + maxLength); int sepLength = separator == NULL ? 0 : strlen(separator); int lengthPart1 = (maxLength - sepLength + 1) / 2; diff --git a/base/ReLogger.hpp b/base/ReLogger.hpp index 8947164..50dfba0 100644 --- a/base/ReLogger.hpp +++ b/base/ReLogger.hpp @@ -59,6 +59,7 @@ enum ReLogCategory{ CAT_PROG = 0x00080000, CAT_RESOURCE = 0x00100000, CAT_TEST = 0x00200000, + CAT_SECURITY = 0x00400000, CAT_ALL = 0xfffff000, }; diff --git a/base/ReTestUnit.cpp b/base/ReTestUnit.cpp index 24ab0c5..db5a4d1 100644 --- a/base/ReTestUnit.cpp +++ b/base/ReTestUnit.cpp @@ -387,6 +387,3 @@ bool ReTestUnit::logF(bool isError, const char* format, ...){ va_end(args); return log(isError, buffer); } - -#if defined RE_TESTUNIT -#endif /*RE_TESTUNIT*/ diff --git a/base/baselocations.hpp b/base/baselocations.hpp index da874a0..a5e99e1 100644 --- a/base/baselocations.hpp +++ b/base/baselocations.hpp @@ -17,6 +17,7 @@ enum RELOC_LIB { LC_DIRTOOLS = 50100, LC_SEQARRAY = 50200, LC_HASHLIST = 50300, + LC_TRAVERSER = 50400, }; enum RELOC_UDPCONNECTION { LC_UDPCONNECTION_CONSTRUCT = 50101, diff --git a/cunit/cuReDirTools.cpp b/cunit/cuReDirTools.cpp index ba878d3..6f00be6 100644 --- a/cunit/cuReDirTools.cpp +++ b/cunit/cuReDirTools.cpp @@ -16,7 +16,12 @@ const int tenYear = (365 * 10 + 2) * 24 * 3600; class TestReDirTools : public ReTestUnit { public: - TestReDirTools() : ReTestUnit("ReDirTools", __FILE__){ + TestReDirTools() : ReTestUnit("ReDirTools", __FILE__), + // m_base + // m_buffer + m_testAll(true), + m_logger(ReLogger::globalLogger()) + { m_base = testDir(); ReDirectory::deleteTree(m_base.str()); m_base.append("dirtool"); @@ -30,6 +35,7 @@ private: ReByteBuffer m_base; ReByteBuffer m_buffer; bool m_testAll; + ReLogger* m_logger; private: const char* makeDir(const char* relPath){ m_buffer = m_base; @@ -67,8 +73,8 @@ private: } void run(){ initTree(); - testList2(); testToolSync(); + testList2(); if (m_testAll){ testToolStatistic(); testBasic(); @@ -83,13 +89,13 @@ private: } // F:\temp\retestunit\dirtool void testList2(){ - const char* argv[] = { "dt", "list", m_base.str(), NULL }; + const char* argv[] = { "dt", "list", "-r", m_base.str(), NULL }; ReDirTools tools; - tools.main(3, (char**) argv); + tools.main(4, (char**) argv); } void testList(){ const char* argv[] = { "list", m_base.str(), NULL }; - ReDirList().run(2, argv); + ReDirList(m_logger).run(2, argv); } int secOfFileTime(ReFileTime_t data){ #if defined __linux__ @@ -215,7 +221,7 @@ private: checkF(hash.get("cache.txt", buffer)); } void testDirStatistic(){ - ReDirStatistic stat; + ReDirStatistic stat(m_logger); const ReStringList& list = stat.calculate(m_base.str(), 1); ReByteBuffer buffer; ReByteBuffer expected; diff --git a/cunit/cuReTraverser.cpp b/cunit/cuReTraverser.cpp index 8d96896..799b54f 100644 --- a/cunit/cuReTraverser.cpp +++ b/cunit/cuReTraverser.cpp @@ -14,7 +14,11 @@ static const char* s_empty[] = { NULL }; class TestReTraverser : public ReTestUnit { public: - TestReTraverser() : ReTestUnit("ReTraverser", __FILE__){ + TestReTraverser() : ReTestUnit("ReTraverser", __FILE__), + m_base(), + m_buffer(), + m_logger(ReLogger::globalLogger()) + { m_base = testDir(); m_base.append("traverser"); _mkdir(m_base.str(), ALLPERMS); @@ -25,6 +29,7 @@ public: private: ReByteBuffer m_base; ReByteBuffer m_buffer; + ReLogger* m_logger; private: const char* makeDir(const char* relPath){ m_buffer = m_base; @@ -68,7 +73,7 @@ private: } void testList(){ const char* argv[] = { "list", m_base.str(), NULL }; - ReDirList().run(2, argv); + ReDirList(m_logger).run(2, argv); } void testCopyFile(){ #if defined __linux__ diff --git a/cunit/testall.cpp b/cunit/testall.cpp index b2c941e..37b07fb 100644 --- a/cunit/testall.cpp +++ b/cunit/testall.cpp @@ -77,8 +77,7 @@ void testMath(){ void testAll(){ try { - testBase(); - //testOs(); + testOs(); if (s_testAll){ testBase(); testString(); diff --git a/os/ReDirTools.cpp b/os/ReDirTools.cpp index edaca86..478852b 100644 --- a/os/ReDirTools.cpp +++ b/os/ReDirTools.cpp @@ -9,6 +9,7 @@ #include "base/rebase.hpp" #include "os/reos.hpp" +#include "math/remath.hpp" enum LOCATION_DIRTOOL { LC_COPY_FILE_1 = LC_DIRTOOLS + 1, // 50101 @@ -24,7 +25,8 @@ enum LOCATION_DIRTOOL { LC_SET_PROPERTIES_3, // 50111 LC_TOUCH_1, // 50112 }; -const char* ReDirTools::m_version = "2015.02.04"; +const char* ReDirTools::m_version = "2015.02.25"; +ReLogger* ReDirTools::m_logger = NULL; static const char* s_helpSummary[] = { "dirtool or dt ", @@ -34,6 +36,7 @@ static const char* s_helpSummary[] = { "batch produce output to handle the found files with a script", "help shows info about the arguments/options", "list shows the meta data of the selected files", + "md5 shows the MD5 checksum of the selected files", "statistic shows statistics about a direcctory tree", "synchronize copies only modified or new files from", " from a source directory tre to a target", @@ -67,6 +70,17 @@ const char* s_listExamples[] = { NULL }; +const char* s_md5Usage[] = { + ": m(d5) [] [ ...]", + " shows the MD5 check sum of the given files", + NULL +}; +const char* s_md5Examples[] = { + "dirtool md5 --buffer-size=512 e:\\data", + "dirtool m --type=f --size=10M -p;*.iso /home/iso /down/debian.iso", + NULL +}; + static const char* s_statisticUsage[] = { ": st(atistic) [] [ ...] []", " shows a statistic about a directory tree", @@ -631,20 +645,21 @@ void ReDirOptions::setFilterFromProgramArgs(ReDirEntryFilter_t& filter){ * @param addCurrentDirIfNoArguments * true: if no arguments are given the current * directory will be added as argument + * @param logger logger for error messages */ ReTool::ReTool(const char* usage[], const char* example[], int minArguments, int reservedFirst, int reservedLast, - bool addCurrentDirIfNoArguments) : + bool addCurrentDirIfNoArguments, ReLogger* logger) : ReDirOptions(usage, example), ReDirTreeStatistic(), m_minArguments(minArguments), m_reservedFirst(reservedFirst), m_reservedLast(reservedLast), m_addCurrentDirIfNoArguments(addCurrentDirIfNoArguments), - m_traverser(NULL, this), + m_traverser(NULL, this, logger), m_filter(), m_start(time(NULL)), - m_logger(ReLogger::globalLogger()) + m_logger(logger) { } @@ -741,7 +756,7 @@ void ReTool::processSingleFile(const char* filename){ name.append(ext); setFilterFromProgramArgs(m_filter); m_traverser.setPropertiesFromFilter(&m_filter); - ReDirStatus_t entry; + ReDirStatus_t entry(m_logger); entry.m_path = protocol; if (entry.findFirst()){ do { @@ -856,9 +871,13 @@ ReDirStatisticData& ReDirStatisticData::operator =(const ReDirStatisticData& sou /** * Constructor. + * + * @param logger logger for error handling + * @param deltaList increment if list must be increased + * @param deltaBuffer increment if content buffer must be increased */ -ReDirStatistic::ReDirStatistic(int deltaList, int deltaBuffer) : - ReTool(s_statisticUsage, s_statisticExamples, 2, 0, 1, false), +ReDirStatistic::ReDirStatistic(ReLogger* logger, int deltaList, int deltaBuffer) : + ReTool(s_statisticUsage, s_statisticExamples, 2, 0, 1, false, logger), m_list(deltaList, deltaBuffer) { // standard short options: D d O o P p T t v y Z z @@ -894,9 +913,11 @@ void ReDirStatisticData::clear(){ } /** * Constructor. + * + * @param logger logger for error handling */ -ReDirBatch::ReDirBatch() : - ReTool(s_batchUsage, s_batchExamples, 0, 0, 0, true), +ReDirBatch::ReDirBatch(ReLogger* logger) : + ReTool(s_batchUsage, s_batchExamples, 0, 0, 0, true, logger), m_arguments(), m_script(), m_isExe(false) @@ -1037,20 +1058,25 @@ void ReDirBatch::processFile(ReDirStatus_t* entry){ /** * Constructor. + * + * @param logger logger for error handling */ -ReDirList::ReDirList() : - ReTool(s_listUsage, s_listExamples, 0, 0, 0, true), +ReDirList::ReDirList(ReLogger* logger) : + ReTool(s_listUsage, s_listExamples, 0, 0, 0, true, logger), + m_widthOwner(13), m_shortFormat(false), - m_hideRights(false), + m_withRights(false), m_numerical(false) { // standard short options: D d O o P p T t v y Z z m_programArgs.addBool("short", i18n("output is only path and basename"), '1', "--short", false); - m_programArgs.addBool("rights", i18n("do not show the permission/right info"), - 'h', "--hide-rights", false); + m_programArgs.addBool("rights", i18n("show the permission/right info"), + 'r', "--rights", false); m_programArgs.addBool("numerical", i18n("the permission/right info is shown as numbers"), 'n', "--numerical", false); + m_programArgs.addInt("owner", i18n("space reserved for owner/group"), + 'w', "--width-owner", 13); addStandardFilterOptions(); } @@ -1059,8 +1085,9 @@ ReDirList::ReDirList() : */ void ReDirList::doIt(){ m_shortFormat = m_programArgs.getBool("short"); - m_hideRights = m_programArgs.getBool("rights"); + m_withRights = m_programArgs.getBool("rights"); m_numerical = m_programArgs.getBool("numerical"); + m_widthOwner = m_programArgs.getInt("owner"); processFileArguments(); printSummary(); } @@ -1084,8 +1111,8 @@ void ReDirList::processFile(ReDirStatus_t* entry){ if (m_shortFormat) fprintf(m_output, "%s%s\n", entry->m_path.str(), entry->node()); else { - if (! m_hideRights) - entry->rightsAsString(bufferRights, m_numerical); + if (m_withRights) + entry->rightsAsString(bufferRights, m_numerical, m_widthOwner); fprintf(m_output, "%c%s %12.6f %s %s%s\n", entry->typeAsChar(), bufferRights.str(), @@ -1095,6 +1122,60 @@ void ReDirList::processFile(ReDirStatus_t* entry){ } } +/** + * Constructor. + * + * @param logger logger for error handling + */ +ReDirMD5::ReDirMD5(ReLogger* logger) : + ReTool(s_md5Usage, s_md5Examples, 0, 0, 0, true, logger), + m_buffer() +{ + // standard short options: D d O o P p T t v y Z z + m_programArgs.addInt("buffersize", i18n("buffer size for file reading (in KiByte)"), + 'b', "--buffer-size", 4*1024); + addStandardFilterOptions(); +} + +/** + * Lists the metadata of the specified files. + */ +void ReDirMD5::doIt(){ + int size = m_programArgs.getInt("buffersize") * 1024; + m_buffer.setLength(size); + processFileArguments(); + printSummary(); +} + +/** + * Processes one directory. + * + * @param entry the properties of the directory to process + */ +void ReDirMD5::processDir(ReDirStatus_t* entry){ +} +/** + * Processes one file. + * + * @param entry the properties of the file to process + */ +void ReDirMD5::processFile(ReDirStatus_t* entry){ + const char* name = entry->fullName(); + FILE* fp = fopen(name, "rb"); + if (fp != NULL) { + ReMD5 digest; + size_t readBytes; + uint8_t* buffer = reinterpret_cast(m_buffer.buffer()); + size_t blockSize = m_buffer.length(); + + while( (readBytes = fread(buffer, 1, blockSize, fp)) > 0){ + digest.update(buffer, readBytes); + } + fclose(fp); + fprintf(m_output, "%s %s\n", digest.hexDigest().str(), name); + } +} + /** * Calculates the statistic of a directory tree. @@ -1256,9 +1337,11 @@ void formatWithSizeFilesAndDirs(const ReDirStatisticData& data, } /** * Constructor. + * + * @param logger logger for error handling */ -ReDirTouch::ReDirTouch() : - ReTool(s_touchUsage, s_touchExamples, 1, 0, 0, false), +ReDirTouch::ReDirTouch(ReLogger* logger) : + ReTool(s_touchUsage, s_touchExamples, 1, 0, 0, false, logger), m_buffer() //m_modified() //m_accessed() @@ -1482,9 +1565,11 @@ void ReDirSync::makeDirWithParents(ReByteBuffer& path, int minWidth, } /** * Constructor. + * + * @param logger logger for error handling */ -ReDirSync::ReDirSync() : - ReTool(s_syncUsage, s_syncExamples, 2, 0, 1, false), +ReDirSync::ReDirSync(ReLogger* logger) : + ReTool(s_syncUsage, s_syncExamples, 2, 0, 1, false, logger), m_buffer() { // standard short options: D d O o P p T t v y Z z @@ -1843,15 +1928,15 @@ void ReDirTools::help(int argc, const char* argv[]){ argv++; const char* arg0 = argv[0]; if (isArg("batch", arg0)){ - ReDirBatch batch; + ReDirBatch batch(m_logger); batch.help(NULL); } else if (isArg("list", arg0)){ - ReDirList list; + ReDirList list(m_logger); list.help(NULL); } else if (isArg("help", arg0)) printField(s_helpSummary); else if (isArg("statistic", arg0)){ - ReDirStatistic stat; + ReDirStatistic stat(m_logger); stat.help(NULL); } else if (isArg("test", arg0)){ void testAll(); @@ -1886,19 +1971,22 @@ int ReDirTools::main(int argc, char* orgArgv[]){ } argc--; argv++; + m_logger = ReLogger::globalLogger(); const char* arg0 = argv[0]; if (isArg("batch", arg0)) - ReDirBatch().run(argc, argv); - else if (isArg("list", arg0)) - ReDirList().run(argc, argv); + ReDirBatch(m_logger).run(argc, argv); else if (isArg("help", arg0)) tools.help(argc, argv); + else if (isArg("list", arg0)) + ReDirList(m_logger).run(argc, argv); + else if (isArg("md5", arg0)) + ReDirMD5(m_logger).run(argc, argv); else if (isArg("statistic", arg0)) - ReDirStatistic().run(argc, argv); + ReDirStatistic(m_logger).run(argc, argv); else if (isArg("synchronize", arg0)) - ReDirSync().run(argc, argv); + ReDirSync(m_logger).run(argc, argv); else if (isArg("touch", arg0)) - ReDirTouch().run(argc, argv); + ReDirTouch(m_logger).run(argc, argv); else if (isArg("test", arg0)){ void testAll(); testAll(); diff --git a/os/ReDirTools.hpp b/os/ReDirTools.hpp index 913f1a3..da857e2 100644 --- a/os/ReDirTools.hpp +++ b/os/ReDirTools.hpp @@ -79,7 +79,7 @@ class ReTool : public ReDirOptions, public ReDirTreeStatistic { public: ReTool(const char* usage[], const char* example[], int minArguments, int reservedFirst, int reservedLast, - bool addCurrentDirIfNoArguments); + bool addCurrentDirIfNoArguments, ReLogger* logger); virtual ~ReTool(); public: virtual bool trace(const char* currentFile); @@ -111,7 +111,7 @@ protected: name.setLength(ix); bool rc = stat(name.str(), &m_statInfo) == 0; if (ix >= 0) - name.append(OS_SEPARATOR_CHAR); + name.appendChar(OS_SEPARATOR_CHAR); return rc; #endif } @@ -130,7 +130,7 @@ protected: class ReDirBatch : public ReTool { public: - ReDirBatch(); + ReDirBatch(ReLogger* logger); protected: virtual void doIt(); virtual void processDir(ReDirStatus_t* entry); @@ -146,15 +146,31 @@ protected: */ class ReDirList : public ReTool { public: - ReDirList(); + ReDirList(ReLogger* logger); protected: virtual void doIt(); virtual void processDir(ReDirStatus_t* entry); virtual void processFile(ReDirStatus_t* entry); protected: + int m_widthOwner; bool m_shortFormat; - bool m_hideRights; + bool m_withRights; bool m_numerical; + +}; + +/** + * List file attributes of files. + */ +class ReDirMD5 : public ReTool { +public: + ReDirMD5(ReLogger* logger); +protected: + virtual void doIt(); + virtual void processDir(ReDirStatus_t* entry); + virtual void processFile(ReDirStatus_t* entry); +protected: + ReByteBuffer m_buffer; }; /** @@ -162,7 +178,7 @@ protected: */ class ReDirSync : public ReTool { public: - ReDirSync(); + ReDirSync(ReLogger* logger); protected: virtual void doIt(); void copyFile(ReDirStatus_t* entry, const char* target); @@ -202,7 +218,7 @@ extern void formatWithSizeFilesAndDirs(const ReDirStatisticData& data, */ class ReDirStatistic : public ReTool { public: - ReDirStatistic(int deltaList = 512, int deltaBuffer = 0x10000); + ReDirStatistic(ReLogger* logger, int deltaList = 512, int deltaBuffer = 0x10000); ~ReDirStatistic(); public: const ReStringList& calculate(const char* base, int depth, @@ -220,7 +236,7 @@ private: */ class ReDirTouch : public ReTool { public: - ReDirTouch(); + ReDirTouch(ReLogger* logger); protected: virtual void doIt(); virtual void processDir(ReDirStatus_t* entry); @@ -236,6 +252,7 @@ protected: class ReDirTools { + public: virtual void usage(const char* msg, const char* msg2 = NULL); void help(int argc, const char* argv[]); @@ -246,5 +263,6 @@ protected: void usage(ReTool& tool); public: static const char* m_version; + static ReLogger* m_logger; }; #endif /* OS_DIRTOOLS_HPP_ */ diff --git a/os/ReTraverser.cpp b/os/ReTraverser.cpp index 1e68133..655468b 100644 --- a/os/ReTraverser.cpp +++ b/os/ReTraverser.cpp @@ -14,20 +14,34 @@ #include "aclapi.h" #pragma comment(lib, "advapi32.lib") #endif + +enum RELOC_TRAVERSER { + LC_RIGHTS_AS_STRING_1 = LC_TRAVERSER + 1, // 50301 + LC_RIGHTS_AS_STRING_2, // 50302 + LC_RIGHTS_AS_STRING_3, // 50303 + LC_GET_PRIVILEGE_1, // 50304 + LC_GET_PRIVILEGE_2, // 50305 + LC_GET_PRIVILEGE_3, // 50306 + LC_GET_FILE_OWNER_1, // 50307 + LC_GET_FILE_OWNER_2, // 50308 +}; + /** * Constructor. */ -ReDirStatus_t::ReDirStatus_t() : +ReDirStatus_t::ReDirStatus_t(ReLogger* logger) : m_path(), m_fullName(), m_passNo(0), + m_logger(logger), #ifdef __linux__ m_handle(NULL), m_data(NULL) //m_status; #elif defined WIN32 - m_handle(INVALID_HANDLE_VALUE) + m_handle(INVALID_HANDLE_VALUE), //m_data; + m_getPrivilege(true) #endif { #ifdef __linux__ @@ -183,6 +197,83 @@ const char* ReDirStatus_t::fullName(){ return m_fullName.str(); } +#if defined __WIN32__ +/** Gets the name of the file owner. +* +* @param handle file handle (see CreateFile()) +* @param name OUT: the owner: [domain\\]name +* @return true: success +*/ +bool ReDirStatus_t::getFileOwner(HANDLE handle, const char* file, + ReByteBuffer& name, ReLogger* logger){ + bool rc = false; + PSID pSidOwner = NULL; + PSECURITY_DESCRIPTOR pSD = NULL; + if (GetSecurityInfo(handle, SE_FILE_OBJECT, + OWNER_SECURITY_INFORMATION, &pSidOwner, NULL, NULL, NULL, &pSD) != ERROR_SUCCESS) { + if (logger != NULL) + logger->sayF(LOG_ERROR | CAT_FILE, LC_GET_FILE_OWNER_1, + "GetSecurityInfo($1): $2").arg(file).arg((int) GetLastError()).end(); + } else { + char accountName[128]; + char domainName[128]; + DWORD dwAcctName = sizeof accountName; + DWORD dwDomainName = sizeof domainName; + SID_NAME_USE eUse = SidTypeUnknown; + if (! LookupAccountSid(NULL, pSidOwner, accountName, &dwAcctName, domainName, + &dwDomainName, &eUse)){ + if (logger != NULL) + logger->sayF(LOG_ERROR | CAT_SECURITY, LC_GET_FILE_OWNER_2, + "LookupAccountSid(): $1").arg((int) GetLastError()).end(); + } else { + if (dwDomainName > 0) + name.append(domainName).appendChar('\\'); + name.append(accountName); + rc = true; + } + } + return rc; +} +#endif /* __WIN32__ */ + +#if defined __WIN32__ +/** Tries to get a privilege. +* +* @param privilege the name of the privilege, e.g. "SeBackup" +* @param logger logger for error logging +*/ +bool ReDirStatus_t::getPrivilege(const char* privilege, ReLogger* logger){ + bool rc = false; + LUID luidPrivilege; + HANDLE hAccessToken; + if (! OpenProcessToken (GetCurrentProcess(), + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hAccessToken)){ + if (logger != NULL) + logger->sayF(LOG_ERROR | CAT_FILE, LC_GET_PRIVILEGE_1, + "OpenProcessToken(): $1").arg((int) GetLastError()).end(); + } else if (! LookupPrivilegeValue (NULL, SE_BACKUP_NAME, &luidPrivilege)) { + if (logger != NULL) + logger->sayF(LOG_ERROR | CAT_FILE, LC_GET_PRIVILEGE_2, + "LookupPrivilegeValue(): $1").arg((int) GetLastError()).end(); + } else { + TOKEN_PRIVILEGES tpPrivileges; + tpPrivileges.PrivilegeCount = 1; + tpPrivileges.Privileges[0].Luid = luidPrivilege; + tpPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + if (AdjustTokenPrivileges (hAccessToken, FALSE, &tpPrivileges, + 0, NULL, NULL) == 0) + rc = true; + else { + int error = GetLastError(); + if (error != 1300 && logger != NULL) + logger->sayF(LOG_ERROR | CAT_FILE, LC_GET_PRIVILEGE_3, + "AdjustTokenPrivileges(): $1").arg((int) GetLastError()).end(); + } + } + return rc; +} +#endif /* __WIN32__ */ + /** * Tests whether the instance is a directory. * @@ -313,10 +404,13 @@ inline void addId(const char* id, int maxLength, ReByteBuffer& buffer){ /** * Returns the file rights as a string. * - * @param buffer OUT: the file rights - * @return buffer.str() (for chaining) + * @param buffer OUT: the file rights + * @param numerical true: the owner/group should be numerical (UID/GID) + * @param ownerWidth the width for group/owner + * @return buffer.str() (for chaining) */ -const char* ReDirStatus_t::rightsAsString(ReByteBuffer& buffer, bool numerical) { +const char* ReDirStatus_t::rightsAsString(ReByteBuffer& buffer, bool numerical, + int ownerWidth) { buffer.setLength(0); #if defined __linux__ if (numerical){ @@ -344,70 +438,28 @@ const char* ReDirStatus_t::rightsAsString(ReByteBuffer& buffer, bool numerical) } #elif defined __WIN32__ const char* name = fullName(); - DWORD access = isDirectory() ? 0 : GENERIC_READ; - DWORD shareFlag = isDirectory() ? 0 : FILE_SHARE_READ; - DWORD flag = isDirectory() ? FILE_FLAG_BACKUP_SEMANTICS : FILE_ATTRIBUTE_NORMAL; - HANDLE handle; + HANDLE handle = INVALID_HANDLE_VALUE; if (! isDirectory()){ - handle = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, flag, NULL); - } else { - LUID luidPrivilege; - DWORD dwErrorCode; - HANDLE hAccessToken; - if (! OpenProcessToken (GetCurrentProcess(), - TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hAccessToken)){ - printf("OpenProcessToken(): %d\n", GetLastError()); + if ( (handle = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) + m_logger->sayF(LOG_ERROR | CAT_FILE, LC_RIGHTS_AS_STRING_1, + "CreateFile($1): $2").arg(name).arg((int) GetLastError()).end(); + } else if (m_getPrivilege){ + // we try only one time: + m_getPrivilege = false; + if (getPrivilege(SE_BACKUP_NAME, m_logger)){ + if ( (handle = CreateFile(name, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, + NULL)) != INVALID_HANDLE_VALUE) + m_logger->sayF(LOG_ERROR | CAT_FILE, LC_RIGHTS_AS_STRING_2, + "CreateFile($1): $2").arg(name).arg((int) GetLastError()).end(); } - if (! LookupPrivilegeValue (NULL, SE_BACKUP_NAME, &luidPrivilege)) { - printf("LookupPrivilegeValue(): %d\n", GetLastError()); - } else { - TOKEN_PRIVILEGES tpPrivileges; - tpPrivileges.PrivilegeCount = 1; - tpPrivileges.Privileges[0].Luid = luidPrivilege; - tpPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - if (AdjustTokenPrivileges (hAccessToken, FALSE, &tpPrivileges, - 0, NULL, NULL) != 0){ - printf("AdjustTokenPrivileges(): %d\n", GetLastError()); - } - } - handle = CreateFile(name, 0, 0, NULL, OPEN_EXISTING, flag, NULL); - } - if (handle == INVALID_HANDLE_VALUE){ - int error = GetLastError(); - printf("CreateFile(%s): %d\n", name, error); - } else { - PSID pSidOwner = NULL; - PSECURITY_DESCRIPTOR pSD = NULL; - DWORD dwRtnCode = GetSecurityInfo(handle, SE_FILE_OBJECT, - OWNER_SECURITY_INFORMATION, &pSidOwner, NULL, NULL, NULL, &pSD); - if (dwRtnCode != ERROR_SUCCESS) { - int error = GetLastError(); - printf("GetSecurityInfo(%s): %d\n", name, error); - } else { - if (numerical){ - buffer.appendInt((int) pSidOwner, " %08x"); - } else { - char accountName[128]; - char domainName[128]; - DWORD dwAcctName = sizeof accountName; - DWORD dwDomainName = sizeof domainName; - SID_NAME_USE eUse = SidTypeUnknown; - BOOL bRtnBool = LookupAccountSid(NULL, // local computer - pSidOwner, accountName, &dwAcctName, domainName, - &dwDomainName, &eUse); - if (! bRtnBool){ - int error = GetLastError(); - printf("LookupAccountSid(%s): %d\n", name, error); - } else { - if (domainName[0] != '\0') - buffer.append(domainName, -1).appendChar('/'); - } - buffer.append(accountName, -1); - } - } } + ReByteBuffer owner; + if (handle != INVALID_HANDLE_VALUE) + getFileOwner(handle, name, owner, m_logger); + CloseHandle(handle); + buffer.appendFix(owner.str(), owner.length(), ownerWidth, ownerWidth); #endif return buffer.str(); } @@ -649,7 +701,7 @@ bool ReTraceUnit::trace(const char* message){ * * @param base the base directory. The traversal starts at this point */ -ReTraverser::ReTraverser(const char* base, ReTraceUnit* tracer) : +ReTraverser::ReTraverser(const char* base, ReTraceUnit* tracer, ReLogger* logger) : ReDirTreeStatistic(), m_minLevel(0), m_maxLevel(512), @@ -658,10 +710,11 @@ ReTraverser::ReTraverser(const char* base, ReTraceUnit* tracer) : // m_dirs m_passNoForDirSearch(2), m_dirPatterns(NULL), - m_tracer(tracer) + m_tracer(tracer), + m_logger(logger) { memset(m_dirs, 0, sizeof m_dirs); - m_dirs[0] = new ReDirStatus_t(); + m_dirs[0] = new ReDirStatus_t(m_logger); // remove a preceeding "./". This simplifies the pattern expressions: if (m_base.startsWith(ReByteBuffer(".").appendChar(OS_SEPARATOR_CHAR).str())){ m_base.remove(0, 2); @@ -684,7 +737,7 @@ void ReTraverser::changeBase(const char* base){ destroy(); m_base.setLength(0).append(base); memset(m_dirs, 0, sizeof m_dirs); - m_dirs[0] = new ReDirStatus_t(); + m_dirs[0] = new ReDirStatus_t(m_logger); // remove a preceeding "./". This simplifies the pattern expressions: if (m_base.startsWith(ReByteBuffer(".").appendChar(OS_SEPARATOR_CHAR).str())){ m_base.remove(0, 2); @@ -823,7 +876,7 @@ bool ReTraverser::initEntry(const ReByteBuffer& parent, const char* node, int le if (level >= 0) m_level = level; if (m_dirs[m_level] == NULL) - m_dirs[m_level] = new ReDirStatus_t(); + m_dirs[m_level] = new ReDirStatus_t(m_logger); ReDirStatus_t* current = m_dirs[m_level]; current->m_passNo = 1; if (level >= 0){ diff --git a/os/ReTraverser.hpp b/os/ReTraverser.hpp index 41d8769..79885b6 100644 --- a/os/ReTraverser.hpp +++ b/os/ReTraverser.hpp @@ -60,7 +60,7 @@ public: }; public: - ReDirStatus_t(); + ReDirStatus_t(ReLogger* logger); public: const ReFileTime_t* accessed(); ReFileSize_t fileSize(); @@ -75,17 +75,23 @@ public: bool isRegular(); const ReFileTime_t* modified(); const char* node() const; - const char* rightsAsString(ReByteBuffer& buffer, bool numerical); + const char* rightsAsString(ReByteBuffer& buffer, bool numerical, int ownerWidth); Type_t type(); char typeAsChar(); public: + static const char* filetimeToString(const ReFileTime_t* time, ReByteBuffer& buffer); static time_t filetimeToTime(const ReFileTime_t* time); +#if defined __WIN32__ + static bool getFileOwner(HANDLE handle, const char* file, ReByteBuffer& name, + ReLogger* logger = NULL); + static bool getPrivilege(const char* privilege, ReLogger* logger); +#endif static void timeToFiletime(time_t time, ReFileTime_t& filetime); - static const char* filetimeToString(const ReFileTime_t* time, ReByteBuffer& buffer); public: ReByteBuffer m_path; ReByteBuffer m_fullName; int m_passNo; + ReLogger* m_logger; #ifdef __linux__ DIR* m_handle; struct dirent* m_data; @@ -95,6 +101,7 @@ public: #elif defined WIN32 HANDLE m_handle; WIN32_FIND_DATAA m_data; + bool m_getPrivilege; #endif }; class ReDirEntryFilter_t{ @@ -173,7 +180,7 @@ public: #define MAX_ENTRY_STACK_DEPTH 256 class ReTraverser : public ReDirTreeStatistic { public: - ReTraverser(const char* base, ReTraceUnit* tracer = NULL); + ReTraverser(const char* base, ReTraceUnit* tracer = NULL, ReLogger* logger = NULL); virtual ~ReTraverser(); public: void changeBase(const char* base); @@ -248,6 +255,7 @@ protected: RePatternList* m_dirPatterns; ReDirTreeStatistic m_statistic; ReTraceUnit* m_tracer; + ReLogger* m_logger; }; #endif /* OS_RETRAVERSER_HPP_ */