summaryrefslogtreecommitdiff
path: root/comphelper
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@cib.de>2016-09-01 16:16:39 +0200
committerArmin Le Grand <Armin.Le.Grand@cib.de>2016-10-11 13:56:22 +0200
commited646dc595b2ee5248b0994a2b44a7a5a7bfbbd5 (patch)
tree8dba8640b8ebc980c0cf94aa8120a70cd64f5f26 /comphelper
parent9c9f184138dd9e3dbd50d5d50fc86ca172ae4dfe (diff)
profilesafe: Initial creation of BackupFileHelper
Added helper class to allow easy creation/deployment of backups of a file (here: registrymodifications). It works like a 'stack' of backups, supports easy push/pop of backed-up versions. Change-Id: Ie19e1209534f23a3dbd6106a5ca13b24b8fefe4d
Diffstat (limited to 'comphelper')
-rw-r--r--comphelper/Library_comphelper.mk1
-rw-r--r--comphelper/source/misc/backupfilehelper.cxx230
2 files changed, 231 insertions, 0 deletions
diff --git a/comphelper/Library_comphelper.mk b/comphelper/Library_comphelper.mk
index 4d4e7345298d..59869a7a393f 100644
--- a/comphelper/Library_comphelper.mk
+++ b/comphelper/Library_comphelper.mk
@@ -76,6 +76,7 @@ $(eval $(call gb_Library_add_exception_objects,comphelper,\
comphelper/source/misc/accimplaccess \
comphelper/source/misc/anytostring \
comphelper/source/misc/asyncnotification \
+ comphelper/source/misc/backupfilehelper \
comphelper/source/misc/comphelper_module \
comphelper/source/misc/comphelper_services \
comphelper/source/misc/componentbase \
diff --git a/comphelper/source/misc/backupfilehelper.cxx b/comphelper/source/misc/backupfilehelper.cxx
new file mode 100644
index 000000000000..778f0a0e7d27
--- /dev/null
+++ b/comphelper/source/misc/backupfilehelper.cxx
@@ -0,0 +1,230 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <comphelper/backupfilehelper.hxx>
+#include <rtl/ustring.hxx>
+
+namespace comphelper
+{
+ sal_uInt16 BackupFileHelper::mnMaxAllowedBackups = 10;
+
+ BackupFileHelper::BackupFileHelper(
+ const OUString& rBaseURL,
+ sal_uInt16 nNumBackups)
+ : mrBaseURL(rBaseURL),
+ mnNumBackups(::std::min(::std::max(nNumBackups, sal_uInt16(1)), mnMaxAllowedBackups)),
+ maBase(),
+ maExt(),
+ maBaseFile(rBaseURL),
+ mbBaseFileIsOpen(false)
+ {
+ }
+
+ bool BackupFileHelper::tryPush()
+ {
+ if (isDifferentOrNew())
+ {
+ // the new file is different or new, create a new first backup
+ // rename/move/cleanup other backup files, make space for new first backup
+ push();
+
+ // copy new one to now free 1st position
+ osl::File::copy(mrBaseURL, getName(1));
+
+ return true;
+ }
+
+ return false;
+ }
+
+ bool BackupFileHelper::isPopPossible()
+ {
+ return firstExists();
+ }
+
+ bool BackupFileHelper::tryPop()
+ {
+ if (firstExists())
+ {
+ // first copy exists, copy over original and delete
+ const OUString aOneName(getName(1));
+ maBaseFile.close();
+ osl::File::copy(aOneName, mrBaseURL);
+ osl::File::remove(aOneName);
+
+ // rename/move/cleanup other backup files
+ pop();
+
+ return true;
+ }
+
+ return false;
+ }
+
+ rtl::OUString BackupFileHelper::getName(sal_uInt16 n)
+ {
+ if (maExt.isEmpty())
+ {
+ return OUString(maBase + "_" + OUString::number(n));
+ }
+
+ return OUString(maBase + "_" + OUString::number(n) + "." + maExt);
+ }
+
+ bool BackupFileHelper::firstExists()
+ {
+ if (baseFileOpen() && splitBaseURL())
+ {
+ // check if 1st copy exists
+ osl::File aOneFile(getName(1));
+ const osl::FileBase::RC aResult(aOneFile.open(osl_File_OpenFlag_Read));
+
+ return (osl::File::E_None == aResult);
+ }
+
+ return false;
+ }
+
+ void BackupFileHelper::pop()
+ {
+ for (sal_uInt16 a(2); a < mnMaxAllowedBackups + 1; a++)
+ {
+ const OUString aSourceName(getName(a));
+
+ if (a > mnNumBackups + 1)
+ {
+ // try to delete that file, it is out of scope
+ osl::File::remove(aSourceName);
+ }
+ else
+ {
+ // rename that file by decreasing index by one
+ osl::File::move(aSourceName, getName(a - 1));
+ }
+ }
+ }
+
+ void BackupFileHelper::push()
+ {
+ for (sal_uInt16 a(0); a < mnMaxAllowedBackups; a++)
+ {
+ const sal_uInt16 nIndex(mnMaxAllowedBackups - a);
+ const OUString aSourceName(getName(nIndex));
+
+ if (nIndex >= mnNumBackups)
+ {
+ // try to delete that file, it is out of scope
+ osl::File::remove(aSourceName);
+ }
+ else
+ {
+ // rename that file by increasing index by one
+ osl::File::move(aSourceName, getName(nIndex + 1));
+ }
+ }
+ }
+
+ bool BackupFileHelper::isDifferentOrNew()
+ {
+ if (baseFileOpen() && splitBaseURL())
+ {
+ osl::File aLastFile(getName(1));
+ const osl::FileBase::RC aResult(aLastFile.open(osl_File_OpenFlag_Read));
+ bool bDifferentOrNew(false);
+
+ if (osl::File::E_None == aResult)
+ {
+ // exists, check for being equal
+ bDifferentOrNew = !equalsBase(aLastFile);
+ }
+ else if (osl::File::E_NOENT == aResult)
+ {
+ // does not exist - also copy
+ bDifferentOrNew = true;
+ }
+
+ return bDifferentOrNew;
+ }
+
+ return false;
+ }
+
+ bool BackupFileHelper::equalsBase(osl::File& rLastFile)
+ {
+ sal_uInt64 nBaseLen(0);
+ sal_uInt64 nLastLen(0);
+ maBaseFile.getSize(nBaseLen);
+ rLastFile.getSize(nLastLen);
+
+ if (nBaseLen == nLastLen)
+ {
+ // same filesize -> need to check content
+ sal_uInt8 aArrayOld[1024];
+ sal_uInt8 aArrayLast[1024];
+ sal_uInt64 nBytesReadBase(0);
+ sal_uInt64 nBytesReadLast(0);
+ bool bDiffers(false);
+
+ // both rewind on start
+ maBaseFile.setPos(0, 0);
+ rLastFile.setPos(0, 0);
+
+ while (!bDiffers
+ && osl::File::E_None == maBaseFile.read(static_cast<void*>(aArrayOld), 1024, nBytesReadBase)
+ && osl::File::E_None == rLastFile.read(static_cast<void*>(aArrayLast), 1024, nBytesReadLast)
+ && 0 != nBytesReadBase
+ && nBytesReadBase == nBytesReadLast)
+ {
+ bDiffers = memcmp(aArrayOld, aArrayLast, nBytesReadBase);
+ }
+
+ return !bDiffers;
+ }
+
+ return false;
+ }
+
+ bool BackupFileHelper::splitBaseURL()
+ {
+ if (maBase.isEmpty() && !mrBaseURL.isEmpty())
+ {
+ const sal_Int32 nIndex(mrBaseURL.lastIndexOf('.'));
+
+ if (-1 == nIndex)
+ {
+ maBase = mrBaseURL;
+ }
+ else if (nIndex > 0)
+ {
+ maBase = mrBaseURL.copy(0, nIndex);
+ }
+
+ if (mrBaseURL.getLength() > nIndex + 1)
+ {
+ maExt = mrBaseURL.copy(nIndex + 1);
+ }
+ }
+
+ return !maBase.isEmpty();
+ }
+
+ bool BackupFileHelper::baseFileOpen()
+ {
+ if (!mbBaseFileIsOpen && !mrBaseURL.isEmpty())
+ {
+ mbBaseFileIsOpen = (osl::File::E_None == maBaseFile.open(osl_File_OpenFlag_Read));
+ }
+
+ return mbBaseFileIsOpen;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */