* otherwise: the length of the integer
*/
int ReQStringUtils::lengthOfUInt64(const ReString& text, int start, int radix,
- int64_t* pValue) {
+ uint64_t* pValue) {
int inputLength = text.size();
int64_t value = 0;
int ix = start;
sizeof ReNameScrambler::m_nodeChars;
+/**
+ * Returns the hash value as hex string.
+ *
+ * Note: After call of this method the hash is reset!
+ *
+ * @return the hash value as hex string, stored in "little endian" byte order
+ */
+QByteArray ReDigest::hexDigest()
+{
+ QByteArray rc;
+ QByteArray hash = digest();
+ for (int ix = 0; ix < hash.length(); ix++){
+ rc.append(ReStringUtils::toNumber(hash.at(ix) & 0xff, "%02x"));
+ }
+ return rc;
+}
+
/**
* Contructor.
*
m_increment(increment),
m_hash(0),
m_sumLength(0),
- m_closed(false),
- m_littleEndian(true)
+ m_rest()
{
- int src = 1;
- int trg = 0;
- memcpy(&trg, &src, 1);
- m_littleEndian = trg != 0;
}
/**
* Return the hash value as 64 bit integer.
*
+ * Note: After call of this method the hash is reset!
+ *
* @return the hash value as 64 bit integer
*/
int64_t ReHmHash64::digestAsInt()
{
- if (! m_closed){
- m_closed = true;
- m_hash ^= (m_sumLength ^ 0x2011195811081965L) * m_factor
- + (m_increment >> m_sumLength % 29);
+# define CalcNextHash(data) m_hash ^= (data ^ 0x2004199111121989L) \
+ * m_factor + (m_increment >> (data % 23))
+ // ; printf("%016lx: -> %016lx\n", data, m_hash)
+
+ int64_t rc;
+ if (m_rest.length() > 0){
+ rc = 0;
+ memcpy(&rc, m_rest.constData(), m_rest.length());
+ CalcNextHash(rc);
}
- return m_hash;
+ CalcNextHash(m_sumLength);
+ rc = m_hash;
+ reset();
+ return rc;
}
/**
* Returns the hash value as byte array.
*
+ * Note: After call of this method the hash is reset!
+ *
* @return the hash value as byte array, stored in "little endian" byte order
*/
QByteArray ReHmHash64::digest()
QByteArray rc;
rc.resize(sizeof m_hash);
int64_t value = digestAsInt();
- if (m_littleEndian){
- * (int64_t*) rc.data() = value;
- } else {
- memcpy(rc.data(), &value, sizeof m_hash);
- }
- return rc;
-}
-
-/**
- * Returns the hash value as hex string.
- * @return the hash value as hex string, stored in "big endian" byte order
- */
-QByteArray ReHmHash64::hexDigest()
-{
- QByteArray rc;
- int size = sizeof m_hash * 2;
- rc.reserve(size);
- rc = QByteArray::number((qlonglong) digestAsInt(), 16);
- if (rc.length() != size)
- rc.insert(0, QByteArray("0000000000000000").mid(0, size - rc.length()));
+ memcpy(rc.data(), &value, sizeof m_hash);
return rc;
}
*/
void ReHmHash64::reset(){
m_hash = m_sumLength = 0;
- m_closed = false;
-}
-
-/**
- * Sets the flag "handle as little endian".
- *
- * @param littleEndian <code>true</code>: the byte order is "little endian"
- */
-void ReHmHash64::setLittleEndian(bool littleEndian)
-{
- m_littleEndian = littleEndian;
+ m_rest.clear();
}
/**
* @param source the data block which will be added to the hash
* @param length the length of the data (in bytes)
*/
-void ReHmHash64::update(void* source, size_t length)
+void ReHmHash64::update(const void* source, size_t length)
{
-#define CalcNextHash(data) m_hash ^= (data ^ 0x2004199111121989L) \
- * m_factor + (m_increment >> (data % 23))
+ const uint8_t* src = reinterpret_cast<const uint8_t*>(source);
int64_t data;
- if (m_sumLength % sizeof m_hash != 0)
- ReLogger::logv(LOG_ERROR, LOC_UPDATE_1,
- "ReHmHash64::update() non last block called with wrong length: %d",
- m_sumLength);
m_sumLength += length;
- if (m_littleEndian){
- const int64_t* src = reinterpret_cast<const int64_t*>(source);
- for (int ix = length / sizeof m_hash - 1; ix >= 0; ix--){
- data = *src++;
- CalcNextHash(data);
- }
- int rest = length % sizeof m_hash;
- if (rest > 0){
- data = 0;
- memcpy(&data, src, rest);
- data <<= sizeof m_hash - rest;
- CalcNextHash(data);
- }
- } else {
- const int8_t* src = reinterpret_cast<const int8_t*>(source);
- for (int ix = length / sizeof m_hash - 1; ix >= 0; ix--){
- data = 0;
- for (int ix2 = 0; ix2 < 8; ix2++)
- data |= (*src++ << ix2 * 8);
- CalcNextHash(data);
- }
- int rest = length % sizeof m_hash;
- if (rest > 0){
- data = 0;
- memcpy(&data, src, rest);
- data <<= sizeof m_hash - rest;
+ if (m_rest.length() > 0){
+ size_t needed = sizeof m_hash - m_rest.length();
+ if (needed > length){
+ m_rest.append(reinterpret_cast<const char*>(src), length);
+ length = 0;
+ } else {
+ m_rest.append(reinterpret_cast<const char*>(src), needed);
+ length -= needed;
+ src += needed;
+ memcpy(&data, m_rest.constData(), sizeof data);
CalcNextHash(data);
+ m_rest.clear();
}
}
+ for (int ix = length / sizeof m_hash - 1; ix >= 0; ix--){
+ memcpy(&data, src, sizeof data);
+ src += sizeof data;
+ CalcNextHash(data);
+ }
+ int rest = length % sizeof m_hash;
+ if (rest > 0){
+ m_rest.append(reinterpret_cast<const char*>(src), rest);
+ }
}
/**
return rc;
}
+/**
+ * @brief Returns binary data with random bytes.
+ *
+ * @param minLength The minimum length of the result data
+ * @param maxLength The maximum length of the result data
+ * @param buffer OUT: The place for the data
+ *
+ * @return <code>buffer</code> (for chaining)
+ */
+QByteArray& ReRandomizer::nextData(int minLength, int maxLength,
+ QByteArray &buffer) {
+ int len = nextInt(maxLength, minLength);
+ buffer.resize(len);
+ seed_t data;
+ seed_t* ptr = reinterpret_cast<seed_t*>(buffer.data());
+ for (int ix = len / sizeof data - 1; ix >= 0; ix--)
+ *ptr = nextSeed64();
+ if (len % sizeof data != 0){
+ data = nextSeed64();
+ memcpy(ptr, &data, len % sizeof data);
+ }
+ return buffer;
+}
+
/**
* @brief Returns the next random integer.
*
#define RANDOMIZER_H_
/**
- * Pure abstract base class for hash generators.
+ * Abstract base class for hash generators.
*/
class ReDigest {
public:
/** Returns the hash value as byte array.
+ * Note: After call of this method the hash is reset!
* @return the hash value as byte array, stored in "little endian" byte order
*/
virtual QByteArray digest() = 0;
- /** Returns the hash value as hex string.
- * @return the hash value as hex string, stored in "little endian" byte order
- */
- virtual QByteArray hexDigest() = 0;
/** Resets the hash.
- * The state is equal after the constructor.
+ * The state of the instance is the same as after the constructor.
*/
virtual void reset() = 0;
- /** Adds the content of a block to the hash.
+ /** Adds the data to the hash.
* @param source the data block which will be added to the hash
* @param length the length of the data (in bytes)
*/
- virtual void update(void* source, size_t length) = 0;
+ virtual void update(const void* source, size_t length) = 0;
+public:
+ QByteArray hexDigest();
+ /** Adds the data to the hash.
+ * @param source the data block which will be added to the hash
+ */
+ inline virtual void updateBlock(const QByteArray& source){
+ update(source.constData(), source.length());
+ }
};
/**
* Implements a very simple (and cheap) checksum.
+ *
+ * Features:
+ * <ul><li>If one bit of the content is changed normally many bits of the sum
+ * are changed</li>
+ * <li>If a '\\0' is appended to a sequence of '\\0'' many bits of the sum
+ * are change too</li>
+ * <li>64 bit checksum: low likelihood of collision</li>
+ * <li>Only 6 basic 64 bit operations (*, 2 ^, +, %, >>) per 8 byte content</li>
+ * <li>Works for little/big endian architectures</li>
+ * </ul>
*/
-class ReHmHash64 : ReDigest{
+class ReHmHash64 : public ReDigest{
public:
ReHmHash64(int64_t factor = 0x70cf79d585f5a313L,
int64_t increment = 0x75c280b9881252dbL);
int64_t digestAsInt();
public:
virtual QByteArray digest();
- virtual QByteArray hexDigest();
virtual void reset();
- virtual void setLittleEndian(bool littleEndian);
- virtual void update(void* source, size_t length);
+ virtual void update(const void* source, size_t length);
private:
int64_t m_factor;
int64_t m_increment;
int64_t m_hash;
int64_t m_sumLength;
- bool m_closed;
- bool m_littleEndian;
+ QByteArray m_rest;
};
/**
const QByteArray& name() const;
seed_t nearTrueRandom();
char nextChar();
+ QByteArray& nextData(int minLength, int maxLength, QByteArray& buffer);
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 testReWriter();
void testReFile();
void testReMatcher();
- testReFileUtils();
testReRandomizer();
+ testReFileUtils();
testReMatcher();
testReQStringUtil();
testReFile();
hash.update((void*) "12345678abcdefghABC", 8+8+3);
int64_t value = hash.digestAsInt();
hash.reset();
- hash.update((void*) "12345678", 8);
- hash.update((void*) "abcdefgh", 8);
+ hash.update((void*) "1234567", 7);
+ hash.update((void*) "8abcdefgh", 9);
hash.update((void*) "ABC", 3);
checkEqu(value, hash.digestAsInt());
+ ReKISSRandomizer random;
+ for (int ii = 0; ii < 1000; ii++){
+ QByteArray string;
+ random.nextString(1, 64, string);
+ testOneHash(string, random);
+ }
+ for (int ii = 0; ii < 1000; ii++){
+ QByteArray data;
+ random.nextData(1, 64, data);
+ testOneHash(data, random);
+ }
printHash("a");
printHash("b");
printHash("aa");
printHash("ab");
+ printHash("ba");
printHash("aaa");
printHash("aab");
printHash("aaaa");
printBinary(ix);
log("ready");
}
+ void testOneHash(QByteArray source, ReRandomizer& random){
+ ReHmHash64 hash;
+ hash.update(source.constData(), source.length());
+ int64_t value = hash.digestAsInt();
+
+ while (source.length() > 8){
+ int count = random.nextInt(1, source.length() - 1);
+ hash.updateBlock(source.mid(0, count));
+ source.remove(0, count);
+ }
+ hash.updateBlock(source);
+ checkEqu(value, hash.digestAsInt());
+ }
+
+ void hashPerformance(){
+ ReHmHash64 hash;
+ QByteArray data;
+ data.fill('x', 1024*1024);
+ clock_t start = clock();
+ int count = 100;
+ for (int ix = 0; ix < 100; ix++){
+ hash.update((void*) data.constData(), data.length());
+ }
+ double duration = double (clock() - start) / CLOCKS_PER_SEC;
+ printf("ReHmHash64: %.3f sec %.3f MByte/sec\n", duration,
+ count / duration);
+ }
+
void special(){
- ReKISSRandomizer rand;
- rand.dump();
- rand.nextSeed64();
- rand.dump();
log("ready");
}
virtual void run(void) {
+ special();
testReHmHash64();
+ hashPerformance();
testNextString();
testRealRandom();
testShuffle();
#include "net/ReTCPPeer.hpp"
#include "net/ReTCPServer.hpp"
-#include "net/ReTCPClient.hpp"
+#include "net/ReTcpClient.hpp"
#include "net/ReNetConfig.hpp"
#endif // RPLNET_HPP
* checksum (from offset 16) (8 byte, encrypted with resetted random)
* marker (2 byte, encrypted with resetted random)
* flags (2 byte) see ReFileHeaderOptions
- * reserved (4 byte)
+ * dynamic filelength (4 byte)
* encrypted file content
* checksum of the original file content
* </pre>
- * Checksum: sum_n ^= content_n * FAC + INC,
- * operands 8 byte signed integer, little endian
- * missing bytes (to 8 byte boundary) are padded with 0
- * FAC=0x7b644ac5d1187d25, INC=0x6b85115d6064365b
+ * <b>Calculation of the checksum:</b><br>
+ * Algorithm: see <code>ReHmHash64</code>
+ * factor=0x7b644ac5d1187d25, increment=0x6b85115d6064365b
+ *
+ * Checksum of the unencrypted file content: straight forward
+ *
+ * Checksum of the encrypted data:<br>
+ * <ul><li>Reset hash</li>
+ * <li>Encrypt data and add it to the hash</li>
+ * <li>Encrypt the checksum of the unencrypted data and add it to the hash</li<
+ * <li>Store the data length (without checksum) to the header</li<
+ * <li>Add the header from offset 16 to the hash</li>
+ * <li>Add the checksum in the header at offset 8</li>
+ * </ul>
*/
enum {
LOC_ADD_ENTRY_1 = LOC_FIRST_OF(LOC_CRYPTFILESYSTEM), // 12301
LOC_WRITE_META_1, // 12306
LOC_WRITE_META_2, // 12307
LOC_MAKE_DIR_1, // 12308
+ LOC_FILE_OPEN_1, // 12309
+ LOC_FILE_WRITE_1, // 12310
};
const int ReCryptFileSystem::NODE_LENGHT = 44;
// space for the struct and the node:
const int ReCryptDirectory::MAX_ENTRY_SIZE = sizeof(ReCryptDirectory::FileEntry_t)
+ 512;
+const int ReCryptDirectory::FILE_MARKER_LENGTH = 2;
+const int ReCryptDirectory::FILE_FLAGS_LENGTH = 2;
+const int ReCryptDirectory::FILE_LENGTH_LENGTH = 4;
+const int ReCryptDirectory::FILE_HEADER_LENGTH = 2 * sizeof(int64_t)
+ + FILE_MARKER_LENGTH + FILE_FLAGS_LENGTH + FILE_LENGTH_LENGTH;
+const int ReCryptDirectory::FILE_CHECKSUM_LENGTH = sizeof(int64_t);
/**
* Constructor.
*/
ReFileSystem::ErrorCode ReCryptFileSystem::write(const QString& target,
int64_t offset, const QByteArray& buffer) {
- return EC_SUCCESS;
+ m_contentRandom.reset();
+ QByteArray m_header;
+ return writeFileBlock(target, offset, buffer);
}
/**
ReCryptFileSystem* parent, ReLogger* logger) :
ReByteScrambler(contentRandom, logger),
m_list(),
- m_parent(parent),
+ m_parentFS(parent),
m_changed(false),
m_logger2(logger),
m_currentNode(),
return id;
}
+/**
+ * Returns the buffer for file data blocks.
+ *
+ * @return the file buffer
+ */
+QByteArray& ReCryptDirectory::fileBuffer()
+{
+ return m_fileBuffer;
+}
+
/**
* Search an file entry by name.
*
return rc;
}
+/**
+ * Returns the logger.
+ *
+ * @return the logger
+ */
+ReLogger*ReCryptDirectory::logger() const
+{
+ return m_logger2;
+}
+
+/**
+ * Returns the parent filesystem.
+ *
+ * @return the parent filesystem
+ */
+ReCryptFileSystem* ReCryptDirectory::parentFS() const
+{
+ return m_parentFS;
+}
+
/**
* Removes an entry given by the name.
*
//@ToDo:
//m_list.removeOne(entry2);
assert(false);
- ReFileSystem& host = m_parent->host();
+ ReFileSystem& host = m_parentFS->host();
ReFileMetaData hostedFile;
QString hostedNode = buildHostedNode(entry->m_id);
if (host.first(hostedNode, hostedFile))
{
bool rc = true;
m_list.clear();
- QString fnMetaFile = m_parent->directory() + ReCryptFileSystem::NODE_META_DIR;
+ QString fnMetaFile = m_parentFS->directory() + ReCryptFileSystem::NODE_META_DIR;
FILE* fp = fopen(fnMetaFile.toUtf8().constData(), "rb");
m_maxFileId = 0;
if (fp != NULL){
int length = node.length();
meta2->m_size += length + (length < 256 ? 0 : 1);
}
- QString fnMetaFile = m_parent->directory() + ReCryptFileSystem::NODE_META_DIR;
+ QString fnMetaFile = m_parentFS->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",
block.remove(0, srcPtr - block.constData());
printf("List: %d Rest: %d\n", m_list.length(), block.length());
}
+
+/**
+ * Returns the block size.
+ * @return the block size
+ */
+int ReCryptDirectory::blockSize() const
+{
+ return m_blockSize;
+}
+/**
+ * Sets the block size.
+ *
+ * @param blockSize the new block size
+ */
+void ReCryptDirectory::setBlockSize(int blockSize)
+{
+ m_blockSize = blockSize;
+}
+
/**
* Gets the filename of an entry in the hosted filesystem.
*
const QString& ReCryptDirectory::hostedFilename(const ReFileMetaData& entry)
{
QString node = buildHostedNode(entry.m_id);
- m_currentNode = ReFileUtils::pathAppend(m_parent->directory(), node);
+ m_currentNode = ReFileUtils::pathAppend(m_parentFS->directory(), node);
return m_currentNode;
}
+/**
+ * Writes a buffer to a file.
+ *
+ * @param target 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 ReCryptDirectory::writeFileBlock(const QString& target,
+ int64_t offset, const QByteArray& buffer)
+{
+ ReFileSystem::ErrorCode rc = ReFileSystem::EC_SUCCESS;
+
+ if (offset == 0){
+ ReFileMetaData metaData;
+ if (! m_parentFS->m_parentFS->exists(target, &metaData)){
+ QDateTime now = QDateTime::currentDateTime();
+ metaData.m_node = target;
+ metaData.m_modified = now;
+ metaData.m_created = now;
+ metaData.m_owner = m_parentFS->osPermissions().m_user;
+ metaData.m_group = m_parentFS->osPermissions().m_group;
+ metaData.m_mode = m_parentFS->osPermissions().m_fileMode;
+ metaData.m_size = buffer.length() + ReCryptDirectory::FILE_HEADER_LENGTH
+ + ReCryptDirectory::FILE_CHECKSUM_LENGTH;
+ metaData.m_id = ++m_maxFileId;
+ }
+ }
+ return rc;
+}
+
+/**
+ * Constructor.
+ *
+ * @param meta the file infos
+ * @param directory the assoziated directory
+ */
+ReCryptFile::ReCryptFile(const ReFileMetaData& meta, ReCryptDirectory& directory) :
+ m_metaData(meta),
+ m_fullHostedName((directory.parentFS()->host().directory()
+ + directory.parentFS()->buildHostedNode(meta.m_id)).toUtf8()),
+ m_fileHeader(),
+ m_dataSum(0x7b644ac5d1187d25L, 0x6b85115d6064365bL),
+ m_sumOfEncrypted(0x7b644ac5d1187d25L, 0x6b85115d6064365bL),
+ m_fp(NULL),
+ m_directory(directory),
+ m_dataSize(0)
+{
+}
+
+/**
+ * Destructor.
+ */
+ReCryptFile::~ReCryptFile()
+{
+ close();
+}
+
+/**
+ * Initializes the file for reading/writing.
+ *
+ * @param writeable <code>true</code>: the file can be written
+ * @return EC_SUCCESS: success<br>
+ * x
+ */
+ReFileSystem::ErrorCode ReCryptFile::open(bool writeable)
+{
+ ReFileSystem::ErrorCode rc = ReFileSystem::EC_SUCCESS;
+ close();
+ m_fp = fopen(m_fullHostedName, writeable? "wb" : "rb");
+ if (m_fp == NULL){
+ m_directory.logger()->logv(LOG_ERROR, LOC_FILE_OPEN_1, "cannot open hosted file (%d): %s",
+ errno, m_fullHostedName.constData());
+ rc = writeable ? ReFileSystem::EC_NOT_WRITEABLE : ReFileSystem::EC_NOT_READABLE;
+ }
+ return rc;
+}
+
+/**
+ * Writes a block to the hosted file.
+ *
+ * @param data data to write
+ * @return EC_SUCCESS: success
+ */
+ReFileSystem::ErrorCode ReCryptFile::writeBlock(const QByteArray& data){
+ ReFileSystem::ErrorCode rc = ReFileSystem::EC_SUCCESS;
+ if (m_fp != NULL && fwrite(data.constData(), data.length(), 1, m_fp)
+ != size_t(data.length())){
+ m_directory.logger()->logv(LOG_ERROR, LOC_FILE_WRITE_1,
+ "cannot write (%d): %s", errno, m_fullHostedName.constData());
+ rc = ReFileSystem::EC_NOT_WRITEABLE;
+ fclose(m_fp);
+ m_fp = NULL;
+ }
+ return rc;
+}
+
+/**
+ * Writes a data block to the file.
+ *
+ * @param data
+ * @return
+ */
+ReFileSystem::ErrorCode ReCryptFile::write(const QByteArray& data)
+{
+ ReFileSystem::ErrorCode rc = ReFileSystem::EC_SUCCESS;
+ m_dataSum.updateBlock(data);
+ QByteArray& target = m_directory.fileBuffer();
+ int blockSize = m_directory.blockSize();
+ if (m_dataSize > 0 && m_dataSize <= blockSize){
+ // write the header...
+ if ( (rc = writeBlock(m_fileHeader)) == ReFileSystem::EC_SUCCESS)
+ // and the first block...
+ rc = writeBlock(target);
+ target.clear();
+ }
+ m_dataSize += data.length();
+ if (rc == ReFileSystem::EC_SUCCESS){
+ m_directory.encodeContent(data, target);
+ m_sumOfEncrypted.updateBlock(target);
+ }
+ return rc;
+}
+
+/**
+ * Calculates the "dynamic length".
+ *
+ * The dynamic length is the length if it can be stored in a 32 bit integer.
+ * If the length is greater it will be shifted to right until 32 bit is enough.
+ *
+ * @param length the 64 bit length
+ * @return the dynamic length
+ */
+uint32_t ReCryptFile::dynamicLength(int64_t length) {
+ while (length > 0xFFFFffffL)
+ length >>= 1;
+ return uint64_t(length);
+}
+
+/**
+ * Flush data and free resources.
+ *
+ * @return EC_SUCCESS: success
+ */
+ReFileSystem::ErrorCode ReCryptFile::close()
+{
+ ReFileSystem::ErrorCode rc = ReFileSystem::EC_SUCCESS;
+ if (m_fp != NULL){
+ QByteArray& target = m_directory.fileBuffer();
+ int blockSize = m_directory.blockSize();
+ bool doFlush = m_dataSize > 0 && m_dataSize <= blockSize;
+ m_metaData.m_size = m_dataSize;
+ QByteArray checkSum = m_dataSum.digest();
+
+ // Add the data checksum at the end of the data block:
+ target.append(reinterpret_cast<const char*>(&checkSum), sizeof checkSum);
+ // Update the encrypted checksum:
+ m_sumOfEncrypted.update(&checkSum, sizeof checkSum);
+
+ // Update the protected part of the header info:
+ uint32_t size = dynamicLength(m_dataSize);
+ memcpy(m_fileHeader.data() + sizeof(ReRandomizer::seed_t)
+ + ReCryptDirectory::FILE_FLAGS_LENGTH, &size, sizeof size);
+
+ // Add the protected part of the header to the encrypted checksum:
+ m_sumOfEncrypted.update(m_fileHeader.constData() + 2 * sizeof(int64_t),
+ m_fileHeader.length() - 2 * sizeof(int64_t));
+ // update the unprotected part of the header:
+ memcpy(m_fileHeader.data() + sizeof(ReRandomizer::seed_t), &checkSum,
+ sizeof checkSum);
+
+ if (doFlush)
+ target.insert(0, m_fileHeader);
+ rc = writeBlock(target);
+ target.clear();
+ if (m_fp != NULL && ! doFlush){
+ fseek(m_fp, 0, SEEK_SET);
+ rc = writeBlock(m_fileHeader);
+ }
+ if (m_fp != NULL){
+ fclose(m_fp);
+ m_fp = NULL;
+ }
+ }
+ return rc;
+}
class ReCryptFileSystem;
-class ReCryptDirectory : protected ReByteScrambler{
+class ReCryptDirectory;
+/**
+ * Administrates an encrypted file for reading / writing.
+ */
+class ReCryptFile {
+public:
+ ReCryptFile(const ReFileMetaData& metaData, ReCryptDirectory& directory);
+ ~ReCryptFile();
+public:
+ ReFileSystem::ErrorCode open(bool writeable);
+ ReFileSystem::ErrorCode write(const QByteArray& data);
+ ReFileSystem::ErrorCode close();
+public:
+ static uint32_t dynamicLength(int64_t length);
+protected:
+ ReFileSystem::ErrorCode writeBlock(const QByteArray& data);
+private:
+ ReFileMetaData m_metaData;
+ QByteArray m_fullHostedName;
+ QByteArray m_fileHeader;
+ /// checksum of the unencrypted data
+ ReHmHash64 m_dataSum;
+ /// checksum of the encrypted data
+ ReHmHash64 m_sumOfEncrypted;
+ FILE* m_fp;
+ ReCryptDirectory& m_directory;
+ int64_t m_dataSize;
+};
+
+/**
+ * Administrates an encrypted directory.
+ */
+class ReCryptDirectory : public ReByteScrambler{
public:
typedef struct {
int64_t m_size;
} MetaInfo_t;
public:
ReCryptDirectory(ReRandomizer& contentRandom, ReCryptFileSystem* parent,
- ReLogger* logger);
+ ReLogger* logger);
~ReCryptDirectory();
public:
bool addEntry(ReFileMetaData& entry);
+ int blockSize() const;
+ QString buildHostedNode(int id) const;
+ QByteArray& fileBuffer();
const ReFileMetaData* find(const QString& node) const;
+ ReLogger* logger() const;
+ ReCryptFileSystem* parentFS() const;
bool removeEntry(const QString& entry);
bool readMetaFile();
+ void setBlockSize(int blockSize);
+ ReFileSystem::ErrorCode writeFileBlock(const QString& target, int64_t offset,
+ const QByteArray& buffer);
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 META_INFO_LENGTH;
static const int META_DIR_HEADER_LENGTH;
static const int MAX_ENTRY_SIZE;
+ static const int FILE_MARKER_LENGTH;
+ static const int FILE_FLAGS_LENGTH;
+ static const int FILE_LENGTH_LENGTH;
+ static const int FILE_HEADER_LENGTH;
+ static const int FILE_CHECKSUM_LENGTH;
+
protected:
ReFileMetaDataList m_list;
- ReCryptFileSystem* m_parent;
+ ReCryptFileSystem* m_parentFS;
bool m_changed;
// to avoid ambigousity:
ReLogger* m_logger2;
* will be encrypted. In the other direction the file content will be decrypted.
*/
class ReCryptFileSystem: public ReFileSystem,
- protected ReCryptDirectory
+ public ReCryptDirectory
{
public:
static const int NODE_LENGHT;
#error "missing evaluating drive"
#endif
}
+ return rc;
}
/**
full.append(node.toUtf8());
if (stat(full.constData(), &info) == 0) {
bool isDir = S_ISDIR(info.st_mode);
- if (isDir && ! withDirs || ! isDir && ! withFiles)
+ if ((isDir && ! withDirs) || (! isDir && ! withFiles))
continue;
if (! earlyMatching){
if ( (! isDir || matchDirs) && ! matcher.matches(node))
m_node(),
m_modified(),
m_created(),
+ m_size(-1),
m_owner(-1),
m_group(-1),
- m_mode(-1),
- m_size(-1) {
+ m_mode(-1)
+{
}
m_group = source.m_group;
m_fileMode = source.m_fileMode;
m_dirMode = source.m_dirMode;
+ return *this;
}