]> gitweb.hamatoma.de Git - reqt/commitdiff
ReCryptFileSystem
authorhama <hama@siduction.net>
Sun, 4 Oct 2015 00:05:36 +0000 (02:05 +0200)
committerhama <hama@siduction.net>
Sun, 4 Oct 2015 00:05:36 +0000 (02:05 +0200)
base/ReRandomizer.cpp [new file with mode: 0644]
base/ReRandomizer.hpp [new file with mode: 0644]
base/rebase.hpp
cunit/cunit.pro
os/ReFileSystem.cpp
os/ReFileSystem.hpp
tools/mk_nodeChar.pl [new file with mode: 0644]

diff --git a/base/ReRandomizer.cpp b/base/ReRandomizer.cpp
new file mode 100644 (file)
index 0000000..9c5b69f
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ * ReRandomizer.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+#include "base/rebase.hpp"
+
+static bool s_trace = false;
+/**
+ * @brief Constructor.
+ */
+ReRandomizer::ReRandomizer() {
+}
+/**
+ * @brief Destructor.
+ */
+ReRandomizer::~ReRandomizer() {
+}
+
+#if defined __linux__
+inline int abs(int x) {
+       return x < 0 ? -x : x;
+}
+#endif
+/**
+ * @brief Returns the next random character.
+ *
+ * The character is in the range ' ' .. chr(127) (inclusive).
+ *
+ * @return The next random character.
+ */
+char ReRandomizer::nextChar() {
+       char rc = nextInt(' ', ' ' + CHARRANGE - 1);
+       return rc;
+}
+
+/**
+ * @brief Returns a random number which is not predictable.
+ *
+ * @return a number which is not predictable
+ */
+ReRandomizer::seed_t ReRandomizer::nearTrueRandom() {
+       seed_t rc = 0;
+#if defined __linux__
+       int fh = open("/dev/urandom", O_RDONLY);
+       char buffer[sizeof(seed_t)];
+       if (read(fh, buffer, sizeof buffer) > 0)
+       rc ^= *(seed_t*) buffer;
+       close(fh);
+#else
+       time_t random = time(NULL);
+       static int dummy = 5;
+       void* dummy2 = malloc(1);
+       free(dummy2);
+       rc = (((seed_t) random) << 31) + ((seed_t) &dummy << 9)
+           + ((-random ^ 0x20111958) ^ (seed_t(dummy2)));
+#endif
+       return rc;
+}
+/**
+ * @brief Returns the next random integer.
+ *
+ *
+ * @param maxValue     The maximum of the result (including).
+ * @param minValue     The minimum of the result.
+ *
+ * @return The next seed.
+ */
+int ReRandomizer::nextInt(int maxValue, int minValue) {
+       int rc;
+       if (minValue > maxValue) {
+               rc = minValue;
+               minValue = maxValue;
+               maxValue = rc;
+       }
+       seed_t seed = nextSeed();
+       if (minValue == maxValue)
+               rc = minValue;
+       else {
+               // we calculate in 64 bit, no range overflow:
+               int64_t range = (int64_t) maxValue - minValue + 1;
+               int64_t offset = seed % range;
+               rc = (int) (minValue + offset);
+       }
+       if (s_trace) {
+               static int count = 0;
+               printf("%c %8x ", count++ % 4 == 0 ? '\n' : ' ', rc);
+       }
+       return rc;
+}
+
+/**
+ * @brief Returns the next random integer.
+ *
+ *
+ * @param maxValue     The maximum of the result (including).
+ * @param minValue     The minimum of the result.
+ *
+ * @return The next seed.
+ */
+int64_t ReRandomizer::nextInt64(int64_t maxValue, int64_t minValue) {
+       seed_t rc;
+       if (minValue > maxValue) {
+               rc = minValue;
+               minValue = maxValue;
+               maxValue = rc;
+       }
+       seed_t seed = nextSeed();
+       if (minValue == maxValue)
+               rc = minValue;
+       else if (minValue == 0 && maxValue == LLONG_MAX)
+               rc = abs((int64_t) seed);
+       else if (uint64_t(maxValue - minValue) < LLONG_MAX)
+               // no signed int64 overflow:
+               rc = minValue + seed % (maxValue - minValue + 1);
+       else {
+               // int64 overflow: we need a higher precision:
+               double rc2 = (double) minValue
+                   + fmod((double) seed, (double) (maxValue - minValue));
+               rc = (int) rc2;
+       }
+       if (s_trace) {
+               static int count = 0;
+               printf("%c %16llx ", count++ % 4 == 0 ? '\n' : ' ', (long long) rc);
+       }
+       return rc;
+}
+
+/**
+ * @brief Calculates the next seed for the generator.
+ *
+ * @return The next seed.
+ */
+ReRandomizer::seed_t ReCongruentialGenerator::nextSeed() {
+       m_seed = m_seed * m_factor + m_increment;
+       return m_seed;
+}
+
+/**
+ * @brief Returns a string with random characters.
+ *
+ * All character will be inside the range ' ' .. chr(127).
+ *
+ * @param minLength    The minimum length of the result string.
+ * @param maxLength    The maximum length of the result string.
+ * @param buffer       Out: The place for the string.
+ *
+ * @result The buffer.
+ */
+const char* ReRandomizer::nextString(int minLength, int maxLength,
+    QByteArray &buffer) {
+       int len = nextInt(maxLength, minLength);
+       buffer.resize(len);
+       char* ptr = buffer.data();
+       for (int ii = 0; ii < len; ii++) {
+               ptr[ii] = nextChar();
+       }
+       return buffer.constData();
+}
+
+/**
+ * @brief Builds a random permutation of an array.
+ *
+ * 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.
+ */
+void ReRandomizer::shuffle(void* array, size_t length, size_t elemSize) {
+       int ii;
+       char* cptr;
+       int* iptr;
+       int count = length * 3 / 2;
+
+       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);
+                       char x = cptr[ix1];
+                       cptr[ix1] = cptr[ix2];
+                       cptr[ix2] = x;
+               }
+               break;
+       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 x = iptr[ix1];
+                       iptr[ix1] = iptr[ix2];
+                       iptr[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);
+                       char* p1 = ((char*) array) + ix1 * elemSize;
+                       char* p2 = ((char*) array) + ix2 * elemSize;
+                       memcpy(buffer, p1, elemSize);
+                       memcpy(p1, p2, elemSize);
+                       memcpy(p2, buffer, elemSize);
+               }
+               break;
+       }
+       }
+}
+/**
+ * @brief Constructor.
+ */
+ReCongruentialGenerator::ReCongruentialGenerator() :
+           m_seed(0x4711),
+           m_factor(214013),
+           m_increment(2531011),
+           m_lastSetSeed(0x4711) {
+}
+/**
+ * @brief Destructor.
+ */
+ReCongruentialGenerator::~ReCongruentialGenerator() {
+}
+
+/**
+ * @brief Returns the current factor.
+ *
+ * @return The current factor.
+ */
+ReRandomizer::seed_t ReCongruentialGenerator::factor() const {
+       return m_factor;
+}
+
+/**
+ * @brief Returns the current increment.
+ *
+ * @return The current increment.
+ */
+ReRandomizer::seed_t ReCongruentialGenerator::increment() const {
+       return m_increment;
+}
+
+/**
+ * Returns the current seed.
+ *
+ * @return The current seed.
+ */
+ReRandomizer::seed_t ReCongruentialGenerator::seed() const {
+       return m_seed;
+}
+
+/**
+ * @brief Sets the seed to the value given by the last <code>setSeed()</code>.
+ *
+ * Note: The constructor does the first <code>setSeed()</code>.
+ */
+void ReCongruentialGenerator::reset() {
+       m_seed = m_lastSetSeed;
+}
+
+/**
+ * Sets the factor.
+ *
+ * @param factor       The new factor.
+ */
+void ReCongruentialGenerator::setFactor(seed_t factor) {
+       this->m_factor = factor;
+}
+
+/**
+ * Sets the increment.
+ *
+ * @param increment    The new increment.
+ */
+void ReCongruentialGenerator::setIncrement(seed_t increment) {
+       this->m_increment = increment;
+}
+
+/** @brief Sets the current seed.
+ *
+ * @param seed The seed to set.
+ */
+void ReCongruentialGenerator::setSeed(seed_t seed) {
+       m_seed = m_lastSetSeed = seed;
+       if (s_trace)
+               printf(" Seed: %llx ", (long long) seed);
+}
+
+/**
+ * Gets the current point of pseudo random.
+ *
+ * @param seed the current point of pseudo random
+ */
+void ReCongruentialGenerator::seed(QByteArray& seed) {
+       seed.resize(sizeof m_seed);
+       memcpy(seed.data(), &m_seed, sizeof m_seed);
+}
+
+/**
+ * Sets the current point of pseudo random.
+ *
+ * @param seed the current point of pseudo random
+ */
+void ReCongruentialGenerator::setSeed(const QByteArray& seed) {
+       if (seed.size() >= sizeof(seed_t)) {
+               memcpy(&m_seed, seed.constData(), sizeof m_seed);
+       } else {
+               QByteArray buffer = seed;
+               buffer.resize(sizeof m_seed);
+               memset(buffer.data() + seed.size(), 0, sizeof(m_seed) - seed.size());
+               memcpy(&m_seed, buffer.constData(), sizeof m_seed);
+       }
+       m_lastSetSeed = m_seed;
+
+}
+
+/** @brief Returns the next 64 bit pseudo random number.
+ *
+ * A congruential generator produces good random in the most significant
+ * bits. Therefore we exchange the bits of the result.
+ * Then x % m returns better results.
+ *
+ * @return a pseudo random number
+ */
+ReRandomizer::seed_t ReShiftRandom::nextSeed() {
+       seed_t rc = ReCongruentialGenerator::nextSeed();
+       rc = ((rc & 0x7fffffff) << 33) | ((rc >> 31) & 0x1ffffffffll);
+       return rc;
+}
diff --git a/base/ReRandomizer.hpp b/base/ReRandomizer.hpp
new file mode 100644 (file)
index 0000000..6e24fa7
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * ReRandomizer.hpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+#ifndef RANDOMIZER_H_
+#define RANDOMIZER_H_
+
+/**
+ * This implements an abstract base class for random generators.
+ */
+class ReRandomizer {
+public:
+       enum {
+               START_RANGE = ' ',
+               CHARRANGE = 128 - START_RANGE
+       };
+       typedef uint64_t seed_t;
+public:
+       ReRandomizer();
+       virtual ~ReRandomizer();
+public:
+       virtual int nextInt(int maxValue = INT_MAX, int minValue = 0);
+       virtual int64_t nextInt64(int64_t maxValue = LLONG_MAX,
+           int64_t minValue = 0);
+       char nextChar();
+       const char* nextString(int minLength, int maxLength, QByteArray& buffer);
+       void shuffle(void* array, size_t length, size_t elemSize);
+       /** @brief Sets the instance to a defined start state.
+        */
+       virtual void reset() = 0;
+       /**
+        * Gets the current point of pseudo random.
+        *
+        * @param seed  the current point of pseudo random
+        */
+       virtual void seed(QByteArray& seed) = 0;
+       /**
+        * Sets the current point of pseudo random.
+        *
+        * @param seed  the current point of pseudo random
+        */
+       virtual void setSeed(QByteArray& seed) = 0;
+protected:
+       /** @brief Returns the next pseudo random number.
+        * @return the next pseudo random number
+        * */
+       virtual seed_t nextSeed() = 0;
+public:
+       seed_t nearTrueRandom();
+};
+
+/**
+ * Implements a simple random generator.
+ * A linear congruential generator produces the next value using this formula:
+ * seed = (seed * factor + increment) % modulus
+ * In this implementation modulus is 2**64.
+ */
+class ReCongruentialGenerator: public ReRandomizer {
+public:
+       ReCongruentialGenerator();
+       virtual ~ReCongruentialGenerator();
+public:
+       seed_t factor() const;
+       seed_t increment() const;
+       virtual void reset();
+       seed_t seed() const;
+       virtual void seed(QByteArray& seed);
+       void setFactor(seed_t factor);
+       void setIncrement(seed_t increment);
+       void setSeed(seed_t m_seed);
+       virtual void setSeed(const QByteArray& seed);
+protected:
+       friend class ReShiftRandom;
+       virtual seed_t nextSeed();
+private:
+       seed_t m_seed;
+       seed_t m_factor;
+       seed_t m_increment;
+       seed_t m_lastSetSeed;
+};
+
+class ReShiftRandom: public ReCongruentialGenerator {
+protected:
+       virtual seed_t nextSeed();
+};
+#endif /* RANDOMIZER_H_ */
index 407cb78f9e3ce0c988a07143c85d65e9570ee8f5..cb8e2db7eed4cc6f8b4a9e6d82bc03521989536b 100644 (file)
@@ -23,6 +23,7 @@
 #ifdef __linux__
 #include <unistd.h>
 #include <sys/time.h>
+#include <fcntl.h>
 #else
 #include <io.h>
 #include <direct.h>
@@ -113,5 +114,5 @@ inline int roundInt(double value) {
 #include "base/ReDiff.hpp"
 #include "base/ReMatcher.hpp"
 #include "base/ReTest.hpp"
-
+#include "base/ReRandomizer.hpp"
 #endif // REBASE_HPP
index 717246bc58ba38660b669388cad9f51cc2225c78..7f33dea7c9770dc83b214bd539fcdf01b5a18140 100644 (file)
@@ -36,6 +36,7 @@ SOURCES += main.cpp \
         ../base/ReMatcher.cpp \
         ../base/ReTest.cpp \
         ../base/ReWriter.cpp \
+        ../base/ReRandomizer.cpp \
         ../gui/ReStateStorage.cpp \
         ../gui/ReSettings.cpp \
        ../gui/ReEdit.cpp \
@@ -54,4 +55,6 @@ SOURCES += main.cpp \
 HEADERS += \
         ../base/ReFile.hpp \
         ../base/rebase.hpp \
-       ../gui/ReEdit.hpp
+       ../gui/ReEdit.hpp \
+       ../math/ReMatrix.hpp \
+       ../math/remath.hpp
index 06c819df284cac81d4ffd9b7f5dba21752db2cda..842814d59744fcc5ef91da9e71d32a0afbeff48a 100644 (file)
@@ -32,22 +32,40 @@ enum {
        LOC_SET_PROPERTIES_5,   // 12017
 };
 
+const char ReCryptFileSystem::ESC = '%';
+const int ReCryptFileSystem::m_indexOfNodeChar[] = { -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, 0, 1, -1, 2, 3, 4, 5, 6, 7, 8, -1, 9, 10, 11, 12,
+    -1, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, -1, -1, -1, 23, -1, -1, 24, 25,
+    26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+    45, 46, 47, 48, 49, 50, 51, -1, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+    63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+    82, 83, 84, 85, 86, };
+const char ReCryptFileSystem::m_nodeChars[] = { ' ', '!', '#', '$', '%', '&',
+    '\'', '(', ')', '+', ',', '-', '.', '0', '1', '2', '3', '4', '5', '6', '7',
+    '8', '9', '=', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
+    'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+    '[', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+    'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
+    'z', '{', '|', '}', '~', '\x7f', };
+const int ReCryptFileSystem::m_countNodeChars =
+    sizeof ReCryptFileSystem::m_nodeChars;
 /**
  * Constructor.
  *
  * @param name the name of the filesystem
  */
 ReFileSystem::ReFileSystem(const QString& name, ReLogger* logger) :
-               m_name(name),
+           m_name(name),
 #ifdef __linux__
-               m_uid(geteuid()),
-               m_gid(getegid()),
+           m_uid(geteuid()),
+           m_gid(getegid()),
 #endif
-               m_writeable(false),
-               m_logger(logger),
-               m_buffer(),
-               m_blocksize(4 * 1024 * 1024),
-               m_undefinedTime() {
+           m_writeable(false),
+           m_logger(logger),
+           m_buffer(),
+           m_blocksize(4 * 1024 * 1024),
+           m_undefinedTime() {
 
 }
 
@@ -66,14 +84,14 @@ ReFileSystem::~ReFileSystem() {
  *
  */
 ReFileSystem::ErrorCode ReFileSystem::copy(ReFileMetaData& source,
-       ReFileSystem& sourceFS) {
+    ReFileSystem& sourceFS) {
        int blocksize = min(m_blocksize, sourceFS.blocksize());
        ErrorCode rc = EC_SUCCESS;
        ErrorCode rc2;
        int64_t size = 0;
        while (rc == EC_SUCCESS && size < source.m_size) {
                if ((rc2 = sourceFS.read(source, size, blocksize, m_buffer))
-                       != EC_SUCCESS)
+                   != EC_SUCCESS)
                        rc = rc2;
                else if ((rc2 = write(source.m_node, size, m_buffer)) != EC_SUCCESS)
                        rc = rc2;
@@ -82,7 +100,7 @@ ReFileSystem::ErrorCode ReFileSystem::copy(ReFileMetaData& source,
        close();
        sourceFS.close();
        ReFileMetaData target(source.m_node, ReFileUtils::m_undefinedTime,
-                       ReFileUtils::m_undefinedTime, m_uid, m_gid);
+           ReFileUtils::m_undefinedTime, m_uid, m_gid);
        setProperties(source, target, false);
        return rc;
 }
@@ -136,7 +154,7 @@ bool ReFileSystem::first(const QString& pattern, ReFileMetaData& file) {
        QStringList names;
        names.append(pattern);
        ReIncludeExcludeMatcher matcher(names, ReQStringUtils::m_emptyList,
-               Qt::CaseInsensitive, true);
+           Qt::CaseInsensitive, true);
        listInfos(matcher, list);
        bool rc = list.size() > 0;
        if (rc)
@@ -162,11 +180,11 @@ void ReFileSystem::setBlocksize(int blocksize) {
  * @param logger
  */
 ReLocalFileSytem::ReLocalFileSytem(const QString& basePath, ReLogger* logger) :
-               ReFileSystem("localfs", logger),
-               m_basePath(basePath),
-               m_dir(basePath),
-               m_readFile(NULL),
-               m_writeFile(NULL) {
+           ReFileSystem("localfs", logger),
+           m_basePath(basePath),
+           m_dir(basePath),
+           m_readFile(NULL),
+           m_writeFile(NULL) {
        m_directory = basePath;
        ReQStringUtils::ensureLastChar(m_directory, OS_SEPARATOR);
        setWriteable(true);
@@ -209,11 +227,11 @@ void ReLocalFileSytem::close() {
  * @return                     the count of the found entries (<code>list.size()</code>)
  */
 int ReLocalFileSytem::listInfos(const ReIncludeExcludeMatcher& matcher,
-       ReFileMetaDataList& list) {
+    ReFileMetaDataList& list) {
        list.clear();
        const QStringList& patterns = matcher.includes().patterns();
        QStringList nodes =
-               patterns.size() == 0 ? m_dir.entryList() : m_dir.entryList(patterns);
+           patterns.size() == 0 ? m_dir.entryList() : m_dir.entryList(patterns);
        QStringList::const_iterator it;
        QByteArray full = m_directory.toUtf8();
        full.append(OS_SEPARATOR);
@@ -225,9 +243,9 @@ int ReLocalFileSytem::listInfos(const ReIncludeExcludeMatcher& matcher,
                full.append(node.toUtf8());
                if (stat(full.constData(), &info) == 0) {
                        list.append(
-                               ReFileMetaData(node, QDateTime::fromTime_t(info.st_mtime),
-                                       QDateTime::fromTime_t(info.st_ctime), info.st_uid,
-                                       info.st_gid, info.st_mode, info.st_size));
+                           ReFileMetaData(node, QDateTime::fromTime_t(info.st_mtime),
+                               QDateTime::fromTime_t(info.st_ctime), info.st_uid,
+                               info.st_gid, info.st_mode, info.st_size));
                }
        }
        return list.size();
@@ -247,11 +265,11 @@ ReFileSystem::ErrorCode ReLocalFileSytem::makeDir(const QString& node) {
                rc = EC_FS_READ_ONLY;
        } else if (m_dir.exists(node)) {
                m_logger->logv(LOG_ERROR, LOC_MAKE_DIR_2, "node exists already: %s",
-                       fullNameAsUTF8(node).constData());
+                   fullNameAsUTF8(node).constData());
                rc = EC_ALREADY_EXISTS;
        } else if (!m_dir.mkdir(node)) {
                m_logger->logv(LOG_ERROR, LOC_MAKE_DIR_2, "cannot create directory: %s",
-                       fullNameAsUTF8(node).constData());
+                   fullNameAsUTF8(node).constData());
                rc = EC_NOT_ACCESSIBLE;
        }
        return rc;
@@ -284,7 +302,7 @@ ReFileSystem::ErrorCode ReLocalFileSytem::setDirectory(const QString& path) {
  *                                     EC_READ: error while reading
  */
 ReFileSystem::ErrorCode ReLocalFileSytem::read(const ReFileMetaData& source,
-       int64_t offset, int size, QByteArray& buffer) {
+    int64_t offset, int size, QByteArray& buffer) {
        ErrorCode rc = EC_SUCCESS;
        if (offset == 0) {
                if (m_readFile != NULL)
@@ -292,8 +310,8 @@ ReFileSystem::ErrorCode ReLocalFileSytem::read(const ReFileMetaData& source,
                QString fn = fullName(source.m_node);
                if ((m_readFile = fopen(fn.toUtf8().constData(), "rb")) == NULL) {
                        m_logger->logv(LOG_ERROR, LOC_READ_1,
-                               "cannot open for reading (%d): %s", errno,
-                               fn.toUtf8().constData());
+                           "cannot open for reading (%d): %s", errno,
+                           fn.toUtf8().constData());
                        rc = EC_NOT_READABLE;
                }
        }
@@ -303,7 +321,7 @@ ReFileSystem::ErrorCode ReLocalFileSytem::read(const ReFileMetaData& source,
                int nRead = fread(buffer.data(), 1, size, m_readFile);
                if (nRead < 0) {
                        m_logger->logv(LOG_ERROR, LOC_READ_2, "cannot read (%d): %s", errno,
-                               source.m_node.toUtf8().constData());
+                           source.m_node.toUtf8().constData());
                        nRead = 0;
                        rc = EC_READ;
                }
@@ -335,21 +353,21 @@ ReFileSystem::ErrorCode ReLocalFileSytem::remove(const ReFileMetaData& node) {
                rc = EC_FS_READ_ONLY;
        } else if (!m_dir.exists(node.m_node)) {
                m_logger->logv(LOG_ERROR, LOC_REMOVE_2, "node does not exists: %s",
-                       fullNameAsUTF8(node.m_node).constData());
+                   fullNameAsUTF8(node.m_node).constData());
                rc = EC_NOT_EXISTS;
        } else {
                if (S_ISDIR(node.m_mode)) {
                        if (!m_dir.rmdir(node.m_node)) {
                                m_logger->logv(LOG_ERROR, LOC_REMOVE_3,
-                                       "cannot remove directory: %s",
-                                       fullNameAsUTF8(node.m_node).constData());
+                                   "cannot remove directory: %s",
+                                   fullNameAsUTF8(node.m_node).constData());
                                rc = EC_NOT_ACCESSIBLE;
                        }
                } else {
                        if (!m_dir.remove(node.m_node)) {
                                m_logger->logv(LOG_ERROR, LOC_REMOVE_3,
-                                       "cannot remove file: %s",
-                                       fullNameAsUTF8(node.m_node).constData());
+                                   "cannot remove file: %s",
+                                   fullNameAsUTF8(node.m_node).constData());
                                rc = EC_NOT_ACCESSIBLE;
                        }
                }
@@ -371,32 +389,31 @@ ReFileSystem::ErrorCode ReLocalFileSytem::remove(const ReFileMetaData& node) {
  *
  */
 ReFileSystem::ErrorCode ReLocalFileSytem::setProperties(
-       const ReFileMetaData& source, ReFileMetaData& target,
-               bool force) {
+    const ReFileMetaData& source, ReFileMetaData& target, bool force) {
        ErrorCode rc = EC_SUCCESS;
        if (!m_writeable) {
                m_logger->log(LOG_ERROR, LOC_SET_PROPERTIES_1,
-                       "filesystem is readonly");
+                   "filesystem is readonly");
                rc = EC_FS_READ_ONLY;
        } else
                do {
                        QByteArray name;
                        bool nameChanged = target.m_node != source.m_node;
                        bool timeChanged = source.m_modified != target.m_modified
-                               && source.m_modified != ReFileUtils::m_undefinedTime;
+                           && source.m_modified != ReFileUtils::m_undefinedTime;
 #ifdef __linux__
-               bool modeChanged = (source.m_mode & ALLPERMS) != (target.m_mode & ALLPERMS)
-                               && source.m_mode != (mode_t) -1;
-               bool ownerChanged = (source.m_owner != target.m_owner
+                       bool modeChanged = (source.m_mode & ALLPERMS) != (target.m_mode & ALLPERMS)
+                       && source.m_mode != (mode_t) -1;
+                       bool ownerChanged = (source.m_owner != target.m_owner
                                && source.m_owner != -1)
                        || (source.m_group != source.m_group
                                && source.m_group != -1);
-               if (force && m_uid != 0 && (nameChanged || timeChanged || modeChanged
-                                                                       || ownerChanged)){
-                       name = fullNameAsUTF8(target.m_node);
-                       chmod(name.constData(), ALLPERMS);
-                       modeChanged = true;
-               }
+                       if (force && m_uid != 0 && (nameChanged || timeChanged || modeChanged
+                                       || ownerChanged)) {
+                               name = fullNameAsUTF8(target.m_node);
+                               chmod(name.constData(), ALLPERMS);
+                               modeChanged = true;
+                       }
 
 #endif
                        if (nameChanged) {
@@ -405,17 +422,16 @@ ReFileSystem::ErrorCode ReLocalFileSytem::setProperties(
                                                name = fullNameAsUTF8(target.m_node);
                                        rc = EC_ALREADY_EXISTS;
                                        m_logger->logv(LOG_ERROR, LOC_SET_PROPERTIES_2,
-                                               "renaming impossible: node exists: %s",
-                                               name.constData());
+                                           "renaming impossible: node exists: %s",
+                                           name.constData());
                                        break;
                                } else if (!m_dir.rename(target.m_node, source.m_node)) {
                                        rc = EC_RENAME;
                                        if (name.length() == 0)
                                                name = fullNameAsUTF8(target.m_node);
                                        m_logger->logv(LOG_ERROR, LOC_SET_PROPERTIES_3,
-                                               "renaming impossible: %s -> %s",
-                                               source.m_node.toUtf8().constData(),
-                                               name.constData());
+                                           "renaming impossible: %s -> %s",
+                                           source.m_node.toUtf8().constData(), name.constData());
                                        break;
                                } else {
                                        name.resize(0);
@@ -426,7 +442,7 @@ ReFileSystem::ErrorCode ReLocalFileSytem::setProperties(
                                if (name.length() == 0)
                                        name = fullNameAsUTF8(target.m_node);
                                if (!ReFileUtils::setTimes(name.constData(), source.m_modified,
-                                       ReFileUtils::m_undefinedTime, m_logger))
+                                   ReFileUtils::m_undefinedTime, m_logger))
                                        rc = EC_NOT_ACCESSIBLE;
 
                        }
@@ -445,7 +461,7 @@ ReFileSystem::ErrorCode ReLocalFileSytem::setProperties(
                        }
                        if (modeChanged) {
                                mode_t mode = source.m_mode == (mode_t) -1
-                                               ? target.m_mode : source.m_mode;
+                               ? target.m_mode : source.m_mode;
                                if (chmod(name.constData(), mode & ALLPERMS) != 0) {
                                        rc = EC_NOT_ACCESSIBLE;
                                        m_logger->logv(LOG_ERROR, LOC_SET_PROPERTIES_4,
@@ -471,7 +487,7 @@ ReFileSystem::ErrorCode ReLocalFileSytem::setProperties(
  *
  */
 ReFileSystem::ErrorCode ReLocalFileSytem::write(const QString& node,
-       int64_t offset, const QByteArray& buffer) {
+    int64_t offset, const QByteArray& buffer) {
        ErrorCode rc = EC_SUCCESS;
        if (!writeable()) {
                m_logger->log(LOG_ERROR, LOC_WRITE_1, "filesystem is readonly");
@@ -483,8 +499,8 @@ ReFileSystem::ErrorCode ReLocalFileSytem::write(const QString& node,
                        QString fn = fullName(node);
                        if ((m_writeFile = fopen(fn.toUtf8().constData(), "wb")) == NULL) {
                                m_logger->logv(LOG_ERROR, LOC_WRITE_2,
-                                       "cannot open for writing (%d): %s", errno,
-                                       fn.toUtf8().constData());
+                                   "cannot open for writing (%d): %s", errno,
+                                   fn.toUtf8().constData());
                                rc = EC_NOT_WRITEABLE;
                        }
                }
@@ -493,14 +509,14 @@ ReFileSystem::ErrorCode ReLocalFileSytem::write(const QString& node,
                        if (position != offset) {
                                rc = EC_POSITION;
                                m_logger->logv(LOG_ERROR, LOC_WRITE_4,
-                                       "wrong file position: %lld/%lld", offset, position);
+                                   "wrong file position: %lld/%lld", offset, position);
                        } else {
                                int nWritten = fwrite(buffer.constData(), 1, buffer.length(),
-                                       m_writeFile);
+                                   m_writeFile);
                                if (nWritten != buffer.length()) {
                                        m_logger->logv(LOG_ERROR, LOC_WRITE_3,
-                                               "cannot write (%d): %s written: %d/%d", errno,
-                                               node.toUtf8().constData(), nWritten, buffer.length());
+                                           "cannot write (%d): %s written: %d/%d", errno,
+                                           node.toUtf8().constData(), nWritten, buffer.length());
                                        rc = EC_WRITE;
                                }
                                fflush(m_writeFile);
@@ -514,13 +530,13 @@ ReFileSystem::ErrorCode ReLocalFileSytem::write(const QString& node,
  * Constructor.
  */
 ReFileMetaData::ReFileMetaData() :
-               m_node(),
-               m_modified(),
-               m_created(),
-               m_owner(-1),
-               m_group(-1),
-               m_mode(-1),
-               m_size(-1) {
+           m_node(),
+           m_modified(),
+           m_created(),
+           m_owner(-1),
+           m_group(-1),
+           m_mode(-1),
+           m_size(-1) {
 
 }
 
@@ -536,14 +552,14 @@ 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) :
-               m_node(node),
-               m_modified(modified),
-               m_created(created),
-               m_owner(owner),
-               m_group(group),
-               m_mode(mode),
-               m_size(size) {
+    const QDateTime& created, int owner, int group, mode_t mode, int64_t size) :
+           m_node(node),
+           m_modified(modified),
+           m_created(created),
+           m_owner(owner),
+           m_group(group),
+           m_mode(mode),
+           m_size(size) {
 
 }
 
@@ -559,13 +575,13 @@ ReFileMetaData::~ReFileMetaData() {
  * @param source       source to copy
  */
 ReFileMetaData::ReFileMetaData(const ReFileMetaData& source) :
-               m_node(source.m_node),
-               m_modified(source.m_modified),
-               m_created(source.m_created),
-               m_owner(source.m_owner),
-               m_group(source.m_group),
-               m_mode(source.m_mode),
-               m_size(source.m_size) {
+           m_node(source.m_node),
+           m_modified(source.m_modified),
+           m_created(source.m_created),
+           m_owner(source.m_owner),
+           m_group(source.m_group),
+           m_mode(source.m_mode),
+           m_size(source.m_size) {
 
 }
 
@@ -585,3 +601,102 @@ ReFileMetaData&ReFileMetaData::operator =(const ReFileMetaData& source) {
        m_size = source.m_size;
        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),
+           m_host(hostFileSystem),
+           m_contentRandom(contentRandom),
+           m_nameRandom(nameRandom),
+           m_contentSeed(),
+           m_nameSeed(),
+           m_buffer() {
+       m_contentRandom.seed(m_contentSeed);
+       m_nameRandom.seed(m_nameSeed);
+       m_buffer.reserve(256);
+}
+
+/**
+ * Destructor.
+ */
+ReCryptFileSystem::~ReCryptFileSystem() {
+}
+
+/**
+ * Makes a clear text filename.
+ *
+ * @param name encrypted filename
+ * @return             the clear text filename
+ */
+QString ReCryptFileSystem::decodeName(const QString& name) {
+       QString rc = name;
+       return rc;
+}
+
+void ReCryptFileSystem::decodeContent(const QByteArray& source,
+    QByteArray& target) {
+
+}
+
+QByteArray& ReCryptFileSystem::encodeName(const QByteArray& node) {
+       QByteArray rc;
+       int length = node.length();
+       int nameLength = rc.lastIndexOf('.');
+       if (nameLength < 0)
+               nameLength = node.length();
+       const char* src = node.constData();
+       unsigned char cc;
+       int ix2 = nameLength - 1;
+       for (int ix = 0; ix < length; ix++) {
+               cc = (unsigned char) src[ix >= nameLength ? ix : ix2--];
+               if (cc != ESC && cc < 128) {
+                       m_buffer.append(cc);
+               } else {
+                       m_buffer.append(ESC);
+                       char hex[3];
+                       snprintf(hex, sizeof hex, "%02x", cc);
+                       m_buffer.append(hex, 2);
+               }
+       }
+       m_nameRandom.reset();
+       char* trg = m_buffer.data();
+       int pred = 0;
+       for (int ix = 0; ix < length; ix++) {
+               int ix2 = (m_indexOfNodeChar[*trg] + pred
+                   + m_nameRandom.nextInt(m_countNodeChars - 1)) % m_countNodeChars;
+               *trg = m_nodeChars[ix2];
+               pred = ix2;
+       }
+       return m_buffer;
+}
+QString ReCryptFileSystem::encodeName(const QString& node) {
+       return encodeName(node.toUtf8());
+}
+
+void ReCryptFileSystem::encodeContent(const QByteArray& source,
+    QByteArray& target) {
+
+}
+
+int ReCryptFileSystem::listInfos(const ReIncludeExcludeMatcher& matcher,
+    ReFileMetaDataList& list) {
+}
+
+ReFileSystem::ErrorCode ReCryptFileSystem::makeDir(const QString& node) {
+}
+
+ReFileSystem::ErrorCode ReCryptFileSystem::read(const ReFileMetaData& source,
+    int64_t offset, int size, QByteArray& buffer) {
+}
+
+ReFileSystem::ErrorCode ReCryptFileSystem::write(const QString& target,
+    int64_t offset, const QByteArray& buffer) {
+}
index 425f38bd0651ae32b834589fde5406b9295a1380..b3daa0f57d64cf3053cc0eeabf4e116108382323 100644 (file)
@@ -16,9 +16,8 @@ class ReFileMetaData {
 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);
+           const QDateTime& created, int owner = -1, int group = -1,
+           mode_t mode = (mode_t) - 1, int64_t size = 0);
        virtual ~ReFileMetaData();
        ReFileMetaData(const ReFileMetaData& source);
        ReFileMetaData& operator =(const ReFileMetaData& source);
@@ -74,7 +73,7 @@ public:
         * @return                      the count of the found entries (<code>list.size()</code>)
         */
        virtual int listInfos(const ReIncludeExcludeMatcher& matcher,
-               ReFileMetaDataList& list) = 0;
+           ReFileMetaDataList& list) = 0;
        /** Creates a directory.
         * @param node  the name without path (in the current directory)
         * @return              EC_SUCCESS or error code
@@ -88,7 +87,7 @@ public:
         * @return                      EC_SUCCESS or error code
         */
        virtual ErrorCode read(const ReFileMetaData& source, int64_t offset,
-               int size, QByteArray& buffer) = 0;
+           int size, QByteArray& buffer) = 0;
        /** Removes a file or directory.
         * @param node  the properties ot the node (in the current directory)
         * @return              EC_SUCCESS or error code
@@ -109,7 +108,7 @@ public:
         * @return                      EC_SUCCESS or error code
         */
        virtual ErrorCode setProperties(const ReFileMetaData& source,
-               ReFileMetaData& target, bool force) = 0;
+           ReFileMetaData& target, bool force) = 0;
        /** Writes a buffer to a file.
         * @param node          the file to write (without path, inside the current directory)
         * @param offset        first position to write
@@ -117,7 +116,7 @@ public:
         * @return                      EC_SUCCESS or error code
         */
        virtual ErrorCode write(const QString& target, int64_t offset,
-               const QByteArray& buffer) = 0;
+           const QByteArray& buffer) = 0;
 public:
        virtual ErrorCode copy(ReFileMetaData& source, ReFileSystem& sourceFS);
 public:
@@ -168,15 +167,15 @@ public:
        // ReFileSystem interface
        virtual void close();
        virtual int listInfos(const ReIncludeExcludeMatcher& matcher,
-               ReFileMetaDataList& list);
+           ReFileMetaDataList& list);
        ErrorCode makeDir(const QString& node);
        virtual ErrorCode read(const ReFileMetaData& source, int64_t offset,
-               int size, QByteArray& buffer);
+           int size, QByteArray& buffer);
        ErrorCode remove(const ReFileMetaData& node);
        ErrorCode setProperties(const ReFileMetaData& source,
-               ReFileMetaData& target, bool force = false);
+           ReFileMetaData& target, bool force = false);
        virtual ErrorCode write(const QString& target, int64_t offset,
-               const QByteArray& buffer);
+           const QByteArray& buffer);
 
 protected:
        QString m_basePath;
@@ -185,5 +184,47 @@ 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: ReFileSystem {
+public:
+       static const char ESC;
+public:
+       ReCryptFileSystem(ReFileSystem& hostFileSystem, ReRandomizer& nameRandom,
+           ReRandomizer& contentRandom, ReLogger* logger);
+       ~ReCryptFileSystem();
+public:
+       QString decodeName(const QString& name);
+       void decodeContent(const QByteArray& source, QByteArray& target);
+       QString encodeName(const QString& name);
+       QByteArray& encodeName(const QByteArray& name);
+       void encodeContent(const QByteArray& source, QByteArray& target);
+       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 write(const QString& target, int64_t offset,
+           const QByteArray& buffer);
+
+protected:
+       ReFileSystem& m_host;
+       ReRandomizer& m_contentRandom;
+       ReRandomizer& m_nameRandom;
+       QByteArray m_contentSeed;
+       QByteArray m_nameSeed;
+       QByteArray m_buffer;
+protected:
+       static const int m_indexOfNodeChar[];
+       static const char m_nodeChars[];
+       static const int m_countNodeChars;
+};
 
 #endif /* OS_REFILESYSTEM_HPP_ */
diff --git a/tools/mk_nodeChar.pl b/tools/mk_nodeChar.pl
new file mode 100644 (file)
index 0000000..966691f
--- /dev/null
@@ -0,0 +1,29 @@
+#! /usr/bin/perl
+
+use strict;
+my (@index, @chars);
+
+push @index, "const int ReCryptFileSystem::m_indexOfNodeChar[] = {";
+push @chars, "const char ReCryptFileSystem::m_nodeChars[] = {";
+
+for (0..31){
+       push @index, "-1,";
+}
+my $ix = 0;
+for (32..127){
+       my $cc = chr($_);
+       if ($cc !~ m!["*:?<>;\\/]!){
+               push @index, $ix++ . ",";
+               if ($cc eq "'"){
+                       push @chars, "'\\'',"; 
+               } else {
+                       push @chars, "'$cc',"; 
+               }
+       } else {
+               push @index, "-1,";
+       }
+}
+print join("\n", @index), "\n";
+print "};\n";
+print join("\n", @chars), "\n";
+print "};\n";