]> gitweb.hamatoma.de Git - reqt/commitdiff
v2016.04.07, rebackgui, warnings found by clang
authorhama <hama@siduction.net>
Mon, 11 Apr 2016 22:52:57 +0000 (00:52 +0200)
committerhama <hama@siduction.net>
Tue, 12 Apr 2016 22:43:27 +0000 (00:43 +0200)
rebackgui:
* test of symbolic link before test of directory
* allows being root by setuid()
* translation improvements
* documentation in rebackgui.html
* trace
lib:
* file copy under linux:
** copying symbolic links
** setting owner and group
* linux: using QT setpermissions() instead of chmod()
* new: modifyToNonExisting()
* ReLogger(): correction of logging file "ring" (incrementing numbers,
  limited count of files)
* ReProcess::executeAndRead(): timeout
* added: I18N::b2s()
* more tests
* uint64_t changed to quint64
* ReGuiApplication(): default base dir is now <home>/.reappl
* ReTracer

33 files changed:
PrepTmp.sh [new file with mode: 0755]
RenTmp.sh [new file with mode: 0755]
appl/rebackgui/BackupEngine.cpp
appl/rebackgui/main.cpp
appl/rebackgui/mainwindow.cpp
appl/rebackgui/mainwindow.ui
appl/rebackgui/rebackgui.de.qm [new file with mode: 0644]
appl/rebackgui/rebackgui.de.ts
appl/rebackgui/rebackgui.html [new file with mode: 0644]
appl/rebackgui/rebackgui.pro
appl/recommand/recommand.pro
base/ReConfig.hpp
base/ReContainer.cpp
base/ReFileUtils.cpp
base/ReFileUtils.hpp
base/ReLogger.cpp
base/ReLogger.hpp
base/ReProcess.cpp
base/ReQStringUtils.hpp
base/ReStringUtils.cpp
base/rebase.hpp
base/retrace.hpp
cunit/allTests.cpp
cunit/cuReByteStorage.cpp
cunit/cuReFileUtils.cpp
cunit/cuReProgArgs.cpp
cunit/cuReQStringUtils.cpp
cunit/cuReRandomizer.cpp
cunit/cunit.pro
cunit/main.cpp
expr/ReLexer.cpp
gui/ReGuiApplication.cpp
gui/ReSettings.hpp

diff --git a/PrepTmp.sh b/PrepTmp.sh
new file mode 100755 (executable)
index 0000000..dd555f5
--- /dev/null
@@ -0,0 +1,8 @@
+#! /bin/bash
+
+mkdir /tmp/trg
+mkdir /tmp/src
+cp -a /home/bin/std/*.py /tmp/src
+mkdir /tmp/src/x
+cp -a /home/bin/std/a*.pl /tmp/src/x
+
diff --git a/RenTmp.sh b/RenTmp.sh
new file mode 100755 (executable)
index 0000000..8259916
--- /dev/null
+++ b/RenTmp.sh
@@ -0,0 +1,4 @@
+#! /bin/bash
+cp -a /tmp/src /tmp/trg
+rename "s/py/px/g" /tmp/trg/src/*
+touch /tmp/trg/src/*
index 9e9a138b33a23693f7c15825cd027da6d154ee93..f723be562016e740833159ee633b62cd6fcfa69e 100644 (file)
  */
 
 #include "backupgui.hpp"
+//#define WITH_TRACE
+#include "base/retrace.hpp"
+DECLARE_TRACER(s_traceSearch, "/tmp/bup_search.log");
+DECLARE_TRACER(s_traceBackup, "/tmp/bup_backup.log");
+DECLARE_TRACER(s_traceChecksum, "/tmp/bup_sum.log");
+DECLARE_TRACER(s_traceClean, "/tmp/bup_clean.log");
+
 ReVerbose_t BackupEngine::m_verboseLevel = VerboseStandard;
 bool BackupEngine::m_shouldStop = false;
 QStringList BackupEngine::m_files;
@@ -130,7 +137,11 @@ BackupTask::BackupTask(const QString& name,
        m_lastRelPath(),
        m_buffer()
 {
-
+       FILETRACE_IT(s_traceBackup, (s_traceBackup.m_fp,
+               "=== new BackupTask (%s): %s -> %s\n",
+               name.toLocal8Bit().constData(),
+               sourceDirs.first().toLocal8Bit().constData(),
+               targetDir.toLocal8Bit().constData()));
 }
 
 /**
@@ -142,6 +153,10 @@ BackupTask::BackupTask(const QString& name,
  */
 void BackupTask::copyFile(int index, const QString& relPath,
                const QString& node){
+       FILETRACE_IT(s_traceBackup, (s_traceBackup.m_fp,
+               "+%s%s\n",
+               relPath.toLocal8Bit().constData(),
+               node.toLocal8Bit().constData()));
        qint64 start = QDateTime::currentMSecsSinceEpoch();
        QString source = m_sourceDirs.at(index) + relPath + node;
        QString targetDir = m_targetDirs.at(index) + relPath;
@@ -157,15 +172,15 @@ void BackupTask::copyFile(int index, const QString& relPath,
                if (! ReFileUtils::makeDirWithParents(targetDir))
                        error(QObject::tr("cannot make directory (%1): %2").arg(errno).arg(targetDir));
        }
-       QFileInfo info(source);
+       QFileInfo sourceInfo(source);
        if (m_verboseLevel >= VerboseStandard)
-               m_mainWindow->addToFileList(source + " " + ReQStringUtils::readableSize(info.size()));
+               m_mainWindow->addToFileList(source + " " + ReQStringUtils::readableSize(sourceInfo.size()));
        m_mutex.lock();
        m_processedFiles++;
-       m_processedBytes += info.size();
+       m_processedBytes += sourceInfo.size();
        m_mutex.unlock();
 
-       QString errorMsg = ReFileUtils::copy(source, target, &info, m_buffer);
+       QString errorMsg = ReFileUtils::copy(source, target, &sourceInfo, m_buffer);
        if (! errorMsg.isEmpty()){
                error(errorMsg);
                if (m_verboseLevel >= VerboseStandard)
@@ -174,6 +189,10 @@ void BackupTask::copyFile(int index, const QString& relPath,
                m_mainWindow->expandFileList(ReQStringUtils::readableDuration(
                                QDateTime::currentMSecsSinceEpoch() - start));
        }
+       FILETRACE_IT(s_traceBackup, (s_traceBackup.m_fp,
+               "~\n",
+               relPath.toLocal8Bit().constData(),
+               node.toLocal8Bit().constData()));
 }
 
 /**
@@ -228,6 +247,8 @@ void BackupTask::run()
                        }
                }
        }
+       FILETRACE_IT(s_traceBackup, (s_traceBackup.m_fp,
+               "=== backup ready\n"));
        m_mainWindow->externalTaskFinished(QObject::tr("backup complete after %1. Errors: %2")
                                .arg(ReQStringUtils::readableDuration(
                                        QDateTime::currentMSecsSinceEpoch() - start.toMSecsSinceEpoch()))
@@ -582,6 +603,11 @@ SearchTask::SearchTask(bool compareWithTarget, const QString& name,
        m_dirMatcher(dirPatterns),
        m_compareWithTarget(compareWithTarget)
 {
+       FILETRACE_IT(s_traceSearch, (s_traceSearch.m_fp,
+               "=== new search (%s): %s -> %s\n",
+               name.toLocal8Bit().constData(),
+               sourceDirs.first().toLocal8Bit().constData(),
+               targetDir.toLocal8Bit().constData()));
 }
 
 /**
@@ -639,13 +665,18 @@ void SearchTask::searchOneDirectory(const QString& source,
        } else {
                prefix = QChar(1 + index) + m_separatorString;
        }
+       FILETRACE_IT(s_traceSearch, (s_traceSearch.m_fp, "=%s\n",
+                        source.toLocal8Bit().constData()));
        while (it.hasNext()){
           if (m_shouldStop){
                  break;
           }
           it.next();
           node = it.fileName();
-          if (it.fileInfo().isDir()){
+          FILETRACE_IT(s_traceSearch, (s_traceSearch.m_fp, "?%s\n",
+                               node.toLocal8Bit().constData()));
+          QFileInfo fileInfo = it.fileInfo();
+          if (! fileInfo.isSymLink() && fileInfo.isDir()){
                   // nothing to do
           } else if (! m_fileMatcher.matches(node)){
                   m_mutex.lock();
@@ -666,7 +697,7 @@ void SearchTask::searchOneDirectory(const QString& source,
                                   const QFileInfo src = it.fileInfo();
                                   if (trg.size() != src.size())
                                           doTransfer = true;
-                                  else if ((diff = abs(src.lastModified().toMSecsSinceEpoch()
+                                  else if ((diff = _abs(src.lastModified().toMSecsSinceEpoch()
                                                   - trg.lastModified().toMSecsSinceEpoch())) >= 2000)
                                           doTransfer = true;
                           }
@@ -674,6 +705,8 @@ void SearchTask::searchOneDirectory(const QString& source,
                   if (doTransfer){
                           info = prefix + it.fileName();
                   }
+                  FILETRACE_IT(s_traceSearch, (s_traceSearch.m_fp, ">%s\n",
+                                       node.toLocal8Bit().constData()));
                   m_mutex.lock();
                   if (doTransfer){
                           m_files.append(info);
@@ -694,8 +727,9 @@ void SearchTask::searchOneDirectory(const QString& source,
                           break;
                        }
                   it2.next();
-
-                  if (it2.fileInfo().isDir() && (node = it2.fileName()) != "." && node != ".."
+                  QFileInfo fileInfo = it2.fileInfo();
+                  if (! fileInfo.isSymLink() && fileInfo.isDir()
+                                  && (node = it2.fileName()) != "." && node != ".."
                                   && m_dirMatcher.matches(node)){
                           if (target.isEmpty())
                                   subTarget.clear();
@@ -743,9 +777,12 @@ SearchTargetTask::SearchTargetTask(const QString& name, const QStringList& sourc
 bool SearchTargetTask::removeOlder(const QString& directory, const QDateTime& time){
        QDirIterator it(directory);
        QString info, node;
+       IF_TRACE(QByteArray directory2(directory.toLocal8Bit()));
        m_mutex.lock();
        m_totalDirs++;
        m_mutex.unlock();
+       FILETRACE_IT(s_traceSearch, (s_traceSearch.m_fp, "=removeOlder: %s\n",
+                       directory2.constData()));
        bool isEmpty = true;
        while (it.hasNext()){
           if (m_shouldStop){
@@ -753,7 +790,8 @@ bool SearchTargetTask::removeOlder(const QString& directory, const QDateTime& ti
           }
           it.next();
           node = it.fileName();
-          if (it.fileInfo().isDir()){
+          QFileInfo fileInfo = it.fileInfo();
+          if (! fileInfo.isSymLink() && fileInfo.isDir()){
                   if (node != "." && node != ".."){
                           if (! removeOlder(ReFileUtils::nativePath(it.filePath()), time))
                                   isEmpty = false;
@@ -771,6 +809,9 @@ bool SearchTargetTask::removeOlder(const QString& directory, const QDateTime& ti
                   m_hotBytes += it.fileInfo().size();
                   m_totalFiles++;
                   m_mutex.unlock();
+                  FILETRACE_IT(s_traceSearch, (s_traceSearch.m_fp, "-%s/%s\n",
+                               directory2.constData(),
+                               fileInfo.baseName().toLocal8Bit().constData()));
           }else {
                   isEmpty = false;
           }
@@ -785,6 +826,8 @@ bool SearchTargetTask::removeOlder(const QString& directory, const QDateTime& ti
                m_matchedFiles++;
                m_hotFiles++;
                m_mutex.unlock();
+               FILETRACE_IT(s_traceSearch, (s_traceSearch.m_fp, "-%s\n",
+                        directory2.constData()));
        }
        return isEmpty;
 }
@@ -820,7 +863,8 @@ void SearchTargetTask::searchOneDirectory(const QString& target,
           }
           it.next();
           node = it.fileName();
-          if (it.fileInfo().isDir()){
+          QFileInfo fileInfo = it.fileInfo();
+          if (! fileInfo.isSymLink() && fileInfo.isDir()){
                   // nothing to do
           } else{
                   Command command = CmdUndef;
@@ -857,12 +901,13 @@ void SearchTargetTask::searchOneDirectory(const QString& target,
                        if (m_shouldStop){
                           break;
                        }
-                  it2.next();
-
-                  if (it2.fileInfo().isDir() && (node = it2.fileName()) != "." && node != ".."){
+                       it2.next();
+                       QFileInfo fileInfo = it2.fileInfo();
+                       if (! fileInfo.isSymLink() && fileInfo.isDir()
+                                       && (node = it2.fileName()) != "." && node != ".."){
                           QString newSource = source + it2.fileName();
                           QFileInfo src(newSource);
-                          if (src.exists() && src.isDir())
+                          if (src.exists() && ! src.isSymLink() && src.isDir())
                                   searchOneDirectory(ReFileUtils::nativePath(it2.filePath()),
                                                                          newSource + OS_SEPARATOR_STR, index);
                           else{
@@ -883,6 +928,25 @@ void SearchTargetTask::searchOneDirectory(const QString& target,
 void SearchTargetTask::moveToShadow(const QString& target, const QString& relPath, int index){
        QString shadowDir = m_shadowDirs.at(index) + relPath;
        ReQStringUtils::chomp(shadowDir, OS_SEPARATOR);
+       if (ReFileUtils::isDirectory(shadowDir)){
+               QString targetName = shadowDir;
+               int pos = targetName.length() / 2;
+               while(pos < shadowDir.length()){
+               char cc = '0' - 1;
+               do{
+                       targetName[pos] = ++cc;
+               } while (cc <= 'Z' && QFileInfo(targetName).exists());
+               if (cc <= 'Z'){
+                       if (rename(I18N::s2b(shadowDir).constData(),
+                                               I18N::s2b(targetName).constData()) != 0)
+                               error(QObject::tr("kann Schattenverzeichnis nicht umbenennen: %1 -> %2")
+                                         .arg(shadowDir, targetName));
+                       else break;
+               }
+               pos++;
+               }
+
+       }
        if (! ReFileUtils::makeDirWithParents(shadowDir)){
 
                error(QObject::tr("cannot create shadow directory (%1): %2")
index df7047fd177217ae9fbdedbff23d0f46282bcae0..2c2fcdec9a1bfb7a645518b13110bbfb37122b28 100644 (file)
 #include <QApplication>
 char** g_argv;
 int main(int argc, char* argv[]) {
-    g_argv = argv;
-    QString homeDir = argc > 1 ? argv[1] : "";
-    QApplication a(argc, argv);
-    MainWindow w(a, homeDir);
-    w.show();
-    return a.exec();
+       g_argv = argv;
+       QString homeDir = argc > 1 ? argv[1] : "";
+       QApplication::setSetuidAllowed(true);
+       QApplication a(argc, argv);
+       MainWindow w(a, homeDir);
+       w.show();
+       return a.exec();
 }
index c430ab99bff58074021838c9006db4bb4270a682..e15d172ca2f7d3483ac0efd92fabee68ab1418d4 100644 (file)
@@ -13,7 +13,7 @@
 #include "aboutdialog.hpp"
 #include <QFileDialog>
 
-const QString VERSION("2016.02.24");
+const QString VERSION("2016.04.07");
 
 /**
  * Constructor.
@@ -23,7 +23,7 @@ const QString VERSION("2016.02.24");
  */
 MainWindow::MainWindow(QApplication& application, const QString& homeDir,
                                           QWidget *parent) :
-       ReGuiApplication(application, "rebackgui", homeDir, 2, 100100100, "de", parent),
+       ReGuiApplication(application, "rebackgui", homeDir, 2, 10100100, "de", parent),
        ReGuiValidator(),
        ui(new Ui::MainWindow),
        m_configuration(this),
@@ -114,7 +114,7 @@ void MainWindow::onGuiTimerUpdate()
        int countStatusMessage = 0;
        clock_t start = clock();
        clock_t diff;
-       while(count-- > 0 || (diff = clock() - start) > CLOCKS_PER_SEC){
+       while(count-- > 0 && (diff = clock() - start) < CLOCKS_PER_SEC * 7 / 8){
                m_mutexGuiQueue.lock();
                ReGuiQueueItem item = m_guiQueue.popFront();
                m_mutexGuiQueue.unlock();
index f556cc3a8b1ebe676abf4f64cdba854bc85300c6..8fb4ae933015db119e878a3f7a90fb6719c468a0 100644 (file)
              </layout>
             </item>
             <item>
-             <layout class="QHBoxLayout" name="horizontalLayout">
+             <layout class="QHBoxLayout" name="horizontalLayoutX1">
               <item>
                <widget class="QPushButton" name="pushButtonBackup">
                 <property name="minimumSize">
      <x>0</x>
      <y>0</y>
      <width>839</width>
-     <height>26</height>
+     <height>29</height>
     </rect>
    </property>
    <widget class="QMenu" name="menuFile">
     <property name="title">
-     <string>File</string>
+     <string>Fi&amp;le</string>
     </property>
     <addaction name="actionLoadConfig"/>
     <addaction name="actionSaveConfig"/>
    </widget>
    <widget class="QMenu" name="menuEdit">
     <property name="title">
-     <string>Edit</string>
+     <string>Edi&amp;t</string>
     </property>
    </widget>
    <widget class="QMenu" name="menuHelp">
     <property name="title">
-     <string>Help</string>
+     <string>Hel&amp;p</string>
     </property>
     <addaction name="actionAbout"/>
     <addaction name="separator"/>
    </widget>
    <widget class="QMenu" name="menuAction">
     <property name="title">
-     <string>Action</string>
+     <string>A&amp;ction</string>
     </property>
     <addaction name="actionStart"/>
     <addaction name="actionStop"/>
   <widget class="QStatusBar" name="statusBar"/>
   <action name="actionLoadConfig">
    <property name="text">
-    <string>Load Config</string>
+    <string>&amp;Load Config</string>
    </property>
   </action>
   <action name="actionSaveConfig">
    <property name="text">
-    <string>Save Config</string>
+    <string>&amp;Save Config</string>
    </property>
   </action>
   <action name="actionExit">
    <property name="text">
-    <string>Exit</string>
+    <string>&amp;Exit</string>
    </property>
   </action>
   <action name="actionStart">
    <property name="text">
-    <string>Start backup</string>
+    <string>&amp;Start backup</string>
    </property>
   </action>
   <action name="actionStop">
    <property name="text">
-    <string>Stop</string>
+    <string>St&amp;op</string>
    </property>
   </action>
   <action name="actionAbout">
    <property name="text">
-    <string>About</string>
+    <string>&amp;About</string>
    </property>
   </action>
   <action name="actionChecksums">
    <property name="text">
-    <string>Checksums</string>
+    <string>&amp;Checksums</string>
    </property>
    <property name="toolTip">
     <string>Calculates checksums for source and target files and reports differences</string>
   </action>
   <action name="actionClean">
    <property name="text">
-    <string>Clean</string>
+    <string>C&amp;lean</string>
    </property>
   </action>
   <action name="actionEnglish">
     <bool>true</bool>
    </property>
    <property name="text">
-    <string>English</string>
+    <string>&amp;English</string>
    </property>
   </action>
   <action name="actionGerman">
     <bool>true</bool>
    </property>
    <property name="text">
-    <string>German</string>
+    <string>&amp;German</string>
    </property>
   </action>
   <action name="actionAutosave">
     <bool>true</bool>
    </property>
    <property name="text">
-    <string>Autosave</string>
+    <string>&amp;Autosave</string>
    </property>
   </action>
  </widget>
diff --git a/appl/rebackgui/rebackgui.de.qm b/appl/rebackgui/rebackgui.de.qm
new file mode 100644 (file)
index 0000000..ca4ccf5
Binary files /dev/null and b/appl/rebackgui/rebackgui.de.qm differ
index e1adf8b763a518ddf3441d925b64271a6f7a2540..b8a17ec871fa2b19dc6ee2a8cf27b3645dd4e029 100644 (file)
@@ -106,7 +106,6 @@ p, li { white-space: pre-wrap; }
     </message>
     <message>
         <location filename="mainwindow.ui" line="25"/>
-        <location filename="mainwindow.ui" line="818"/>
         <source>Action</source>
         <translation>Aktion</translation>
     </message>
@@ -205,7 +204,6 @@ p, li { white-space: pre-wrap; }
     </message>
     <message>
         <location filename="mainwindow.ui" line="226"/>
-        <location filename="mainwindow.ui" line="861"/>
         <source>Stop</source>
         <translation>Beenden</translation>
     </message>
@@ -217,7 +215,6 @@ p, li { white-space: pre-wrap; }
     </message>
     <message>
         <location filename="mainwindow.ui" line="255"/>
-        <location filename="mainwindow.ui" line="871"/>
         <source>Checksums</source>
         <translation>Prüfsummen</translation>
     </message>
@@ -228,7 +225,6 @@ p, li { white-space: pre-wrap; }
     </message>
     <message>
         <location filename="mainwindow.ui" line="271"/>
-        <location filename="mainwindow.ui" line="879"/>
         <source>Clean</source>
         <translatorcomment>Protokoll:</translatorcomment>
         <translation>Bereinigen</translation>
@@ -272,7 +268,6 @@ p, li { white-space: pre-wrap; }
     </message>
     <message>
         <location filename="mainwindow.ui" line="462"/>
-        <location filename="mainwindow.ui" line="903"/>
         <source>Autosave</source>
         <translation>Autom. Speichern</translation>
     </message>
@@ -356,81 +351,91 @@ p, li { white-space: pre-wrap; }
     </message>
     <message>
         <location filename="mainwindow.ui" line="793"/>
-        <source>File</source>
+        <source>Fi&amp;le</source>
+        <oldsource>File</oldsource>
         <translatorcomment>Bearbeiten</translatorcomment>
-        <translation>Datei</translation>
+        <translation type="unfinished">Datei</translation>
     </message>
     <message>
         <location filename="mainwindow.ui" line="804"/>
-        <source>Edit</source>
-        <translation>Bearbeiten</translation>
+        <source>Edi&amp;t</source>
+        <oldsource>Edit</oldsource>
+        <translation type="unfinished">Bearbeiten</translation>
     </message>
     <message>
         <location filename="mainwindow.ui" line="809"/>
-        <source>Help</source>
-        <translation>Hilfe</translation>
+        <source>Hel&amp;p</source>
+        <oldsource>Help</oldsource>
+        <translation type="unfinished">Hilfe</translation>
     </message>
     <message>
         <location filename="mainwindow.ui" line="841"/>
-        <source>Load Config</source>
-        <translation>Konfiguration laden</translation>
+        <source>&amp;Load Config</source>
+        <oldsource>Load Config</oldsource>
+        <translation type="unfinished">Konfiguration laden</translation>
     </message>
     <message>
         <location filename="mainwindow.ui" line="846"/>
-        <source>Save Config</source>
-        <translation>Konfiguration sichern</translation>
+        <source>&amp;Save Config</source>
+        <oldsource>Save Config</oldsource>
+        <translation type="unfinished">Konfiguration sichern</translation>
     </message>
     <message>
         <location filename="mainwindow.ui" line="851"/>
-        <source>Exit</source>
-        <translation>Beenden</translation>
+        <source>&amp;Exit</source>
+        <oldsource>Exit</oldsource>
+        <translation type="unfinished">Beenden</translation>
     </message>
     <message>
         <location filename="mainwindow.ui" line="856"/>
-        <source>Start backup</source>
-        <translation>Sicherung starten</translation>
+        <source>&amp;Start backup</source>
+        <oldsource>Start backup</oldsource>
+        <translation type="unfinished">Sicherung starten</translation>
     </message>
     <message>
         <location filename="mainwindow.ui" line="866"/>
-        <source>About</source>
-        <translation>Ãœber</translation>
+        <source>&amp;About</source>
+        <oldsource>About</oldsource>
+        <translation type="unfinished">Ãœber</translation>
     </message>
     <message>
         <location filename="mainwindow.ui" line="887"/>
-        <source>English</source>
-        <translation></translation>
+        <source>&amp;English</source>
+        <oldsource>English</oldsource>
+        <translation type="unfinished"></translation>
     </message>
     <message>
         <location filename="mainwindow.ui" line="895"/>
-        <source>German</source>
-        <translation></translation>
+        <source>&amp;German</source>
+        <oldsource>German</oldsource>
+        <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="mainwindow.cpp" line="359"/>
-        <location filename="mainwindow.cpp" line="393"/>
-        <location filename="mainwindow.cpp" line="583"/>
+        <location filename="mainwindow.cpp" line="361"/>
+        <location filename="mainwindow.cpp" line="395"/>
+        <location filename="mainwindow.cpp" line="588"/>
         <source>no backup item selected</source>
         <translation>Kein Sicherungselement ausgewählt</translation>
     </message>
     <message>
-        <location filename="mainwindow.cpp" line="364"/>
-        <location filename="mainwindow.cpp" line="398"/>
-        <location filename="mainwindow.cpp" line="588"/>
+        <location filename="mainwindow.cpp" line="366"/>
+        <location filename="mainwindow.cpp" line="400"/>
+        <location filename="mainwindow.cpp" line="593"/>
         <source>Target not available</source>
         <translation>Ziel nicht vorhanden</translation>
     </message>
     <message>
-        <location filename="mainwindow.cpp" line="303"/>
+        <location filename="mainwindow.cpp" line="305"/>
         <source>Select Source Directory</source>
         <translation>Quellverzeichnis auswählen</translation>
     </message>
     <message>
-        <location filename="mainwindow.cpp" line="566"/>
+        <location filename="mainwindow.cpp" line="568"/>
         <source>Select Target Directory</source>
         <translation>Zielverzeichnis auswählen</translation>
     </message>
     <message>
-        <location filename="mainwindow.cpp" line="572"/>
+        <location filename="mainwindow.cpp" line="574"/>
         <source>target initialized with %1</source>
         <translation>Ziel mit %1 vorbelegt</translation>
     </message>
@@ -519,17 +524,22 @@ p, li { white-space: pre-wrap; }
         <translation>Suche beendet: zu behandeln: %1 mit %2 passend: %3 gesamt: %4 Unterverz: %5 Laufzeit: %6</translation>
     </message>
     <message>
-        <location filename="BackupEngine.cpp" line="888"/>
+        <location filename="BackupEngine.cpp" line="897"/>
+        <source>kann Schattenverzeichnis nicht umbenennen: %1 -&gt; %2</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="BackupEngine.cpp" line="907"/>
         <source>cannot create shadow directory (%1): %2</source>
         <translation>Kann Schattenverzeichnis nicht erstellen (%1): %2</translation>
     </message>
     <message>
-        <location filename="BackupEngine.cpp" line="893"/>
+        <location filename="BackupEngine.cpp" line="912"/>
         <source>cannot move to shadow directory (%1): %2 -&gt; %3</source>
         <translation>Kann Datei nicht in Schattenverzeichnis verschieben (%1): %2 -&gt; %3</translation>
     </message>
     <message>
-        <location filename="BackupEngine.cpp" line="918"/>
+        <location filename="BackupEngine.cpp" line="937"/>
         <source>Search in target finished: to process: %1 with %2 dirs to delete: %3 total: %4 subdirs: %5 runtime: %6</source>
         <translation>Suche im Ziel bendet: zu behandeln: %1 mit %2 zu löschende Verzeichnisse: %3 gesamt: %4 Unterverz.: %5 Laufzeit: %6</translation>
     </message>
@@ -540,9 +550,9 @@ p, li { white-space: pre-wrap; }
     </message>
     <message>
         <location filename="Configuration.cpp" line="119"/>
-        <location filename="Configuration.cpp" line="206"/>
-        <location filename="../../base/ReFileUtils.cpp" line="181"/>
-        <location filename="../../base/ReFileUtils.cpp" line="185"/>
+        <location filename="Configuration.cpp" line="205"/>
+        <location filename="../../base/ReFileUtils.cpp" line="191"/>
+        <location filename="../../base/ReFileUtils.cpp" line="195"/>
         <source>cannot open (%1): %2</source>
         <translation>Kann nicht Ã¶ffnen (%1): %2</translation>
     </message>
@@ -552,33 +562,33 @@ p, li { white-space: pre-wrap; }
         <translation>Unbekanntes Format in %1-%2: %3</translation>
     </message>
     <message>
-        <location filename="Configuration.cpp" line="227"/>
+        <location filename="Configuration.cpp" line="226"/>
         <source>cannot write (%1): %2</source>
         <translation>Kann nicht schreiben (%1): %2</translation>
     </message>
     <message>
-        <location filename="Configuration.cpp" line="231"/>
+        <location filename="Configuration.cpp" line="230"/>
         <source>configuration saved: %1</source>
         <oldsource>configuration changed: %1</oldsource>
         <translation>Konfiguration gespeichert: %1</translation>
     </message>
     <message>
-        <location filename="mainwindow.cpp" line="242"/>
+        <location filename="mainwindow.cpp" line="244"/>
         <source>Search started...</source>
         <translation>Suche gestartet...</translation>
     </message>
     <message>
-        <location filename="mainwindow.cpp" line="763"/>
+        <location filename="mainwindow.cpp" line="782"/>
         <source>yes</source>
         <translation>Ja</translation>
     </message>
     <message>
-        <location filename="mainwindow.cpp" line="763"/>
+        <location filename="mainwindow.cpp" line="782"/>
         <source>no</source>
         <translation>nein</translation>
     </message>
     <message>
-        <location filename="../../base/ReFileUtils.cpp" line="177"/>
+        <location filename="../../base/ReFileUtils.cpp" line="187"/>
         <source>not found: %1</source>
         <translation>Nicht gefunden: %1</translation>
     </message>
@@ -587,32 +597,37 @@ p, li { white-space: pre-wrap; }
         <translation type="obsolete">Kann nicht schreiben(%1): %2 [%3/%4]</translation>
     </message>
     <message>
-        <location filename="../../base/ReFileUtils.cpp" line="202"/>
+        <location filename="../../base/ReFileUtils.cpp" line="176"/>
+        <source>copy file failed (%1): %2</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../base/ReFileUtils.cpp" line="212"/>
         <source>cannot write (%1): %2 [%3/%4]</source>
         <translation>Kann nicht schreiben(%1): %2 [%3/%4]</translation>
     </message>
     <message>
-        <location filename="../../base/ReFileUtils.cpp" line="209"/>
+        <location filename="../../base/ReFileUtils.cpp" line="219"/>
         <source>file can be read only partitionally: %1 [%2/%3]</source>
         <translation>Datei kann nur teilweise gelesen werden: %1 [%2/%3]</translation>
     </message>
     <message>
-        <location filename="../../base/ReFileUtils.cpp" line="214"/>
+        <location filename="../../base/ReFileUtils.cpp" line="224"/>
         <source>cannot set date/time (%1): %2</source>
         <translation>Kann Datum/Zeit nicht setzen (%1): %2</translation>
     </message>
     <message>
-        <location filename="../../base/ReFileUtils.cpp" line="217"/>
+        <location filename="../../base/ReFileUtils.cpp" line="227"/>
         <source>cannot set permissions (%1): %2</source>
         <translation>Kann Dateirechte nicht setzen (%1): %2</translation>
     </message>
     <message>
-        <location filename="../../base/ReFileUtils.cpp" line="491"/>
+        <location filename="../../base/ReFileUtils.cpp" line="569"/>
         <source>can&apos;t create directory (%1): %2</source>
         <translation>Kann Verzeichnis nicht erzeugen (%1): %2</translation>
     </message>
     <message>
-        <location filename="../../base/ReFileUtils.cpp" line="497"/>
+        <location filename="../../base/ReFileUtils.cpp" line="575"/>
         <source>can&apos;t create directory (is a file): </source>
         <translation>Kann Verzeichnis nicht erzeugen (ist eine Datei): </translation>
     </message>
diff --git a/appl/rebackgui/rebackgui.html b/appl/rebackgui/rebackgui.html
new file mode 100644 (file)
index 0000000..8ca4bc0
--- /dev/null
@@ -0,0 +1,73 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<style>#doc_header { font-size: 3em; color: blue; }
+h1 { border-bottom: 1px solid red; }
+h2 { border-bottom: 1px solid blue; }
+h3 { border-bottom: 1px solid black; }
+</style>
+<body>
+<div id="doc_header">Documentation of rebackgui</div>
+<h1>Release Notes</h1>
+<p>
+<ul>
+<li>v2016.04.06<br/>
+       <ul><li>Basic version</li>
+       </ul>
+</li>
+</ul>
+</p>
+
+<h1>User Manual</h1>
+<h2>Purpose:</h2>
+<p>This program makes backups.</p>
+
+<h2>Usage</h2>
+<pre>hmbackgui [&lt;home_dir&gt;]
+&lt;home_dir&gt;:
+&nbsp;the base directory for the configuration directory ".reappl"
+&nbsp;Default: the home directory of the user
+</pre>
+<p>Example:</p>
+<pre>hmbackgui /home/hugo
+</pre>
+
+<h2>Installation</h2>
+<h3>Linux</h3>
+<p>
+<ul><li>Copy rebackgui to /usr/local/bin</li>
+<li>Copy rebackgui.*.qm to the configuration directory, e.g. /home/hm/.reappl</li>
+</ul>
+<pre><code>cd /usr/local/bin
+chown root.root rebackgui
+chmod u+s rebackgui
+</code></pre>
+</p>
+
+<h2>Configuration</h2>
+<p>The configuration is stored in &lt;home_dir&gt;/.rebackgui/rebackgui.conf
+</p>
+
+<h1>Program Documentation</h1>
+
+<h2>Programming Features</h2>
+
+<p>This is a example for a complete QT application with the following features:
+<ul>
+<li>multithreaded</li>
+<li>pattern matching</li>
+<li>multithreaded GUI building</li>
+</ul>
+</p>
+
+<h1>(Un)License: Public Domain</h1>
+
+<p>You can use and modify this file without any restriction.<br/>
+Do what you want.<br/>
+No warranties and disclaimer of any damages.<br/>
+More info: <a href="http://unlicense.org">http://unlicense.org</a><br/>
+The latest sources: <a href="https://github.com/republib">https://github.com/republib</a>.
+</p>
+
+</body>
+</html>
index 4b10c3d14ee7c0decde3926fed356232e0b233bf..ba86e1cd5bc5cce2a32ff6d5eea967d8959b8124 100644 (file)
@@ -53,7 +53,8 @@ FORMS    += mainwindow.ui \
 
 DISTFILES += \
        ReBackGui.html \
-       osconnect.pl
+       osconnect.pl \
+    rebackgui.html
 
 TRANSLATIONS    = rebackgui.de.ts
 CODECFORTR      = UTF-8
index 8efbe4f8c05d997ec0bc0d7579ac89b1a47db8e6..318b324bd92b3be3f77525f760d83da0acb52cc3 100644 (file)
@@ -29,7 +29,8 @@ SOURCES += main.cpp\
         ../../gui/ReGuiQueue.cpp \
        ../../gui/ReGuiUtils.cpp \
                mainwindow.cpp \
-       CommandProcessor.cpp
+       CommandProcessor.cpp \
+    ../../base/ReProcess.cpp
 
 HEADERS  += mainwindow.hpp \
        CommandProcessor.hpp \
index 617e5668f39b702431b9c47fae06e4249e0460d8..b2bdb44785a3d1218ff3e2df36be1ed27d48f60b 100644 (file)
@@ -11,7 +11,7 @@
 #ifndef RECONFIG_HPP
 #define RECONFIG_HPP
 
-class ReConfig: public ReConfigurator, protected QHash<QByteArray, QByteArray> {
+class ReConfig: public ReConfigurator, public QHash<QByteArray, QByteArray> {
 public:
        ReConfig(const char* file = NULL, bool readOnly = true, ReLogger* logger =
                NULL);
index 62d7683a5f02af92e6db4d03e2ce8f098e46db3e..9f50f2d454f617ae2e91de8a988eb05a70e2eef6 100644 (file)
@@ -67,12 +67,12 @@ const char* ReContainer::MAGIC_1 = "Rpl&1";
  * @param sizeHint      Probable length of the container
  */
 ReContainer::ReContainer(size_t sizeHint) :
-           m_data(""),
-           m_countBags(0),
-           m_typeList(""),
-           m_ixItem(0),
-           m_ixBag(0),
-           m_readPosition(NULL) {
+               m_data(""),
+               m_countBags(0),
+               m_typeList(""),
+               m_ixItem(0),
+               m_ixBag(0),
+               m_readPosition(NULL) {
        if (sizeHint > 0)
                m_data.reserve(sizeHint);
 }
@@ -188,10 +188,10 @@ const QByteArray& ReContainer::getData() {
                char buffer[128];
                // RPL&1 0a b5[2]cis: !12
                qsnprintf(buffer, sizeof buffer, "%x[%d]%s:",
-                   (unsigned int) m_data.length(), m_countBags, m_typeList.data());
+                       (unsigned int) m_data.length(), m_countBags, m_typeList.data());
                char header[128 + 8];
                qsnprintf(header, sizeof header, "%s%02x%s", MAGIC_1,
-                   (unsigned int) strlen(buffer), buffer);
+                       (unsigned int) strlen(buffer), buffer);
                m_data.insert(0, header);
        }
        return m_data;
@@ -207,25 +207,25 @@ void ReContainer::fill(const QByteArray& data) {
        const char* ptr = m_data.data();
        if (strncmp(ptr, MAGIC_1, strlen(MAGIC_1)) != 0)
                throw RplInvalidDataException(LOG_ERROR, LOC_FILL_1,
-                   "container has no magic", data.data(), data.length());
+                       "container has no magic", data.data(), data.length());
        ptr += strlen(MAGIC_1);
        unsigned int headerSize = 0;
        if (sscanf(ptr, "%02x", &headerSize) != 1)
                throw RplInvalidDataException(LOG_ERROR, LOC_FILL_2,
-                   "container has no header size", ptr, 2);
+                       "container has no header size", ptr, 2);
        ptr += 2;
 
        unsigned int dataSize = 0;
        unsigned int countBags = 0;
        if (sscanf(ptr, "%x[%x]", &dataSize, &countBags) != 2)
                throw RplInvalidDataException(LOG_ERROR, LOC_FILL_2,
-                   "container has no data_size[bag_count]", ptr, 16);
+                       "container has no data_size[bag_count]", ptr, 16);
        m_countBags = countBags;
        ptr = strchr(ptr, ']') + 1;
        const char* end = ptr + strspn(ptr, "cisdDX!");
        if (end == ptr || *end != ':') {
                throw RplInvalidDataException(LOG_ERROR, LOC_FILL_2,
-                   "container has no valid typelist", ptr, 16);
+                       "container has no valid typelist", ptr, 16);
        }
        m_typeList.clear();
        m_typeList.append(ptr, end - ptr);
@@ -247,13 +247,13 @@ int ReContainer::getCountBags() const {
 void ReContainer::nextBag() {
        if (m_ixItem < m_typeList.length() && m_ixItem != -1)
                throw ReException(LOG_ERROR, LOC_NEXT_BAG_1, NULL,
-                   "end of bag not reached: remaining items: %s",
-                   m_typeList.data() + m_ixItem);
+                       "end of bag not reached: remaining items: %s",
+                       m_typeList.data() + m_ixItem);
        m_ixItem = 0;
        m_ixBag++;
        if (m_ixBag >= m_countBags)
                throw ReException(LOG_ERROR, LOC_NEXT_BAG_2, NULL, "no more bags: %d",
-                   m_ixBag);
+                       m_ixBag);
 }
 /**
  * @brief Sets the next item.
@@ -267,20 +267,20 @@ void ReContainer::nextItem(type_tag_t expected) {
        }
        if (m_ixItem >= m_typeList.length())
                throw ReException(LOG_ERROR, LOC_NEXT_ITEM_1, ReLogger::globalLogger(),
-                   "no more items in the bag");
+                       "no more items in the bag");
        type_tag_t current = (type_tag_t) m_typeList.at(m_ixItem);
        // Unify all data types:
        if (current == TAG_DATA4G || current == TAG_DATA64K)
                current = TAG_DATA255;
        if (current != expected)
                throw ReException(LOG_ERROR, LOC_NEXT_ITEM_2, NULL,
-                   "current item is a %c, not a %c", (char) m_typeList.at(m_ixItem),
-                   (char) expected);
+                       "current item is a %c, not a %c", (char) m_typeList.at(m_ixItem),
+                       (char) expected);
        m_ixItem++;
        if (m_readPosition > (uint8_t*) (m_data.data() + m_data.length()))
                throw ReException(LOG_ERROR, LOC_NEXT_ITEM_3, NULL,
-                   "container size too small. Bag: %d of %d Item: %d of %d",
-                   1 + m_ixBag, m_countBags, 1 + m_ixItem, m_typeList.length());
+                       "container size too small. Bag: %d of %d Item: %d of %d",
+                       1 + m_ixBag, m_countBags, 1 + m_ixItem, m_typeList.length());
 }
 
 /**
@@ -307,7 +307,7 @@ int ReContainer::nextInt() {
        unsigned int value = 0;
        if (sscanf((const char*) m_readPosition, "%x ", &value) != 1)
                throw RplInvalidDataException(LOG_ERROR, LOC_NEXT_INT_1,
-                   "not a hex_number<blank>", m_readPosition, 16);
+                       "not a hex_number<blank>", m_readPosition, 16);
        m_readPosition = (uint8_t*) strchr((const char*) m_readPosition, ' ') + 1;
        if (isNegativ)
                value = -value;
@@ -323,10 +323,10 @@ int64_t ReContainer::nextInt64() {
        bool isNegativ = *m_readPosition == '-';
        if (isNegativ)
                m_readPosition++;
-       uint64_t value = 0;
+       quint64 value = 0;
        if (sscanf((const char*) m_readPosition, "%llx ", &value) != 1)
                throw RplInvalidDataException(LOG_ERROR, LOC_NEXT_INT_1,
-                   "not a hex_number<blank>", m_readPosition, 16);
+                       "not a hex_number<blank>", m_readPosition, 16);
        m_readPosition = (uint8_t*) strchr((const char*) m_readPosition, ' ') + 1;
        if (isNegativ)
                value = -value;
@@ -392,7 +392,7 @@ size_t ReContainer::nextData(QByteArray& data, bool append) {
  * @return                  a human readable string describing the container
  */
 QByteArray ReContainer::dump(const char* title, int maxBags,
-    int maxStringLength, int maxBlobLength, char separatorItems) {
+       int maxStringLength, int maxBlobLength, char separatorItems) {
        QByteArray rc;
        rc.reserve(64000);
        rc.append("=== ").append(title).append('\n');
@@ -409,7 +409,7 @@ QByteArray ReContainer::dump(const char* title, int maxBags,
                maxBags = m_countBags;
        for (int ixBag = 0; ixBag < maxBags; ixBag++) {
                rc.append("--- bag ").append(ReStringUtils::toNumber(ixBag)).append(
-                   ":\n");
+                       ":\n");
                nextBag();
                QByteArray item;
                int maxLength;
@@ -422,9 +422,9 @@ QByteArray ReContainer::dump(const char* title, int maxBags,
                        case TAG_INT:
                                iValue = nextInt();
                                rc.append(" i: ").append(ReStringUtils::toNumber(iValue)).append(
-                                   " / ");
+                                       " / ");
                                rc.append(ReStringUtils::toNumber(iValue, "%x")).append(
-                                   separatorItems);
+                                       separatorItems);
                                break;
                        case TAG_STRING:
                                sValue = nextString();
@@ -439,10 +439,10 @@ QByteArray ReContainer::dump(const char* title, int maxBags,
                                rc.append(' ').append((char) currentType).append(": [");
                                rc.append(ReStringUtils::toNumber(item.length())).append("] ");
                                maxLength =
-                                   item.length() < maxBlobLength ?
-                                       item.length() : maxBlobLength;
+                                       item.length() < maxBlobLength ?
+                                               item.length() : maxBlobLength;
                                rc.append(ReStringUtils::hexDump(item.data(), maxLength, 16))
-                                   .append(separatorItems);
+                                       .append(separatorItems);
                                break;
                        default:
                                break;
index 0897aa811ec8e641ba93bb81f368ace004c01f8b..6f9b56fe62b638c264036a281facd6e9db8fa26c 100644 (file)
@@ -21,6 +21,7 @@ enum {
        LOC_MAKE_DIR_2,                 // 12506
        LOC_SET_TIMES_2,        // 12507
 };
+int ReFileUtils::m_maxCharSet = 128;
 
 QDateTime ReFileUtils::m_undefinedTime;
 
@@ -161,11 +162,13 @@ QString ReFileUtils::cleanPath(const QString& path) {
  * @param source               full path of the source file
  * @param target               full path of the target name
  * @param sourceInfo   NULL or the info about the surce
- * @param buffer               IN/OUT: used as
+ * @param buffer               IN/OUT: used for buffering the file content
+ *
  * @return
  */
 QString ReFileUtils::copy(const QString& source, const QString& target,
-                                               const QFileInfo* sourceInfo, QByteArray& buffer){
+                                               const QFileInfo* sourceInfo, QByteArray& buffer,
+                                               bool setUser){
        QString rc;
 #if defined _WIN32
        const ushort* src = source.utf16();
@@ -182,9 +185,23 @@ QString ReFileUtils::copy(const QString& source, const QString& target,
                sourceInfo2.setFile(source);
                sourceInfo = &sourceInfo2;
        }
-       if (! sourceInfo->exists())
+       if (! sourceInfo->exists()){
                rc = QObject::tr("not found: %1").arg(source);
-       else {
+       } else if (sourceInfo->isSymLink()){
+               // sourceInfo->symLink() returns the absolute path for relative links too.
+               // Though we use readlink():
+               size_t size = buffer.capacity();
+               if (size < 4096){
+                       buffer.resize(4096);
+                       size = buffer.capacity();
+               }
+               int length = readlink(source2.constData(), buffer.data(), size);
+               buffer.resize(length);
+               QString link = I18N::s2b(buffer);
+               QFile::link(link, target);
+       } else if (! sourceInfo->isFile()){
+                       rc = QObject::tr("not a regular file: %1").arg(source);
+               } else {
                FILE* fpSource = fopen(source2.constData(), "rb");
                if (fpSource == NULL){
                        rc = QObject::tr("cannot open (%1): %2").arg(errno).arg(source);
@@ -228,6 +245,15 @@ QString ReFileUtils::copy(const QString& source, const QString& target,
                                }
                        }
                        fclose(fpSource);
+#ifdef __linux__
+                       if (setUser){
+                               if (chown(target2.constData(), sourceInfo->ownerId(),
+                                                 sourceInfo->groupId()) != 0 && rc.isEmpty()){
+                                       rc = QObject::tr("cannot set user/gid (%1): %2")
+                                                       .arg(errno).arg(target);
+                               }
+                       }
+#endif
                }
        }
 #endif
@@ -372,6 +398,73 @@ QStringList ReFileUtils::findRootDirs()
        return rc;
 }
 
+/**
+ * Modify a filename until the file does not exist.
+ *
+ * @param filename     filename to modify
+ * @return     "": no unused filename found<br>
+ *                     otherwise: a modification of filename which does not exist
+ */
+QString ReFileUtils::modifyToNonExisting(const QString& path){
+       static const char* charSet = "$_-+=!^#%~01234567890abcdefghijklmnopqrstuvwxyz";
+       static int charSetLength = 0;
+       static char indexOf[128] = { 0 };
+       if (charSetLength == 0){
+               charSetLength = min(m_maxCharSet, strlen(charSet));
+               memset(indexOf, charSetLength, sizeof indexOf);
+               for (int ix = 0; ix < charSetLength; ix++){
+                       indexOf[(int) charSet[ix]] = ix;
+               }
+       }
+       QString rc = path;
+       int ix;
+       // begin is the first index of the filename (without path)
+       int begin = 0;
+       // last is the last index of the filename (without extension)
+       int last = -1;
+       for (ix = rc.length() - 1; ix >= 0; ix--){
+               if (rc.at(ix) == OS_SEPARATOR || rc.at(ix) == OS_2nd_SEPARATOR){
+                       begin = ix - 1;
+                       if (last < 0)
+                               last = rc.length() - 1;
+                       break;
+               } else if (last < 0 && rc.at(ix) == '.')
+                       last = ix + 1;
+       }
+       if (last <= 0)
+               last = rc.length() - 1;
+       // first is the index of the first modified character in the filename
+       int first = last + 1;
+       while (first <= begin && QFile(rc).exists()){
+               if (first < last){
+                                       first++;
+                                       rc[last] = charSet[0];
+               } else if ( (ix = indexOf[rc.at(last).unicode()]) < charSetLength - 1){
+                       rc[last] = charSet[ix + 1];
+               } else {
+                       int pos = last;
+                       rc[last] = charSet[0];
+                       while(true){
+                               if (--pos < begin){
+                                       first = begin + 1;
+                                       rc = "";
+                                       break;
+                               }
+                               if (pos > first){
+                                       first++;
+                                       rc[first] = charSet[0];
+                                       break;
+                               } else if ( (ix = indexOf[rc.at(pos).unicode()]) < charSetLength - 1){
+                                       rc[pos] = charSet[ix + 1];
+                                       break;
+                               } else {
+                                       rc[pos] = charSet[0];
+                               }
+                       }
+               }
+       }
+       return rc;
+}
 /**
  * Returns whether a path is an absolute path.
  *
@@ -413,14 +506,15 @@ bool ReFileUtils::isAbsolutPath(const char* path) {
  *
  * @param path         full name of the directory to inspect
  * @param isFile       OUT: <code>true</code>: this is a file (and not a directory)
- * @return                     <code>true</code>: path is a directory
+ * @return                     <code>true</code>: path is a directory (and not a symbolic
+ *                                     link)
  */
 bool ReFileUtils::isDirectory(const QString& path, bool* isFile)
 {
        QFileInfo info(path);
        bool rc = info.exists();
        if (rc){
-               if (! info.isDir())
+               if (info.isSymLink() || ! info.isDir())
                        rc = false;
                if (isFile != NULL)
                        *isFile = ! rc;
@@ -776,72 +870,6 @@ QByteArray ReFileUtils::replaceExtension(const char* path, const char* ext) {
        return rc;
 }
 
-/**
- * Splits an URL into its parts.
- *
- * Examples:
- * <pre>url: "file:///path/name.ext"
- * protocol: "file:" host: "//" path: "/path/" node: "name.ext" param: ""
- *
- * url: "http://b2.de/xy/index.htm?id=1"
- * protocol: "http:" host: "//b2.de" path: "/xy/" node: "index.htm" param: "?id=1"
- * </pre>
- *
- * @param url          the URL to split
- * @param protocol     OUT: NULL or the protocol
- * @param host         OUT: NULL or the host part
- * @param path         OUT: NULL or the path without the last node
- * @param node         OUT: NULL or the last node of the path
- * @param params       OUT: NULL or the parameters (e.g. at http)
- */
-void ReFileUtils::splitUrl(const QString& url, QString* protocol, QString* host,
-                       QString* path, QString* node, QString* params){
-       if (protocol != NULL)
-               *protocol = ReQStringUtils::m_empty;
-       if (host != NULL)
-               *host = ReQStringUtils::m_empty;
-       if (path != NULL)
-               *path = ReQStringUtils::m_empty;
-       if (params != NULL)
-               *params = ReQStringUtils::m_empty;
-       int ix = url.indexOf(':');
-       if (ix < 0){
-               ix = 0;
-       } else {
-               ix++;
-               if (protocol != NULL)
-                       *protocol = url.mid(0, ix);
-       }
-       int start = ix;
-       if (url.length() >= start + 2 && url.at(start) == '/' && url.at(start + 1) == '/'){
-               ix = url.indexOf("/", start + 2);
-               if (ix < 0)
-                       ix = start + 2;
-               if (host != NULL)
-                       *host = url.mid(start, ix - start);
-               start = ix;
-       }
-       ix = url.lastIndexOf(OS_SEPARATOR);
-       if (ix < 0)
-               ix = url.lastIndexOf(OS_2nd_SEPARATOR);
-       if (ix >= 0){
-               ix++;
-               if (path != NULL)
-                       *path = url.mid(start, ix - start);
-               start = ix;
-       }
-       ix = url.indexOf('?', start);
-       if (ix < 0){
-               if (node != NULL)
-                       *node = url.mid(start);
-       } else {
-               if (node != NULL)
-                       *node = url.mid(start, ix - start);
-               if (params != NULL)
-                       *params = url.mid(ix);
-       }
-}
-
 /**
  * Sets the permissions.
  *
@@ -853,10 +881,10 @@ void ReFileUtils::splitUrl(const QString& url, QString* protocol, QString* host,
 bool ReFileUtils::setPermissions(const char* filename,
                QFile::Permissions permissions, ReLogger* logger) {
        bool rc = true;
-       if (chmod(filename, nativePermissions(permissions)) != 0){
+       if (! QFile::setPermissions(QString(filename), permissions)){
                if (logger != NULL)
                        logger->logv(LOG_ERROR, LOC_SET_TIMES_1,
-                                                "cannot change permissions (%d): $s", errno, filename);
+                                                "cannot change permissions (%d): %s", errno, filename);
                rc = false;
        }
        return rc;
@@ -986,6 +1014,72 @@ int ReFileUtils::seek(FILE* file, int64_t offset, int whence) {
        return rc;
 }
 
+/**
+ * Splits an URL into its parts.
+ *
+ * Examples:
+ * <pre>url: "file:///path/name.ext"
+ * protocol: "file:" host: "//" path: "/path/" node: "name.ext" param: ""
+ *
+ * url: "http://b2.de/xy/index.htm?id=1"
+ * protocol: "http:" host: "//b2.de" path: "/xy/" node: "index.htm" param: "?id=1"
+ * </pre>
+ *
+ * @param url          the URL to split
+ * @param protocol     OUT: NULL or the protocol
+ * @param host         OUT: NULL or the host part
+ * @param path         OUT: NULL or the path without the last node
+ * @param node         OUT: NULL or the last node of the path
+ * @param params       OUT: NULL or the parameters (e.g. at http)
+ */
+void ReFileUtils::splitUrl(const QString& url, QString* protocol, QString* host,
+                          QString* path, QString* node, QString* params){
+       if (protocol != NULL)
+               *protocol = ReQStringUtils::m_empty;
+       if (host != NULL)
+               *host = ReQStringUtils::m_empty;
+       if (path != NULL)
+               *path = ReQStringUtils::m_empty;
+       if (params != NULL)
+               *params = ReQStringUtils::m_empty;
+       int ix = url.indexOf(':');
+       if (ix < 0){
+               ix = 0;
+       } else {
+                       ix++;
+                       if (protocol != NULL)
+                       *protocol = url.mid(0, ix);
+       }
+       int start = ix;
+       if (url.length() >= start + 2 && url.at(start) == '/' && url.at(start + 1) == '/'){
+               ix = url.indexOf("/", start + 2);
+               if (ix < 0)
+                       ix = start + 2;
+               if (host != NULL)
+                       *host = url.mid(start, ix - start);
+               start = ix;
+       }
+       ix = url.lastIndexOf(OS_SEPARATOR);
+       if (ix < 0)
+               ix = url.lastIndexOf(OS_2nd_SEPARATOR);
+       if (ix >= 0){
+               ix++;
+               if (path != NULL)
+                       *path = url.mid(start, ix - start);
+               start = ix;
+       }
+       ix = url.indexOf('?', start);
+       if (ix < 0){
+               if (node != NULL)
+                       *node = url.mid(start);
+       } else {
+               if (node != NULL)
+                       *node = url.mid(start, ix - start);
+               if (params != NULL)
+                       *params = url.mid(ix);
+       }
+}
+
 /**
  * Returns the current file position.
  *
@@ -1003,6 +1097,7 @@ int64_t ReFileUtils::tell(FILE* file) {
        return rc;
 }
 
+
 /**
  * @brief Returns the name of a directory in the temp dir.
  *
index aab4356d63c20e23a8b7ef486164e5f40509a0b4..3c8a7b1048e334f2e115ca559c76635d723cc582 100644 (file)
@@ -47,7 +47,8 @@ public:
        static QByteArray cleanPath(const char* path);
        static QString cleanPath(const QString& path);
        static QString copy(const QString& source, const QString& target,
-                       const QFileInfo* sourceInfo, QByteArray& buffer);
+                       const QFileInfo* sourceInfo, QByteArray& buffer,
+                       bool setUser = true);
        static bool deleteTree(const QString& path, bool withBase,
                ReLogger* logger = NULL);
        static QString extensionOf(const QString& filename);
@@ -57,6 +58,7 @@ public:
        static bool isAbsolutPath(const char* path);
        static bool isDirectory(const QString& path, bool* isFile = NULL);
        static bool isRootDir(const char* path);
+       static QString modifyToNonExisting(const QString& filename);
        static mode_t nativePermissions(QFile::Permissions permissions);
        /** Returns a path with native separators.
         * QT under windows can operator with 2 separators: '\\' and '/'.
@@ -121,6 +123,8 @@ public:
                size_t contentLength = (size_t) - 1, const char* mode = "w");
 public:
        static QDateTime m_undefinedTime;
+       /// see modifyToNonExisting()
+       static int m_maxCharSet;
 };
 
 #endif // REFILEUTILS_HPP
index 8c2037c8f160a4ea5192f4d4b824115ee705139f..2147d6a49a627e76f0f9d88c65183ef80d18b962 100644 (file)
@@ -324,24 +324,6 @@ bool ReLogger::logv(ReLoggerLevel level, int location, const char* format,
        return log(level, location, buffer);
 }
 
-/**
- * @brief Logs (or not) the calling location.
- *
- * @param level                the level of the location
- * @param location     an unique identifier of the location
- * @param format       the logging message with placeholders (like printf).
- * @param ...          the values of the placeholders (varargs)
- * @return                     true: for chaining
- */
-bool ReLogger::logv(ReLoggerLevel level, int location, const QByteArray& format,
-       ...) {
-       char buffer[64000];
-       va_list ap;
-       va_start(ap, format);
-       qvsnprintf(buffer, sizeof buffer, format, ap);
-       va_end(ap);
-       return log(level, location, buffer);
-}
 
 /**
  * @brief Logs (or not) the calling location.
@@ -524,7 +506,8 @@ ReFileAppender::ReFileAppender(const QByteArray& prefix, int maxSize,
                m_currentSize(0),
                m_currentNo(0),
                m_fp(NULL) {
-       open();
+       findLastNo();
+       reopen(true);
 }
 
 /**
@@ -537,21 +520,68 @@ ReFileAppender::~ReFileAppender() {
        }
 }
 
+/**
+ * Finds the largest number of all files with the given pattern.
+ */
+void ReFileAppender::findLastNo()
+{
+       QFileInfo info(m_prefix);
+       QDir parent = info.dir();
+       QStringList patterns;
+       QString basename = info.baseName();
+       patterns << basename + ".*.log";
+       QStringList files = parent.entryList(patterns);
+       m_currentNo = 0;
+       int prefixLength = basename.length() + 1;
+       QString lastFile;
+       int maxNo = 0;
+       for (int ix = 0; ix < files.count(); ix++){
+               int no = atoi(files.at(ix).mid(prefixLength).toLatin1().constData());
+               if (no > maxNo){
+                       m_currentNo = no;
+                       lastFile = files.at(ix);
+               }
+       }
+       qint64 size = QFile(parent.absoluteFilePath(lastFile)).size();
+       if (size < m_maxSize)
+               m_currentNo--;
+       QByteArray fullName;
+       for (int ix = m_currentNo; ix > 0 && ix > m_currentNo - 10; ix--){
+               fullName = nameOf(ix);
+               unlink(fullName);
+       }
+}
+
+/**
+ * Returns the full logfile name of a given number.
+ *
+ * @param no   the number of the logfile
+ * @return             the full name of the logfile
+ */
+QByteArray ReFileAppender::nameOf(int no){
+       char rc[512];
+       qsnprintf(rc, sizeof rc, "%s.%03d.log", m_prefix.data(), no);
+       return rc;
+}
+
 /**
  * @brief Opens the next log file.
+ *
+ * @param first        <code>true</code>: the first open, file should be appended
  */
-void ReFileAppender::open() {
+void ReFileAppender::reopen(bool isFirst) {
        if (m_fp != NULL)
                fclose(m_fp);
-       char fullName[512];
-       qsnprintf(fullName, sizeof fullName, "%s.%03d.log", m_prefix.data(),
-               ++m_currentNo);
-       m_fp = fopen(fullName, "a");
+       QByteArray fullName = nameOf(++m_currentNo);
+       m_fp = fopen(fullName, isFirst ? "a" : "w");
        if (m_fp == NULL)
-               fprintf(stderr, "cannot open: %s\n", fullName);
+               fprintf(stderr, "cannot open: %s\n", fullName.constData());
        else {
-               //@ToDo
-               m_currentSize = 0;
+               m_currentSize = isFirst ? QFile(fullName).size() : 0;
+       }
+       if (m_currentNo - m_maxCount > 0){
+               fullName = nameOf(m_currentNo - m_maxCount);
+               unlink(fullName.constData());
        }
 }
 
@@ -571,6 +601,15 @@ void ReFileAppender::log(ReLoggerLevel level, int location, const char* message,
                fputs(message, m_fp);
                fputc('\n', m_fp);
                fflush(m_fp);
+               const int NEWLINE_LENGTH
+#ifdef __linux__
+                               = 1;
+#else
+                               = 2;
+#endif
+               m_currentSize += prefix.length() + strlen(message) + NEWLINE_LENGTH;
+               if (m_currentSize >= m_maxSize)
+                       reopen(false);
        }
 }
 
index a8063d471c6e4d0ad3b6b0cc80ef0fed39e30391..f3cc7520a058d82e619127e8a15d270f89bd53a1 100644 (file)
@@ -92,7 +92,6 @@ public:
        bool log(ReLoggerLevel level, int location, const QByteArray& message);
        bool log(ReLoggerLevel level, int location, const ReString& message);
        bool logv(ReLoggerLevel level, int location, const char* format, ...);
-       bool logv(ReLoggerLevel level, int location, const QByteArray& format, ...);
        bool log(ReLoggerLevel level, int location, const char* format,
                va_list& varlist);
        void addAppender(ReAppender* appender);
@@ -149,10 +148,12 @@ public:
                const char* appenderName = "FileAppender");
        virtual ~ReFileAppender();
 public:
-       void open();
+       void findLastNo();
+       void reopen(bool first);
        virtual void log(ReLoggerLevel level, int location, const char* message,
                ReLogger* logger);
 
+       QByteArray nameOf(int no);
 private:
        // prefix of the log file name. Will be appended by ".<no>.log"
        QByteArray m_prefix;
index 7469921f83a6d63fa5baa56dcc9f6e1f4d1521c0..2fdd8569570c8ac243ca37df17c389f89e4740cd 100644 (file)
@@ -37,7 +37,7 @@ QByteArray ReProcess::executeAndRead(const QString& program,
        if (mergeStdError)
                process.setProcessChannelMode(QProcess::MergedChannels);
        process.start(program, args, QIODevice::ReadOnly);
-       process.waitForFinished();
+       process.waitForFinished(timeout * 1000);
        QByteArray rc = process.readAllStandardOutput();
        QString error = process.errorString();
        return rc;
index 6bb421f28f7a7532f1d844c3b79f7c3e015bb69b..c05b8c503c0571c0c438780e3f85dcdba49b9415 100644 (file)
@@ -31,6 +31,19 @@ public:
                else
                        return source.toLocal8Bit();
        }
+       /** Converts a <code>QString</code> into a <code>QByteArray</code>.
+        * The character set is a global setting: <code>m_standardCharSet</code>.
+        * @param source        the string to convert
+        * @return      the converted string
+        */
+       inline static QString b2s(const QByteArray& source){
+               if (m_standardCharSet == UTF8)
+                       return QString::fromUtf8(source);
+               else if (m_standardCharSet == LATIN)
+                       return QString::fromLatin1(source);
+               else
+                       return QString::fromLocal8Bit(source);
+       }
 public:
        static CharSet m_standardCharSet;
 };
index 70391252bf3474a5c7f9ceec6127521cfa2d6762..d8b450e0d07b145e4ecd426350028db8b59b22ad 100644 (file)
@@ -41,7 +41,7 @@ static const char* m_base64Chars =
  */
 QByteArray& ReStringUtils::base64Decode(const char* input, int inputLength, QByteArray& output) {
        static uint8_t decoder[256] = {0};
-       if (decoder['A'] == 0){
+       if (decoder[(int)'A'] == 0){
                for (int ix = strlen(m_base64Chars) - 1; ix >= 0; ix--)
                        decoder[(int) m_base64Chars[ix]] = ix;
        }
index fd6898bd5ec3d64296692bfcdc67ecfeedb6da58..60dfb22b5e0c4a3459b5844a361cf67c426d1d67 100644 (file)
@@ -150,6 +150,9 @@ inline double max(double a, double b) {
 inline double min(double a, double b) {
        return a < b ? a : b;
 }
+inline qint64 _abs(qint64 a){
+       return a >= 0 ? a : -1;
+}
 
 /** Returns the integer value of a hex digit.
  * @param hex                  the hex digit
index 80a8b18509dff90ccf5f712d06e16cba3fc2e1a8..21f7d91b35e051a0800be1264963372162cbc88b 100644 (file)
 #define TRACE2(format, a1, a2) printf(format, a1, a2)
 #define TRACE_IT(args) printf args
 #define IF_TRACE(statem) statem
+#define DECLARE_TRACER(varName, fileName) static ReTracer varName(fileName)
+// Example: FILETRACE_IT(s_tracerLoop, (s_tracerLoop.m_fp, "value: %d", 33));
+#define FILETRACE_IT(varName, args) do { fprintf args; fflush(varName.m_fp); } while(false)
 #else
 #define TRACE(m)
 #define TRACE1(format, a1)
 #define TRACE2(format, a1, a2)
 #define TRACE_IT(args)
 #define IF_TRACE(statem)
+#define DECLARE_TRACER(varName, fileName)
+#define FILETRACE_IT(varName, args)
 #endif
 
 #ifdef WITH_TRACE
-static QByteArray hexBytes(const void* arg, int length = 8){
-       char buffer[16+1];
-       const unsigned char* src = reinterpret_cast<const unsigned char*>(arg);
-       QByteArray rc;
-       rc.reserve(length * 2);
-       for (int ii = 0; ii < length; ii++){
-               snprintf(buffer, sizeof buffer, "%02x", src[ii]);
-               rc += buffer;
-       }
-       return rc;
+#define DECLARE_HEX_BYTES static QByteArray hexBytes(const void* arg, int length = 8){ \
+       char buffer[16+1]; \
+       const unsigned char* src = reinterpret_cast<const unsigned char*>(arg); \
+       QByteArray rc; \
+       rc.reserve(length * 2); \
+       for (int ii = 0; ii < length; ii++){ \
+               snprintf(buffer, sizeof buffer, "%02x", src[ii]); \
+               rc += buffer; \
+       } \
+       return rc; \
 }
+
+class ReTracer {
+public:
+       ReTracer(const char* filename) :
+               m_file(filename),
+               m_fp(fopen(filename, "a")){
+               if (m_fp == NULL)
+                       fprintf(stderr, "+++ cannot open: %s", filename);
+       }
+       ~ReTracer(){
+               if (m_fp != NULL)
+                       fclose(m_fp);
+               m_fp = NULL;
+       }
+protected:
+       QByteArray m_file;
+public:
+       FILE* m_fp;
+};
+#else
+#define DECLARE_HEX_BYTES
 #endif // WITH_TRACE
 #endif // RETRACE_HPP
 
index d5394674d768810b84aa7193a57a511a50cca399..cc5dc8119a48e8ad5cd8ebf11df62b0d2aaddb43 100644 (file)
 
 static bool s_allTest = false;
 
-static void testGui() {
-       char* argv[2] = { (char*) "dummy", NULL };
-       int argc = 1;
-       QApplication a(argc, argv);
-       void testReStateStorage();
-       void testReEdit();
-       void testReSettings();
-       testReSettings();
-       testReStateStorage();
-       testReEdit();
-}
-
 static void testBase() {
        void testReProgArgs();
        void testReProcess();
@@ -64,6 +52,20 @@ static void testBase() {
                testReWriter();
        }
 }
+
+#if 0
+static void testGui() {
+       char* argv[2] = { (char*) "dummy", NULL };
+       int argc = 1;
+       QApplication a(argc, argv);
+       void testReStateStorage();
+       void testReEdit();
+       void testReSettings();
+       testReSettings();
+       testReStateStorage();
+       testReEdit();
+}
+
 static void testMath() {
 
 }
@@ -100,8 +102,10 @@ static void testOs() {
        testReFileSystem();
        testReCryptFileSystem();
 }
+#endif
 void allTests() {
        testBase();
+#if 0
        testOs();
        testExpr();
        testGui();
@@ -111,5 +115,6 @@ void allTests() {
                testNet();
                testOs();
        }
+#endif
 }
 
index 13c80af8cc00cd9856a7432fa064951b63036f81..ef4dc7bdb805c767b93caa2f78cd4b35786d83a2 100644 (file)
@@ -17,7 +17,7 @@
 class TestReByteStorage: public ReTest {
 public:
        TestReByteStorage() :
-                   ReTest("ReByteStorage") {
+                       ReTest("ReByteStorage") {
                doIt();
        }
 private:
index af4f614c7fe2f5492c9584d54a5341f96bb407f1..533d777f47cd6eab60841738f144865fce5f9e5c 100644 (file)
@@ -45,7 +45,7 @@ public:
                        ReFileUtils::tempDirEmpty("subdir2", "cuReFileUtils", true));
                QByteArray subdir(dir);
                subdir.append("subdirX");
-        _mkdir(subdir.constData());
+               _mkdir(subdir.constData());
                struct stat info;
                checkEqu(0, stat(subdir.constData(), &info));
                ReFileUtils::tempDirEmpty("subdir2", "cuReFileUtils", true);
@@ -65,13 +65,13 @@ public:
                QByteArray base = ReFileUtils::tempDir("ReFileUtils");
                for (char cc = 'a'; cc < 'f'; cc++) {
                        QByteArray subdir(base + cc);
-            _mkdir(subdir.constData());
+                       _mkdir(subdir.constData());
                        for (char cc2 = '1'; cc2 < '5'; cc2++) {
                                QByteArray name(subdir);
                                name.append(OS_SEPARATOR_STR).append(&cc2, 1);
                                ReFileUtils::writeToFile(name, name);
                                name += "dir";
-                _mkdir(name.constData());
+                               _mkdir(name.constData());
                                name.append(OS_SEPARATOR_STR).append("x.txt");
                                ReFileUtils::writeToFile(name, name);
                        }
@@ -87,7 +87,7 @@ public:
                // the dir must exist:
                checkEqu(0, stat(base, &info));
                // rmdir() works only if the dir is empty:
-        checkEqu(0, _rmdir(base));
+               checkEqu(0, _rmdir(base));
                buildTree();
                checkT(ReFileUtils::deleteTree(QString(base), false, &m_logger));
                checkEqu(0, stat(base, &info));
@@ -354,8 +354,45 @@ public:
                checkLogContainsLocation(51003);
                checkLogContains(dir.constData(), false);
        }
+       void testIsDirectoy(){
+               QByteArray dir(ReFileUtils::tempDir("subdir", "cuReFileUtils", false));
+               checkT(ReFileUtils::isDirectory(dir));
+               QByteArray fn(ReFileUtils::tempFile("node.txt", "subdir", false));
+               ReStringUtils::write(fn);
+               checkF(ReFileUtils::isDirectory(fn));
+               checkF(ReFileUtils::isDirectory("/isImpossible/dir/nowhere"));
+       }
+       void testIsRoot(){
+#if defined __linux__
+               checkT(ReFileUtils::isRootDir("/"));
+               checkF(ReFileUtils::isRootDir("/doesNotExist"));
+               checkF(ReFileUtils::isRootDir("/etc"));
+#elif defined _WIN32
+               checkT(ReFileUtils::isRootDir("c:\\"));
+               checkF(ReFileUtils::isRootDir("z:\\doesNotExist"));
+               checkF(ReFileUtils::isRootDir("c:\\windows"));
+#endif
+       }
+       void testSetPermissions(){
+               QByteArray fn(ReFileUtils::tempFile("node.txt", "subdir", false));
+               ReStringUtils::write(fn);
+               QFile::Permissions perms = QFile::ReadUser | QFile::WriteUser | QFile::ExeUser;
+               checkT(ReFileUtils::setPermissions(fn, perms));
+               checkT(perms == QFile::permissions(fn));
+       }
+       void testMakeDir(){
+               QByteArray base(ReFileUtils::tempDir("cuReFileUtils", NULL, true));
+               QByteArray dir = base + "newdir";
+               ReFileUtils::deleteTree(dir, true, &m_logger);
+               checkT(ReFileUtils::makeDir(dir.constData(), &m_logger));
+               ReFileUtils::deleteTree(dir, true, &m_logger);
+               checkT(ReFileUtils::makeDir(QString(dir), &m_logger));
+       }
 
        virtual void runTests() {
+               testSetPermissions();
+               testIsRoot();
+               testIsDirectoy();
                testMakeDirectoryWithParents();
 
                testSplitUrl();
index 2155eb08cb02f05606cc1083a351b950ddc92928..07c118a41d30a21e9fa7079bb9e87e142bdd4ce1 100644 (file)
@@ -146,7 +146,6 @@ public:
                args.addBool("boolArg", "a bool arg", 'b', "bool-arg", false);
                args.addInt("intArg", "integer arg", 'i', "int-arg", 99);
                args.addString("stringArg", "string argument", 's', "string-arg", true, "");
-               const char* arguments[] = { "example" };
                QByteArrayList list;
                args.help("dummy error", false, list);
                QByteArray expected = "usage: example prog\n"
index ed9c3bb58aabbcb113f82d3d0bd70a8b94b35faa..fe743cbe1674afc3aea61343875e85b6a5ef2164 100644 (file)
@@ -33,7 +33,7 @@ public:
        }
 
        void testLengthOfUInt64() {
-               uint64_t value = -3;
+               quint64 value = -3;
                checkEqu(1,
                        ReQStringUtils::lengthOfUInt64(ReString("0"), 0, 10, &value));
                checkEqu(int64_t(0), value);
index 4a06f5d1ba9ef017c4ec6f91ea9f227aa902fdd4..b6adb3c9a73276e3af93595072768abfc7a9a5e8 100644 (file)
@@ -39,7 +39,7 @@ public:
                rand.saveSeed(seed2);
                checkEqu(seed1, seed2);
                char cc2 = rand.nextChar();
-               if (cc1 != cc1) {
+               if (cc1 != cc2) {
                        checkEqu(cc1, cc2);
                }
 
index 7cb6f61c2510e7beffa2a3d92126b32d46bb0a0e..e510dc247107f45741dabd587df5ab5c409477f2 100644 (file)
@@ -18,17 +18,6 @@ TEMPLATE = app
 INCLUDEPATH = ..
 
 SOURCES += main.cpp \
-       cuReLexer.cpp \
-       cuReProgArgs.cpp \
-        cuReFileSystem.cpp \
-        cuReCryptFileSystem.cpp \
-        cuReRandomizer.cpp \
-        cuReQStringUtils.cpp \
-        cuReStringUtils.cpp \
-        cuReFile.cpp \
-        cuReFileUtils.cpp \
-        cuReByteStorage.cpp \
-        cuReException.cpp \
        ../expr/ReSource.cpp \
        ../expr/ReLexer.cpp \
         ../base/ReByteStorage.cpp \
@@ -51,18 +40,31 @@ SOURCES += main.cpp \
        ../gui/ReEdit.cpp \
        ../os/ReFileSystem.cpp \
        ../os/ReCryptFileSystem.cpp \
+        allTests.cpp \
+        cuReException.cpp \
+       cuReProcess.cpp \
+       cuReMatcher.cpp \
         cuReConfig.cpp \
         cuReContainer.cpp \
         cuReWriter.cpp \
         cuReCharPtrMap.cpp \
+        cuReRandomizer.cpp \
+        cuReQStringUtils.cpp \
+        cuReStringUtils.cpp \
+        cuReFile.cpp \
+        cuReFileUtils.cpp \
+        cuReByteStorage.cpp \
+       cuReProgArgs.cpp \
+       ../base/ReProcess.cpp \
+       ../base/ReProgramArgs.cpp
+
+RESERVE =      \
        cuReEdit.cpp \
        cuReStateStorage.cpp \
        cuReSettings.cpp \
-       cuReMatcher.cpp \
-        allTests.cpp \
-       ../base/ReProcess.cpp \
-       cuReProcess.cpp \
-       ../base/ReProgramArgs.cpp
+       cuReLexer.cpp \
+        cuReFileSystem.cpp \
+        cuReCryptFileSystem.cpp \
 
 HEADERS += \
         ../base/ReFile.hpp \
index 19adf491305dee790117c0254941c748f738ec61..447ea6be84867ef681a31b103f435e221249948f 100644 (file)
 #include <QCoreApplication>
 
 int main(int argc, char *argv[]) {
-       QCoreApplication a(argc, argv);
+       printf("main...\n");
+       //QCoreApplication a(argc, argv);
        void allTests();
        allTests();
-       return a.exec();
+       //return a.exec();
+       return 0;
 }
index 66cc75f2069b20913e772e1b2b80470aed4dd47b..a57fb4cd3af6d50ae1b3dac96fc7bf59fcd454fe 100644 (file)
@@ -428,7 +428,7 @@ static void charClassToCharInfo(const char* charClass, int flag,
                if (charClass[ix + 1] == '-') {
                        unsigned char ubound = charClass[ix + 2];
                        if (ubound == '\0')
-                               charInfo['-'] |= flag;
+                               charInfo[(int) '-'] |= flag;
                        else if (cc >= ubound)
                                throw new ReException("wrong character class range: %c-%c (%s)",
                                        cc, ubound, charClass);
index cea4ab519487a1e5eea21a3450903daf155bc10c..a2340c812e431c55538610ef11ef89b8f2fcb5b9 100644 (file)
@@ -96,6 +96,10 @@ QString ReGuiApplication::buildHomeDir(QString homeDirBase, const QString& node)
                homeDir = ReFileUtils::nativePath(QDir::home().absoluteFilePath(node));
        } else if (ReFileUtils::isRootDir(homeDirBase.toLatin1().constData())){
                homeDir = homeDirBase + node;
+       } else {
+               homeDir = homeDirBase;
+               ReQStringUtils::ensureLastChar(homeDir, OS_SEPARATOR);
+               homeDir += node;
        }
        ReQStringUtils::chomp(homeDir, OS_SEPARATOR);
        QDir home(homeDir);
@@ -197,7 +201,7 @@ void ReGuiApplication::initializeGuiElements(){
        QCoreApplication* app = QCoreApplication::instance();
        QObject::connect(app, SIGNAL(aboutToQuit()), this, SLOT(onAboutToQuit()));
        connect(m_guiTimer, SIGNAL(timeout()), this, SLOT(onGuiTimerUpdate()));
-       m_guiTimer->start(100);
+       m_guiTimer->start(500);
        statusBar()->addWidget(m_statusMessage);
        m_guiIsInitialized = true;
 }
index eed6b29f9446d49896282ffc5bef99638cd3e06a..135d639801f14f19e71a5d425908427697f1bc51 100644 (file)
@@ -71,8 +71,8 @@ typedef QMap<QByteArray, QList<ReProperty*>*> ReChapterMap;
 
 class ReSettings {
 public:
-       static QString m_TRUE;
-       static QString m_FALSE;
+       static QString TRUE;
+       static QString FALSE;
 public:
        ReSettings(const QString& path, const QString& prefix, ReLogger* logger);
        ~ReSettings();