]> gitweb.hamatoma.de Git - crepublib/commitdiff
ReDirChecksum
authorhama <hama@siduction.net>
Sun, 1 Mar 2015 23:05:04 +0000 (00:05 +0100)
committerhama <hama@siduction.net>
Sun, 1 Mar 2015 23:05:04 +0000 (00:05 +0100)
21 files changed:
base/ReByteBuffer.cpp
base/ReByteBuffer.hpp
base/ReDirectory.cpp
base/ReHashList.cpp
base/ReProgramArgs.cpp
base/ReStringList.cpp
base/ReTestUnit.cpp
base/ReVarArgs.hpp
cunit/cuReDirTools.cpp
cunit/cuReRPD64.cpp
cunit/cuReTraverser.cpp
cunit/testall.cpp
math/ReMD5.cpp
math/ReMD5.hpp
math/ReRPD64.cpp
math/ReRPD64.hpp
os/ReDirTools.cpp
os/ReDirTools.hpp
os/ReTraverser.cpp
os/ReTraverser.hpp
os/reos.hpp

index b08ebb6e1f2df1a6f0d9e69d91800b58be7f6be9..947774655f2a515006abeb564b32e56941a02482 100644 (file)
@@ -231,7 +231,7 @@ ReByteBuffer& ReByteBuffer::appendFix(const char* data, size_t length,
 ReByteBuffer& ReByteBuffer::appendHexDump(const char* data, size_t length,
     int offset, int bytesPerLine, const char* offsetFormat, bool withAscii,
     int groupWidth, int gapBehind, const char* separator) {
-       if (length == -1)
+       if (length == (size_t) -1)
                length = strlen(data);
        if (gapBehind < 0)
                gapBehind = bytesPerLine / 2;
index 6914d70aaa6f0f937085a4b14d841403cb05c425..d18ff71056977451e7b30ca20378c4cd26777ffd 100644 (file)
@@ -131,8 +131,8 @@ public:
                if (length == (size_t) -1)
                        length = strlen(data);
                bool rc = length == m_length
-                   && (!ignoreCase && _memcmp(data, m_buffer, length) == 0
-                       || ignoreCase && _strnicmp(data, m_buffer, length) == 0);
+                   && ((!ignoreCase && _memcmp(data, m_buffer, length) == 0)
+                       || (ignoreCase && _strnicmp(data, m_buffer, length) == 0));
                return rc;
        }
        /** @brief Tests whether another instance is equal to this instance.
@@ -143,9 +143,9 @@ public:
        inline
        bool equals(const ReByteBuffer& buffer, bool ignoreCase = false) const {
                bool rc = buffer.length() == m_length
-                   && (!ignoreCase && _memcmp(buffer.str(), m_buffer, m_length) == 0
-                       || ignoreCase
-                           && _strnicmp(buffer.str(), m_buffer, m_length) == 0);
+                   && ((!ignoreCase && _memcmp(buffer.str(), m_buffer, m_length) == 0)
+                       || (ignoreCase
+                           && _strnicmp(buffer.str(), m_buffer, m_length) == 0));
                return rc;
        }
        ReByteBuffer& fill(Byte filler = 0, int start = 0, int end = -1);
index 5c7afde0874b086873ae4cf641db99d35f0d9502..83411c2aed3c4c3b1ed88b5fdf98442d834b8f10 100644 (file)
@@ -104,8 +104,9 @@ void ReDirectory::deleteTree(const char* base, bool deleteBaseToo) {
                        do {
                                struct stat info;
                                const char* node = dir.currentFile();
-                               if (!(node[0] == '.'
-                                   && (node[1] == '\0' || node[1] == '.' && node[2] == '\0'))
+                               if ((!(node[0] == '.'
+                                   && (node[1] == '\0'
+                                       || (node[1] == '.' && node[2] == '\0'))))
                                    && stat(dir.fullpath(full).str(), &info) == 0) {
                                        if (S_ISDIR(info.st_mode))
                                                deleteTree(full.str(), true);
index 5d8d18cf2e356f034c3158cf312a15498c41feb8..95be346a43ba08d8656d8069cb01eb3403ff09c1 100644 (file)
@@ -71,7 +71,7 @@ void ReHashList::dump(FILE* stream, const char* prefix) const {
        ReArrayPosition position;
        ReByteBuffer key, value;
        while (next(position, &key, &value)) {
-               fprintf(stream, "%s : [%3d] %s\n", key.str(), value.length(),
+               fprintf(stream, "%s : [%3d] %s\n", key.str(), (int) value.length(),
                    value.str());
        }
 }
index 92800340086f8d63753ec5d4802f9a163a77f862..637caf905d1a1fb35c042f2d663948bcae67cbd2 100644 (file)
@@ -338,7 +338,6 @@ void ReProgramArgs::search(char shortName, const char* longName,
                        lengthLongName = strlen(longName);
        }
        while (!found && m_properties.next(position, &name, &properties)) {
-               const char* ptr = properties.str();
                list.split(properties.str(), '\1');
                if (longName == NULL && list.count() > IxShort
                    && shortName == list.strOf(IxShort)[0])
index 89271a3ec47de4b777b82807438eb07c4f4e8aaa..e08a453026df7b7bca115af336010b2bffcf25f9 100644 (file)
@@ -42,7 +42,7 @@ ReStringList& ReStringList::append(const char* source, Tag tagOf) {
  * @return                     the instance itself (for chaining)
  */
 ReStringList& ReStringList::append(const ReByteBuffer& source, Tag tag) {
-       int ix = add(-1, source.str(), source.length() + 1, tag);
+       add(-1, source.str(), source.length() + 1, tag);
        return *this;
 }
 
index 542f558a3f43388c5ff5b6cb5eacc3ef1ad3d073..27bac118c01c2dfc0a102057603acf1c2ae4679f 100644 (file)
@@ -259,6 +259,8 @@ void ReTestUnit::createTestDir() {
                        if (_mkdir(m_tempDir.str(), ALLPERMS) != 0) {
                                error = getLastOSError();
                        }
+               if (error != 0)
+                       logF(true, "cannot create directory: %s", m_tempDir.str());
                ReDirectory::deleteTree(m_tempDir.str(), false);
                m_tempDir.ensureLastChar(OS_SEPARATOR_CHAR);
        }
index c662585e737c24e22bc2eef448a2e4bafaae34f4..8658ff0698922c1101dc9504ae4da2bd9b15d750 100644 (file)
@@ -46,8 +46,18 @@ public:
        ReVarArgs& arg(int64_t value, const char* format = "%lld");
        ReVarArgs& arg(unsigned int arg, const char* format = "%u");
        ReVarArgs& arg(uint64_t value, const char* format = "%llu");
-       ReVarArgs& arg(const char* arg, int minWidth = 0, int maxWidth = 1024,
+       ReVarArgs& arg(const char* value, int minWidth = 0, int maxWidth = 1024,
            bool alignRight = false);
+       /** Appends an argument of the type <code>ReByteBuffer</code>.
+        * @param value                 argument value
+        * @param minWidth              minimum width of the appended string. Padding with ' '
+        * @param maxWidth              maximum width of the string
+        * @param alignRight    <code>true</code>: padding is done at the start
+        */
+       inline ReVarArgs& arg(const ReByteBuffer& value, int minWidth = 0,
+               int maxWidth = 1024, bool alignRight = false){
+               return arg(value.str(), minWidth, maxWidth, alignRight);
+       }
        ReVarArgs& arg(double arg, const char* format = "%f");
        const char* asCString();
        virtual void end(void);
index b7e089a101552391b21c7cb5d9c1f2e9f0c6925d..2ee6c15b55504f99e417defd2383fbd96cb35d1b 100644 (file)
@@ -74,6 +74,7 @@ private:
        void run() {\r
                initTree();\r
                if (m_testAll) {\r
+                       testChecksumBuild();\r
                        testList2();\r
                        testToolStatistic();\r
                        testBasic();\r
@@ -86,6 +87,22 @@ private:
                        testBatch();\r
                }\r
        }\r
+       void testChecksumBuild(){\r
+               ReByteBuffer nameCurrent;\r
+               buildFilename("current", nameCurrent);\r
+               ReByteBuffer optOutput("--output-file=");\r
+               optOutput.append(nameCurrent);\r
+               const char* argv[] = { "dt", "checksum", "-P;*;-cache", "-tr", "-p;*.txt",\r
+                   "-s4711", "-arpd64", "-cBuild",\r
+                   optOutput.str(), m_base.str(), NULL };\r
+               ReDirTools tools;\r
+               tools.main(-1, (char**) argv);\r
+               // checkFile(nameCurrent, "");\r
+               const char* argv2[] = { "dt", "checksum", "-P;*;-cache", "-tr", "-p;*.txt",\r
+                   "-s4711", "-arpd64", "-cCompare",\r
+                   optOutput.str(), m_base.str(), NULL };\r
+               tools.main(-1, (char**) argv2);\r
+       }\r
        // F:\temp\retestunit\dirtool\r
        void testList2() {\r
                const char* argv[] = { "dt", "list", "-r", m_base.str(), NULL };\r
index 0c2e4b33937a9c56f0a0218430f5c4f0a95c2625..41676ac25bcbde02d01650ee5d1a221398ce65fa 100644 (file)
@@ -28,14 +28,14 @@ private:
                const char* text =
                    "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVEXYZ01234567890\n";
                RPD64.update((const uint8_t*) text, strlen(text));
-               checkEqu("148517865cc2ca2c4ea2c2130a485769", RPD64.hexDigest());
+               checkEqu("096a35ff313aeeace1de611a4c391eb5", RPD64.hexDigest());
                RPD64.reset();
                text = "The quick brown fox jumps over the lazy dog";
                RPD64.update((const uint8_t*) text, -1);
-               checkEqu("064f9242cfaa1e270f9c28d7a90a6bcc", RPD64.hexDigest());
+               checkEqu("a978d3ccb8c3e37ec715f30a3ea4f979", RPD64.hexDigest());
                RPD64.reset();
                RPD64.update((const uint8_t*) "", 0);
-               checkEqu("e602b42cc6d1e20b6b56f2b2f7542f38", RPD64.hexDigest());
+               checkEqu("3c7b4e20d8ee3cf7716c2dacdddd9e30", RPD64.hexDigest());
        }
        int testOneLong(ReByteBuffer& text, int seed2 = 0) {
                ReRPD64 RPD64;
index fd94366433db7af22780632acde979b51efa31bd..01e2c247e0eee301da4eaba6386bba5b01ad3b53 100644 (file)
@@ -10,8 +10,6 @@
 #include "base/rebase.hpp"
 #include "os/reos.hpp"
 
-static const char* s_empty[] = { NULL };
-
 class TestReTraverser: public ReTestUnit {
 public:
        TestReTraverser() :
index ddc73aed3a17707e30805659f8d639803596d649..f853161f66690d605f21dcf1968e4b811ab37c3c 100644 (file)
@@ -78,7 +78,7 @@ void testMath() {
 }
 void testAll() {
        try {
-               testMath();
+               testOs();
                if (s_testAll) {
                        testBase();
                        testString();
index 000252d5397a0bded5f2ad3da8391dfd6b2fc7bd..9c05b7c1c128625cdb026c3f111cacd07ac5997a 100644 (file)
@@ -34,14 +34,21 @@ const uint32_t ReMD5::m_K[RE_DIGEST_CHUNK_SIZE] = {
  *\r
  * @param digest               the buffer for the binary checksum\r
  * @param digestSize   the length of <code>digest</code>\r
+ * @param waiting              a buffer for a chunk. Must have space for at least 2*chunksize bytes\r
+ *                                             NULL: an intrinsic buffer will be used\r
+ * @param chunkSize            the length of one full input block\r
  */\r
-ReDigest::ReDigest(uint8_t* digest, size_t digestSize) :\r
+ReDigest::ReDigest(uint8_t* digest, size_t digestSize, uint8_t* waiting,\r
+       size_t chunkSize) :\r
            m_digest(digest),\r
            m_digestSize(digestSize),\r
-           // m_waiting[RE_DIGEST_CHUNK_SIZE];\r
+           // m_waitingBuffer[RE_DIGEST_CHUNK_SIZE];\r
+           m_waiting(waiting != NULL ? waiting : m_waitingBuffer),\r
            m_lengthWaiting(0),\r
+           m_chunkSize(chunkSize),\r
            m_length(0),\r
-           m_finalized(false) {\r
+           m_finalized(false),\r
+           m_salt(0) {\r
 }\r
 /**\r
  * Destructor.\r
@@ -87,7 +94,7 @@ void ReDigest::update(const uint8_t* block, int blockLength) {
        // process the "waiting" input (incomplete chunk):\r
        m_length += blockLength;\r
        if (m_lengthWaiting > 0) {\r
-               int rest = m_digestSize - m_lengthWaiting;\r
+               int rest = m_chunkSize - m_lengthWaiting;\r
                if (rest > blockLength)\r
                        rest = blockLength;\r
                memcpy(m_waiting + m_lengthWaiting, block, rest);\r
@@ -95,17 +102,17 @@ void ReDigest::update(const uint8_t* block, int blockLength) {
                block += rest;\r
                m_lengthWaiting += rest;\r
                // Is the chunk complete?\r
-               if (m_lengthWaiting == RE_DIGEST_CHUNK_SIZE) {\r
+               if (m_lengthWaiting == m_chunkSize) {\r
                        processChunk(m_waiting);\r
                        m_lengthWaiting = 0;\r
                }\r
        }\r
        // process full 512 bit chunks (64 byte blocks):\r
-       for (int ix = blockLength / RE_DIGEST_CHUNK_SIZE; ix > 0; ix--) {\r
+       for (int ix = blockLength / m_chunkSize; ix > 0; ix--) {\r
                processChunk(block);\r
-               block += RE_DIGEST_CHUNK_SIZE;\r
+               block += m_chunkSize;\r
        }\r
-       blockLength %= RE_DIGEST_CHUNK_SIZE;\r
+       blockLength %= m_chunkSize;\r
        if (blockLength != 0) {\r
                assert(m_lengthWaiting == 0);\r
                memcpy(m_waiting, block, blockLength);\r
@@ -113,6 +120,19 @@ void ReDigest::update(const uint8_t* block, int blockLength) {
        }\r
 }\r
 \r
+/**\r
+ * Sets the salt of the checksum algorithm.\r
+ *\r
+ * Important: set the salt before you make the first <code>update()</code>!\r
+ *\r
+ * The salt makes that the checksum of the same input is (extremly) different\r
+ * to another salt.\r
+ *\r
+ * @param salt the salt to set\r
+ */\r
+void ReDigest::setSalt(uint64_t salt){\r
+       m_salt = salt;\r
+}\r
 /**\r
  * Constructor.\r
  */\r
@@ -157,7 +177,7 @@ void ReMD5::finalize() {
        memset(block + blockLength, 0, zeros);\r
        blockLength += zeros;\r
        //append original length in bits mod (2 pow 64) to message\r
-       uint64_t lengthBits = 8LL * m_length;\r
+       uint64_t lengthBits = 8LL * m_length + m_salt;\r
 #if defined __LITTLE_ENDIAN__\r
        memcpy(block + blockLength, &lengthBits, 8);\r
        blockLength += 8;\r
@@ -488,7 +508,7 @@ void ReMD5::reset() {
        m_c0 = 0x98badcfe;\r
        m_d0 = 0x10325476;\r
        memset(m_digest, 0, sizeof m_digest);\r
-       memset(m_waiting, 0, sizeof m_waiting);\r
+       memset(m_waiting, 0, m_chunkSize);\r
        m_lengthWaiting = 0;\r
        m_length = 0;\r
        m_hexDigest.setLength(0);\r
index 427db8c340b85257f2f46199ef3de2a65358cef2..1a3695ec101fe77012bc8c4e1a233c9eeb9d9725 100644 (file)
@@ -13,14 +13,23 @@ typedef uint8_t ReMD5Digest_t[16];
 
 class ReDigest {
 public:
-       ReDigest(uint8_t* buffer, size_t bufferSize);
+       ReDigest(uint8_t* buffer, size_t bufferSize, uint8_t* waiting = NULL,
+               size_t blocksize = RE_DIGEST_CHUNK_SIZE);
        virtual ~ReDigest();
 public:
        const uint8_t* digest();
        const ReByteBuffer& hexDigest();
        virtual void update(const uint8_t* block, int blockLength);
+       /** Updates the digest with data of any length.
+        * @param block the data to process
+        */
+       inline void update(const ReByteBuffer& block) {
+               update(reinterpret_cast<const uint8_t*>(block.str()),
+                       (int) block.length());
+       }
        virtual void processChunk(const uint8_t* block) = 0;
        virtual void reset() = 0;
+       virtual void setSalt(uint64_t salt);
 protected:
        virtual void finalize() = 0;
 protected:
@@ -29,11 +38,14 @@ protected:
        ReByteBuffer m_hexDigest;
        // normally only the first chunk is used (64 byte), but while finalization
        // a 2nd chunk may be needed.
-       uint8_t m_waiting[RE_DIGEST_CHUNK_SIZE + RE_DIGEST_CHUNK_SIZE];
+       uint8_t m_waitingBuffer[2 *RE_DIGEST_CHUNK_SIZE];
+       uint8_t* m_waiting;
        int m_lengthWaiting;
+       int m_chunkSize;
        // total count of input bytes:
        uint32_t m_length;
        bool m_finalized;
+       uint64_t m_salt;
 };
 
 /**
index 5fa6a2665c9a6d3e29a100cd2a58dac4cd608018..19598b0eb8afa51b2c9bb71fd13237679ede9257 100644 (file)
  * Constructor.\r
  */\r
 ReRPD64::ReRPD64() :\r
+               ReDigest(m_digest, sizeof m_digest),\r
            //m_digest\r
-           // m_hexDigest;\r
-           // m_waiting[64];\r
-           m_lengthWaiting(0),\r
-           m_length(0),\r
            m_a0(0),\r
            m_b0(0),\r
            m_c0(0),\r
-           m_d0(0),\r
-           m_finalized(false),\r
-           m_salt(1) {\r
+           m_d0(0) {\r
        reset();\r
 }\r
 \r
@@ -32,18 +27,6 @@ ReRPD64::ReRPD64() :
 ReRPD64::~ReRPD64() {\r
 }\r
 \r
-/**\r
- * Returns the binary digest value.\r
- *\r
- * @return     the binary digest (16 byte array)\r
- */\r
-const uint8_t* ReRPD64::digest() {\r
-       if (!m_finalized) {\r
-               finalize();\r
-       }\r
-       return m_digest;\r
-}\r
-\r
 /**\r
  * Finalizes the digest.\r
  *\r
@@ -111,20 +94,6 @@ void ReRPD64::finalize() {
 #endif\r
 }\r
 \r
-/**\r
- * Returns the binary digest value.\r
- *\r
- * @return     the binary digest (16 byte array)\r
- */\r
-const ReByteBuffer& ReRPD64::hexDigest() {\r
-       if (m_hexDigest.length() == 0) {\r
-               digest();\r
-               for (int ix = 0; ix < 16; ix++) {\r
-                       m_hexDigest.appendInt(m_digest[ix], "%02x");\r
-               }\r
-       }\r
-       return m_hexDigest;\r
-}\r
 #define F1(B, C, D) ((B & C) | (~ B & D))\r
 #define F2(B, C, D) ((D & B) | (C & ~ D))\r
 #define F3(B, C, D)    ((B ^ C) ^ D)\r
@@ -257,41 +226,4 @@ void ReRPD64::reset() {
        m_hexDigest.setLength(0);\r
        m_finalized = false;\r
 }\r
-/**\r
- * Processes a 64 byte block.\r
- *\r
- * @param block                        a block which should be added to the digest\r
- * @param blockLength  the length of <code>block</code>\r
- */\r
-void ReRPD64::update(const uint8_t* block, int blockLength) {\r
-       if (blockLength == -1)\r
-               blockLength = strlen((const char*) block);\r
-       // process the "waiting" input (incomplete chunk):\r
-       m_length += blockLength;\r
-       if (m_lengthWaiting > 0) {\r
-               int rest = 64 - m_lengthWaiting;\r
-               if (rest > blockLength)\r
-                       rest = blockLength;\r
-               memcpy(m_waiting + m_lengthWaiting, block, rest);\r
-               blockLength -= rest;\r
-               block += rest;\r
-               m_lengthWaiting += rest;\r
-               // Is the chunk complete?\r
-               if (m_lengthWaiting == 64) {\r
-                       processChunk (m_waiting);\r
-                       m_lengthWaiting = 0;\r
-               }\r
-       }\r
-       // process full 512 bit chunks (64 byte blocks):\r
-       for (int ix = blockLength / 64; ix > 0; ix--) {\r
-               processChunk(block);\r
-               block += 64;\r
-       }\r
-       blockLength %= 64;\r
-       if (blockLength != 0) {\r
-               assert(m_lengthWaiting == 0);\r
-               memcpy(m_waiting, block, blockLength);\r
-               m_lengthWaiting = blockLength;\r
-       }\r
-}\r
 \r
index 21ba5fae2d1b74f87fafe2277b704a105c9f0012..8a4fa093a06ab78a76420e94ca70be602081f09f 100644 (file)
@@ -14,34 +14,22 @@ typedef uint8_t ReRPD64Digest[16];
  *
  * The algorithm is similar to MD5, but calculation is done in 64-bit.
  */
-class ReRPD64 {
+class ReRPD64 : public ReDigest {
 public:
        ReRPD64();
        virtual ~ReRPD64();
 public:
-       const uint8_t* digest();
-       const ReByteBuffer& hexDigest();
-       void update(const uint8_t* block, int blockLength);
-       void processChunk(const uint8_t block[64]);
-       void reset();
-       void setSalt(uint64_t salt);
+       virtual void processChunk(const uint8_t*_block);
+       virtual void reset();
 private:
-       void finalize();
+       virtual void finalize();
 
 private:
        ReRPD64Digest m_digest;
-       ReByteBuffer m_hexDigest;
-       // normally only the first chunk is used (64 byte), but while finalization
-       // a 2nd chunk may be needed.
-       uint8_t m_waiting[64 + 64];
-       int m_lengthWaiting;
-       // total count of input bytes:
-       uint64_t m_length;
        uint64_t m_a0;
        uint64_t m_b0;
        uint64_t m_c0;
        uint64_t m_d0;
-       bool m_finalized;
        uint64_t m_salt;
 };
 
index 5d2825ebb00419c66276418f29034938574e53d7..ca9c86e1f795bc3137582c403dbd2b35bbf7c56e 100644 (file)
@@ -8,8 +8,8 @@
  */\r
 \r
 #include "base/rebase.hpp"\r
-#include "os/reos.hpp"\r
 #include "math/remath.hpp"\r
+#include "os/reos.hpp"\r
 \r
 enum LOCATION_DIRTOOL {\r
        LC_COPY_FILE_1 = LC_DIRTOOLS + 1, // 50101\r
@@ -24,6 +24,16 @@ enum LOCATION_DIRTOOL {
        LC_SET_PROPERTIES_2,    // 50110\r
        LC_SET_PROPERTIES_3,    // 50111\r
        LC_TOUCH_1,                             // 50112\r
+       LC_CALCULATE_CHECKSUM_1,        // 50113\r
+       LC_BUILD_DIRECTORY_1,           // 50114\r
+       LC_COMPARE_STORAGE_1,           // 50115\r
+       LC_COMPARE_STORAGE_2,           // 50116\r
+       LC_COMPARE_STORAGE_3,           // 50117\r
+       LC_COMPARE_STORAGE_4,           // 50118\r
+       LC_COMPARE_STORAGE_5,           // 50119\r
+       LC_COMPARE_STORAGE_6,           // 50120\r
+       LC_COMPARE_STORAGE_7,           // 50121\r
+       LC_COMPARE_DIR_1,                       // 50122\r
 };\r
 const char* ReDirTools::m_version = "2015.02.25";\r
 ReLogger* ReDirTools::m_logger = NULL;\r
@@ -32,9 +42,10 @@ static const char* s_helpSummary[] = { "dirtool or dt <command> <opts>",
     "   Useful commands around directory trees.",\r
     "   Type 'dirtool help <command>' for more help.", "<command>:",\r
     "batch         produce output to handle the found files with a script",\r
+    "checksum      shows the checksum (MD5 or other) of the selected files",\r
+    "delete        delete the selected files",\r
     "help          shows info about the arguments/options",\r
     "list          shows the meta data of the selected files",\r
-    "md5           shows the MD5 checksum of the selected files",\r
     "statistic     shows statistics about a direcctory tree",\r
     "synchronize   copies only modified or new files from",\r
     "              from a source directory tre to a target",\r
@@ -64,12 +75,15 @@ const char* s_listExamples[] =
         "dirtool li --type=f -y7d --size=10M -p;*.cpp;*.hpp;Makefile*;-*~ /home/data",\r
         NULL };\r
 \r
-const char* s_md5Usage[] = {\r
-    "<command>: m(d5) [<opts>] <dir_or_file1> [<dir_or_file2> ...]",\r
-    "   shows the MD5 check sum of the given files",\r
+const char* s_checksumUsage[] = {\r
+    "<command>: c(hecksum) [<opts>] <dir_or_file1> [<dir_or_file2> ...]",\r
+    "   shows a check sum of the given files or manages a checksum storage file in each directory for observing",\r
     NULL };\r
-const char* s_md5Examples[] = { "dirtool md5 --buffer-size=512 e:\\data",\r
-    "dirtool m --type=f --size=10M -p;*.iso /home/iso /down/debian.iso",\r
+const char* s_checksumExamples[] = { "dirtool ch --buffer-size=512 e:\\data",\r
+    "dirtool check -cList -p;*.iso /home/iso /down/debian.iso",\r
+    "dirtool checksum -cBuild -aMD5 /home",\r
+    "dirtool checksum --command=Compare /home",\r
+    "dirtool checksum -cUpdate -O/var/log/checksum.log /home",\r
     NULL };\r
 \r
 static const char* s_statisticUsage[] =\r
@@ -521,7 +535,7 @@ void ReDirOptions::checkStandardFilterOptions() {
        if (m_programArgs.getString("verbose", buffer)[0] != '\0') {\r
                unsigned level = V_NORMAL;\r
                if (ReStringUtils::lengthOfUnsigned(buffer.str(), -1, &level)\r
-                   != buffer.length())\r
+                   != (int) buffer.length())\r
                        help(i18n("verbose level is not a number (or '')"), buffer.str());\r
                else\r
                        m_verboseLevel = VerboseLevel(level);\r
@@ -1062,6 +1076,334 @@ void ReDirBatch::processFile(ReDirStatus_t* entry) {
        fprintf(m_output, "%s\n", line.str());\r
 }\r
 \r
+/**\r
+ * Constructor.\r
+ *\r
+ * @param logger       logger for error handling\r
+ */\r
+ReDirChecksum::ReDirChecksum(ReLogger* logger) :\r
+           ReTool(s_checksumUsage, s_checksumExamples, 0, 0, 0, true, logger),\r
+           m_command(CMD_LIST),\r
+           m_digest(NULL),\r
+           m_buffer() {\r
+       // standard short options: D d O o P p T t v y Z z\r
+       m_programArgs.addString("algorithm",\r
+               i18n("algorithm: 'MD5' or 'RPD64'"), 'a', "--algorithm", false, "MD5");\r
+       m_programArgs.addInt("buffersize",\r
+           i18n("buffer size for file reading (in KiByte)"), 'b', "--buffer-size",\r
+           4 * 1024);\r
+       m_programArgs.addString("command",\r
+               i18n("'build': builds in each directory a file '.dt.chksum' with sum and name\n"\r
+                       "'compare': shows differences between the content of '.dt.chksum' and the current files\n"\r
+                       "'list': shows checksum and filename\n"\r
+                       "'update': like compare, but update the content of '.dt.chksum'"),\r
+               'c', "--command", false, "list");\r
+       m_programArgs.addInt("salt",\r
+           i18n("a number which change the checksum"), 's', "--salt", 0);\r
+       addStandardFilterOptions();\r
+}\r
+\r
+/**\r
+ * Destructor.\r
+ */\r
+ReDirChecksum::~ReDirChecksum(){\r
+       delete m_digest;\r
+       m_digest = NULL;\r
+}\r
+/**\r
+ * Builds a checksum storage for a given directory.\r
+ *\r
+ * @param path the directory to process\r
+ */\r
+void ReDirChecksum::buildStorage(const char* path, const char* storageFile){\r
+       ReTraverser traverser(path);\r
+       traverser.setMaxLevel(0);\r
+       ReDirStatus_t* entry;\r
+       ReRPD64 digest2;\r
+       digest2.setSalt(0x2004199111121989ll);\r
+       ReByteBuffer line;\r
+       FILE* fp = fopen(storageFile, "w");\r
+       if (fp == NULL){\r
+               m_logger->sayF(LOG_ERROR | CAT_FILE, LC_BUILD_DIRECTORY_1,\r
+                   i18n("cannot open file: $1 (errno: $2)")).arg(storageFile).arg(\r
+                   errno).end();\r
+\r
+       } else {\r
+               int level;\r
+               while ((entry = traverser.nextFile(level, &m_filter)) != NULL) {\r
+                       line.setLength(0);\r
+                       if (!entry->isDirectory()){\r
+                               calculateChecksum(entry->fullName(), *m_digest, m_buffer,\r
+                                       m_logger);\r
+                               line.append(m_digest->hexDigest());\r
+                       }\r
+                       line.appendChar('\t').append(entry->node());\r
+                       digest2.update(line);\r
+                       fprintf(fp, "%s\n", line.str());\r
+                       if (m_verboseLevel >= V_NORMAL)\r
+                               fprintf(m_output, "%16s\t\%s",\r
+                                       entry->isDirectory() ? "" : m_digest->hexDigest().str(),\r
+                                       entry->fullName());\r
+               }\r
+               fprintf(fp, "%s\n", digest2.hexDigest().str());\r
+               fclose(fp);\r
+       }\r
+}\r
+\r
+/**\r
+ * Compares the files of a directory with the files in the storage file\r
+ *\r
+ * @param path                 the directory\r
+ * @param storageFile  the file with the checksums\r
+ */\r
+void ReDirChecksum::compareDir(const char* path, ReStringList& names,\r
+               const char* storageFile){\r
+       // forget the last line (checksum):\r
+       int count = names.count() - 1;\r
+       names.remove(count - 1);\r
+       for (int ii = 0; ii < count; ii++){\r
+               const char* name = names.strOf(ii);\r
+               const char* ptr = strchr(name, '\t');\r
+               if (ptr != NULL)\r
+                       names.replaceString(ii, ptr + 1);\r
+       }\r
+       names.sort();\r
+       names.setSorted(true);\r
+       ReTraverser traverser(path);\r
+       traverser.setMaxLevel(0);\r
+       ReDirStatus_t* entry;\r
+       int level;\r
+       while ((entry = traverser.nextFile(level, &m_filter)) != NULL) {\r
+               ReSeqArray::Index index;\r
+               const char* node = entry->node();\r
+               // the stringlist stores the string with trailing '\0'\r
+               if (! names.binarySearch(node, strlen(node) + 1, index)){\r
+                       m_logger->sayF(LOG_ERROR | CAT_SECURITY, LC_COMPARE_DIR_1,\r
+                       i18n("missing file $1 in storage $2")).arg(entry->fullName())\r
+                       .arg(storageFile).end();\r
+               }\r
+       }\r
+}\r
+\r
+/**\r
+ * Compares a storage file with the files of a directory.\r
+ *\r
+ * @param path                 the directory\r
+ * @param storageFile  the file with the checksums\r
+ */\r
+void ReDirChecksum::compareStorage(const char* path, const char* storageFile){\r
+       ReStringList storage;\r
+       storage.readFromFile(storageFile);\r
+       if (storage.count() <= 0){\r
+               m_logger->sayF(LOG_ERROR | CAT_SECURITY, LC_COMPARE_STORAGE_1,\r
+                       i18n("empty storage file: $1")).arg(storageFile).end();\r
+       } else if (! isValid(storage)){\r
+               m_logger->sayF(LOG_ERROR | CAT_SECURITY, LC_COMPARE_STORAGE_2,\r
+                       i18n("corrupted storage file: $1")).arg(storageFile).end();\r
+       } else {\r
+               ReStringList cols;\r
+               ReByteBuffer fullname(path);\r
+               fullname.ensureLastChar(OS_SEPARATOR_CHAR);\r
+               int pathLength = fullname.length();\r
+               struct stat info;\r
+               // test all files of the storage:\r
+               for (size_t ii = 0; ii < storage.count() - 1; ii++){\r
+                       cols.split(storage.strOf(ii), '\t');\r
+                       int colCount = cols.count();\r
+                       if (colCount != 2){\r
+                               m_logger->sayF(LOG_ERROR | CAT_SECURITY, LC_COMPARE_STORAGE_3,\r
+                                                       i18n("wrong format ($1) in storage file $2-$3"))\r
+                                                       .arg(colCount).arg(storageFile).arg(ii+1).end();\r
+                               break;\r
+                       } else {\r
+                               fullname.setLength(pathLength).append(cols.strOf(1));\r
+                               if (cols.strLengthOf(0) == 0){\r
+                                       // a directory:\r
+                                       if (stat(fullname.str(), &info) != 0){\r
+                                               m_logger->sayF(LOG_ERROR | CAT_SECURITY,\r
+                                                       LC_COMPARE_STORAGE_4,\r
+                                                       i18n("missing directory $1 ($2-$3)"))\r
+                                                               .arg(fullname).arg(storageFile).arg(ii+1).end();\r
+                                       } else if (! S_ISDIR(info.st_mode)){\r
+                                               m_logger->sayF(LOG_ERROR | CAT_SECURITY,\r
+                                                       LC_COMPARE_STORAGE_5,\r
+                                                       i18n("directory is now a file: $1 ($2-$3)"))\r
+                                                       .arg(fullname).arg(storageFile).arg(ii+1).end();\r
+                                       }\r
+                               } else {\r
+                                       // a directory:\r
+                                       if (stat(fullname.str(), &info) != 0){\r
+                                               m_logger->sayF(LOG_ERROR | CAT_SECURITY,\r
+                                                       LC_COMPARE_STORAGE_6,\r
+                                                       i18n("missing file $1 ($2-$3)"))\r
+                                                               .arg(fullname).arg(storageFile).arg(ii+1).end();\r
+                                       } else if (S_ISDIR(info.st_mode)){\r
+                                               m_logger->sayF(LOG_ERROR | CAT_SECURITY,\r
+                                                       LC_COMPARE_STORAGE_7,\r
+                                                       i18n("file is now a directory: $1 ($2-$3)"))\r
+                                                       .arg(fullname).arg(storageFile).arg(ii+1).end();\r
+                                       } else {\r
+                                               calculateChecksum(fullname.str(), *m_digest, m_buffer,\r
+                                                       m_logger);\r
+                                               if (! m_digest->hexDigest().equals(cols.strOf(0))){\r
+                                                       m_logger->sayF(LOG_ERROR | CAT_SECURITY,\r
+                                                               LC_COMPARE_STORAGE_7,\r
+                                                               i18n("checksum different: $1 ($2-$3)"))\r
+                                                               .arg(fullname).arg(storageFile).arg(ii+1).end();\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               compareDir(path, storage, storageFile);\r
+       }\r
+}\r
+/**\r
+ * Checks the validity of a storage file.\r
+ *\r
+ * The storage file is protected with a checksum.\r
+ * The checksum has another salt as the checksums of the files. This makes it\r
+ * much harder to manipulate the storage file.\r
+ *\r
+ * @param storage      the storage file as string list.\r
+ */\r
+bool ReDirChecksum::isValid(const ReStringList& storage){\r
+       int count = storage.count();\r
+       ReRPD64 digest2;\r
+       digest2.setSalt(0x2004199111121989ll);\r
+\r
+       for (int ii = 0; ii < count - 1; ii++){\r
+               const char* line = storage.strOf(ii);\r
+               digest2.update(line);\r
+       }\r
+       bool rc = true;\r
+       const char* hex = storage.strOf(count - 1);\r
+       if (! digest2.hexDigest().equals(hex))\r
+               rc = false;\r
+       return rc;\r
+}\r
+/**\r
+ * Lists the metadata of the specified files.\r
+ */\r
+void ReDirChecksum::doIt() {\r
+       int size = m_programArgs.getInt("buffersize") * 1024;\r
+       m_buffer.setLength(size);\r
+       ReByteBuffer value;\r
+       m_programArgs.getString("command", value);\r
+       if (value.equals("list", -1, true))\r
+               m_command = CMD_LIST;\r
+       else if (value.equals("build", -1, true))\r
+               m_command = CMD_BUILD;\r
+       else if (value.equals("compare", -1, true))\r
+               m_command = CMD_COMPARE;\r
+       else if (value.equals("update", -1, true))\r
+               m_command = CMD_UPDATE;\r
+       else\r
+               help(i18n("unknown command (expected: build compare list update): "),\r
+                       value.str());\r
+\r
+       m_programArgs.getString("algorithm", value);\r
+       if (value.equals("md5", -1, true))\r
+               m_digest = new ReMD5();\r
+       else if (value.equals("rpd64", -1, true))\r
+               m_digest = new ReRPD64();\r
+       else\r
+               help(i18n("unknown algorithm (expected: MD5 RPD64): "),\r
+                       value.str());\r
+       int salt = m_programArgs.getInt("salt");\r
+       if (salt != 0)\r
+               m_digest->setSalt(salt);\r
+       m_filter.m_allDirectories = true;\r
+       processFileArguments();\r
+       printSummary();\r
+}\r
+\r
+/**\r
+ * Processes one directory.\r
+ *\r
+ * @param entry        the properties of the directory to process\r
+ */\r
+void ReDirChecksum::processDir(ReDirStatus_t* entry) {\r
+       ReByteBuffer storageFile;\r
+       if (m_command != CMD_LIST) {\r
+               storageFile.append(entry->fullName());\r
+               storageFile.ensureLastChar(OS_SEPARATOR_CHAR);\r
+               storageFile.append(".dt.chksum");\r
+       }\r
+       switch(m_command){\r
+       case CMD_BUILD:\r
+               buildStorage(entry->fullName(), storageFile.str());\r
+               break;\r
+       case CMD_COMPARE:\r
+               compareStorage(entry->fullName(), storageFile.str());\r
+               break;\r
+       case CMD_UPDATE:\r
+               printf("update not implemented");\r
+               break;\r
+       default:\r
+               break;\r
+       }\r
+}\r
+/**\r
+ * Processes one file.\r
+ *\r
+ * @param entry        the properties of the file to process\r
+ */\r
+void ReDirChecksum::processFile(ReDirStatus_t* entry) {\r
+       const char* name = entry->fullName();\r
+       switch(m_command){\r
+       case CMD_LIST:\r
+               calculateChecksum(name, *m_digest, m_buffer, m_logger);\r
+               fprintf(m_output, "%s %s\n", m_digest->hexDigest().str(), name);\r
+               break;\r
+       default:\r
+               break;\r
+       }\r
+}\r
+/**\r
+ * Compares a storage file with the files of a directory.\r
+ *\r
+ * @param path                 the directory\r
+ * @param storageFile  the file with the checksums\r
+ */\r
+void ReDirChecksum::updateStorage(const char* path, const char* storageFile){\r
+\r
+}\r
+\r
+/**\r
+ * Calculates the checksum of a given file.\r
+ *\r
+ * @param name         the full filename\r
+ * @param digest       IN: defines the kind of checksum<br>\r
+ *                                     OUT: contains the calculated checksum\r
+ * @param buffer       IN/OUT: a buffer for file reading\r
+ * @param logger       logger for error processing\r
+ * @return                     <code>digest</code> (for chaining)\r
+ */\r
+ReDigest& ReDirChecksum::calculateChecksum(const char* name,\r
+               ReDigest& digest, ReByteBuffer& buffer, ReLogger* logger){\r
+       FILE* fp = fopen(name, "rb");\r
+       if (fp == NULL) {\r
+               if (logger != NULL)\r
+                       logger->sayF(LOG_ERROR | CAT_FILE, LC_CALCULATE_CHECKSUM_1,\r
+                           i18n("cannot open file: $1 (errno: $2)")).arg(name).arg(\r
+                           errno).end();\r
+       } else {\r
+               ReMD5 digest;\r
+               size_t readBytes;\r
+               uint8_t* buf = reinterpret_cast<uint8_t*>(buffer.buffer());\r
+               size_t blockSize = buffer.length();\r
+\r
+               while ((readBytes = fread(buf, 1, blockSize, fp)) > 0) {\r
+                       digest.update(buf, readBytes);\r
+               }\r
+               fclose(fp);\r
+       }\r
+       return digest;\r
+}\r
+\r
+\r
+\r
 /**\r
  * Constructor.\r
  *\r
@@ -1126,60 +1468,6 @@ void ReDirList::processFile(ReDirStatus_t* entry) {
        }\r
 }\r
 \r
-/**\r
- * Constructor.\r
- *\r
- * @param logger       logger for error handling\r
- */\r
-ReDirMD5::ReDirMD5(ReLogger* logger) :\r
-           ReTool(s_md5Usage, s_md5Examples, 0, 0, 0, true, logger),\r
-           m_buffer() {\r
-       // standard short options: D d O o P p T t v y Z z\r
-       m_programArgs.addInt("buffersize",\r
-           i18n("buffer size for file reading (in KiByte)"), 'b', "--buffer-size",\r
-           4 * 1024);\r
-       addStandardFilterOptions();\r
-}\r
-\r
-/**\r
- * Lists the metadata of the specified files.\r
- */\r
-void ReDirMD5::doIt() {\r
-       int size = m_programArgs.getInt("buffersize") * 1024;\r
-       m_buffer.setLength(size);\r
-       processFileArguments();\r
-       printSummary();\r
-}\r
-\r
-/**\r
- * Processes one directory.\r
- *\r
- * @param entry        the properties of the directory to process\r
- */\r
-void ReDirMD5::processDir(ReDirStatus_t* entry) {\r
-}\r
-/**\r
- * Processes one file.\r
- *\r
- * @param entry        the properties of the file to process\r
- */\r
-void ReDirMD5::processFile(ReDirStatus_t* entry) {\r
-       const char* name = entry->fullName();\r
-       FILE* fp = fopen(name, "rb");\r
-       if (fp != NULL) {\r
-               ReMD5 digest;\r
-               size_t readBytes;\r
-               uint8_t* buffer = reinterpret_cast<uint8_t*>(m_buffer.buffer());\r
-               size_t blockSize = m_buffer.length();\r
-\r
-               while ((readBytes = fread(buffer, 1, blockSize, fp)) > 0) {\r
-                       digest.update(buffer, readBytes);\r
-               }\r
-               fclose(fp);\r
-               fprintf(m_output, "%s %s\n", digest.hexDigest().str(), name);\r
-       }\r
-}\r
-\r
 /**\r
  * Calculates the statistic of a directory tree.\r
  *\r
@@ -1475,7 +1763,10 @@ void ReDirTouch::processFile(ReDirStatus_t* entry) {
                                ReDirStatus_t::filetimeToString(\r
                                    filetimeIsUndefined(m_modified) ? &m_accessed : &m_modified,\r
                                    bufferTime);\r
-                               fprintf(m_output, "%s -> %s %s\n", bufferTime.str(), name);\r
+                               fprintf(m_output, "%s -> %s %s\n",\r
+                                       ReDirStatus_t::filetimeToString(entry->modified(),\r
+                                               bufferTime2),\r
+                               bufferTime.str(), (char*) name);\r
                        }\r
                }\r
        }\r
@@ -1882,9 +2173,7 @@ void ReDirSync::doIt() {
                                    m_statInfo.st_mtime\r
                                        - entry->filetimeToTime(entry->modified()));\r
                                if (!ignoreDate\r
-                                   && m_statInfo.st_mtime\r
-                                       - entry->filetimeToTime(entry->modified())\r
-                                       <= maxFileTimeDiff) {\r
+                                       && diff <= maxFileTimeDiff) {\r
                                        if (m_verboseLevel >= V_CHATTER)\r
                                                fprintf(m_output, "=ignored: %s same time\n",\r
                                                    targetRelativePath);\r
@@ -2018,14 +2307,14 @@ void ReDirTools::help(int argc, const char* argv[]) {
                if (isArg("batch", arg0)) {\r
                        ReDirBatch batch(m_logger);\r
                        batch.help(NULL);\r
+               } else if (isArg("checksum", arg0)) {\r
+                       ReDirChecksum sum(m_logger);\r
+                       sum.help(NULL);\r
                } else if (isArg("list", arg0)) {\r
                        ReDirList list(m_logger);\r
                        list.help(NULL);\r
                } else if (isArg("help", arg0)) {\r
                        printField(s_helpSummary);\r
-               } else if (isArg("md5", arg0)) {\r
-                       ReDirMD5 md5(m_logger);\r
-                       md5.help(NULL);\r
                } else if (isArg("statistic", arg0)) {\r
                        ReDirStatistic stat(m_logger);\r
                        stat.help(NULL);\r
@@ -2061,6 +2350,11 @@ void ReDirTools::run(int argc, const char* argv[], ReTool& tool) {
  */\r
 int ReDirTools::main(int argc, char* orgArgv[]) {\r
        ReDirTools tools;\r
+       if (argc < 0){\r
+               argc = 0;\r
+               for (int ix = 0; orgArgv[ix] != NULL; ix++)\r
+                       argc++;\r
+       }\r
        const char** argv = (const char**) orgArgv;\r
        if (argc < 2) {\r
                tools.help(0, argv);\r
@@ -2072,12 +2366,12 @@ int ReDirTools::main(int argc, char* orgArgv[]) {
        const char* arg0 = argv[0];\r
        if (isArg("batch", arg0))\r
                ReDirBatch(m_logger).run(argc, argv);\r
+       else if (isArg("checksum", arg0))\r
+               ReDirChecksum(m_logger).run(argc, argv);\r
        else if (isArg("help", arg0))\r
                tools.help(argc, argv);\r
        else if (isArg("list", arg0))\r
                ReDirList(m_logger).run(argc, argv);\r
-       else if (isArg("md5", arg0))\r
-               ReDirMD5(m_logger).run(argc, argv);\r
        else if (isArg("statistic", arg0))\r
                ReDirStatistic(m_logger).run(argc, argv);\r
        else if (isArg("synchronize", arg0))\r
index 9e7cfe804299e07c84dab0972a0e467299f4032a..3777e5cfe0a6dc2b09f6bbd129f982d5ce36096e 100644 (file)
@@ -162,18 +162,42 @@ protected:
        bool m_numerical;
 
 };
-
+class ReDigest;
 /**
- * Calculates the MD5 checksum of files.
+ * Calculates / compares the checksum of files.
+ *
+ * MD5 or a RPD64 (similar to MD5, but calculated in 64 bit) can be used
+ * as algorithms.
  */
-class ReDirMD5: public ReTool {
+class ReDirChecksum: public ReTool {
+public:
+       enum Command {
+               CMD_UNDEF,
+               CMD_BUILD,
+               CMD_COMPARE,
+               CMD_LIST,
+               CMD_UPDATE
+       };
 public:
-       ReDirMD5(ReLogger* logger);
+       ReDirChecksum(ReLogger* logger);
+       ~ReDirChecksum();
 protected:
        virtual void doIt();
        virtual void processDir(ReDirStatus_t* entry);
        virtual void processFile(ReDirStatus_t* entry);
+private:
+       void buildStorage(const char* path, const char* storageFile);
+       void compareDir(const char* path, ReStringList& names,
+               const char* storageFile);
+       void compareStorage(const char* path, const char* storageFile);
+       bool isValid(const ReStringList& storage);
+       void updateStorage(const char* path, const char* storageFile);
+public:
+       static ReDigest& calculateChecksum(const char* name,
+               ReDigest& digest, ReByteBuffer& buffer, ReLogger* logger);
 protected:
+       Command m_command;
+       ReDigest* m_digest;
        ReByteBuffer m_buffer;
 };
 
index 344da80c499b5208be81c159b40a7f19d1aa7bd4..ada7afa3c2cafc166561ca4da550fb11967c7197 100644 (file)
@@ -578,7 +578,8 @@ ReDirEntryFilter_t::ReDirEntryFilter_t() :
            //m_minAge(0),\r
            //m_maxAge(0),\r
            m_minDepth(0),\r
-           m_maxDepth(512) {\r
+           m_maxDepth(512),\r
+           m_allDirectories(false){\r
        setFiletimeUndef(m_minAge);\r
        setFiletimeUndef(m_maxAge);\r
 }\r
@@ -594,6 +595,10 @@ ReDirEntryFilter_t::~ReDirEntryFilter_t() {
 bool ReDirEntryFilter_t::match(ReDirStatus_t& entry) {\r
        bool rc = false;\r
        do {\r
+               if (m_allDirectories && entry.isDirectory()){\r
+                       rc = true;\r
+                       break;\r
+               }\r
                if (0 == (entry.type() & m_types))\r
                        break;\r
                int64_t size = entry.fileSize();\r
@@ -691,7 +696,7 @@ ReTraceUnit::~ReTraceUnit() {
  * @return                     <code>true</code> (for chaining)\r
  */\r
 bool ReTraceUnit::trace(const char* message) {\r
-       printf("%d\n", message);\r
+       printf("%s\n", message);\r
        return true;\r
 }\r
 \r
index 75ddb62d7cccefbf6c4dbcaa4fe36af1bcebce57..d97add56ce655473a8d18977e8371d41915c9547 100644 (file)
@@ -122,6 +122,7 @@ public:
        ReFileTime_t m_maxAge;
        int m_minDepth;
        int m_maxDepth;
+       bool m_allDirectories;
 };
 class ReTraceUnit {
 public:
index 68f63c796400920241da1484cda47c32e234cc0f..ccc7b8a2566e54365a5276b2fa111fbfb1bf100f 100644 (file)
  */
 inline bool operator >(const ReFileTime_t& time1, const ReFileTime_t& time2) {
 #if defined __linux__
-       return time1.tv_sec > time2.tv_sec || time1.tv_sec == time2.tv_sec && time1.tv_nsec > time2.tv_nsec;
+       return time1.tv_sec > time2.tv_sec
+               || (time1.tv_sec == time2.tv_sec && time1.tv_nsec > time2.tv_nsec);
 #else
        return time1.dwHighDateTime > time2.dwHighDateTime
-           || time1.dwHighDateTime == time2.dwHighDateTime
-               && time1.dwLowDateTime > time2.dwLowDateTime;
+           || (time1.dwHighDateTime == time2.dwHighDateTime
+               && time1.dwLowDateTime > time2.dwLowDateTime);
 #endif
 }
 #include "os/ReTraverser.hpp"