From fa5dd7d5905a82dd6d53cc9261d5d5119283c5d4 Mon Sep 17 00:00:00 2001
From: hama
Date: Tue, 12 Apr 2016 00:52:57 +0200
Subject: [PATCH] v2016.04.07, rebackgui, warnings found by clang
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 /.reappl
* ReTracer
---
PrepTmp.sh | 8 ++
RenTmp.sh | 4 +
appl/rebackgui/BackupEngine.cpp | 94 ++++++++++--
appl/rebackgui/main.cpp | 13 +-
appl/rebackgui/mainwindow.cpp | 6 +-
appl/rebackgui/mainwindow.ui | 34 ++---
appl/rebackgui/rebackgui.de.qm | Bin 0 -> 21696 bytes
appl/rebackgui/rebackgui.de.ts | 119 +++++++++-------
appl/rebackgui/rebackgui.html | 73 ++++++++++
appl/rebackgui/rebackgui.pro | 3 +-
appl/recommand/recommand.pro | 3 +-
base/ReConfig.hpp | 2 +-
base/ReContainer.cpp | 60 ++++----
base/ReFileUtils.cpp | 243 ++++++++++++++++++++++----------
base/ReFileUtils.hpp | 6 +-
base/ReLogger.cpp | 93 ++++++++----
base/ReLogger.hpp | 5 +-
base/ReProcess.cpp | 2 +-
base/ReQStringUtils.hpp | 13 ++
base/ReStringUtils.cpp | 2 +-
base/rebase.hpp | 3 +
base/retrace.hpp | 46 ++++--
cunit/allTests.cpp | 29 ++--
cunit/cuReByteStorage.cpp | 2 +-
cunit/cuReFileUtils.cpp | 45 +++++-
cunit/cuReProgArgs.cpp | 1 -
cunit/cuReQStringUtils.cpp | 2 +-
cunit/cuReRandomizer.cpp | 2 +-
cunit/cunit.pro | 34 ++---
cunit/main.cpp | 6 +-
expr/ReLexer.cpp | 2 +-
gui/ReGuiApplication.cpp | 6 +-
gui/ReSettings.hpp | 4 +-
33 files changed, 681 insertions(+), 284 deletions(-)
create mode 100755 PrepTmp.sh
create mode 100755 RenTmp.sh
create mode 100644 appl/rebackgui/rebackgui.de.qm
create mode 100644 appl/rebackgui/rebackgui.html
diff --git a/PrepTmp.sh b/PrepTmp.sh
new file mode 100755
index 0000000..dd555f5
--- /dev/null
+++ b/PrepTmp.sh
@@ -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
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/*
diff --git a/appl/rebackgui/BackupEngine.cpp b/appl/rebackgui/BackupEngine.cpp
index 9e9a138..f723be5 100644
--- a/appl/rebackgui/BackupEngine.cpp
+++ b/appl/rebackgui/BackupEngine.cpp
@@ -10,6 +10,13 @@
*/
#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")
diff --git a/appl/rebackgui/main.cpp b/appl/rebackgui/main.cpp
index df7047f..2c2fcde 100644
--- a/appl/rebackgui/main.cpp
+++ b/appl/rebackgui/main.cpp
@@ -15,10 +15,11 @@
#include
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();
}
diff --git a/appl/rebackgui/mainwindow.cpp b/appl/rebackgui/mainwindow.cpp
index c430ab9..e15d172 100644
--- a/appl/rebackgui/mainwindow.cpp
+++ b/appl/rebackgui/mainwindow.cpp
@@ -13,7 +13,7 @@
#include "aboutdialog.hpp"
#include
-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();
diff --git a/appl/rebackgui/mainwindow.ui b/appl/rebackgui/mainwindow.ui
index f556cc3..8fb4ae9 100644
--- a/appl/rebackgui/mainwindow.ui
+++ b/appl/rebackgui/mainwindow.ui
@@ -197,7 +197,7 @@
-
-
+
-
@@ -785,12 +785,12 @@
0
0
839
- 26
+ 29
diff --git a/appl/rebackgui/rebackgui.de.qm b/appl/rebackgui/rebackgui.de.qm
new file mode 100644
index 0000000000000000000000000000000000000000..ca4ccf55cbd745f203875ecdb6ddf58326a21cdd
GIT binary patch
literal 21696
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 )
zWYSvA9$o%5v$fU4iBys>6=H6&h?uBwMmA7{2(pZ;t}D7zFK3{g^>+Qe!2w(e}=%9
zmn*z&N;y29xm3*InVtx&rXn}+I;1_rL%I{AUS(jWAzxY~7JzY>uCMhrRd%JfXQ&r_
zzd3N6g}*xfw(!|!AK>OQ`t-lbMqY^qD0Nl~qO)&MTh^Waq>j7H915%EPA-1g2@_9H
V9x9daWRrS|r|Dg|x~Zw@{{T)VO$-14
literal 0
HcmV?d00001
diff --git a/appl/rebackgui/rebackgui.de.ts b/appl/rebackgui/rebackgui.de.ts
index e1adf8b..b8a17ec 100644
--- a/appl/rebackgui/rebackgui.de.ts
+++ b/appl/rebackgui/rebackgui.de.ts
@@ -106,7 +106,6 @@ p, li { white-space: pre-wrap; }
-
Action
Aktion
@@ -205,7 +204,6 @@ p, li { white-space: pre-wrap; }
-
Stop
Beenden
@@ -217,7 +215,6 @@ p, li { white-space: pre-wrap; }
-
Checksums
Prüfsummen
@@ -228,7 +225,6 @@ p, li { white-space: pre-wrap; }
-
Clean
Protokoll:
Bereinigen
@@ -272,7 +268,6 @@ p, li { white-space: pre-wrap; }
-
Autosave
Autom. Speichern
@@ -356,81 +351,91 @@ p, li { white-space: pre-wrap; }
- File
+ Fi&le
+ File
Bearbeiten
- Datei
+ Datei
- Edit
- Bearbeiten
+ Edi&t
+ Edit
+ Bearbeiten
- Help
- Hilfe
+ Hel&p
+ Help
+ Hilfe
- Load Config
- Konfiguration laden
+ &Load Config
+ Load Config
+ Konfiguration laden
- Save Config
- Konfiguration sichern
+ &Save Config
+ Save Config
+ Konfiguration sichern
- Exit
- Beenden
+ &Exit
+ Exit
+ Beenden
- Start backup
- Sicherung starten
+ &Start backup
+ Start backup
+ Sicherung starten
- About
- Ãber
+ &About
+ About
+ Ãber
- English
-
+ &English
+ English
+
- German
-
+ &German
+ German
+
-
-
-
+
+
+
no backup item selected
Kein Sicherungselement ausgewählt
-
-
-
+
+
+
Target not available
Ziel nicht vorhanden
-
+
Select Source Directory
Quellverzeichnis auswählen
-
+
Select Target Directory
Zielverzeichnis auswählen
-
+
target initialized with %1
Ziel mit %1 vorbelegt
@@ -519,17 +524,22 @@ p, li { white-space: pre-wrap; }
Suche beendet: zu behandeln: %1 mit %2 passend: %3 gesamt: %4 Unterverz: %5 Laufzeit: %6
-
+
+ kann Schattenverzeichnis nicht umbenennen: %1 -> %2
+
+
+
+
cannot create shadow directory (%1): %2
Kann Schattenverzeichnis nicht erstellen (%1): %2
-
+
cannot move to shadow directory (%1): %2 -> %3
Kann Datei nicht in Schattenverzeichnis verschieben (%1): %2 -> %3
-
+
Search in target finished: to process: %1 with %2 dirs to delete: %3 total: %4 subdirs: %5 runtime: %6
Suche im Ziel bendet: zu behandeln: %1 mit %2 zu löschende Verzeichnisse: %3 gesamt: %4 Unterverz.: %5 Laufzeit: %6
@@ -540,9 +550,9 @@ p, li { white-space: pre-wrap; }
-
-
-
+
+
+
cannot open (%1): %2
Kann nicht öffnen (%1): %2
@@ -552,33 +562,33 @@ p, li { white-space: pre-wrap; }
Unbekanntes Format in %1-%2: %3
-
+
cannot write (%1): %2
Kann nicht schreiben (%1): %2
-
+
configuration saved: %1
configuration changed: %1
Konfiguration gespeichert: %1
-
+
Search started...
Suche gestartet...
-
+
yes
Ja
-
+
no
nein
-
+
not found: %1
Nicht gefunden: %1
@@ -587,32 +597,37 @@ p, li { white-space: pre-wrap; }
Kann nicht schreiben(%1): %2 [%3/%4]
-
+
+ copy file failed (%1): %2
+
+
+
+
cannot write (%1): %2 [%3/%4]
Kann nicht schreiben(%1): %2 [%3/%4]
-
+
file can be read only partitionally: %1 [%2/%3]
Datei kann nur teilweise gelesen werden: %1 [%2/%3]
-
+
cannot set date/time (%1): %2
Kann Datum/Zeit nicht setzen (%1): %2
-
+
cannot set permissions (%1): %2
Kann Dateirechte nicht setzen (%1): %2
-
+
can't create directory (%1): %2
Kann Verzeichnis nicht erzeugen (%1): %2
-
+
can't create directory (is a file):
Kann Verzeichnis nicht erzeugen (ist eine Datei):
diff --git a/appl/rebackgui/rebackgui.html b/appl/rebackgui/rebackgui.html
new file mode 100644
index 0000000..8ca4bc0
--- /dev/null
+++ b/appl/rebackgui/rebackgui.html
@@ -0,0 +1,73 @@
+
+
+
+
+
+Release Notes
+
+
+
+
+User Manual
+Purpose:
+This program makes backups.
+
+Usage
+hmbackgui [<home_dir>]
+<home_dir>:
+ the base directory for the configuration directory ".reappl"
+ Default: the home directory of the user
+
+Example:
+hmbackgui /home/hugo
+
+
+Installation
+Linux
+
+
Copy rebackgui to /usr/local/bin
+Copy rebackgui.*.qm to the configuration directory, e.g. /home/hm/.reappl
+
+cd /usr/local/bin
+chown root.root rebackgui
+chmod u+s rebackgui
+
+
+
+Configuration
+The configuration is stored in <home_dir>/.rebackgui/rebackgui.conf
+
+
+Program Documentation
+
+Programming Features
+
+This is a example for a complete QT application with the following features:
+
+multithreaded
+pattern matching
+multithreaded GUI building
+
+
+
+(Un)License: Public Domain
+
+You can use and modify this file without any restriction.
+Do what you want.
+No warranties and disclaimer of any damages.
+More info: http://unlicense.org
+The latest sources: https://github.com/republib .
+
+
+
+
diff --git a/appl/rebackgui/rebackgui.pro b/appl/rebackgui/rebackgui.pro
index 4b10c3d..ba86e1c 100644
--- a/appl/rebackgui/rebackgui.pro
+++ b/appl/rebackgui/rebackgui.pro
@@ -53,7 +53,8 @@ FORMS += mainwindow.ui \
DISTFILES += \
ReBackGui.html \
- osconnect.pl
+ osconnect.pl \
+ rebackgui.html
TRANSLATIONS = rebackgui.de.ts
CODECFORTR = UTF-8
diff --git a/appl/recommand/recommand.pro b/appl/recommand/recommand.pro
index 8efbe4f..318b324 100644
--- a/appl/recommand/recommand.pro
+++ b/appl/recommand/recommand.pro
@@ -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 \
diff --git a/base/ReConfig.hpp b/base/ReConfig.hpp
index 617e566..b2bdb44 100644
--- a/base/ReConfig.hpp
+++ b/base/ReConfig.hpp
@@ -11,7 +11,7 @@
#ifndef RECONFIG_HPP
#define RECONFIG_HPP
-class ReConfig: public ReConfigurator, protected QHash {
+class ReConfig: public ReConfigurator, public QHash {
public:
ReConfig(const char* file = NULL, bool readOnly = true, ReLogger* logger =
NULL);
diff --git a/base/ReContainer.cpp b/base/ReContainer.cpp
index 62d7683..9f50f2d 100644
--- a/base/ReContainer.cpp
+++ b/base/ReContainer.cpp
@@ -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", m_readPosition, 16);
+ "not a hex_number", 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", m_readPosition, 16);
+ "not a hex_number", 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;
diff --git a/base/ReFileUtils.cpp b/base/ReFileUtils.cpp
index 0897aa8..6f9b56f 100644
--- a/base/ReFileUtils.cpp
+++ b/base/ReFileUtils.cpp
@@ -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
+ * 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: true
: this is a file (and not a directory)
- * @return true
: path is a directory
+ * @return true
: 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:
- * 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"
- *
- *
- * @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:
+ * 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"
+ *
+ *
+ * @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.
*
diff --git a/base/ReFileUtils.hpp b/base/ReFileUtils.hpp
index aab4356..3c8a7b1 100644
--- a/base/ReFileUtils.hpp
+++ b/base/ReFileUtils.hpp
@@ -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
diff --git a/base/ReLogger.cpp b/base/ReLogger.cpp
index 8c2037c..2147d6a 100644
--- a/base/ReLogger.cpp
+++ b/base/ReLogger.cpp
@@ -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 true
: 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);
}
}
diff --git a/base/ReLogger.hpp b/base/ReLogger.hpp
index a8063d4..f3cc752 100644
--- a/base/ReLogger.hpp
+++ b/base/ReLogger.hpp
@@ -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 "..log"
QByteArray m_prefix;
diff --git a/base/ReProcess.cpp b/base/ReProcess.cpp
index 7469921..2fdd856 100644
--- a/base/ReProcess.cpp
+++ b/base/ReProcess.cpp
@@ -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;
diff --git a/base/ReQStringUtils.hpp b/base/ReQStringUtils.hpp
index 6bb421f..c05b8c5 100644
--- a/base/ReQStringUtils.hpp
+++ b/base/ReQStringUtils.hpp
@@ -31,6 +31,19 @@ public:
else
return source.toLocal8Bit();
}
+ /** Converts a QString
into a QByteArray
.
+ * The character set is a global setting: m_standardCharSet
.
+ * @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;
};
diff --git a/base/ReStringUtils.cpp b/base/ReStringUtils.cpp
index 7039125..d8b450e 100644
--- a/base/ReStringUtils.cpp
+++ b/base/ReStringUtils.cpp
@@ -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;
}
diff --git a/base/rebase.hpp b/base/rebase.hpp
index fd6898b..60dfb22 100644
--- a/base/rebase.hpp
+++ b/base/rebase.hpp
@@ -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
diff --git a/base/retrace.hpp b/base/retrace.hpp
index 80a8b18..21f7d91 100644
--- a/base/retrace.hpp
+++ b/base/retrace.hpp
@@ -19,26 +19,52 @@
#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(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(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
diff --git a/cunit/allTests.cpp b/cunit/allTests.cpp
index d539467..cc5dc81 100644
--- a/cunit/allTests.cpp
+++ b/cunit/allTests.cpp
@@ -17,18 +17,6 @@
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
}
diff --git a/cunit/cuReByteStorage.cpp b/cunit/cuReByteStorage.cpp
index 13c80af..ef4dc7b 100644
--- a/cunit/cuReByteStorage.cpp
+++ b/cunit/cuReByteStorage.cpp
@@ -17,7 +17,7 @@
class TestReByteStorage: public ReTest {
public:
TestReByteStorage() :
- ReTest("ReByteStorage") {
+ ReTest("ReByteStorage") {
doIt();
}
private:
diff --git a/cunit/cuReFileUtils.cpp b/cunit/cuReFileUtils.cpp
index af4f614..533d777 100644
--- a/cunit/cuReFileUtils.cpp
+++ b/cunit/cuReFileUtils.cpp
@@ -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();
diff --git a/cunit/cuReProgArgs.cpp b/cunit/cuReProgArgs.cpp
index 2155eb0..07c118a 100644
--- a/cunit/cuReProgArgs.cpp
+++ b/cunit/cuReProgArgs.cpp
@@ -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"
diff --git a/cunit/cuReQStringUtils.cpp b/cunit/cuReQStringUtils.cpp
index ed9c3bb..fe743cb 100644
--- a/cunit/cuReQStringUtils.cpp
+++ b/cunit/cuReQStringUtils.cpp
@@ -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);
diff --git a/cunit/cuReRandomizer.cpp b/cunit/cuReRandomizer.cpp
index 4a06f5d..b6adb3c 100644
--- a/cunit/cuReRandomizer.cpp
+++ b/cunit/cuReRandomizer.cpp
@@ -39,7 +39,7 @@ public:
rand.saveSeed(seed2);
checkEqu(seed1, seed2);
char cc2 = rand.nextChar();
- if (cc1 != cc1) {
+ if (cc1 != cc2) {
checkEqu(cc1, cc2);
}
diff --git a/cunit/cunit.pro b/cunit/cunit.pro
index 7cb6f61..e510dc2 100644
--- a/cunit/cunit.pro
+++ b/cunit/cunit.pro
@@ -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 \
diff --git a/cunit/main.cpp b/cunit/main.cpp
index 19adf49..447ea6b 100644
--- a/cunit/main.cpp
+++ b/cunit/main.cpp
@@ -12,8 +12,10 @@
#include
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;
}
diff --git a/expr/ReLexer.cpp b/expr/ReLexer.cpp
index 66cc75f..a57fb4c 100644
--- a/expr/ReLexer.cpp
+++ b/expr/ReLexer.cpp
@@ -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);
diff --git a/gui/ReGuiApplication.cpp b/gui/ReGuiApplication.cpp
index cea4ab5..a2340c8 100644
--- a/gui/ReGuiApplication.cpp
+++ b/gui/ReGuiApplication.cpp
@@ -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;
}
diff --git a/gui/ReSettings.hpp b/gui/ReSettings.hpp
index eed6b29..135d639 100644
--- a/gui/ReSettings.hpp
+++ b/gui/ReSettings.hpp
@@ -71,8 +71,8 @@ typedef QMap*> 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();
--
2.39.5