]> gitweb.hamatoma.de Git - crepublib/commitdiff
Refactoring: ReFileTime_t, touch
authorhama <hama@siduction.net>
Fri, 20 Feb 2015 22:37:44 +0000 (23:37 +0100)
committerhama <hama@siduction.net>
Fri, 20 Feb 2015 22:37:44 +0000 (23:37 +0100)
base/ReProgramArgs.cpp
base/rebase.hpp
cunit/cuReDirTools.cpp
cunit/cuReMD5.cpp
cunit/cuReTraverser.cpp
os/ReDirTools.cpp
os/ReDirTools.hpp
os/ReTraverser.cpp
os/ReTraverser.hpp
os/reos.hpp

index 1ef93f9a18c7d70f9a60d8be77baec4c57b113b9..701a742375898b4601a98e97cc317e9db6084a79 100644 (file)
@@ -27,8 +27,7 @@ ReOptionException::ReOptionException(ReProgramArgs* caller, const char* message,
 {
        ReVarArgs args(message);
     if (strchr(message, '$') == NULL)
-        throw ReFormatException(i18n("Missing placeholder: "),
-                                       message); 
+        throw ReFormatException(i18n("Missing placeholder: "), message);
        args.arg(arg1);
        if (arg2 != NULL)
                args.arg(arg2);
index 221c98b3a860ced206d766bb1fe55c9fa33add88..d22d67b13003d0eeecad5d504ac77c6f540992dc 100644 (file)
@@ -14,6 +14,7 @@
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/time.h>
 #include <time.h>
 #include <errno.h>
 #include <ctype.h>
 #      include <unistd.h>
 #      include <inttypes.h>
 #      include <fcntl.h>
-typedef u_int64_t uint64_t;
-typedef u_int8_t uint8_t;
+       typedef u_int64_t uint64_t;
+       typedef u_int8_t uint8_t;
+       typedef __off_t ReFileSize_t;
+       typedef timespec ReFileTime_t;
 #      define _strdup strdup
 #      define _unlink unlink
 #      define _strnicmp(s1, s2, n) strncasecmp(s1, s2, n)
@@ -53,6 +56,8 @@ typedef u_int8_t uint8_t;
     typedef unsigned char uint8_t;
     typedef unsigned long uint32_t;
     typedef long int int32_t;
+       typedef int64_t ReFileSize_t;
+       typedef FILETIME ReFileTime_t;
 #      define S_ISDIR(mode) (((mode) & _S_IFDIR) != 0)
 #      define ALLPERMS 0
 #      define _mkdir(name, mode) _mkdir(name)
@@ -75,6 +80,6 @@ typedef u_int8_t uint8_t;
 #include "base/ReProgramArgs.hpp"
 
 typedef unsigned char byte_t;
-
+typedef int ReErrNo_t;
 #include "../base/baselocations.hpp"
 #endif /* REBASE_HPP_ */
index 68102414aac472ccd33be438d45234a9aae72303..578c22301d74d22ffc7b33e204407ab5f8afd0fb 100644 (file)
@@ -61,6 +61,7 @@ private:
        void run(){
                initTree();
 
+        testTouch();
                testDirStatistic();
 
                testToolStatistic();
@@ -76,6 +77,9 @@ private:
         const char* argv[] = { "list", m_base.str(), NULL };
         ReDirList().run(2, argv);
     }
+       int secOfFileTime(ReFileTime_t data){
+               return data.tv_sec;
+       }
     void testCopyFile(){
 #if defined __linux__
         ReByteBuffer src(m_base);
@@ -92,13 +96,12 @@ private:
 #endif
     }
 
-    void checkRelDate(time_t absTime, int relTime){
-        int diff = int(time(NULL) - relTime - absTime);
+    void checkRelDate(ReFileTime_t absTime, int relTime){
+        int diff = int(time(NULL) - relTime - secOfFileTime(absTime));
         if (diff < 0)
             diff = - diff;
         checkT(diff < 2);
     }
-
     void testDirOptions(){
         class MyOptions : public ReDirOptions{
         public:
@@ -122,9 +125,10 @@ private:
 
         // local time: +3600
         const int DIFF = 3600;
-        checkEqu(24*60*60 - DIFF, (int) opts.checkDate("1970.01.02"));
-        checkEqu(24*60*60+3600-DIFF, (int) opts.checkDate("1970.01.02/1"));
-        checkEqu(24*60*60 + 2*3600 + 33*60 - DIFF, (int) opts.checkDate("1970.01.02/02:33"));
+               const int tenYear = (365 * 10 + 2) * 24 * 3600;
+        checkEqu(tenYear + 24*60*60 - DIFF, secOfFileTime(opts.checkDate("1980.01.02")));
+        checkEqu(tenYear + 24*60*60+3600-DIFF, secOfFileTime(opts.checkDate("1980.01.02/1")));
+        checkEqu(tenYear + 24*60*60 + 2*3600 + 33*60 - DIFF, secOfFileTime(opts.checkDate("1980.01.02/02:33")));
         checkRelDate(opts.checkDate("3m"), 3*60);
         checkRelDate(opts.checkDate("7h"), 7*60*60);
         checkRelDate(opts.checkDate("5d"), 5*24*60*60);
@@ -142,7 +146,7 @@ private:
     void checkSetFilterFromProgramArgs(){
         ReDirOptions opts(s_empty, s_empty);
         opts.addStandardFilterOptions();
-        const char* argv[] = { "x", "-y1970.01.02", "-o1970.01.03",
+        const char* argv[] = { "x", "-y1980.01.02", "-o1980.01.03",
             "-D5", "-d1", "-z1k", "-Z2M", "-p;*;-*~"
         };
         ReDirEntryFilter_t filter;
@@ -150,8 +154,8 @@ private:
         opts.setFilterFromProgramArgs(filter);
         // local time: +3600
         const int DIFF = 3600;
-        checkEqu(1*24*3600 - DIFF, (int) filter.m_maxAge);
-        checkEqu(2*24*3600 - DIFF, (int) filter.m_minAge);
+        checkEqu(1*24*3600 - DIFF, secOfFileTime(filter.m_maxAge));
+        checkEqu(2*24*3600 - DIFF, secOfFileTime(filter.m_minAge));
         checkEqu(5, (int) filter.m_maxDepth);
         checkEqu(1, (int) filter.m_minDepth);
         checkEqu(1000ll, filter.m_minSize);
@@ -227,6 +231,55 @@ private:
         checkT(buffer.startsWith("      0.000087 MB       5       6\t"));
         expected.set(m_base.str(), m_base.length());
     }
+    /**
+        * Tests a file with a given context.
+        *
+        * @param filename      name of the file to test
+        * @param content       expected content: each line must contain a '*',
+        *                                      separating the start of line and the end of line
+        */
+    void checkFile(ReByteBuffer& filename, const char* content){
+               ReStringList current;
+               current.readFromFile(filename.str());
+               ReStringList expected;
+               expected.split(content, '\n');
+               checkEqu(expected.count(), current.count());
+               ReByteBuffer line;
+               ReStringList cols;
+               for (int ix = 0; ix < current.count(); ix++){
+                       line.setLength(0).append(current.strOf(ix), -1);
+                       cols.split(expected.strOf(ix), '*');
+                       checkT(line.startsWith(cols.strOf(0)));
+                       checkT(line.endsWith(cols.strOf(1)));
+               }
+    }
+    void testTouch(){
+               ReByteBuffer nameCurrent;
+               buildFilename("current", nameCurrent);
+               ReByteBuffer optOutput("--output-file=");
+               optOutput.append(nameCurrent);
+               ReDirTools tools;
+               const char* argv[] = { "dt", "touch", "-P;*;-cache", "-tr", "-p;*.txt",
+                       "-m2015.03.28/10:21:31", optOutput.str(), m_base.str(), NULL };
+               tools.main(8, (char**) argv);
+
+               checkFile(nameCurrent,
+                       "2015.03.28 10:21:31 *traverser/1.txt\n"
+                       "2015.03.28 10:21:31 *traverser/dir1/dir1_2/dir1_2_1/x1.txt\n"
+                       "2015.03.28 10:21:31 *traverser/dir1/dir1_2/dir1_2_1/x2.txt\n"
+                       "===        3 file(s)     0.000059 MByte       0 dirs(s) * sec");
+
+               const char* argv2[] = { "dt", "list", "-P;*;-cache", "-tr", "-p;*.txt",
+                       optOutput.str(), m_base.str(), NULL };
+               tools.main(7, (char**) argv2);
+
+               checkFile(nameCurrent,
+                       "     0.000005 2015.03.28 10:21:31 02 *traverser/1.txt\n"
+                       "     0.000027 2015.03.28 10:21:31 02 *traverser/dir1/dir1_2/dir1_2_1/x1.txt\n"
+                       "     0.000027 2015.03.28 10:21:31 02 *traverser/dir1/dir1_2/dir1_2_1/x2.txt\n"
+                       "===        3 file(s)     0.000059 MByte       0 dirs(s) * sec");
+
+       }
        void testToolStatistic(){
                ReDirTools tools;
                const char* argv[] = { "dt", "stat", "-P;*;-cache", m_base.str(), "2" };
index 9b32c4a70a6dbd1c5281ef41ad548baba307099f..4bd88fc0d8745cdf4e6e885d4a5f8eec6f0373a5 100644 (file)
@@ -116,7 +116,7 @@ private:
                int duration = milliSecSince(start);
                if (duration == 0)
                        duration = 1;
-               printf("size: %.3f MiByte count: %d rate: %.3f MiB/sec duration: %s\n",
+               printf("size: %.1f MiByte count: %d rate: %.2f MiB/sec duration: %s\n",
                        max / 1024.0 / 1024, passes,
                        max / 1024.0 / 1024 * 1000 * passes / duration,
                        ReByteBuffer("").appendMilliSec(duration).str());
index 39b740a7c48e98b82f257094aac77be433ee6a7d..0d21f1fa90accd6d9a42e221e788ee86792c3cae 100644 (file)
@@ -62,8 +62,6 @@ private:
                initTree();
 
                testBasic();
-               testDirOptions();
-               checkSetFilterFromProgramArgs();
         testList();
        }
     void testList(){
@@ -93,66 +91,6 @@ private:
         checkT(diff < 2);
     }
 
-    void testDirOptions(){
-        class MyOptions : public ReDirOptions{
-        public:
-            MyOptions() : ReDirOptions(s_empty, s_empty) {}
-        public:
-            int count() { return m_countCompoundUsage; }
-            const char** usage() { return m_compoundUsage; }
-        };
-        static const char* usage1[] = { "line1", "line2", NULL };
-        static const char* usage2[] = { "x1", "x2", "x3", NULL };
-        MyOptions opts;
-        opts.initCompoundUsage(sizeof usage1 + sizeof usage2);
-        opts.addCompoundUsage(usage1);
-        opts.addCompoundUsage(usage2);
-        checkEqu(7, opts.count());
-        checkEqu("line1", opts.usage()[0]);
-        checkEqu("line2", opts.usage()[1]);
-        checkEqu("x1", opts.usage()[2]);
-        checkEqu("x2", opts.usage()[3]);
-        checkEqu("x3", opts.usage()[4]);
-
-        // local time: +3600
-        const int DIFF = 3600;
-        checkEqu(24*60*60 - DIFF, (int) opts.checkDate("1970.01.02"));
-        checkEqu(24*60*60+3600-DIFF, (int) opts.checkDate("1970.01.02/1"));
-        checkEqu(24*60*60 + 2*3600 + 33*60 - DIFF, (int) opts.checkDate("1970.01.02/02:33"));
-        checkRelDate(opts.checkDate("3m"), 3*60);
-        checkRelDate(opts.checkDate("7h"), 7*60*60);
-        checkRelDate(opts.checkDate("5d"), 5*24*60*60);
-
-        checkEqu(125ll, opts.checkSize("125"));
-        checkEqu(125ll, opts.checkSize("125b"));
-        checkEqu(3000ll, opts.checkSize("3k"));
-        checkEqu(3*1024ll, opts.checkSize("3K"));
-        checkEqu(4*1000*1000ll, opts.checkSize("4m"));
-        checkEqu(4*1024*1024ll, opts.checkSize("4M"));
-        checkEqu(5*1000*1000*1000ll, opts.checkSize("5g"));
-        checkEqu(5*1024*1024*1024ll, opts.checkSize("5G"));
-
-    }
-    void checkSetFilterFromProgramArgs(){
-        ReDirOptions opts(s_empty, s_empty);
-        opts.addStandardFilterOptions();
-        const char* argv[] = { "x", "-y1970.01.02", "-o1970.01.03",
-            "-D5", "-d1", "-z1k", "-Z2M", "-p;*;-*~"
-        };
-        ReDirEntryFilter_t filter;
-        opts.programArgsChangeable().init(sizeof argv / sizeof argv[0], argv);
-        opts.setFilterFromProgramArgs(filter);
-        // local time: +3600
-        const int DIFF = 3600;
-        checkEqu(1*24*3600 - DIFF, (int) filter.m_maxAge);
-        checkEqu(2*24*3600 - DIFF, (int) filter.m_minAge);
-        checkEqu(5, (int) filter.m_maxDepth);
-        checkEqu(1, (int) filter.m_minDepth);
-        checkEqu(1000ll, filter.m_minSize);
-        checkEqu(2*1024*1024ll, filter.m_maxSize);
-        checkNN(filter.m_nodePatterns);
-        checkEqu(";*;-*~", filter.m_nodePatterns->patternString());
-    }
     void checkOneFile(const char* node, const char* parent, const ReHashList& hash){
         ReByteBuffer path, expected;
         checkT(hash.get(ReByteBuffer(node), path));
index ee0252859d4f19343844a958c4d2a39da6e6af89..0544b3bb062d7f3f3b75f2562a49801301d4819b 100644 (file)
@@ -22,6 +22,7 @@ enum LOCATION_DIRTOOL {
        LC_SET_PROPERTIES_1,    // 50109\r
        LC_SET_PROPERTIES_2,    // 50110\r
        LC_SET_PROPERTIES_3,    // 50111\r
+       LC_TOUCH_1,                             // 50112\r
 };\r
 const char* ReDirTools::m_version = "2015.02.04";\r
 \r
@@ -244,9 +245,9 @@ void ReDirOptions::addStandardFilterOptions(){
  * @return          the value converted into the absolute (or relative) time\r
  * @throws          ReOptionExecption\r
  */\r
-time_t ReDirOptions::checkDate(const char* value){\r
+ReFileTime_t ReDirOptions::checkDate(const char* value){\r
     ReByteBuffer theValue(value, -1);\r
-    time_t rc = 0;\r
+       time_t rcTime;\r
     if (theValue.count(".") == 2){\r
         // a date:\r
         int year, month, day;\r
@@ -259,9 +260,9 @@ time_t ReDirOptions::checkDate(const char* value){
                case 5:\r
                case 6:\r
         {\r
-            if (year < 1970)\r
+            if (year < 1980)\r
                 throw ReOptionException(&m_programArgs, \r
-                    i18n("date < 1970.01.01: "), value);\r
+                    i18n("date < 1980.01.01: $1"), value);\r
             struct tm time;\r
             memset(&time, 0, sizeof time);\r
             time.tm_year = year - 1900;\r
@@ -269,12 +270,13 @@ time_t ReDirOptions::checkDate(const char* value){
             time.tm_mday = day;\r
             time.tm_hour = hour;\r
             time.tm_min = minute;\r
-            rc = mktime(&time);\r
+                       time.tm_sec = sec;\r
+            rcTime = mktime(&time);\r
             break;\r
         }\r
         default:\r
             throw ReOptionException(&m_programArgs, \r
-                i18n("invalid date/date-time value. yyyy.mm.dd/hh:MM expected"), value);\r
+                i18n("invalid date/date-time value: $1 yyyy.mm.dd/hh:MM expected"), value);\r
         }\r
        } else if (theValue.count(":") >= 1){\r
         // a time:\r
@@ -286,12 +288,12 @@ time_t ReDirOptions::checkDate(const char* value){
         case 3:\r
         {\r
                        // the time (today)\r
-                       rc = time(NULL) / 86400 * 86400 + hour * 3600 + minute * 60 + sec;\r
+                       rcTime = time(NULL) / 86400 * 86400 + hour * 3600 + minute * 60 + sec;\r
             break;\r
         }\r
         default:\r
             throw ReOptionException(&m_programArgs,\r
-                i18n("invalid time value. HH:MM:SS expected"), value);\r
+                i18n("invalid time value: $1. HH:MM:SS expected"), value);\r
         }\r
     } else {\r
         // a time distance value:\r
@@ -299,7 +301,7 @@ time_t ReDirOptions::checkDate(const char* value){
         int count = 0;\r
                int isNegative = false;\r
                if (theValue.startsWith("now")){\r
-                       rc = time(NULL);\r
+                       rcTime = time(NULL);\r
                        theValue.remove(0, 3);\r
                }\r
                if (theValue.str()[0] == '-')\r
@@ -323,20 +325,22 @@ time_t ReDirOptions::checkDate(const char* value){
                 break;\r
             default:\r
                 throw ReOptionException(&m_programArgs, \r
-                    i18n("invalid unit. expected: s(econds) m(inutes) h(ours) d(ays)"), value);\r
+                    i18n("invalid unit $1. expected: s(econds) m(inutes) h(ours) d(ays)"), value);\r
             }\r
-            rc = time(NULL) - count;\r
+            rcTime = time(NULL) - count;\r
             break;\r
         default:\r
             throw ReOptionException(&m_programArgs, \r
-                i18n("invalid relative time value <number><unit> expected. <unit>: s m h d"),\r
+                i18n("invalid relative time value $1 (<number><unit> expected). <unit>: s m h d"),\r
                 value);\r
         }\r
         if (isNegative)\r
-                       rc -= count;\r
+                       rcTime -= count;\r
                else\r
-                       rc += count;\r
+                       rcTime += count;\r
     }\r
+    ReFileTime_t rc;\r
+       ReDirStatus_t::timeToFiletime(rcTime, rc);\r
     return rc;\r
 }\r
 /**\r
@@ -378,13 +382,13 @@ time_t ReDirOptions::checkSize(const char* value){
             break;\r
         default:\r
              throw ReOptionException(&m_programArgs, \r
-                i18n("invalid <unit>. Expected: b k K m M g G"), \r
+                i18n("invalid <unit>: $1. Expected: b k K m M g G"),\r
                 value);\r
         }\r
         break;\r
     default:\r
         throw ReOptionException(&m_programArgs, \r
-            i18n("invalid size value: <number><unit> <unit>: b k K m M g G"), \r
+            i18n("invalid size value: $1 expected: <number><unit> <unit>: b k K m M g G"),\r
             value);\r
     }\r
     return rc;\r
@@ -663,7 +667,7 @@ bool ReTool::trace(const char* currentFile){
        int duration = int(time(NULL) - m_startTime);\r
        buffer.appendInt(duration / 60).appendInt(duration % 60, ":%02d: ");\r
        buffer.appendInt(m_files).append("/", 1).appendInt(m_traverser.directories()).append(" dir(s)");\r
-       buffer.appendInt(m_files).append("/", 1).appendInt(m_traverser.files()).append(" dir(s)");\r
+       buffer.appendInt(m_files).append("/", 1).appendInt(m_traverser.files()).append(" file(s)");\r
        buffer.append(currentFile);\r
        fputs(buffer.str(), stdout);\r
        return true;\r
@@ -768,10 +772,14 @@ void ReTool::processTree(const char* directory){
        ReDirStatus_t* entry;\r
        int level;\r
        while( (entry = m_traverser.nextFile(level, &m_filter)) != NULL){\r
-               if (entry->isDirectory())\r
+               if (entry->isDirectory()){\r
                        processDir(entry);\r
-               else\r
+                       m_directories++;\r
+               } else {\r
                        processFile(entry);\r
+                       m_files++;\r
+                       m_sizes += entry->fileSize();\r
+               }\r
        }\r
 }\r
 /**\r
@@ -784,6 +792,19 @@ void ReTool::processTree(const char* directory){
 void ReTool::processFile(ReDirStatus_t* entry){\r
        fprintf(m_output, "+++ ignored (not a directory): %s\n", entry->fullName());\r
 }\r
+/**\r
+ * Issues a summary message if verbose level allows this.\r
+ */\r
+void ReTool::printSummary(){\r
+       if (m_verboseLevel >= V_SUMMARY){\r
+               int duration = int(time(NULL) - m_start);\r
+               ReByteBuffer line;\r
+               statisticAsString(line);\r
+               line.append(" ", 1).appendTime(duration).append(" ", 1).append(i18n("sec"));\r
+               fprintf(m_output, "=== %s\n", line.str());\r
+       }\r
+\r
+}\r
 /**\r
  * Processes one directory.\r
  *\r
@@ -968,7 +989,7 @@ void ReDirBatch::doIt(){
 #elif defined __WIN32__\r
                const char* prefix = "rem";\r
 #endif\r
-               toString(buffer);\r
+               statisticAsString(buffer);\r
                buffer.append(" ").appendTime(duration);\r
                fprintf(m_output, "%s %s\n", buffer.str());\r
        }\r
@@ -1030,8 +1051,8 @@ void ReDirList::doIt(){
        if (m_verboseLevel >= V_SUMMARY){\r
                int duration = int(time(NULL) - m_start);\r
                ReByteBuffer line;\r
-               toString(line);\r
-               line.appendTime(duration).append(" ", 1).append(i18n("sec"));\r
+               statisticAsString(line);\r
+               line.append(" ", 1).appendTime(duration).append(" ", 1).append(i18n("sec"));\r
                fprintf(m_output, "=== %s\n", line.str());\r
        }\r
 }\r
@@ -1091,7 +1112,7 @@ const ReStringList& ReDirStatistic::calculate(const char* base, int level,
        current->m_path.set(base, -1);\r
        ReByteBuffer line;\r
        bool useFilter = filter.m_minSize > 0 || filter.m_maxSize != -1\r
-                               || filter.m_minAge != 0 || filter.m_maxAge != 0\r
+                               || ! filetimeIsUndefined(filter.m_minAge) || ! filetimeIsUndefined(filter.m_maxAge)\r
                                || m_nodePatterns.count() > 0;\r
        while( (entry = traverser.rawNextFile(currentDepth))){\r
                if (currentDepth <= level && ! entry->m_path.equals(current->m_path)){\r
@@ -1226,10 +1247,13 @@ void formatWithSizeFilesAndDirs(const ReDirStatisticData& data,
  * Constructor.\r
  */\r
 ReDirTouch::ReDirTouch() :\r
-       ReTool(s_touchUsage, s_touchExamples, 2, 1, 0, false),\r
-       m_buffer(),\r
-       m_properties()\r
+       ReTool(s_touchUsage, s_touchExamples, 1, 0, 0, false),\r
+       m_buffer()\r
+       //m_modified()\r
+       //m_accessed()\r
 {\r
+       setFiletimeUndef(m_modified);\r
+       setFiletimeUndef(m_accessed);\r
        // standard short options: D d O o P p T t v y Z z\r
     m_programArgs.addString("accessed",\r
                i18n("the new access time.\n"\r
@@ -1256,21 +1280,98 @@ void ReDirTouch::doIt(){
                m_modified = checkDate(buffer.str());\r
        if (m_programArgs.getString("accessed", buffer)[0] != '\0')\r
                m_accessed = checkDate(buffer.str());\r
+       if (filetimeIsUndefined(m_modified) && filetimeIsUndefined(m_accessed))\r
+               help("missing --modified and/or --accessed");\r
        processFileArguments();\r
-       if (m_verboseLevel >= V_SUMMARY){\r
-               int duration = int(time(NULL) - m_start);\r
-               ReByteBuffer line;\r
-               toString(line);\r
-               line.appendTime(duration).append(" ", 1).append(i18n("sec"));\r
-               fprintf(m_output, "=== %s\n", line.str());\r
-       }\r
+       printSummary();\r
 }\r
 \r
+/**\r
+ * Processes one directory.\r
+ *\r
+ * @param entry        the properties of the directory to process\r
+ */\r
 void ReDirTouch::processDir(ReDirStatus_t* entry){\r
        processFile(entry);\r
 }\r
-void ReDirTouch::processFile(ReDirStatus_t* entry){\r
 \r
+static bool isAbsoluteTime(ReFileTime_t& time){\r
+       static struct tm year1980 = { 0, 0, 0, 1, 1 - 1, 1980-1900 };\r
+       static time_t time1980 = mktime(&year1980);\r
+#if defined __linux__\r
+       return time.tv_sec >= time1980;\r
+#elif defined __WIN32__\r
+#endif\r
+}\r
+static void addRelativeTime(ReFileTime_t& absTime, const ReFileTime_t& relTime){\r
+#if defined __linux__\r
+       if ( (absTime.tv_nsec += relTime.tv_nsec) >= 1000*1000*1000){\r
+               absTime.tv_nsec -= 1000*1000*1000;\r
+               absTime.tv_sec += 1;\r
+       }\r
+       absTime.tv_sec += relTime.tv_sec;\r
+#elif defined __WIN32__\r
+#endif\r
+\r
+}\r
+/**\r
+ * Processes one file.\r
+ *\r
+ * @param entry        the properties of the file to process\r
+ */\r
+void ReDirTouch::processFile(ReDirStatus_t* entry){\r
+       ReFileTime_t modified = *entry->modified();\r
+       int countTimes = 0;\r
+       if (! filetimeIsUndefined(m_modified)){\r
+               countTimes++;\r
+               if (isAbsoluteTime(m_modified))\r
+                       modified = m_modified;\r
+               else\r
+                       addRelativeTime(modified, m_modified);\r
+       }\r
+       ReFileTime_t accessed = *entry->accessed();\r
+       if (! filetimeIsUndefined(m_accessed)){\r
+               countTimes++;\r
+               if (isAbsoluteTime(m_accessed))\r
+                       accessed = m_accessed;\r
+               else\r
+                       addRelativeTime(accessed, m_accessed);\r
+       }\r
+       const char* name = entry->fullName();\r
+       if (touch(name, modified, accessed, ReLogger::globalLogger()) == 0\r
+                       && m_verboseLevel >= V_NORMAL){\r
+               ReByteBuffer bufferTime;\r
+               ReByteBuffer bufferTime2;\r
+               if (m_verboseLevel == V_NORMAL){\r
+                       if (countTimes == 2)\r
+                               fprintf(m_output, "%s | %s | %s\n",\r
+                                               ReDirStatus_t::filetimeToString(&modified, bufferTime),\r
+                                               ReDirStatus_t::filetimeToString(&accessed, bufferTime2),\r
+                                               name);\r
+                       else {\r
+                               ReDirStatus_t::filetimeToString(\r
+                                       filetimeIsUndefined(m_modified) ? &accessed : &modified,\r
+                                       bufferTime);\r
+                               fprintf(m_output, "%s %s\n", bufferTime.str(), name);\r
+                       }\r
+               } else {\r
+                       ReByteBuffer bufferTime3;\r
+                       ReByteBuffer bufferTime4;\r
+                       if (countTimes == 2)\r
+                               fprintf(m_output, "%s -> %s | %s -> %s | %s\n",\r
+                                               ReDirStatus_t::filetimeToString(entry->modified(), bufferTime),\r
+                                               ReDirStatus_t::filetimeToString(&modified, bufferTime2),\r
+                                               ReDirStatus_t::filetimeToString(entry->accessed(), bufferTime3),\r
+                                               ReDirStatus_t::filetimeToString(&accessed, bufferTime4),\r
+                                               name);\r
+                       else {\r
+                               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
+                       }\r
+               }\r
+       }\r
 }\r
 \r
 /**\r
@@ -1280,8 +1381,34 @@ void ReDirTouch::processFile(ReDirStatus_t* entry){
  * @param properties   contains modification and access time\r
  * @param logger               NULL or the logger\r
  */\r
-bool ReDirTouch::touch(const char* filename, ReFileProperties_t* properties,\r
-               ReLogger* logger){\r
+ReErrNo_t ReDirTouch::touch(const char* filename, const ReFileTime_t& modified,\r
+               const ReFileTime_t& accessed, ReLogger* logger){\r
+#if defined __linux__\r
+       timeval times[2];\r
+       times[0].tv_sec = accessed.tv_sec;\r
+       times[0].tv_usec = accessed.tv_nsec / 1000;\r
+       times[1].tv_sec = modified.tv_sec;\r
+       times[1].tv_usec = modified.tv_nsec / 1000;\r
+       ReErrNo_t rc = utimes(filename, times) == 0 ? 0 : errno;\r
+\r
+#elif defined __WIN32__\r
+       ReErrNo_t rc = 0;\r
+       HANDLE handle = CreateFile(filename, FILE_WRITE_ATTRIBUTES,\r
+               FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,\r
+               FILE_ATTRIBUTE_NORMAL, NULL);\r
+       if (handle == UNDEF_HANDLE)\r
+               rc = GetLastError();\r
+       else {\r
+               if (SetFileTime(handle, (LPFILETIME) NULL,(LPFILETIME) NULL,&thefiletime) != 0)\r
+                       rc = GetLastError();\r
+               CloseHandle(handle);\r
+       }\r
+#endif\r
+       if (rc != 0 && logger != NULL)\r
+               logger->sayF(LOG_ERROR | CAT_FILE, LC_TOUCH_1,\r
+                       i18n("cannot change filetime: $1 (errno: $2)")).arg(filename)\r
+                       .arg(errno).end();\r
+       return rc;\r
 }\r
 \r
 \r
@@ -1413,7 +1540,7 @@ bool ReDirSync::copyFile(const char* source, ReFileProperties_t* properties,
                else {\r
                        if (logger != NULL)\r
                                logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_1,\r
-                                       i18n("could not find: $ (errno: $2)")).arg(source)\r
+                                       i18n("could not find: $1 (errno: $2)")).arg(source)\r
                                                .arg(errno).end();\r
                }\r
        }\r
@@ -1424,7 +1551,7 @@ bool ReDirSync::copyFile(const char* source, ReFileProperties_t* properties,
                                        i18n("cannot open $1 (errno: $2)"))\r
                                .arg(source).arg(errno).end();\r
        } else {\r
-               FileSize_t size = properties == NULL ? 0x7fffffff : properties->st_size;\r
+               ReFileSize_t size = properties == NULL ? 0x7fffffff : properties->st_size;\r
                FILE* fpTarget = fopen(target, "w");\r
                if (fpTarget == NULL){\r
                        if (logger != NULL)\r
@@ -1483,10 +1610,12 @@ bool ReDirSync::setProperties(const char* fullName,
                ReFileProperties_t* properties, ReLogger* logger){\r
        bool rc = true;\r
 #if defined __linux__\r
-       struct utimbuf times;\r
-       times.actime = properties->st_atime;\r
-       times.modtime = properties->st_mtime;\r
-       if (utime(fullName, &times) != 0){\r
+       timeval times[2];\r
+       times[0].tv_sec = properties->st_atim.tv_sec;\r
+       times[0].tv_usec = properties->st_atim.tv_nsec / 1000;\r
+       times[1].tv_sec = properties->st_mtim.tv_sec;\r
+       times[1].tv_usec = properties->st_mtim.tv_nsec / 1000;\r
+       if (utimes(fullName, times) != 0){\r
                if (logger != NULL)\r
                        logger->sayF(LOG_ERROR | CAT_FILE, LC_SET_PROPERTIES_1,\r
                                i18n("cannot change file times: $1 (errno: $2)"))\r
index 87a49cac022548c5cd428f84439c80065471da02..259f415facd45c7a136a1b2f5cccee24b21aa2eb 100644 (file)
@@ -26,7 +26,7 @@ public:
 public:
     void addCompoundUsage(const char** usage);
     void addStandardFilterOptions();
-    time_t checkDate(const char* value);
+    ReFileTime_t checkDate(const char* value);
     const char* checkPatternList(const char* value);
     int64_t checkSize(const char* value);
     void checkStandardFilterOptions();
@@ -89,6 +89,7 @@ protected:
         * Normally it calls <code>processFileArguments()</code> after some initializations.
         */
        virtual void doIt() = 0;
+       void printSummary();
        virtual void processDir(ReDirStatus_t* status);
        virtual void processFile(ReDirStatus_t* status);
        void processFileArguments();
@@ -201,13 +202,12 @@ protected:
        virtual void processDir(ReDirStatus_t* entry);
        virtual void processFile(ReDirStatus_t* entry);
 public:
-       static bool touch(const char* filename, ReFileProperties_t* properties,
-               ReLogger* logger = NULL);
+       static ReErrNo_t touch(const char* filename, const ReFileTime_t& modified,
+               const ReFileTime_t& accessed, ReLogger* logger = NULL);
 protected:
        ReByteBuffer m_buffer;
-       time_t m_modified;
-       time_t m_accessed;
-       ReFileProperties_t m_properties;
+       ReFileTime_t m_modified;
+       ReFileTime_t m_accessed;
 };
 
 
index 6513a801f7e63dd4e95a8fe41bc1e1113397fd2e..30004cf15b6bc13fac7a62c7238da623d13f4368 100644 (file)
@@ -85,11 +85,7 @@ const char* ReDirStatus_t::rightsAsString(ReByteBuffer& buffer) {
  * @return          <code>buffer.str()</code> (for chaining)\r
  */\r
 const char* ReDirStatus_t::filetimeAsString(ReByteBuffer& buffer) {\r
-    time_t time1 = filetimeToTime(modified());\r
-    struct tm* time2 = gmtime(&time1);\r
-    buffer.setLength(4+2*2+2*2+1+3*2+2*1);\r
-    strftime(buffer.buffer(), buffer.length(), "%Y.%m.%d %H:%M:%S", time2);\r
-    return buffer.str();\r
+    return filetimeToString(modified(), buffer);\r
 }\r
 \r
 \r
@@ -258,7 +254,7 @@ bool ReDirStatus_t::isRegular() {
  *\r
  * @return     the filesize\r
  */\r
-FileSize_t ReDirStatus_t::fileSize() {\r
+ReFileSize_t ReDirStatus_t::fileSize() {\r
 #ifdef __linux__\r
     return getStatus()->st_size;\r
 #elif defined __WIN32__\r
@@ -270,9 +266,9 @@ FileSize_t ReDirStatus_t::fileSize() {
  *\r
  * @return     the modification time\r
  */\r
-const FileTime_t* ReDirStatus_t::modified() {\r
+const ReFileTime_t* ReDirStatus_t::modified() {\r
 #ifdef __linux__\r
-    return &(getStatus()->st_mtime);\r
+    return &(getStatus()->st_mtim);\r
 #elif defined __WIN32__\r
     return &m_data.ftLastWriteTime;\r
 #endif\r
@@ -283,17 +279,38 @@ const FileTime_t* ReDirStatus_t::modified() {
  *\r
  * @return     the last access time\r
  */\r
-const FileTime_t* ReDirStatus_t::accessed() {\r
+const ReFileTime_t* ReDirStatus_t::accessed() {\r
 #ifdef __linux__\r
-    return &(getStatus()->st_atime);\r
+    return &(getStatus()->st_atim);\r
 #elif defined __WIN32__\r
     return &m_data.ftLastAccessTime;\r
 #endif\r
 }\r
 \r
-time_t ReDirStatus_t::filetimeToTime(const FileTime_t* filetime){\r
+/**\r
+ * Converts a filetime to a string.\r
+ *\r
+ * @param time         the filetime to convert\r
+ * @param buffer       OUT: the buffer for the string\r
+ * @return                     <code>buffer.str()</code>, e.g. "2014.01.07 02:59:43"\r
+ */\r
+const char* ReDirStatus_t::filetimeToString(const ReFileTime_t* time, ReByteBuffer& buffer){\r
+    time_t time1 = filetimeToTime(time);\r
+    struct tm* time2 = localtime(&time1);\r
+    buffer.setLength(4+2*2+2*2+1+3*2+2*1);\r
+    strftime(buffer.buffer(), buffer.length(), "%Y.%m.%d %H:%M:%S", time2);\r
+       return buffer.str();\r
+}\r
+\r
+/**\r
+ * Converts a filetime to a unix time (seconds since the Epoche).\r
+ *\r
+ * @param filetime             the filetime to convert\r
+ * @return                             the count of seconds since 1.1.1970\r
+ */\r
+time_t ReDirStatus_t::filetimeToTime(const ReFileTime_t* filetime){\r
 #ifdef __linux__\r
-    return *filetime;\r
+    return filetime->tv_sec;\r
 #elif defined __WIN32__\r
     // takes the last modified date\r
     LARGE_INTEGER date, adjust;\r
@@ -313,9 +330,10 @@ time_t ReDirStatus_t::filetimeToTime(const FileTime_t* filetime){
  * @param time                 the unix time (secondes since 1.1.1970)\r
  * @param filetime     OUT: the OS specific filetime\r
  */\r
-void  ReDirStatus_t::timeToFiletime(time_t time, FileTime_t& filetime){\r
+void  ReDirStatus_t::timeToFiletime(time_t time, ReFileTime_t& filetime){\r
 #ifdef __linux__\r
-    filetime = time;\r
+    filetime.tv_sec = time;\r
+       filetime.tv_nsec = 0;\r
 #elif defined __WIN32__\r
     LONGLONG ll = Int32x32To64(time, 10000000) + 116444736000000000;\r
     filetime.dwLowDateTime = (DWORD)ll;\r
@@ -332,11 +350,13 @@ ReDirEntryFilter_t::ReDirEntryFilter_t() :
        m_pathPatterns(NULL),\r
        m_minSize(0),\r
        m_maxSize(-1),\r
-       m_minAge(0),\r
-       m_maxAge(0),\r
+       //m_minAge(0),\r
+       //m_maxAge(0),\r
     m_minDepth(0),\r
     m_maxDepth(512)\r
 {\r
+       setFiletimeUndef(m_minAge);\r
+       setFiletimeUndef(m_maxAge);\r
 }\r
 \r
 /**\r
@@ -357,9 +377,9 @@ bool ReDirEntryFilter_t::match(ReDirStatus_t& entry){
                        break;\r
                if (m_maxSize >= 0 && size > m_maxSize)\r
                        break;\r
-               if (m_minAge != 0 && ReDirStatus_t::filetimeToTime(entry.modified()) > m_minAge)\r
+               if (! filetimeIsUndefined(m_minAge) && *entry.modified() > m_minAge)\r
                        break;\r
-               if (m_maxAge != 0 && ReDirStatus_t::filetimeToTime(entry.modified()) < m_maxAge)\r
+               if (! filetimeIsUndefined(m_maxAge) && m_maxAge > *entry.modified())\r
                        break;\r
                const char* node = entry.node();\r
                if (m_nodePatterns != NULL && ! m_nodePatterns->match(node))\r
@@ -404,7 +424,7 @@ ReDirTreeStatistic::ReDirTreeStatistic() :
  * @param formatFiles  the <code>sprintf</code> format for the directory count, e.g. "%6d"\r
  * @return                             a human readable string\r
  */\r
-const char* ReDirTreeStatistic::toString(ReByteBuffer& buffer, bool append,\r
+const char* ReDirTreeStatistic::statisticAsString(ReByteBuffer& buffer, bool append,\r
        const char* formatFiles, const char* formatSizes, const char* formatDirs)\r
 {\r
        if (! append)\r
index 50576746df6c05deaed048c1be43e35827ff3f7e..2b967f5e73cd25ffcd8a8b33e91bf5ec3d0ace4b 100644 (file)
 #include <sys/stat.h>
 
 typedef DIR* FindFileHandle_t;
-typedef __off_t FileSize_t;
-typedef time_t FileTime_t;
-#else
-typedef int64_t FileSize_t;
-typedef FILETIME FileTime_t;
 #endif
+/** Returns whether a filetime is undefined.
+ * @param time the filetime to test
+ * @return             <code>true</code>: the given filetime is undefined
+ */
+inline bool filetimeIsUndefined(ReFileTime_t& time){
+#if defined __linux__
+       return time.tv_sec == 0 && time.tv_nsec == 0;
+#elif defined __WIN32__
+#endif
+}
+/** Sets the filetime to undefined.
+ * @param time the filetime to clear
+ */
+inline void setFiletimeUndef(ReFileTime_t& time){
+#if defined __linux__
+       time.tv_sec = time.tv_nsec = 0;
+#elif defined __WIN32__
+#endif
+}
+
 class ReDirStatus_t{
 public:
     enum Type_t {
@@ -54,9 +69,9 @@ public:
     bool isDirectory();
     bool isLink();
     bool isRegular();
-    FileSize_t fileSize();
-    const FileTime_t* modified();
-    const FileTime_t* accessed();
+    ReFileSize_t fileSize();
+    const ReFileTime_t* modified();
+    const ReFileTime_t* accessed();
     bool isDotDir() const;
     const char* rightsAsString(ReByteBuffer& buffer);
     const char* filetimeAsString(ReByteBuffer& buffer);
@@ -76,8 +91,9 @@ public:
        WIN32_FIND_DATAA m_data;
 #endif
 public:
-    static time_t filetimeToTime(const FileTime_t* time);
-    static void timeToFiletime(time_t time, FileTime_t& filetime);
+    static time_t filetimeToTime(const ReFileTime_t* time);
+    static void timeToFiletime(time_t time, ReFileTime_t& filetime);
+    static const char* filetimeToString(const ReFileTime_t* time, ReByteBuffer& buffer);
 };
 class ReDirEntryFilter_t{
 public:
@@ -89,10 +105,10 @@ public:
        ReDirStatus_t::Type_t m_types;
        RePatternList* m_nodePatterns;
        RePatternList* m_pathPatterns;
-       FileSize_t m_minSize;
-       FileSize_t m_maxSize;
-       time_t m_minAge;
-       time_t m_maxAge;
+       ReFileSize_t m_minSize;
+       ReFileSize_t m_maxSize;
+       ReFileTime_t m_minAge;
+       ReFileTime_t m_maxAge;
     int m_minDepth;
     int m_maxDepth;
 };
@@ -135,9 +151,9 @@ class ReDirTreeStatistic {
 public:
        ReDirTreeStatistic();
 public:
-       const char* toString(ReByteBuffer& buffer, bool append = false,
-               const char* formatFiles = "%8d", const char* formatSizes = "%12.6f",
-               const char* formatDirs = "%7d");
+       const char* statisticAsString(ReByteBuffer& buffer, bool append = false,
+               const char* formatFiles = "%8d ", const char* formatSizes = "%12.6f",
+               const char* formatDirs = "%7d ");
        /**
         * Resets the counters.
         */
index 696bdae637d61262127782f7fea921b82502de5c..f9aeaf4a66e750e7a2930bbd924370690f0537eb 100644 (file)
@@ -13,7 +13,6 @@
 #if defined __linux__
 #include "unistd.h"
 #include <dirent.h>
-#include <utime.h>
 #elif defined __WIN32__
 #include <tchar.h>
 #include "windows.h"
 #error "unknown os"
 #endif
 
+/** Returns whether a time is greater (younger) than another.
+ * @param time1                first operand
+ * @param time2                second operand
+ * @return                     <code>true</code>: time1 > time2
+ */
+inline bool operator >(const ReFileTime_t& time1, const ReFileTime_t& time2){
+#if defined __linux__
+       return time1.tv_sec > time1.tv_sec || time1.tv_sec == time2.tv_sec && time1.tv_nsec > time2.tv_nsec;
+#else
+#endif
+}
 #include "os/ReTraverser.hpp"
 #include "os/ReDirTools.hpp"