--- /dev/null
+/*
+ * 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;
+}
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() {
}
*
*/
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;
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;
}
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)
* @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);
* @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);
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();
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;
* 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)
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;
}
}
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;
}
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;
}
}
*
*/
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) {
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);
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;
}
}
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,
*
*/
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");
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;
}
}
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);
* 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) {
}
* @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) {
}
* @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) {
}
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) {
+}
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);
* @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
* @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
* @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
* @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:
// 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;
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_ */