]> gitweb.hamatoma.de Git - reqt/commitdiff
ReLeafFile implementation
authorhama <hama@siduction.net>
Mon, 23 Nov 2015 23:14:09 +0000 (00:14 +0100)
committerhama <hama@siduction.net>
Mon, 23 Nov 2015 23:14:09 +0000 (00:14 +0100)
appl/resh/.gitignore [new file with mode: 0644]
appl/resh/ReShellTree.cpp [new file with mode: 0644]
appl/resh/ReShellTree.hpp [new file with mode: 0644]
appl/resh/main.cpp [new file with mode: 0644]
appl/resh/resh.hpp [new file with mode: 0644]
appl/resh/resh.pro [new file with mode: 0644]
cunit/cuReFileSystem.cpp
os/ReCryptFileSystem.cpp
os/ReCryptFileSystem.hpp
os/ReFileSystem.cpp
os/ReFileSystem.hpp

diff --git a/appl/resh/.gitignore b/appl/resh/.gitignore
new file mode 100644 (file)
index 0000000..5439c79
--- /dev/null
@@ -0,0 +1,73 @@
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
+
diff --git a/appl/resh/ReShellTree.cpp b/appl/resh/ReShellTree.cpp
new file mode 100644 (file)
index 0000000..6f8cce0
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Licence:
+ * You can use and modify this file without any restriction.
+ * There is no warranty.
+ * You also can use the licence from http://www.wtfpl.net/.
+ * The original sources can be found on https://github.com/republib.
+*/
+
+
+#include "resh.hpp"
+
+ReShellTree::ReShellTree()
+{
+
+}
+
diff --git a/appl/resh/ReShellTree.hpp b/appl/resh/ReShellTree.hpp
new file mode 100644 (file)
index 0000000..ab58302
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Licence:
+ * You can use and modify this file without any restriction.
+ * There is no warranty.
+ * You also can use the licence from http://www.wtfpl.net/.
+ * The original sources can be found on https://github.com/republib.
+*/
+
+
+#ifndef RESHELLTREE_HPP
+#define RESHELLTREE_HPP
+
+class ReShellStatement{
+public:
+       enum StatementFlags {
+               SF_UNDEF,
+               SF_INTERNAL_CMD = 1,
+               SF_VAR_EXPANSION = 2,
+               SF_INTERPOLATION = 4,
+               SF_INP_REDIRECT = 8,
+               SF_OUT_REDIRECT = 16,
+               SF_SHELL_SCRIPT = 32,
+               SF_OUT_TO_STRING = 64,
+       };
+public:
+       ReSource* source;
+       ReShellStatement* m_next;
+       int m_flags;
+};
+
+class ReShellIf : public ReShellStatement{
+public:
+       ReShellStatement* m_condition;
+       ReShellStatement* m_then;
+       ReShellStatement* m_else;
+};
+
+class ReShellWhile : public ReShellStatement{
+public:
+       ReShellStatement* m_condition;
+       ReShellStatement* m_body;
+};
+
+class ReCaseAlternative {
+public:
+       QByteArray m_value;
+       ReShellStatement* m_statement;
+       ReCaseAlternative* m_next;
+};
+
+
+class ReShellCase : public ReShellStatement{
+protected:
+       ReCaseAlternative* m_condition;
+       ReShellStatement* m_body;
+};
+
+class ReShellFunction {
+public:
+       QByteArray m_name;
+       ReShellStatement* m_body;
+};
+
+
+class ReShellTree
+{
+public:
+       ReShellTree();
+public:
+       QList<ReShellFunction> m_functions;
+       ReShellStatement m_body;
+};
+
+#endif // RESHELLTREE_HPP
diff --git a/appl/resh/main.cpp b/appl/resh/main.cpp
new file mode 100644 (file)
index 0000000..8a70156
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Licence:
+ * You can use and modify this file without any restriction.
+ * There is no warranty.
+ * You also can use the licence from http://www.wtfpl.net/.
+ * The original sources can be found on https://github.com/republib.
+*/
+
+
+#include <QCoreApplication>
+
+int main(int argc, char *argv[])
+{
+       QCoreApplication a(argc, argv);
+
+       return a.exec();
+}
+
diff --git a/appl/resh/resh.hpp b/appl/resh/resh.hpp
new file mode 100644 (file)
index 0000000..6bfb778
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Licence:
+ * You can use and modify this file without any restriction.
+ * There is no warranty.
+ * You also can use the licence from http://www.wtfpl.net/.
+ * The original sources can be found on https://github.com/republib.
+*/
+
+
+#ifndef RESH_HPP
+#define RESH_HPP
+
+#include "base/rebase.hpp"
+#include "expr/reexpr.hpp"
+#include "os/reos.hpp"
+#include "ReShellTree.hpp"
+#endif // RESH_HPP
+
diff --git a/appl/resh/resh.pro b/appl/resh/resh.pro
new file mode 100644 (file)
index 0000000..03707b3
--- /dev/null
@@ -0,0 +1,26 @@
+QT += core
+#QT -= gui
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+TARGET = resh
+CONFIG += console
+CONFIG -= app_bundle
+
+TEMPLATE = app
+
+INCLUDEPATH = ../..
+
+SOURCES += main.cpp \
+       ../../base/ReStringUtils.cpp \
+       ../../base/ReQStringUtils.cpp \
+       ../../base/ReCharPtrMap.cpp \
+       ../../base/ReException.cpp \
+       ../../base/ReLogger.cpp \
+       ../../expr/ReSource.cpp \
+       ../../expr/ReLexer.cpp \
+       ReShellTree.cpp
+#      ../../expr/ReExpression.cpp \
+
+HEADERS += \
+       resh.hpp
+
index 6c0da088fb05423a9a99d6a84c18651f14ce640d..b1fce075992033d82094e8a560ec53b476cd27de 100644 (file)
@@ -67,21 +67,39 @@ protected:
                ReLocalFileSystem fs(m_base, &m_logger);
                QByteArray buffer;
                buffer.append("abcdefghijklmnopqrstuvwxyz");
-               checkEqu(0, fs.write("abc.txt", 0LL, buffer));
-               checkEqu(0, fs.write("abc.txt", 26LL, buffer));
+
+               //checkEqu(0, fs.write("abc.txt", 0LL, buffer));
+               //checkEqu(0, fs.write("abc.txt", 26LL, buffer));
                QByteArray buffer2;
                ReFileMetaDataList nodes;
                QStringList names;
                names.append("abc.txt");
+               names.append("new.txt");
                ReIncludeExcludeMatcher matcher(names, ReQStringUtils::m_emptyList,
                        Qt::CaseInsensitive, true);
                checkEqu(1, fs.listInfos(matcher, nodes, ReFileSystem::LO_UNDEF));
                checkEqu(1, nodes.size());
-               checkEqu(0, fs.read(nodes.at(0), 0LL, 3, buffer2));
+               QByteArray content("This is a content\nLine 2");
+               checkEqu(0, fs.createFile("new.txt", false));
+               ReFileMetaData meta;
+               checkT(fs.exists("new.txt", &meta));
+               ReLeafFile* leaf1 = fs.buildFile(meta);
+               leaf1->open(true);
+               leaf1->write(content);
+               leaf1->close();
+               delete leaf1;
+               checkT(fs.exists("new.txt", &meta));
+               ReLeafFile* leaf2 = fs.buildFile(meta);
+               leaf2->open(false);
+               leaf2->read(500, buffer);
+               leaf2->close();
+               delete leaf2;
+
+               //checkEqu(0, fs.read(nodes.at(0), 0LL, 3, buffer2));
                checkEqu("abc", buffer2);
-               checkEqu(0, fs.read(nodes.at(0), 3LL, 7, buffer2));
+               //checkEqu(0, fs.read(nodes.at(0), 3LL, 7, buffer2));
                checkEqu("defghij", buffer2);
-               checkEqu(0, fs.read(nodes.at(0), 10LL, 99, buffer2));
+               //checkEqu(0, fs.read(nodes.at(0), 10LL, 99, buffer2));
                checkEqu("klmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", buffer2);
        }
        void testSetProperties() {
index 99e4096770ebebe943b530db85b7272f336c7e7b..f41c1d905ad2731374fcad38d7bfee8af80d842f 100644 (file)
@@ -49,6 +49,7 @@ enum {
        LOC_MAKE_DIR_1,                 // 12308
        LOC_FILE_OPEN_1,                // 12309
        LOC_FILE_WRITE_1,               // 12310
+       LOC_CREATE_FILE_1,              // 12311
 };
 
 const int ReCryptFileSystem::NODE_LENGHT = 44;
@@ -95,15 +96,67 @@ ReCryptFileSystem::ReCryptFileSystem(ReFileSystem& hostFileSystem,
 ReCryptFileSystem::~ReCryptFileSystem() {
 }
 
+/**
+ * Returns a filesystem dependent instance of a file.
+ *
+ * The file must exist in the current directory.
+ * The caller must free the instance.
+ *
+ * @param meta the metadata of the file
+ * @return             NULL: no file found<br>
+ *                             otherwise: the file
+ */
+ReLeafFile* ReCryptFileSystem::buildFile(const ReFileMetaData& metadata)
+{
+       return new ReCryptLeafFile(metadata, fullName(metadata.m_node), m_logger2);
+}
+
 QString ReCryptFileSystem::canonicalPathOf(const QString& path)
 {
        return ReFileUtils::cleanPath(path);
 }
 
-/** Frees resources like open files.
+/**
+ * Creates a new file in the current directory.
+ *
+ * @param node                         the name of the new file
+ * @param inDirectoryOnly      <code>false</code>: the file is made physically<br>
+ *                                                     otherwise: the file exists only in the metadata
+ *                                                     of the directory
+ * @param metadata                     OUT: NULL or the metadata of the new file
+ * @return                                     EC_SUCCESS: success<br>
+ *                                                     EC_ALREADY_EXISTS: the file already exists
+ *                                                     EC_WRITE: the file could not be written
  */
-void ReCryptFileSystem::close()
+ReFileSystem::ErrorCode ReCryptFileSystem::createFile(const QString& node,
+               bool inDirectoryOnly, ReFileMetaData* metadata)
 {
+       ErrorCode rc = EC_SUCCESS;
+       if (exists(node, NULL))
+               rc = EC_ALREADY_EXISTS;
+       else{
+               QDateTime now = QDateTime::currentDateTime();
+               int id = ++m_maxFileId;
+               ReFileMetaData meta = ReFileMetaData(node, now, now,
+                       m_osPermissions.m_user, m_osPermissions.m_group,
+                       m_osPermissions.m_dirMode, 0, id);
+               m_list.append(meta);
+               if (metadata != NULL){
+                       *metadata = meta;
+               }
+               if (! inDirectoryOnly){
+                       QString hostName = buildHostedNode(id);
+                       QByteArray fullName = fullNameAsUTF8(hostName);
+                       FILE* fp = fopen(fullName.constData(), "w");
+                       if (fp == NULL){
+                               rc = EC_WRITE;
+                               m_logger2->logv(LOG_ERROR, LOC_CREATE_FILE_1, "cannot open (%d): %s",
+                                                          errno, fullName.constData());
+                       } else
+                               fclose(fp);
+               }
+       }
+       return rc;
 }
 
 /**
@@ -830,3 +883,49 @@ ReFileSystem::ErrorCode ReCryptFile::close()
        }
        return rc;
 }
+
+/**
+ * Constructor.
+ *
+ * @param metaData     metadata of the file
+ * @param fullName     filename with path
+ * @param logger       the logger
+ */
+ReCryptLeafFile::ReCryptLeafFile(const ReFileMetaData& metaData,
+                                                                const QString& fullName, ReLogger* logger) :
+       ReLeafFile(metaData, fullName, logger)
+{
+
+}
+
+/**
+ * Destructor.
+ */
+ReCryptLeafFile::~ReCryptLeafFile()
+{
+
+}
+
+ReFileSystem::ErrorCode ReCryptLeafFile::open(bool writeable)
+{
+       ReFileSystem::ErrorCode rc = ReFileSystem::EC_SUCCESS;
+       return rc;
+}
+
+ReFileSystem::ErrorCode ReCryptLeafFile::close()
+{
+       ReFileSystem::ErrorCode rc = ReFileSystem::EC_SUCCESS;
+       return rc;
+}
+
+ReFileSystem::ErrorCode ReCryptLeafFile::read(int size, QByteArray& buffer)
+{
+       ReFileSystem::ErrorCode rc = ReFileSystem::EC_SUCCESS;
+       return rc;
+}
+
+ReFileSystem::ErrorCode ReCryptLeafFile::write(const QByteArray& buffer)
+{
+       ReFileSystem::ErrorCode rc = ReFileSystem::EC_SUCCESS;
+       return rc;
+}
index 45ed45d3b1ef408e2a9ea847fbfae30b376e2f27..5ede305a94e2991e79ab5ec5f58bd9d8594de685 100644 (file)
@@ -110,6 +110,23 @@ protected:
        int m_maxFileId;
 };
 
+/**
+ * An abstract base class for leafs of the tree spanned by a filesystem.
+ *
+ * A leaf file could not be a directory.
+ */
+class ReCryptLeafFile : public ReLeafFile{
+public:
+       ReCryptLeafFile(const ReFileMetaData& metaData, const QString& fullName,
+                                       ReLogger* logger);
+       virtual ~ReCryptLeafFile();
+public:
+       virtual ReFileSystem::ErrorCode open(bool writeable);
+       virtual ReFileSystem::ErrorCode close();
+       virtual ReFileSystem::ErrorCode read(int size, QByteArray& buffer);
+       virtual ReFileSystem::ErrorCode write(const QByteArray& buffer);
+};
+
 /**
  * A filesystem with encrypted filenames and file content.
  *
@@ -134,8 +151,10 @@ public:
                ReRandomizer& contentRandom, ReLogger* logger);
        ~ReCryptFileSystem();
 public:
+       virtual ReLeafFile* buildFile(const ReFileMetaData& metadata);
        virtual QString canonicalPathOf(const QString& path);
-       virtual void close();
+       virtual ErrorCode createFile(const QString& node, bool inDirectoryOnly,
+                       ReFileMetaData* metadata = NULL);
        virtual bool exists(const QString& node, ReFileMetaData* metaInfo) const;
        virtual int listInfos(const ReIncludeExcludeMatcher& matcher,
                ReFileMetaDataList& list, ListOptions options = LO_ALL);
index 9e8734915fdfc558defdaa7e83ccc1e1197e56cf..962256f4d834b56b485afd721bd0b51e64b50755 100644 (file)
@@ -30,6 +30,8 @@ enum {
        LOC_REMOVE_3,           // 12015
        LOC_SET_PROPERTIES_4,   // 12016
        LOC_SET_PROPERTIES_5,   // 12017
+       LOC_OPEN_1,                             // 12018
+       LOC_CREATE_FILE_1,              // 12019
 };
 
 /**
@@ -101,19 +103,32 @@ ReFileSystem::ErrorCode ReFileSystem::copy(ReFileMetaData& source,
        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)
-                       rc = rc2;
-               else if ((rc2 = write(source.m_node, size, m_buffer)) != EC_SUCCESS)
-                       rc = rc2;
-               size += blocksize;
+       ReLeafFile* sourceFile = sourceFS.buildFile(source);
+       ReFileMetaData targetMeta;
+       if (! exists(source.m_node, &targetMeta)){
+               rc = createFile(source.m_node, false, &targetMeta);
+       }
+       if (rc == EC_SUCCESS){
+               ReLeafFile* targetFile = buildFile(targetMeta);
+               if (sourceFile->open(false) == EC_SUCCESS
+                               && targetFile->open(true) == EC_SUCCESS){
+                       while (rc == EC_SUCCESS && size < source.m_size) {
+                               if ((rc2 = sourceFile->read(blocksize, m_buffer))
+                                               != EC_SUCCESS)
+                                       rc = rc2;
+                               else if ((rc2 = targetFile->write(m_buffer)) != EC_SUCCESS)
+                                       rc = rc2;
+                               size += blocksize;
+                       }
+               }
+               sourceFile->close();
+               targetFile->close();
+               ReFileMetaData target(source.m_node, ReFileUtils::m_undefinedTime,
+                                                         ReFileUtils::m_undefinedTime, m_uid, m_gid);
+               setProperties(source, target, false);
+               delete sourceFile;
+               delete targetFile;
        }
-       close();
-       sourceFS.close();
-       ReFileMetaData target(source.m_node, ReFileUtils::m_undefinedTime,
-               ReFileUtils::m_undefinedTime, m_uid, m_gid);
-       setProperties(source, target, false);
        return rc;
 }
 
@@ -330,9 +345,7 @@ bool ReFileSystem::writeable() const {
 ReLocalFileSystem::ReLocalFileSystem(const QString& basePath, ReLogger* logger) :
                ReFileSystem("localfs", logger),
                m_basePath(basePath),
-               m_dir(basePath),
-               m_readFile(NULL),
-               m_writeFile(NULL) {
+               m_dir(basePath) {
        m_directory = basePath;
        ReQStringUtils::ensureLastChar(m_directory, OS_SEPARATOR);
        setWriteable(true);
@@ -354,20 +367,6 @@ const QString& ReLocalFileSystem::basePath() const {
        return m_basePath;
 }
 
-/**
- * Closes the open files.
- */
-void ReLocalFileSystem::close() {
-       if (m_readFile != NULL) {
-               fclose(m_readFile);
-               m_readFile = NULL;
-       }
-       if (m_writeFile != NULL) {
-               fclose(m_writeFile);
-               m_writeFile = NULL;
-       }
-}
-
 /**
  * Search a file in the current directory given by name.
  *
@@ -498,6 +497,44 @@ ReFileSystem::ErrorCode ReLocalFileSystem::setDirectory(const QString& path) {
        return rc;
 }
 
+/**
+ * Creates a new file in the current directory.
+ *
+ * @param node                         the name of the new file
+ * @param inDirectoryOnly      <code>false</code>: the file is made physically<br>
+ *                                                     otherwise: the file exists only in the metadata
+ *                                                     of the directory
+ * @param metadata                     OUT: NULL or the metadata of the new file
+ * @return                                     EC_SUCCESS: success<br>
+ *                                                     EC_ALREADY_EXISTS: the file already exists
+ *                                                     EC_WRITE: the file could not be written
+ */
+ReFileSystem::ErrorCode ReLocalFileSystem::createFile(const QString& node,
+               bool inDirectoryOnly, ReFileMetaData* metadata)
+{
+       ErrorCode rc = EC_SUCCESS;
+       if (exists(node))
+               rc = EC_ALREADY_EXISTS;
+       else{
+               if (metadata != NULL){
+                       QDateTime now = QDateTime::currentDateTime();
+                       *metadata = ReFileMetaData(node, now, now, m_osPermissions.m_user,
+                                       m_osPermissions.m_group, m_osPermissions.m_dirMode, 0);
+               }
+               if (! inDirectoryOnly){
+                       QByteArray name(fullNameAsUTF8(node));
+                       FILE* fp = fopen(name.constData(), "w");
+                       if (fp == NULL){
+                               rc = EC_WRITE;
+                               m_logger->logv(LOG_ERROR, LOC_CREATE_FILE_1, "cannot open (%d): %s",
+                                                          errno, name.constData());
+                       } else
+                               fclose(fp);
+               }
+       }
+       return rc;
+}
+
 /**
  * Returns the canonical form of a given path.
  *
@@ -512,52 +549,6 @@ QString ReLocalFileSystem::canonicalPathOf(const QString& path)
        return rc;
 }
 
-/**
- * Reads a part of a file into a buffer.
- *
- * @param source       the file to move
- * @param offset       first position to read
- * @param size         number of bytes to read
- * @param buffer       OUT: content of the file
- * @return                     EC_SUCCESS: success<br>
- *                                     EC_NOT_READABLE: file can't be opened<br>
- *                                     EC_READ: error while reading
- */
-ReFileSystem::ErrorCode ReLocalFileSystem::read(const ReFileMetaData& source,
-       int64_t offset, int size, QByteArray& buffer) {
-       ErrorCode rc = EC_SUCCESS;
-       if (offset == 0) {
-               if (m_readFile != NULL)
-                       fclose(m_readFile);
-               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());
-                       rc = EC_NOT_READABLE;
-               }
-       }
-       if (m_readFile != NULL) {
-               ReFileUtils::seek(m_readFile, offset, SEEK_SET);
-               buffer.reserve(size);
-               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());
-                       nRead = 0;
-                       rc = EC_READ;
-               }
-               buffer.resize(nRead);
-               if (feof(m_readFile)) {
-                       fclose(m_readFile);
-                       m_readFile = NULL;
-               } else {
-                       fflush(m_readFile);
-               }
-       }
-       return rc;
-}
-
 /**
  * Removes a file or directory.
  *
@@ -695,59 +686,6 @@ ReFileSystem::ErrorCode ReLocalFileSystem::setProperties(
        return rc;
 }
 
-/**
- * Writes a buffer to a file.
- *
- * @param node         the file to write (without path, inside the current directory)
- * @param offset       first position to write
- * @param buffer       content to write
- * @return                     EC_SUCCESS: successful<br>
- *                                     EC_FS_READ_ONLY: filesystem is readonly<br>
- *                                     EC_NOT_WRITEABLE: open for writing failed
- *                                     EC_POSITION: file position not equals to <code>offset</code>
- *                                     EC_WRITE: writing failed
- *
- */
-ReFileSystem::ErrorCode ReLocalFileSystem::write(const QString& node,
-       int64_t offset, const QByteArray& buffer) {
-       ErrorCode rc = EC_SUCCESS;
-       if (!writeable()) {
-               m_logger->log(LOG_ERROR, LOC_WRITE_1, "filesystem is readonly");
-               rc = EC_FS_READ_ONLY;
-       } else {
-               if (offset == 0) {
-                       if (m_writeFile != NULL)
-                               fclose(m_writeFile);
-                       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());
-                               rc = EC_NOT_WRITEABLE;
-                       }
-               }
-               if (m_writeFile != NULL) {
-                       int64_t position = ReFileUtils::tell(m_writeFile);
-                       if (position != offset) {
-                               rc = EC_POSITION;
-                               m_logger->logv(LOG_ERROR, LOC_WRITE_4,
-                                       "wrong file position: %lld/%lld", offset, position);
-                       } else {
-                               int nWritten = fwrite(buffer.constData(), 1, buffer.length(),
-                                       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());
-                                       rc = EC_WRITE;
-                               }
-                               fflush(m_writeFile);
-                       }
-               }
-       }
-       return rc;
-}
-
 /**
  * Constructor.
  */
@@ -875,3 +813,123 @@ ReOSPermissions&ReOSPermissions::operator =(const ReOSPermissions& source)
        return *this;
 }
 
+/**
+ * Constructor.
+ *
+ * @param metaData     the meta data of the file
+ */
+ReLocalLeafFile::ReLocalLeafFile(const ReFileMetaData& metaData,
+               const QString& fullName, ReLogger* logger) :
+       ReLeafFile(metaData, fullName, logger),
+       m_fp(NULL)
+{
+}
+
+/**
+ * Destructor.
+ */
+ReLocalLeafFile::~ReLocalLeafFile(){
+}
+
+/**
+ * Opens a file for reading or writing.
+ *
+ * @param writeable    <code>true</code>: open for writing
+ * @return                     EC_SUCCESS: success<br>
+ *                                     EC_CANNOT_OPEN: opening failed
+ */
+ReFileSystem::ErrorCode ReLocalLeafFile::open(bool writeable){
+       ReFileSystem::ErrorCode  rc = ReFileSystem::EC_SUCCESS;
+       if ( (m_fp = fopen(m_fullName.toUtf8().constData(),
+                                          writeable ?"wb" : "rb")) == NULL){
+               rc = ReFileSystem::EC_NOT_EXISTS;
+               m_logger->logv(LOG_ERROR, LOC_OPEN_1, "cannot open: %s",
+                                          m_fullName.toUtf8().constData());
+       }
+       return rc;
+}
+
+/** Frees the resources occupied by <code>open()</code>.
+ *
+ * @return                     EC_SUCCESS: success
+ */
+ReFileSystem::ErrorCode ReLocalLeafFile::close(){
+       ReFileSystem::ErrorCode  rc = ReFileSystem::EC_SUCCESS;
+       if (m_fp != NULL){
+               fclose(m_fp);
+               m_fp = NULL;
+       }
+       return rc;
+}
+/**
+ * Reads data from the current position into a buffer.
+ *
+ * @param size         number of bytes to read
+ * @param buffer       OUT: content of the file
+ * @return                     EC_SUCCESS: success<br>
+ *                                     EC_INVALID_STATE: file not open
+ */
+ReFileSystem::ErrorCode ReLocalLeafFile::read(int maxSize,
+                       QByteArray& buffer){
+       ReFileSystem::ErrorCode  rc = ReFileSystem::EC_SUCCESS;
+       if (m_fp == NULL){
+               rc = ReFileSystem::EC_INVALID_STATE;
+       } else {
+               maxSize = min(maxSize, m_meta.m_size - ftell(m_fp));
+               buffer.resize(maxSize);
+               int nRead = 0;
+               if ( (nRead = fread(buffer.data(), 1, maxSize, m_fp)) != maxSize){
+                       rc = ReFileSystem::EC_READ;
+                       m_logger->logv(LOG_ERROR, LOC_READ_1, "cannnot read %s (%d): %d/%d",
+                               m_fullName.toUtf8().constData(), errno, nRead, maxSize);
+               }
+       }
+       return rc;
+}
+
+/**
+ * Writes a buffer to a file at the current position.
+ *
+ * @param buffer       content to write
+ * @return                     EC_SUCCESS or error code
+ */
+ReFileSystem::ErrorCode ReLocalLeafFile::write(const QByteArray& buffer){
+       ReFileSystem::ErrorCode  rc = ReFileSystem::EC_SUCCESS;
+       if (m_fp == NULL){
+               rc = ReFileSystem::EC_INVALID_STATE;
+       } else {
+               int nWritten = 0;
+               int nToWrite = buffer.length();
+               if ( (nWritten = fwrite(buffer.constData(), 1, nToWrite, m_fp)) != nToWrite){
+                       rc = ReFileSystem::EC_WRITE;
+                       m_logger->logv(LOG_ERROR, LOC_WRITE_1, "cannnot read %s (%d): %d/%d",
+                               m_fullName.toUtf8().constData(), errno, nWritten, nToWrite);
+               }
+       }
+       return rc;
+}
+
+
+/**
+ * Constructor.
+ *
+ * @param metaData     metadata of the file
+ * @param fullName     filename with path
+ * @param logger       the logger
+ */
+ReLeafFile::ReLeafFile(const ReFileMetaData& metaData, const QString& fullName,
+       ReLogger* logger) :
+       m_fullName(fullName),
+       m_logger(logger),
+       m_meta(metaData)
+{
+}
+
+/**
+ * Destructor.
+ */
+ReLeafFile::~ReLeafFile()
+{
+}
+
+
index 122b1138b0074ef7ec98f5f83333c25b7ffebda9..2f99cb0c09ffaadb0ea078f6c4917ff403999dc9 100644 (file)
@@ -46,6 +46,13 @@ public:
 };
 typedef QList<ReFileMetaData> ReFileMetaDataList;
 
+class ReLeafFile;
+/**
+ * Base class of file systems.
+ *
+ * A file system is a hierarchical set of directories with exact one root
+ * (dirctory). Each directory can contain files and directories.
+ */
 class ReFileSystem {
 public:
        enum ListOptions {
@@ -73,21 +80,42 @@ public:
                EC_MARKER,
                EC_DIR_ALREADY_EXISTS,
                EC_REMOTE_MKDIR,
+               EC_CANNOT_OPEN,
+               EC_INVALID_STATE,
+               EC_ALREADY_EXISTS,
        };
 
 public:
        ReFileSystem(const QString& name, ReLogger* logger);
        virtual ~ReFileSystem();
 public:
+       /** Creates a new file in the current directory.
+        * @param node                          the name of the new file
+        * @param inDirectoryOnly       <code>false</code>: the file is made physically<br>
+        *                                                      otherwise: the file exists only in the metadata
+        *                                                      of the directory
+        * @param metadata                      OUT: NULL or the metadata of the new file
+        * @return                                      EC_SUCCESS or the error code
+        */
+       virtual ErrorCode createFile(const QString& node, bool inDirectoryOnly,
+                               ReFileMetaData* metadata = NULL) = 0;
+       /**
+        * Returns a filesystem dependent instance of a file.
+        *
+        * The file must exist in the current directory.
+        * The caller must free the instance.
+        *
+        * @param meta  the metadata of the file
+        * @return              NULL: no file found<br>
+        *                              otherwise: the file
+        */
+       virtual ReLeafFile* buildFile(const ReFileMetaData& meta) = 0;
        /** Returns the canonical form of a given path.
         * @param path  path to convert
         * @return              all nodes of the parts which are links are replaced by its
         *                              link targets
         */
        virtual QString canonicalPathOf(const QString& path) = 0;
-       /** Frees resources like open files.
-        */
-       virtual void close() = 0;
        /** Returns the name of the current directory.
         * @return      the name of the current directory
         */
@@ -113,15 +141,6 @@ public:
         * @return              EC_SUCCESS or error code
         */
        virtual ErrorCode makeDir(const QString& node) = 0;
-       /** Reads a part of a file into a buffer.
-        * @param source        the file to read (inside the current directory)
-        * @param offset        first position to read
-        * @param size          number of bytes to read
-        * @param buffer        OUT: content of the file
-        * @return                      EC_SUCCESS or error code
-        */
-       virtual ErrorCode read(const ReFileMetaData& source, int64_t offset,
-               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
@@ -143,15 +162,21 @@ public:
         */
        virtual ErrorCode setProperties(const ReFileMetaData& source,
                ReFileMetaData& target, bool force) = 0;
-       /** 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
-        */
-       virtual ErrorCode write(const QString& target, int64_t offset,
-               const QByteArray& buffer) = 0;
 public:
+       /** Returns a filesystem dependent instance of a file.
+        *
+        * The file must exist in the current directory.
+        * The caller must free the instance.
+        *
+        * @param node  the filename without path
+        * @return              NULL: no file found<br>
+        *                              otherwise: the file
+        */
+       ReLeafFile* buildFile(const QString& node) {
+               ReFileMetaData meta;
+               return exists(node, &meta) ? buildFile(meta) : NULL;
+       }
+
        virtual ErrorCode copy(ReFileMetaData& source, ReFileSystem& sourceFS);
        virtual QString errorMessage(ErrorCode rc);
 public:
@@ -199,6 +224,65 @@ protected:
        ReOSPermissions m_osPermissions;
 };
 
+/**
+ * An abstract base class for leafs of the tree spanned by a filesystem.
+ *
+ * A leaf file could not be a directory.
+ */
+class ReLeafFile : public ReFileMetaData{
+public:
+       ReLeafFile(const ReFileMetaData& metaData, const QString& fullName,
+                          ReLogger* logger);
+       virtual ~ReLeafFile();
+public:
+       /** Opens a file for reading or writing.
+        * @param writeable     <code>true</code>: open for writing
+        * @return                      EC_SUCCESS: success<br>
+        *                                      otherwise: the error code
+        */
+       virtual ReFileSystem::ErrorCode open(bool writeable) = 0;
+       /** Frees the resources occupied by <code>open()</code>.
+        * @return                      EC_SUCCESS: success<br>
+        *                                      otherwise: the error code
+        */
+       virtual ReFileSystem::ErrorCode close() = 0;
+       /** Reads data from the current position into a buffer.
+        * @param maxSize       number of bytes to read
+        * @param buffer        OUT: content of the file
+        * @return                      EC_SUCCESS or error code
+        */
+       virtual ReFileSystem::ErrorCode read(int maxSize, QByteArray& buffer) = 0;
+       /** Writes a buffer to a file at the current position.
+        * @param buffer        content to write
+        * @return                      EC_SUCCESS or error code
+        */
+       virtual ReFileSystem::ErrorCode write(const QByteArray& buffer) = 0;
+protected:
+       QString m_fullName;
+       ReLogger* m_logger;
+       ReFileMetaData m_meta;
+};
+
+
+/**
+ * An abstract base class for leafs of the tree spanned by a filesystem.
+ *
+ * A leaf file could not be a directory.
+ */
+class ReLocalLeafFile : public ReLeafFile{
+public:
+       ReLocalLeafFile(const ReFileMetaData& metaData, const QString& fullName,
+               ReLogger* logger);
+       virtual ~ReLocalLeafFile();
+public:
+       virtual ReFileSystem::ErrorCode open(bool writeable);
+       virtual ReFileSystem::ErrorCode close();
+       virtual ReFileSystem::ErrorCode read(int maxSize, QByteArray& buffer);
+       virtual ReFileSystem::ErrorCode write(const QByteArray& buffer);
+protected:
+       FILE* m_fp;
+};
+
 class ReLocalFileSystem: public ReFileSystem {
 public:
        ReLocalFileSystem(const QString& basePath, ReLogger* logger);
@@ -208,31 +292,36 @@ public:
        ErrorCode setDirectory(const QString& path);
 
 public:
+       /** Returns a file instance of the local filesystem.
+        * @param meta  the metadata of the file
+        * @return              NULL: not found<br>
+        *                              otherwise: the file
+        */
+       virtual ReLeafFile* buildFile(const ReFileMetaData& meta){
+               return new ReLocalLeafFile(meta, fullName(meta.m_node), m_logger);
+       }
        /** Returns the canonical form of a given path.
         * @param path  path to convert
         * @return              all nodes of the parts which are links are replaced by its
         *                              link targets
         */
        virtual QString canonicalPathOf(const QString& path);
-       // ReFileSystem interface
-       virtual void close();
+       virtual ErrorCode createFile(const QString& node, bool inDirectoryOnly,
+                       ReFileMetaData* metadata = NULL);
        virtual bool exists(const QString& node, ReFileMetaData* metaData = NULL) const;
        virtual int listInfos(const ReIncludeExcludeMatcher& matcher,
                ReFileMetaDataList& list, ListOptions options);
-       ErrorCode makeDir(const QString& node);
-       virtual ErrorCode read(const ReFileMetaData& source, int64_t offset,
-               int size, QByteArray& buffer);
-       ErrorCode remove(const ReFileMetaData& node);
-       ErrorCode setProperties(const ReFileMetaData& source,
+       virtual ErrorCode makeDir(const QString& node);
+       virtual ErrorCode remove(const ReFileMetaData& node);
+       virtual ErrorCode setProperties(const ReFileMetaData& source,
                ReFileMetaData& target, bool force = false);
-       virtual ErrorCode write(const QString& target, int64_t offset,
-               const QByteArray& buffer);
 protected:
        QString m_basePath;
        QDir m_dir;
-       FILE* m_readFile;
-       FILE* m_writeFile;
+
 
 };
 
+
+
 #endif /* OS_REFILESYSTEM_HPP_ */