]> gitweb.hamatoma.de Git - reqt/commitdiff
ReRandomizer::shuffle corrected, project reprime
authorhama <hama@siduction.net>
Tue, 20 Oct 2015 22:07:41 +0000 (00:07 +0200)
committerhama <hama@siduction.net>
Tue, 20 Oct 2015 22:07:41 +0000 (00:07 +0200)
15 files changed:
appl/reprime/.gitignore [new file with mode: 0644]
appl/reprime/Prime.cpp [new file with mode: 0644]
appl/reprime/Prime.hpp [new file with mode: 0644]
appl/reprime/main.cpp [new file with mode: 0644]
appl/reprime/reprime.pro [new file with mode: 0644]
base/ReRandomizer.cpp
base/ReRandomizer.hpp
cunit/cuReRandomizer.cpp
cunit/cunit.pro
os/ReCryptFileSystem.cpp [new file with mode: 0644]
os/ReCryptFileSystem.hpp [new file with mode: 0644]
os/ReFileSystem.cpp
os/ReFileSystem.hpp
os/reos.hpp
remodules.hpp

diff --git a/appl/reprime/.gitignore b/appl/reprime/.gitignore
new file mode 100644 (file)
index 0000000..5439c79
--- /dev/null
@@ -0,0 +1,73 @@
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
+
diff --git a/appl/reprime/Prime.cpp b/appl/reprime/Prime.cpp
new file mode 100644 (file)
index 0000000..6d46371
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Prime.cpp
+ *
+ *  Created on: Oct 8, 2015
+ *      Author: kawi
+ */
+#include "math.h"
+#include "stdlib.h"
+#include "math.h"
+#include "stdio.h"
+#include "unistd.h"
+#include "time.h"
+#include "assert.h"
+#include "base/rebase.hpp"
+#include "Prime.hpp"
+
+Prime::Prime(int64_t from, int count) :
+       m_from(from),
+       m_count(count),
+       m_primes(NULL),
+       m_sizePrimes(0),
+       m_countPrimes(0),
+       m_maxStoredPrimes(0){
+       m_maxStoredPrimes = int (sqrt((double) m_from / 3 / log(sqrt(m_from)))) + 100;
+       m_sizePrimes = m_maxStoredPrimes + 10;
+       fprintf(stderr, "Storing %d primes\n", m_sizePrimes);
+       m_primes = new int64_t[m_sizePrimes];
+       m_primes[0] = 2;
+       m_countPrimes = 1;
+}
+
+Prime::~Prime() {
+}
+void toFile(const char* prefix, int64_t* primes, int count){
+       QByteArray fn = QByteArray(prefix) + "."
+                       + QDateTime::currentDateTime().toLocalTime()
+                       .toString("yyyy.MM.dd_hh_mm_ss").toUtf8() + ".txt";
+       FILE* fp = fopen(fn.constData(), "w");
+       if (fp != NULL){
+               fprintf(stderr, "Result in %s\n", fn.constData());
+               for (int ix = 0; ix < count; ix++){
+                       fprintf(fp, "%lldL, // %llx\n",
+                                       (long long) primes[ix], (long long) primes[ix]);
+               }
+               fclose(fp);
+       }
+
+}
+
+void Prime::calculate() {
+       int64_t x = lastPrime() * lastPrime();
+       int64_t* primes = new int64_t[m_count];
+
+       assert(x % 2 == 1);
+       int nPrinted = 0;
+       while (nPrinted < m_count){
+               while (x > 0){
+                       x -= 2;
+                       bool isPrime = true;
+                       for (int ix = 0; ix < m_countPrimes; ix++){
+                               int64_t fac = m_primes[ix];
+                               if (x % fac == 0){
+                                       isPrime = false;
+                                       break;
+                               }
+                       }
+                       if (isPrime){
+                               printf("%lld, // %llx\n", (long long) x, (long long) x);
+                               fflush(stdout);
+                               primes[nPrinted++] = x;
+                               x -= m_from / m_count / 5;
+                               if (x % 2 == 0)
+                                       x--;
+                               break;
+                       }
+               }
+       }
+       toFile("primes.sorted", primes, m_count);
+       ReKISSRandomizer random;
+       random.nearTrueRandom();
+       random.shuffle(primes, m_count, sizeof primes[0]);
+       toFile("primes.shuffled", primes, m_count);
+}
+
+void Prime::storePrimes() {
+       clock_t start = clock();
+       int counter2 = 0;
+       for (int64_t x = 3; true; x += 2){
+               if (x % (10*1000*1000) == 1){
+                       fprintf(stderr, "%ld Mio: %8.3f\n", x / (1000*1000),
+                                       (clock() - start) / double(CLOCKS_PER_SEC));
+                       if (counter2++ % 5 == 0)
+                               dump();
+                       fflush(stderr);
+               }
+               bool isPrime = true;
+               for (int ix = 0; ix < m_countPrimes; ix++){
+                       int64_t fac = m_primes[ix];
+                       if (x % fac == 0){
+                               isPrime = false;
+                               break;
+                       } else if (fac * fac > x)
+                               break;
+               }
+               if (isPrime) {
+                       m_primes[m_countPrimes++] = x;
+                       if (m_countPrimes >= m_maxStoredPrimes || x * x > m_from)
+                               break;
+               }
+       }
+       dump();
+}
+
+void Prime::dump() {
+       int64_t last = lastPrime();
+       fprintf(stderr, "count primes: %d size primes: %d last prime: %ld lp*lp: %ld\n",
+                  m_countPrimes, m_sizePrimes, last, last * last);
+}
+
+void Prime::run(int argc, char* argv[]){
+       int64_t from = 0x82L * 0x10000 * 0x10000 * 10000; //* 0x10000;
+       int count = 150;
+       if (argc > 1){
+               int64_t lValue;
+               if (sscanf(argv[1], "0x%lx", &lValue) == 1){
+               } else if (sscanf(argv[1], "%ld", &lValue) != 1)
+                       printf("wrong argument 1: %s", argv[1]);
+               else
+                       from = lValue;
+
+               if (argc > 2){
+                       int nValue;
+                       if (sscanf(argv[2], "%d", &nValue) != 1)
+                               printf("wrong argument 2: %s", argv[2]);
+                       else
+                               count = nValue;
+               }
+       }
+
+       fprintf(stderr, "from: %ld/%lx count: %d\n", from, from, count);
+       clock_t start = clock();
+       Prime prime(from, count);
+       prime.storePrimes();
+       fprintf (stderr, "storePrime: %f sec\n",
+                        double (clock() - start) / CLOCKS_PER_SEC);
+       prime.dump();
+       prime.calculate();
+       double duration = double (clock() - start) / CLOCKS_PER_SEC;
+       fprintf (stderr, "duration: %f sec\n", duration);
+}
+
diff --git a/appl/reprime/Prime.hpp b/appl/reprime/Prime.hpp
new file mode 100644 (file)
index 0000000..3c4b4f1
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Prime.hpp
+ *
+ *  Created on: Oct 8, 2015
+ *      Author: kawi
+ */
+
+#ifndef PRIME_HPP_
+#define PRIME_HPP_
+
+//typedef long long int int64_t;
+class Prime {
+public:
+       Prime(int64_t from, int count);
+       virtual ~Prime();
+public:
+       void storePrimes();
+       void calculate();
+       void dump();
+       int64_t lastPrime() const {
+               return m_primes[m_countPrimes - 1];
+       }
+public:
+       static void run(int argc, char* argv[]);
+private:
+       int64_t m_from;
+       int m_count;
+       int64_t* m_primes;
+       int m_sizePrimes;
+       int m_countPrimes;
+       int m_maxStoredPrimes;
+};
+
+#endif /* PRIME_HPP_ */
diff --git a/appl/reprime/main.cpp b/appl/reprime/main.cpp
new file mode 100644 (file)
index 0000000..32f2bfd
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Licence:
+ * You can use and modify this file without any restriction.
+ * There is no warranty.
+ * You also can use the licence from http://www.wtfpl.net/.
+ * The original sources can be found on https://github.com/republib.
+*/
+
+
+#include <QCoreApplication>
+#include "Prime.hpp"
+int main(int argc, char *argv[])
+{
+       QCoreApplication a(argc, argv);
+       Prime::run(argc, argv);
+       exit(0);
+       return a.exec();
+}
+
diff --git a/appl/reprime/reprime.pro b/appl/reprime/reprime.pro
new file mode 100644 (file)
index 0000000..3e275a8
--- /dev/null
@@ -0,0 +1,20 @@
+QT       += core network gui
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+TARGET = reprime
+
+CONFIG += console
+CONFIG -= app_bundle
+
+TEMPLATE = app
+
+INCLUDEPATH = ../..
+
+SOURCES += main.cpp \
+       ../../base/ReLogger.cpp \
+       ../../base/ReRandomizer.cpp \
+       ../../base/ReStringUtils.cpp \
+       ../../base/ReException.cpp \
+       Prime.cpp
+
+
index 25e51cbe365c209f738d6af6facdfaba18a8472d..cda4079813f6b8424dfbcb4cb0c6546cc6c079ea 100644 (file)
@@ -20,15 +20,133 @@ enum {
 
 const char ReNameScrambler::ESC = '%';
 
-const int ReRandomizer::m_primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31,
-       37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109,
-       113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193,
-       197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277,
-       281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373,
-       379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461,
-       463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569,
-       571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653,
-       659, 661, 673, 677, 683, 691 };
+const int64_t ReRandomizer::m_primes[] = {
+       4794328877860651L, // 11086aadb3872b
+       4958110297415603L, // 119d600308dfb3
+       4623102848326049L, // 106cb00308d9a1
+       4891108807597633L, // 1160700308de41
+       4578435188447437L, // 1044100308d8cd
+       5546234485817489L, // 13b445585e4091
+       5389897676242243L, // 132615585e3d43
+       4786884267880873L, // 1101a5585e31a9
+       5241005476646707L, // 129eaaadb38f33
+       4734771998022511L, // 10d2400308db6f
+       5278228526545621L, // 12c085585e3ad5
+       4652881288245079L, // 1087c5585e2f57
+       5181448596808493L, // 1268800308e32d
+       4920887247516739L, // 117b85585e3443
+       5360119236323197L, // 130b000308e77d
+       5471788386019861L, // 1370900308ea15
+       4645436678265319L, // 1081000308d9e7
+       4481655258710579L, // fec0aadb38233
+       5523900655878179L, // 139ff5585e4023
+       5203782426747811L, // 127cd00308e3a3
+       5375008456282711L, // 13188aadb39257
+       5226116256687127L, // 1291200308e417
+       5419676116161323L, // 13412aadb3932b
+       5218671646707367L, // 128a5aadb38ea7
+       5136780936929903L, // 123fe00308e26f
+       4556101358508169L, // 102fc00308d889
+       5263339306586077L, // 12b2faadb38fdd
+       4518878308609331L, // 100de5585e2d33
+       4533767528568833L, // 101b700308d801
+       4764550437941633L, // 10ed55585e3181
+       5509011435918673L, // 13926aadb39551
+       5166559376848937L, // 125af5585e3829
+       4489099868690317L, // ff2d00308d78d
+       4727327388042733L, // 10cb7aadb385ed
+       5330340796404157L, // 12efeaadb391bd
+       4801773487840397L, // 110f300308dc8d
+       5397342286222069L, // 132cdaadb392f5
+       5308006966464857L, // 12db9aadb39159
+       5084668667071573L, // 12107aadb38c55
+       4816662707799941L, // 111cbaadb38785
+       4704993558103493L, // 10b72aadb385c5
+       5114447106990601L, // 122b900308e209
+       4712438168083259L, // 10bdf00308db3b
+       5479232995999613L, // 137755585e3f7d
+       4660325898224963L, // 108e8aadb38543
+       5040001007192867L, // 11e7daadb38b23
+       4972999517375089L, // 11aaeaadb38a71
+       4853885757698843L, // 113e95585e331b
+       5315451576444613L, // 12e2600308e6c5
+       5412231506181583L, // 133a65585e3dcf
+       5144225546909639L, // 1246a5585e37c7
+       4548656748528367L, // 1028faadb382ef
+       4615658238346273L, // 1065eaadb38421
+       5583457535716339L, // 13d6200308ebf3
+       4474210648730791L, // fe545585e2ca7
+       4838996537739323L, // 11310aadb3883b
+       4600769018386699L, // 1058600308d90b
+       4742216608002253L, // 10d905585e30cd
+       4570990578467701L, // 103d4aadb38375
+       5032556397213109L, // 11e115585e35b5
+       5025111787233371L, // 11da500308e05b
+       5568568315756819L, // 13c895585e4113
+       5174003986828717L, // 1261baadb38dad
+       4675215118184491L, // 109c15585e302b
+       5494122215959133L, // 1384e00308ea5d
+       4980444127354847L, // 11b1b00308dfdf
+       4697548948123739L, // 10b065585e305b
+       4779439657901123L, // 10fae00308dc43
+       5129336326950151L, // 12391aadb38d07
+       5464343776040087L, // 1369caadb39497
+       5248450086626447L, // 12a5700308e48f
+       4905998027557141L, // 116dfaadb38915
+       5047445617172633L, // 11eea00308e099
+       5345230016363663L, // 12fd75585e3c8f
+       5442009946100803L, // 13557aadb39443
+       4630547458305841L, // 107375585e2f31
+       5501566825938893L, // 138ba5585e3fcd
+       5077224057091819L, // 1209b5585e36eb
+       4913442637536913L, // 1174c00308de91
+       4935776467476299L, // 1189100308df4b
+       4541212138548581L, // 102235585e2d65
+       5404786896201841L, // 1333a00308e871
+       5159114766869153L, // 1254300308e2a1
+       5010222567273893L, // 11ccc5585e35a5
+       5531345265857969L, // 13a6baadb395b1
+       4757105827961849L, // 10e6900308dbf9
+       4563545968487959L, // 103685585e2e17
+       4719882778062997L, // 10c4b5585e3095
+       4928331857496557L, // 11824aadb389ed
+       5322896186424389L, // 12e925585e3c45
+       5538789875837723L, // 13ad800308eb1b
+       4690104338143981L, // 10a9a00308daed
+       4943221077456049L, // 118fd5585e34b1
+       4987888737334627L, // 11b875585e3563
+       5300562356485079L, // 12d4d5585e3bd7
+       5367563846302937L, // 1311c5585e3cd9
+       5293117746505229L, // 12ce100308e60d
+       5255894696606263L, // 12ac35585e3a37
+       5211227036727601L, // 128395585e3931
+       5285673136525447L, // 12c74aadb39087
+       4526322918589091L, // 1014aaadb382a3
+       4593324408406963L, // 10519aadb383b3
+       5449454556080573L, // 135c400308e9bd
+       4995333347314369L, // 11bf3aadb38ac1
+       5107002497010847L, // 1224caadb38c9f
+       5382453066262463L, // 131f500308e7bf
+       5553679095797237L, // 13bb0aadb395f5
+       4898553417577403L, // 116735585e33bb
+       4682659728164237L, // 10a2daadb3858d
+       4771995047921369L, // 10f41aadb386d9
+       4585879798427209L, // 104ad5585e2e49
+       5069779447111979L, // 1202f00308e12b
+       4861330367678597L, // 11455aadb38885
+       4965554907395353L, // 11a425585e3519
+       5188893206788243L, // 126f45585e3893
+       4831551927759449L, // 112a45585e3259
+       5337785406383909L, // 12f6b00308e725
+       5092113277051363L, // 1217400308e1e3
+       5456899166060341L, // 136305585e3f35
+       5427120726141077L, // 1347f00308e895
+       5270783916565829L, // 12b9c00308e545
+       5561123705777023L, // 13c1d00308eb7f
+       4749661217982049L, // 10dfcaadb38661
+       5121891716970409L, // 123255585e37a9
+       5486677605979391L, // 137e1aadb394ff
+ };
 const int ReRandomizer::m_countPrimes = sizeof ReRandomizer::m_primes
        / sizeof(int);
 const int ReNameScrambler::m_indexOfNodeChar[] = { -1, -1, -1, -1, -1, -1, -1,
@@ -189,6 +307,8 @@ int ReRandomizer::nextInt(int maxValue, int minValue) {
                maxValue = rc;
        }
        seed_t seed = nextSeed64();
+       if (minValue >= 0)
+               seed = abs(seed);
        if (minValue == maxValue)
                rc = minValue;
        else {
@@ -260,22 +380,26 @@ const char* ReRandomizer::nextString(int minLength, int maxLength,
  *
  * The operation will be done in place:
  *
- * @param array                In/Out: The array to shuffle.
- * @param length       The length of the array.
- * @param elemSize     The size of one element of the array.
+ * @param array                IN/OUT: the array to shuffle
+ * @param length       the length of the array
+ * @param elemSize     the size of one element of the array
+ * @param exchanges    count of exchanges: two randomly selected entries will be
+ *                                     exchanged. If <= 0 a default value will be taken: 1.5*length
  */
-void ReRandomizer::shuffle(void* array, size_t length, size_t elemSize) {
+void ReRandomizer::shuffle(void* array, size_t length, size_t elemSize,
+                                                  int exchanges) {
        int ii;
        char* cptr;
        int* iptr;
-       int count = length * 3 / 2;
-
+       int64_t* i64ptr;
+       int count = exchanges <= 0 ? length * 3 / 2 : exchanges;
+       int maxIx = length - 1;
        switch (elemSize) {
        case 1:
                cptr = (char*) array;
                for (ii = 0; ii < count; ii++) {
-                       int ix1 = length - nextInt(1, length);
-                       int ix2 = length - nextInt(1, length);
+                       int ix1 =nextInt(maxIx);
+                       int ix2 =nextInt(maxIx);
                        char x = cptr[ix1];
                        cptr[ix1] = cptr[ix2];
                        cptr[ix2] = x;
@@ -284,20 +408,32 @@ void ReRandomizer::shuffle(void* array, size_t length, size_t elemSize) {
        case sizeof(int):
                iptr = (int*) array;
                for (ii = 0; ii < count; ii++) {
-                       int ix1 = length - nextInt(1, length);
-                       int ix2 = length - nextInt(1, length);
+                       int ix1 =nextInt(maxIx);
+                       int ix2 =nextInt(maxIx);
                        int x = iptr[ix1];
                        iptr[ix1] = iptr[ix2];
                        iptr[ix2] = x;
                }
                break;
+       case sizeof(int64_t):
+               i64ptr = (int64_t*) array;
+               for (ii = 0; ii < count; ii++) {
+                       int ix1 = nextInt(maxIx);
+                       int ix2 = nextInt(maxIx);
+                       if (i64ptr[ix1] <= 0 || i64ptr[ix2] <= 0)
+                               ix1 += 0;
+                       int64_t x = i64ptr[ix1];
+                       i64ptr[ix1] = i64ptr[ix2];
+                       i64ptr[ix2] = x;
+               }
+               break;
        default: {
                char buffer[0x10000];
                assert(elemSize < sizeof buffer);
                iptr = (int*) array;
                for (ii = 0; ii < count; ii++) {
-                       int ix1 = length - nextInt(1, length);
-                       int ix2 = length - nextInt(1, length);
+                       int ix1 =nextInt(maxIx);
+                       int ix2 =nextInt(maxIx);
                        char* p1 = ((char*) array) + ix1 * elemSize;
                        char* p2 = ((char*) array) + ix2 * elemSize;
                        memcpy(buffer, p1, elemSize);
@@ -518,7 +654,9 @@ ReMultiSeedRandomizer::ReMultiSeedRandomizer(int countSeeds, const char* name) :
  */
 ReRandomizer::seed_t ReMultiCongruentialGenerator::nextSeed64() {
        m_currentSeed = (m_currentSeed + 1) % m_countSeeds;
-       seed_t rc = m_seeds[m_currentSeed] * m_factor + m_increment;
+       int ixFactor = int((m_seeds[m_currentSeed] >> 7) % (m_countPrimes - 1));
+       seed_t rc = m_seeds[m_currentSeed] * m_primes[ixFactor]
+                       + (m_primes[ixFactor + 1] >> 1);
        m_seeds[m_currentSeed] = rc;
        rc = ((rc & 0x7fffffff) << 33) | ((rc >> 31) & 0x1ffffffffLL);
        ++m_counter;
@@ -729,23 +867,17 @@ void ReKISSRandomizer::textToSeed(const QByteArray& text) {
  * @param contentRandom        a pseudo random generator
  * @param logger               the logger
  */
-ReByteScrambler::ReByteScrambler(ReRandomizer& contentRandom,
-                       int reservedLength, int markerLength, ReLogger* logger) :
+ReByteScrambler::ReByteScrambler(ReRandomizer& contentRandom, ReLogger* logger) :
        m_contentRandom(contentRandom),
        m_realRandom(),
        m_contentSeed(),
        m_buffer(),
        m_header(),
-       m_reservedLength(reservedLength),
-       m_markerLength(max(0, min(sizeof(int64_t), markerLength))),
-       m_headerLength(0),
        m_logger(logger)
 {
        m_contentRandom.saveSeed(m_contentSeed);
        m_buffer.reserve(256);
        m_realRandom.nearTrueRandom();
-       m_headerLength = sizeof (int64_t) + markerLength + m_reservedLength;
-       m_header.resize(m_headerLength);
 }
 
 /**
@@ -875,20 +1007,24 @@ void ReByteScrambler::encodeContent(const QByteArray& source,
 /**
  * Initializes the scrambler from a header.
  *
- * @param header       the header with the initializing info. If NULL the internal
- *                                     header will be used
- * @param info         OUT: the reserved area in the header
- * @return                     <code>true</code>: success
+ * @param metaInfoLength       the length of the "reserved area"
+ * @param markerLength         length of a mark to ensure header's integrity
+ * @param header                       the header with the initializing info. If NULL the
+ *                                                     internal header will be used
+ * @param info                         OUT: the reserved area in the header
+ * @return                                     <code>true</code>: success
  */
-bool ReByteScrambler::initFromHeader(const QByteArray* header, QByteArray& info)
+bool ReByteScrambler::initFromHeader(int metaInfoLength, int markerLength,
+                                                                        const QByteArray* header, QByteArray& info)
 {
        TRACE("initFromHeader():\n");
        bool rc = true;
        if (header == NULL)
                header = &m_header;
-       if (header->length() < m_headerLength ){
+       int headerLength = sizeof(int64_t) + markerLength + metaInfoLength;
+       if (header->length() < headerLength ){
                m_logger->logv(LOG_ERROR, LOC_DECODE_CONTENT_1, "header length too small: %d/%d",
-                                       header->length(), m_headerLength);
+                                       header->length(), headerLength);
                rc = false;
        } else {
                int64_t random = * reinterpret_cast<const int64_t*>(header->constData());
@@ -896,17 +1032,20 @@ bool ReByteScrambler::initFromHeader(const QByteArray* header, QByteArray& info)
                m_contentRandom.modifySeed(random);
                QByteArray marker;
                marker.append(reinterpret_cast<const char*>(header->constData()+ sizeof(int64_t)),
-                                                                                                       m_markerLength);
+                                                                                                       markerLength);
                QByteArray marker2;
-               m_contentRandom.nextString(m_markerLength, m_markerLength, marker2);
-               if (marker != marker2){
-                       m_logger->logv(LOG_ERROR, LOC_DECODE_CONTENT_2, "invalid marker: %s / %s",
-                               ReStringUtils::hexDump(marker, m_markerLength, m_markerLength).constData(),
-                               ReStringUtils::hexDump(marker2, m_markerLength, m_markerLength).constData());
-                       rc = false;
+               if (markerLength > 0){
+                       m_contentRandom.nextString(markerLength, markerLength, marker2);
+                       if (marker != marker2){
+                               m_logger->logv(LOG_ERROR, LOC_DECODE_CONTENT_2, "invalid marker: %s / %s",
+                                                          ReStringUtils::hexDump(marker, markerLength, markerLength).constData(),
+                                                          ReStringUtils::hexDump(marker2, markerLength, markerLength).constData());
+                               rc = false;
+                       }
                }
                char last = 0x47;
-               const char* src = reinterpret_cast<const char*>(header->data() + sizeof (int64_t) + m_markerLength);
+               const char* src = reinterpret_cast<const char*>(header->data()
+                                                       + sizeof (int64_t) + markerLength);
                int length = *src++;
                TRACE1("info: Length: %d\n", length);
                info.resize(0);
@@ -924,33 +1063,39 @@ bool ReByteScrambler::initFromHeader(const QByteArray* header, QByteArray& info)
 /**
  * Initializes the scrambler header.
  *
+ *
  * Format of the header:
  * <pre>random (8 byte)
  * marker (m_markerLength byte)
- * reserved (m_reservedLength byte)
+ * reserved (reservedLength byte)
  * </pre>
  *
- * @param info the content of the "reserved area"
+ * @param metaInfoLength       the length of the "reserved area"
+ * @param markerLength         length of a mark to ensure header's integrity
+ * @param info                         the content of the "reserved area". If too few space
+ *                                                     the content will be cut
  */
-void ReByteScrambler::initHeader(const QByteArray& info)
+void ReByteScrambler::initHeader(int metaInfoLength, int markerLength,
+                                                                const QByteArray& info)
 {
        TRACE("initHeader():\n");
        int64_t random = m_realRandom.nextSeed64();
        m_contentRandom.reset();
        m_contentRandom.modifySeed(random);
-       m_header.fill(' ', m_headerLength);
+       int headerLength = sizeof(int64_t) + markerLength + metaInfoLength;
+       m_header.fill(' ', headerLength);
        * reinterpret_cast<int64_t*>(m_header.data()) = random;
-       if (m_markerLength > 0){
+       if (markerLength > 0){
                m_buffer.resize(0);
-               m_contentRandom.nextString(m_markerLength, m_markerLength, m_buffer);
-               memcpy(m_header.data() + sizeof(int64_t), m_buffer, m_markerLength);
+               m_contentRandom.nextString(markerLength, markerLength, m_buffer);
+               memcpy(m_header.data() + sizeof(int64_t), m_buffer, markerLength);
        }
        char last = 0x47;
-       char* trg = reinterpret_cast<char*>(m_header.data() + sizeof (int64_t) + m_markerLength);
-       int infoLength = min(info.length(), m_reservedLength - 1);
-       TRACE2("info: length: %d reserved: %d\n", infoLength, m_reservedLength);
+       char* trg = reinterpret_cast<char*>(m_header.data() + sizeof (int64_t) + markerLength);
+       int infoLength = min(info.length(), metaInfoLength - 1);
+       TRACE2("info: length: %d reserved: %d\n", infoLength, metaInfoLength);
        *trg++ = infoLength;
-       for (int ix = 0; ix < infoLength && ix < m_reservedLength; ix++){
+       for (int ix = 0; ix < infoLength && ix < metaInfoLength; ix++){
                last = *trg++ = m_contentRandom.nextChar() ^ info.at(ix) ^ last;
        }
        TRACE_IT(("random: %016lx marker: %s\n", random,
index 4fb334eef23dc6902d04672dfb417687b850cceb..c296edb9e67e48247093c2a29e10de3d049d690e 100644 (file)
@@ -32,7 +32,8 @@ public:
        int nextInt(int maxValue = INT_MAX, int minValue = 0);
        int64_t nextInt64(int64_t maxValue = LLONG_MAX, int64_t minValue = 0);
        const char* nextString(int minLength, int maxLength, QByteArray& buffer);
-       void shuffle(void* array, size_t length, size_t elemSize);
+       void shuffle(void* array, size_t length, size_t elemSize,
+                                int exchanges = -1);
 public:
        virtual void dump() {
        }
@@ -75,7 +76,7 @@ protected:
        int m_counter;
 public:
        // the first 125 prime numbers
-       static const int m_primes[];
+       static const int64_t m_primes[];
        static const int m_countPrimes;
 };
 
@@ -237,22 +238,20 @@ private:
  */
 class ReByteScrambler{
 public:
-       ReByteScrambler(ReRandomizer& contentRandom,
-                                       int reservedLength, int markerLength, ReLogger* logger);
+       ReByteScrambler(ReRandomizer& contentRandom, ReLogger* logger);
 public:
        bool decodeContent(const QByteArray& source, QByteArray& target);
        void encodeContent(const QByteArray& source, QByteArray& target);
-       void initHeader(const QByteArray& info = ReStringUtils::m_empty);
-       bool initFromHeader(const QByteArray* header, QByteArray& info);
+       void initHeader(int metaInfoLength, int markerLength,
+                                       const QByteArray& info = ReStringUtils::m_empty);
+       bool initFromHeader(int metaInfoLength, int markerLength,
+                                               const QByteArray* header, QByteArray& info);
 protected:
        ReRandomizer& m_contentRandom;
        ReKISSRandomizer m_realRandom;
        QByteArray m_contentSeed;
        QByteArray m_buffer;
        QByteArray m_header;
-       int m_reservedLength;
-       int m_markerLength;
-       int m_headerLength;
        ReLogger* m_logger;
 };
 
index f840b6658e0c276a1fb589b94a210ab19ba76f31..48c8840c2d748c990520f30fdd9bd58d07e20e87 100644 (file)
@@ -198,21 +198,23 @@ public:
                QByteArray src(content);
                QByteArray trg;
                QByteArray trg2;
+               int markerLength = 4;
+               int metaInfoLength = 8;
                ReKISSRandomizer rand;
                rand.nearTrueRandom();
                QByteArray info;
                rand.nextString(10, 20, info);
-               scrambler.initHeader(info);
+               scrambler.initHeader(metaInfoLength, markerLength, info);
                scrambler.encodeContent(src, trg);
                QByteArray info2;
-               scrambler.initFromHeader(NULL, info2);
+               scrambler.initFromHeader(metaInfoLength, markerLength, NULL, info2);
                scrambler.decodeContent(trg, trg2);
                checkEqu(src, trg2);
                checkT(info.startsWith(info2));
        }
        void testContentEncoding(){
                ReKISSRandomizer dataRandom;
-               ReByteScrambler scrambler(dataRandom, 8, 4, &m_logger);
+               ReByteScrambler scrambler(dataRandom, &m_logger);
                checkContent("12345678abc", scrambler);
                checkContent("8765432112345678ab", scrambler);
                checkContent("8765432112345678", scrambler);
index 1a2bb9dff362ec4df65068b8d077dd6ac669910f..8f8bf06470fba160712ab98f6ca586b51432f010 100644 (file)
@@ -51,11 +51,13 @@ SOURCES += main.cpp \
        cuReStateStorage.cpp \
        cuReSettings.cpp \
        cuReMatcher.cpp \
-        allTests.cpp
+        allTests.cpp \
+    ../os/ReCryptFileSystem.cpp
 
 HEADERS += \
         ../base/ReFile.hpp \
         ../base/rebase.hpp \
        ../gui/ReEdit.hpp \
        ../math/ReMatrix.hpp \
-       ../math/remath.hpp
+       ../math/remath.hpp \
+    ../os/ReCryptFileSystem.hpp
diff --git a/os/ReCryptFileSystem.cpp b/os/ReCryptFileSystem.cpp
new file mode 100644 (file)
index 0000000..1af6608
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * Licence:
+ * You can use and modify this file without any restriction.
+ * There is no warranty.
+ * You also can use the licence from http://www.wtfpl.net/.
+ * The original sources can be found on https://github.com/republib.
+*/
+
+
+#include "base/rebase.hpp"
+#include "os/reos.hpp"
+
+enum {
+       LOC_ADD_ENTRY_1 = LOC_FIRST_OF(LOC_CRYPTFILESYSTEM), // 12301
+       LOC_REMOVE_ENTRY_1,             // 12302
+       LOC_READ_META_FILE_1,   // 12303
+       LOC_READ_META_FILE_2,   // 12304
+       LOC_READ_META_FILE_3,   // 12305
+       LOC_WRITE_META_1,               // 12306
+       LOC_WRITE_META_2,               // 12307
+};
+
+const int ReCryptFileSystem::NODE_LENGHT = 44;
+const int ReCryptFileSystem::MARKER_LENGHT = 4;
+const int ReCryptFileSystem::CHECKSUM_LENGHT = 16;
+const int ReCryptFileSystem::HEADER_LENGTH = sizeof(int64_t)
+               + ReCryptFileSystem::NODE_LENGHT
+               + ReCryptFileSystem::MARKER_LENGHT;
+const QString ReCryptFileSystem::NODE_META_DEVICE = ".0";
+const QString ReCryptFileSystem::NODE_META_DIR = ".1";
+const int ReCryptDirectory::MARKER_LENGTH = 4;
+const int ReCryptDirectory::META_INFO_LENGTH = sizeof (ReCryptDirectory::MetaInfo_t);
+const int ReCryptDirectory::META_DIR_HEADER_LENGTH = sizeof(int64_t)
+               + ReCryptDirectory::MARKER_LENGTH + ReCryptDirectory::META_INFO_LENGTH;
+// space for the struct and the node:
+const int ReCryptDirectory::MAX_ENTRY_SIZE = sizeof(ReCryptDirectory::FileEntry_t)
+               + 512;
+
+/**
+ * Constructor.
+ *
+ * @param hostFileSystem       the filesystem which does the storage (with
+ *                                                     encrypted names and content
+ * @param nameRandom           a pseudo random generator for names
+ * @param contentRandom                a pseudo random generator for content
+ */
+ReCryptFileSystem::ReCryptFileSystem(ReFileSystem& hostFileSystem,
+       ReRandomizer& contentRandom, ReLogger* logger) :
+               ReFileSystem("cryptfs", logger),
+               ReCryptDirectory(contentRandom, this, logger),
+         m_host(hostFileSystem)
+{
+}
+
+/**
+ * Destructor.
+ */
+ReCryptFileSystem::~ReCryptFileSystem() {
+}
+
+/** Frees resources like open files.
+ */
+void ReCryptFileSystem::close()
+{
+}
+
+/**
+ * Fills a list with the items of the current directory.
+ *
+ * @param matcher      the matching processor
+ * @return                     the count of the found entries (<code>list.size()</code>)
+ */
+int ReCryptFileSystem::listInfos(const ReIncludeExcludeMatcher& matcher,
+       ReFileMetaDataList& list) {
+       return 0;
+}
+
+/**
+ * Creates a directory.
+ *
+ * @param node the name without path (in the current directory)
+ * @return             EC_SUCCESS or error code
+ */
+ReFileSystem::ErrorCode ReCryptFileSystem::makeDir(const QString& node) {
+       return EC_SUCCESS;
+}
+
+/**
+ * Reads a part of a file into a buffer.
+ *
+ * @param source       the file to read (inside the current directory)
+ * @param offset       first position to read
+ * @param size         number of bytes to read
+ * @param buffer       OUT: content of the file
+ * @return                     EC_SUCCESS or error code
+ */
+ReFileSystem::ErrorCode ReCryptFileSystem::read(const ReFileMetaData& source,
+       int64_t offset, int size, QByteArray& buffer) {
+       return EC_SUCCESS;
+}
+
+/** Removes a file or directory.
+ * @param node the properties ot the node (in the current directory)
+ * @return             EC_SUCCESS or error code
+ */
+ReFileSystem::ErrorCode ReCryptFileSystem::remove(const ReFileMetaData& node)
+{
+       return EC_SUCCESS;
+}
+
+/**
+ * Sets the current directory.
+ *
+ * @param path relative or absolute path. If absolute it must be part of the
+ *                             base path
+ * @return             EC_SUCCESS or error code
+ */
+ReFileSystem::ErrorCode ReCryptFileSystem::setDirectory(const QString& path)
+{
+       return EC_SUCCESS;
+}
+
+/**
+ * Sets the properties of a file in the current directory.
+ *
+ * @param source       the properties to copy
+ * @param target       the properties of the file to change
+ * @param force                <code>true</code>: try to change rights to enable
+ *                                     other changes<br>
+ *                                     <code>false</code>: current rights will be respected
+ * @return                     EC_SUCCESS or error code
+ */
+ReFileSystem::ErrorCode ReCryptFileSystem::setProperties(const ReFileMetaData& source,
+                                                                                  ReFileMetaData& target, bool force)
+{
+       return EC_SUCCESS;
+}
+
+/**
+ * Writes a buffer to a file.
+ *
+ * @param node         the file to write (without path, inside the current directory)
+ * @param offset       first position to write
+ * @param buffer       content to write
+ * @return                     EC_SUCCESS or error code
+ */
+ReFileSystem::ErrorCode ReCryptFileSystem::write(const QString& target,
+       int64_t offset, const QByteArray& buffer) {
+       return EC_SUCCESS;
+}
+
+/**
+ * Constructor
+ *
+ * @param parent       the parent filesystem
+ * @param logger       the logger
+ */
+ReCryptDirectory::ReCryptDirectory(ReRandomizer& contentRandom,
+                                                                  ReCryptFileSystem* parent, ReLogger* logger) :
+       ReByteScrambler(contentRandom, logger),
+       m_list(),
+       m_parent(parent),
+       m_changed(false),
+       m_logger(logger),
+       m_currentNode(),
+       m_fileBuffer(),
+       m_entryBuffer(),
+       m_blockSize(1024 * 1024)
+{
+       m_fileBuffer.reserve(m_blockSize);
+       m_entryBuffer.reserve(m_blockSize + MAX_ENTRY_SIZE + 10);
+}
+
+/**
+ * Destructor.
+ */
+ReCryptDirectory::~ReCryptDirectory()
+{
+       if (m_changed)
+               writeMetaFile();
+}
+
+/**
+ * Adds an file entry to the directory.
+ *
+ * @param entry        the meta data of the file to add
+ * @return             <code>true</code>: success
+ */
+bool ReCryptDirectory::addEntry(ReFileMetaData& entry)
+{
+       bool rc = true;
+       if (find(entry.m_node)){
+               rc = ! m_logger->logv(LOG_ERROR, LOC_ADD_ENTRY_1, "file exists yet: %s",
+                                          entry.m_node.constData());
+       } else {
+               m_list.append(entry);
+               m_changed = true;
+       }
+       return rc;
+}
+
+/**
+ * Makes a node name from an id.
+ *
+ * @param id   a unique number of the file
+ * @return             a unique node name derived from the id
+ */
+QString ReCryptDirectory::buildHostedNode(int id) const{
+       QByteArray rc;
+       static const int BASE = 'Z' - 'A' + 1;
+       while(id > 0){
+               rc.insert(0, 'a' + id % BASE);
+               id /= BASE;
+       }
+       return QString(rc);
+}
+
+/**
+ * Makes an id from an node name in the hosted filesystem.
+ *
+ * @param hostedNode   the node to convert
+ * @return                             -1: invalid node name<br>
+ *                                             otherwise: the id of the node
+ */
+int ReCryptDirectory::buildId(const QString& hostedNode) const{
+       int id = 0;
+       static const int BASE = 'Z' - 'A' + 1;
+       for (int ix = 0; id >= 0 && ix < hostedNode.length(); ix++){
+               int digit = hostedNode.at(ix).unicode() - QChar('a').unicode();
+               if (digit < 0 || digit >= BASE)
+                       id = -1;
+               else
+                       id = id*BASE + digit;
+       }
+       return id;
+}
+
+/**
+ * Search an file entry by name.
+ *
+ * @param node the filename without path
+ * @return             NULL: not found<br>
+ *                             otherwise: the found file
+ *
+ */
+const ReFileMetaData* ReCryptDirectory::find(const QString& node) const
+{
+       const ReFileMetaData* rc = NULL;
+       ReFileMetaDataList::const_iterator it;
+       for (it = m_list.cbegin(); it != m_list.cend(); ++it){
+               if (it->m_node == node){
+                       rc = &*it;
+               }
+       }
+       return rc;
+}
+
+/**
+ * Removes an entry given by the name.
+ *
+ * @param node the filename without path
+ * @return
+ */
+bool ReCryptDirectory::removeEntry(const QString& node)
+{
+       bool rc = true;
+       const ReFileMetaData* entry = find(node);
+       if (entry == NULL)
+               rc = ! m_logger->logv(LOG_ERROR, LOC_REMOVE_ENTRY_1, "cannot remove file %s: not found",
+                                                         node.toUtf8().constData());
+       else {
+               ReFileMetaData& entry2 = *(ReFileMetaData*) entry;
+               //@ToDo:
+               //m_list.removeOne(entry2);
+               assert(false);
+               ReFileSystem& host = m_parent->host();
+               ReFileMetaData hostedFile;
+               QString hostedNode = buildHostedNode(entry->m_id);
+               if (host.first(hostedNode, hostedFile))
+                       host.remove(hostedFile);
+               m_changed = true;
+       }
+       return rc;
+}
+
+/**
+ * Reads the file containing the metadata of the files.
+ *
+ * @return     <code>true</code>: success
+ */
+bool ReCryptDirectory::readMetaFile()
+{
+       bool rc = true;
+       m_list.clear();
+       QString fnMetaFile = m_parent->directory() + ReCryptFileSystem::NODE_META_DIR;
+       FILE* fp = fopen(fnMetaFile.toUtf8().constData(), "rb");
+       if (fp != NULL){
+               QByteArray header;
+               header.resize(META_DIR_HEADER_LENGTH);
+               int nRead = fread(header.data(), 1, META_DIR_HEADER_LENGTH, fp);
+               if (nRead != META_DIR_HEADER_LENGTH){
+                       rc = ! m_logger->logv(LOG_ERROR, LOC_READ_META_FILE_1,
+                                                                 "header of %s too small: %d/%d",
+                                                  fnMetaFile.toUtf8().constData(), nRead, META_DIR_HEADER_LENGTH);
+               } else {
+                       QByteArray info;
+                       rc = initFromHeader(META_INFO_LENGTH, MARKER_LENGTH, &header, info);
+                       if (rc){
+                               const MetaInfo_t* meta = reinterpret_cast<const MetaInfo_t*>(info.constData());
+                               if (meta->m_countFiles > 0){
+                                       m_fileBuffer.resize(m_blockSize);
+                                       m_entryBuffer.resize(0);
+                                       int sumLength = 0;
+                                       while ( (nRead = fread(m_fileBuffer.data(),
+                                                                                  1, m_blockSize, fp)) > 0){
+                                               sumLength += nRead;
+                                               if (nRead < m_blockSize)
+                                                       m_fileBuffer.resize(nRead);
+                                               decodeContent(m_fileBuffer, m_fileBuffer);
+                                               m_entryBuffer.append(m_fileBuffer);
+                                               splitBlock(sumLength < meta->m_size,
+                                                                                       m_entryBuffer);
+                                       }
+                                       if (sumLength != meta->m_size){
+                                               m_logger->logv(LOG_ERROR, LOC_READ_META_FILE_2,
+                                                                                         "file %s too small: %d/%d",
+                                                                          fnMetaFile.toUtf8().constData(),
+                                                                          sumLength, meta->m_size);
+                                       }
+                               }
+                       }
+               }
+       }
+       return rc;
+}
+
+/**
+ * Writes the metadata of the directory into a file.
+ *
+ * @return     <code>true</code>: success
+ */
+bool ReCryptDirectory::writeMetaFile()
+{
+       bool rc = true;
+       QByteArray header;
+       QByteArray meta;
+       meta.resize(sizeof(MetaInfo_t));
+       MetaInfo_t* meta2 = reinterpret_cast<MetaInfo_t*>(meta.data());
+       meta2->m_countFiles = m_list.length();
+       meta2->m_size = meta2->m_countFiles * sizeof(FileEntry_t);
+       ReFileMetaDataList::const_iterator it;
+       for (it = m_list.cbegin(); it != m_list.cend(); ++it){
+               int length = it->m_node.toUtf8().length();
+               meta2->m_size += length + (length < 256 ? 0 : 1);
+       }
+       initHeader(META_INFO_LENGTH, MARKER_LENGTH, meta);
+       QByteArray node;
+       for (it = m_list.cbegin(); it != m_list.cend(); ++it){
+               node = it->m_node.toUtf8();
+               int length = node.length();
+               meta2->m_size += length + (length < 256 ? 0 : 1);
+       }
+       QString fnMetaFile = m_parent->directory() + ReCryptFileSystem::NODE_META_DIR;
+       FILE* fp = fopen(fnMetaFile.toUtf8().constData(), "rb");
+       if (fp == NULL){
+               m_logger->logv(LOG_ERROR, LOC_WRITE_META_1, "cannot write (%d): %s",
+                                          errno, fnMetaFile);
+       } else {
+               m_fileBuffer.append(header);
+               int ixList = 0;
+               while (ixList++ < m_list.length()){
+                       const ReFileMetaData& file = m_list.at(ixList++);
+                       FileEntry_t trg;
+                       trg.m_created = file.m_created.toMSecsSinceEpoch();
+                       trg.m_modified = file.m_modified.toMSecsSinceEpoch();
+                       trg.m_owner = file.m_owner;
+                       trg.m_group = file.m_group;
+                       trg.m_size = file.m_size;
+                       trg.m_mode = file.m_mode;
+                       trg.m_id = file.m_id;
+                       node = file.m_node.toUtf8();
+                       int length = node.length();
+                       trg.m_nodeLength = length < 256 ? length : 0;
+                       m_fileBuffer.append(reinterpret_cast<const char*>(&trg), sizeof trg);
+                       m_fileBuffer.append(node);
+                       if (length >= 256)
+                               m_fileBuffer.append('\0');
+                       if (m_fileBuffer.length() >= m_blockSize || ixList >= m_list.length()){
+                               m_entryBuffer.resize(0);
+                               if (m_fileBuffer.length() > m_blockSize){
+                                       m_entryBuffer = m_fileBuffer.mid(m_blockSize);
+                                       m_fileBuffer.resize(m_blockSize);
+                               }
+                               encodeContent(m_fileBuffer, m_fileBuffer);
+                               int nWritten = fwrite(m_fileBuffer.constData(), 1,
+                                                                         m_fileBuffer.length(), fp);
+                               if (nWritten != m_fileBuffer.length()){
+                                       rc = ! m_logger->logv(LOG_ERROR, LOC_WRITE_META_2,
+                                                                  "write error (%d): %s [%d/%d]", errno,
+                                                                  nWritten, m_fileBuffer.length());
+                               }
+                       }
+               }
+       }
+       return rc;
+}
+
+/**
+ * Splits a block with many metadata entries into single entries.
+ *
+ * @param isLast       <code>true</code>the given block is the last in the file
+ * @param block                the data to split.<br>
+ *                                     Format: FileEntry_t_1 node1 File_entry2 node2 ...<br>
+ *                                     Precondition: the block starts with a FileEntry_t<br>
+ *                                     Postcondition: the block is empty or starts with the
+ *                                     first FileEntry_t which is not processed. All processed
+ *                                     entries are deleted from the buffer. block.length() < MAX_ENTRY_SIZE
+ */
+void ReCryptDirectory::splitBlock(bool isLast, QByteArray& block){
+       const FileEntry_t* src = reinterpret_cast<const FileEntry_t*>
+                       (block.constData());
+       ReFileMetaData file;
+       int position = 0;
+       const char* srcPtr = reinterpret_cast<const char*>(block.constData());
+       const char* endPtr = srcPtr + block.length() - (isLast ? 0 : MAX_ENTRY_SIZE);
+       while (srcPtr < endPtr){
+               const FileEntry_t* src = reinterpret_cast<const FileEntry_t*>(srcPtr);
+               file.m_created.setMSecsSinceEpoch(src->m_created);
+               file.m_modified.setMSecsSinceEpoch(src->m_modified);
+               file.m_owner = src->m_owner;
+               file.m_group = src->m_group;
+               file.m_size = src->m_size;
+               file.m_mode = src->m_mode;
+               file.m_id = src->m_id;
+               srcPtr += sizeof(FileEntry_t);
+               int nodeLength = src->m_nodeLength != 0 ? src->m_nodeLength : strlen(srcPtr);
+               QByteArray node(srcPtr, nodeLength);
+               file.m_node = node;
+               m_list.append(file);
+               srcPtr += nodeLength + (src->m_nodeLength != 0 ? 0 : 1);
+       }
+       block.remove(0, srcPtr - block.constData());
+       printf("List: %d Rest: %d\n", m_list.length(), block.length());
+}
+/**
+ * Gets the filename of an entry in the hosted filesystem.
+ *
+ * @param entry        the name was built for this file
+ * @return             the full name of the hosted (encrypted) file
+ */
+const QString& ReCryptDirectory::hostedFilename(const ReFileMetaData& entry)
+{
+       QString node = buildHostedNode(entry.m_id);
+       m_currentNode = ReFileUtils::pathAppend(m_parent->directory(), node);
+       return m_currentNode;
+}
diff --git a/os/ReCryptFileSystem.hpp b/os/ReCryptFileSystem.hpp
new file mode 100644 (file)
index 0000000..9d4c139
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Licence:
+ * You can use and modify this file without any restriction.
+ * There is no warranty.
+ * You also can use the licence from http://www.wtfpl.net/.
+ * The original sources can be found on https://github.com/republib.
+*/
+
+
+#ifndef RECRYPTFILESYSTEM_HPP
+#define RECRYPTFILESYSTEM_HPP
+
+class ReCryptFileSystem;
+
+class ReCryptDirectory : protected ReByteScrambler{
+public:
+       typedef struct {
+               int64_t m_size;
+               //@ millisec from epoch
+               int64_t m_modified;
+               //@ millisec from epoch
+               int64_t m_created;
+               int32_t m_id;
+               int16_t m_owner;
+               int16_t m_group;
+               mode_t m_mode;
+               // 0: strlen(node) > 255
+               uint8_t m_nodeLength;
+       } FileEntry_t;
+       typedef struct {
+               int32_t m_countFiles;
+               int32_t m_size;
+       } MetaInfo_t;
+public:
+       ReCryptDirectory(ReRandomizer& contentRandom, ReCryptFileSystem* parent,
+                                        ReLogger* logger);
+       ~ReCryptDirectory();
+public:
+       bool addEntry(ReFileMetaData& entry);
+       const ReFileMetaData* find(const QString& node) const;
+       bool removeEntry(const QString& entry);
+       bool readMetaFile();
+       bool writeMetaFile();
+protected:
+       int buildId(const QString& hostedNode) const;
+       QString buildHostedNode(int id) const;
+       const QString& hostedFilename(const ReFileMetaData& entry);
+       void splitBlock(bool isLast, QByteArray& block);
+public:
+       static const int MARKER_LENGTH;
+       static const int META_INFO_LENGTH;
+       static const int META_DIR_HEADER_LENGTH;
+       static const int MAX_ENTRY_SIZE;
+protected:
+       ReFileMetaDataList m_list;
+       ReCryptFileSystem* m_parent;
+       bool m_changed;
+       ReLogger* m_logger;
+       QString m_currentNode;
+       QByteArray m_fileBuffer;
+       QByteArray m_entryBuffer;
+       int m_blockSize;
+};
+
+/**
+ * A filesystem with encrypted filenames and file content.
+ *
+ * The storage is done with a 'host filesystem'.
+ * The filenames used in the interface (parameters) are clear text.
+ * The filenames of the base filesystem are encrypted.
+ * If a file content is copied / moved to the base filesystem the content
+ * will be encrypted. In the other direction the file content will be decrypted.
+ */
+class ReCryptFileSystem: public ReFileSystem,
+               protected ReCryptDirectory
+{
+public:
+       static const int NODE_LENGHT;
+       static const int HEADER_LENGTH;
+       static const int CHECKSUM_LENGHT;
+       static const int MARKER_LENGHT;
+       static const QString NODE_META_DIR;
+       static const QString NODE_META_DEVICE;
+public:
+       ReCryptFileSystem(ReFileSystem& hostFileSystem,
+               ReRandomizer& contentRandom, ReLogger* logger);
+       ~ReCryptFileSystem();
+public:
+       virtual void close();
+       virtual int listInfos(const ReIncludeExcludeMatcher& matcher,
+               ReFileMetaDataList& list);
+       virtual ErrorCode makeDir(const QString& node);
+       virtual ErrorCode read(const ReFileMetaData& source, int64_t offset,
+               int size, QByteArray& buffer);
+       virtual ErrorCode remove(const ReFileMetaData& node);
+       virtual ErrorCode setDirectory(const QString& path);
+       virtual ErrorCode setProperties(const ReFileMetaData& source, ReFileMetaData& target, bool force);
+       virtual ErrorCode write(const QString& target, int64_t offset,
+               const QByteArray& buffer);
+public:
+       /** Returns the filesystem hosting the encrypted files.
+        * @return      the hosting filesystem
+        */
+       ReFileSystem& host() const {
+               return m_host;
+       }
+
+protected:
+       ReFileSystem& m_host;
+};
+
+#endif // RECRYPTFILESYSTEM_HPP
index 7ff1ebe81ae4df2d35c34819f0c7a6cc39987a4a..516ebfd159ff47640660d879644b1fc8220879e3 100644 (file)
@@ -32,17 +32,6 @@ enum {
        LOC_SET_PROPERTIES_5,   // 12017
 };
 
-const int ReCryptFileSystem::NODE_LENGHT = 44;
-const int ReCryptFileSystem::MARKER_LENGHT = 4;
-const int ReCryptFileSystem::CHECKSUM_LENGHT = 16;
-const int ReCryptFileSystem::HEADER_LENGTH = sizeof(int64_t)
-               + ReCryptFileSystem::NODE_LENGHT
-               + ReCryptFileSystem::MARKER_LENGHT;
-
-#ifdef WITH_TRACE
-static bool s_trace = true;
-#endif
-
 /**
  * Constructor.
  *
@@ -277,7 +266,13 @@ ReFileSystem::ErrorCode ReLocalFileSystem::makeDir(const QString& node) {
  *                             EC_NOT_ACCESSIBLE       parent not readable
  */
 ReFileSystem::ErrorCode ReLocalFileSystem::setDirectory(const QString& path) {
-       ErrorCode rc = m_dir.setCurrent(path) ? EC_SUCCESS : EC_PATH_NOT_FOUND;
+       ErrorCode rc;
+       if (ReFileUtils::isAbsolutPath(path))
+               rc = m_dir.setCurrent(path) ? EC_SUCCESS : EC_PATH_NOT_FOUND;
+       else
+               rc = m_dir.setCurrent(ReFileUtils::pathAppend(
+                       m_dir.absolutePath(), path))
+                               ? EC_SUCCESS : EC_PATH_NOT_FOUND;
        m_directory = m_dir.absolutePath();
        ReQStringUtils::ensureLastChar(m_directory, OS_SEPARATOR);
        return rc;
@@ -545,14 +540,17 @@ ReFileMetaData::ReFileMetaData() :
  * @param size         the filesize (0 for directories)
  */
 ReFileMetaData::ReFileMetaData(const QString& node, const QDateTime& modified,
-       const QDateTime& created, int owner, int group, mode_t mode, int64_t size) :
+       const QDateTime& created, int owner, int group, mode_t mode, int64_t size,
+                                                          int32_t id) :
                m_node(node),
                m_modified(modified),
                m_created(created),
+               m_size(size),
                m_owner(owner),
                m_group(group),
-               m_mode(mode),
-               m_size(size) {
+               m_id(id),
+               m_mode(mode)
+{
 
 }
 
@@ -571,10 +569,12 @@ ReFileMetaData::ReFileMetaData(const ReFileMetaData& source) :
                m_node(source.m_node),
                m_modified(source.m_modified),
                m_created(source.m_created),
+               m_size(source.m_size),
                m_owner(source.m_owner),
                m_group(source.m_group),
-               m_mode(source.m_mode),
-               m_size(source.m_size) {
+               m_id(source.m_id),
+               m_mode(source.m_mode)
+{
 
 }
 
@@ -592,118 +592,7 @@ ReFileMetaData&ReFileMetaData::operator =(const ReFileMetaData& source) {
        m_group = source.m_group;
        m_mode = source.m_mode;
        m_size = source.m_size;
+       m_id = source.m_id;
        return *this;
 }
 
-/**
- * Constructor.
- *
- * @param hostFileSystem       the filesystem which does the storage (with
- *                                                     encrypted names and content
- * @param nameRandom           a pseudo random generator for names
- * @param contentRandom                a pseudo random generator for content
- */
-ReCryptFileSystem::ReCryptFileSystem(ReFileSystem& hostFileSystem,
-       ReRandomizer& nameRandom, ReRandomizer& contentRandom, ReLogger* logger) :
-               ReFileSystem("cryptfs", logger),
-               ReByteScrambler(contentRandom, NODE_LENGHT, sizeof(int32_t), logger),
-               m_host(hostFileSystem) {
-}
-
-/**
- * Destructor.
- */
-ReCryptFileSystem::~ReCryptFileSystem() {
-}
-
-/** Frees resources like open files.
- */
-void ReCryptFileSystem::close()
-{
-}
-
-/**
- * Fills a list with the items of the current directory.
- *
- * @param matcher      the matching processor
- * @return                     the count of the found entries (<code>list.size()</code>)
- */
-int ReCryptFileSystem::listInfos(const ReIncludeExcludeMatcher& matcher,
-       ReFileMetaDataList& list) {
-       return 0;
-}
-
-/**
- * Creates a directory.
- *
- * @param node the name without path (in the current directory)
- * @return             EC_SUCCESS or error code
- */
-ReFileSystem::ErrorCode ReCryptFileSystem::makeDir(const QString& node) {
-       return EC_SUCCESS;
-}
-
-/**
- * Reads a part of a file into a buffer.
- *
- * @param source       the file to read (inside the current directory)
- * @param offset       first position to read
- * @param size         number of bytes to read
- * @param buffer       OUT: content of the file
- * @return                     EC_SUCCESS or error code
- */
-ReFileSystem::ErrorCode ReCryptFileSystem::read(const ReFileMetaData& source,
-       int64_t offset, int size, QByteArray& buffer) {
-       return EC_SUCCESS;
-}
-
-/** Removes a file or directory.
- * @param node the properties ot the node (in the current directory)
- * @return             EC_SUCCESS or error code
- */
-ReFileSystem::ErrorCode ReCryptFileSystem::remove(const ReFileMetaData& node)
-{
-       return EC_SUCCESS;
-}
-
-/**
- * Sets the current directory.
- *
- * @param path relative or absolute path. If absolute it must be part of the
- *                             base path
- * @return             EC_SUCCESS or error code
- */
-ReFileSystem::ErrorCode ReCryptFileSystem::setDirectory(const QString& path)
-{
-       return EC_SUCCESS;
-}
-
-/**
- * Sets the properties of a file in the current directory.
- *
- * @param source       the properties to copy
- * @param target       the properties of the file to change
- * @param force                <code>true</code>: try to change rights to enable
- *                                     other changes<br>
- *                                     <code>false</code>: current rights will be respected
- * @return                     EC_SUCCESS or error code
- */
-ReFileSystem::ErrorCode ReCryptFileSystem::setProperties(const ReFileMetaData& source,
-                                                                                  ReFileMetaData& target, bool force)
-{
-       return EC_SUCCESS;
-}
-
-/**
- * Writes a buffer to a file.
- *
- * @param node         the file to write (without path, inside the current directory)
- * @param offset       first position to write
- * @param buffer       content to write
- * @return                     EC_SUCCESS or error code
- */
-ReFileSystem::ErrorCode ReCryptFileSystem::write(const QString& target,
-       int64_t offset, const QByteArray& buffer) {
-       return EC_SUCCESS;
-}
-
index 90d67f2f68b41f494592ca83b8845451cf80011b..f664234b7abe3d63c356d70e579a5e64fe3a1459 100644 (file)
@@ -17,7 +17,7 @@ public:
        ReFileMetaData();
        ReFileMetaData(const QString& node, const QDateTime& modified,
                const QDateTime& created, int owner = -1, int group = -1,
-               mode_t mode = (mode_t) - 1, int64_t size = 0);
+               mode_t mode = (mode_t) - 1, int64_t size = 0, int32_t id = 0);
        virtual ~ReFileMetaData();
        ReFileMetaData(const ReFileMetaData& source);
        ReFileMetaData& operator =(const ReFileMetaData& source);
@@ -25,10 +25,12 @@ public:
        QString m_node;
        QDateTime m_modified;
        QDateTime m_created;
+       int64_t m_size;
        int16_t m_owner;
        int16_t m_group;
+       // unique inside the directory:
+       int32_t m_id;
        mode_t m_mode;
-       int64_t m_size;
 };
 typedef QList<ReFileMetaData> ReFileMetaDataList;
 
@@ -186,40 +188,5 @@ protected:
        FILE* m_writeFile;
 
 };
-/**
- * A filesystem with encrypted filenames and file content.
- *
- * The storage is done with a 'host filesystem'.
- * The filenames used in the interface (parameters) are clear text.
- * The filenames of the base filesystem are encrypted.
- * If a file content is copied / moved to the base filesystem the content
- * will be encrypted. In the other direction the file content will be decrypted.
- */
-class ReCryptFileSystem: public ReFileSystem, protected ReByteScrambler {
-public:
-       static const int NODE_LENGHT;
-       static const int HEADER_LENGTH;
-       static const int CHECKSUM_LENGHT;
-       static const int MARKER_LENGHT;
-public:
-       ReCryptFileSystem(ReFileSystem& hostFileSystem, ReRandomizer& nameRandom,
-               ReRandomizer& contentRandom, ReLogger* logger);
-       ~ReCryptFileSystem();
-public:
-public:
-       virtual void close();
-       virtual int listInfos(const ReIncludeExcludeMatcher& matcher,
-               ReFileMetaDataList& list);
-       virtual ErrorCode makeDir(const QString& node);
-       virtual ErrorCode read(const ReFileMetaData& source, int64_t offset,
-               int size, QByteArray& buffer);
-       virtual ErrorCode remove(const ReFileMetaData& node);
-       virtual ErrorCode setDirectory(const QString& path);
-       virtual ErrorCode setProperties(const ReFileMetaData& source, ReFileMetaData& target, bool force);
-       virtual ErrorCode write(const QString& target, int64_t offset,
-               const QByteArray& buffer);
-protected:
-       ReFileSystem& m_host;
-};
 
 #endif /* OS_REFILESYSTEM_HPP_ */
index a93b8d87728cbc9ec08866d9cc7eb0e4654999aa..ba2c10e72fde51e019dfd07d90cbeee96f425403 100644 (file)
@@ -50,5 +50,6 @@ inline bool operator >(const ReFileTime_t& time1, const ReFileTime_t& time2) {
 #endif
 }
 #include "os/ReFileSystem.hpp"
+#include "os/ReCryptFileSystem.hpp"
 
 #endif /* OS_REOS_HPP_ */
index 35a8073cb9cf5b3d715eba9ee2a50c8146b28391..0d27c65baaa00953347618190f788cff477be3f4 100644 (file)
@@ -34,6 +34,7 @@ enum {
        LOC_STATESTORAGE,       // 120
        LOC_FILESYSTEM,
        LOC_RANDOMIZER,
+       LOC_CRYPTFILESYSTEM,
 };
 #define LOC_FIRST_OF(moduleNo) (moduleNo*100+1)
 class RplModules {