[Libreoffice-commits] core.git: Branch 'feature/profilesafemode' - 148 commits - basic/source chart2/source comphelper/Library_comphelper.mk comphelper/source compilerplugins/clang configmgr/source connectivity/source cppu/source cui/source dbaccess/qa dbaccess/source desktop/inc desktop/source desktop/uiconfig drawinglayer/source editeng/source extensions/source filter/Library_gie.mk filter/source forms/source framework/inc framework/source helpcontent2 i18npool/inc i18npool/source include/comphelper include/connectivity include/editeng include/sfx2 include/svl include/svx include/toolkit include/tools include/unotools include/vbahelper include/vcl libreofficekit/source officecfg/registry rsc/inc rsc/source sal/qa sc/inc sc/qa sc/source sd/inc sd/qa sd/source sfx2/source slideshow/source starmath/inc starmath/source svl/qa svl/source svtools/source svx/inc svx/source sw/CppunitTest_sw_filters_test.mk sw/inc sw/qa sw/source toolkit/inc toolkit/source tools/source unoxml/source vcl/headless vcl/in c vcl/opengl vcl/qa vcl/quartz vcl/source vcl/unx vcl/win vcl/workben writerfilter/source xmloff/source
Armin Le Grand
Armin.Le.Grand at cib.de
Thu Sep 29 13:33:24 UTC 2016
Rebased ref, commits from common ancestor:
commit 396217be6e1b912a38758171601f3550ed64be8b
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date: Thu Sep 29 15:28:15 2016 +0200
profilesafe: clang warnings corrected
Change-Id: Ieb059baeea323bb48ec5b1cf6b8df09da97cfb93
diff --git a/comphelper/source/misc/backupfilehelper.cxx b/comphelper/source/misc/backupfilehelper.cxx
index 4d89f7f..e02a855 100644
--- a/comphelper/source/misc/backupfilehelper.cxx
+++ b/comphelper/source/misc/backupfilehelper.cxx
@@ -112,12 +112,12 @@ namespace
{
const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)BACKUP_FILE_HELPER_BLOCK_SIZE));
- if (osl::File::E_None != maFile->read(reinterpret_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer)
+ if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer)
{
break;
}
- if (osl_File_E_None != osl_writeFile(rTargetHandle, reinterpret_cast<const void*>(aArray), nToTransfer, &nBytesTransfer) || nBytesTransfer != nToTransfer)
+ if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aArray), nToTransfer, &nBytesTransfer) || nBytesTransfer != nToTransfer)
{
break;
}
@@ -155,7 +155,7 @@ namespace
{
const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)BACKUP_FILE_HELPER_BLOCK_SIZE));
- if (osl::File::E_None != maFile->read(reinterpret_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer)
+ if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer)
{
break;
}
@@ -179,7 +179,7 @@ namespace
{
const sal_uInt64 nAvailable(BACKUP_FILE_HELPER_BLOCK_SIZE - zstream->avail_out);
- if (osl_File_E_None != osl_writeFile(rTargetHandle, reinterpret_cast<const void*>(aBuffer), nAvailable, &nBytesTransfer) || nBytesTransfer != nAvailable)
+ if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aBuffer), nAvailable, &nBytesTransfer) || nBytesTransfer != nAvailable)
{
bOkay = false;
}
@@ -238,7 +238,7 @@ namespace
{
const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)BACKUP_FILE_HELPER_BLOCK_SIZE));
- if (osl::File::E_None != maFile->read(reinterpret_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer)
+ if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer)
{
break;
}
@@ -262,7 +262,7 @@ namespace
{
const sal_uInt64 nAvailable(BACKUP_FILE_HELPER_BLOCK_SIZE - zstream->avail_out);
- if (osl_File_E_None != osl_writeFile(rTargetHandle, reinterpret_cast<const void*>(aBuffer), nAvailable, &nBytesTransfer) || nBytesTransfer != nAvailable)
+ if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aBuffer), nAvailable, &nBytesTransfer) || nBytesTransfer != nAvailable)
{
bOkay = false;
}
commit e548029aba21a14f0e61d6f5a4ea52ff11096efb
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date: Thu Sep 29 09:57:06 2016 +0200
profilesafe: warnings corrected
Change-Id: I7ec1c3030bc2705a7114678a4f84acdc78b88cbc
diff --git a/comphelper/source/misc/backupfilehelper.cxx b/comphelper/source/misc/backupfilehelper.cxx
index bf9a669..4d89f7f 100644
--- a/comphelper/source/misc/backupfilehelper.cxx
+++ b/comphelper/source/misc/backupfilehelper.cxx
@@ -167,9 +167,9 @@ namespace
zstream->avail_out = BACKUP_FILE_HELPER_BLOCK_SIZE;
zstream->next_out = reinterpret_cast<unsigned char*>(aBuffer);
#if !defined Z_PREFIX
- const sal_uInt64 nRetval(deflate(zstream.get(), nSize == nToTransfer ? Z_FINISH : Z_NO_FLUSH));
+ const sal_Int64 nRetval(deflate(zstream.get(), nSize == nToTransfer ? Z_FINISH : Z_NO_FLUSH));
#else
- const sal_uInt64 nRetval(z_deflate(zstream.get(), nSize == nToTransfer ? Z_FINISH : Z_NO_FLUSH));
+ const sal_Int64 nRetval(z_deflate(zstream.get(), nSize == nToTransfer ? Z_FINISH : Z_NO_FLUSH));
#endif
if (Z_STREAM_ERROR == nRetval)
{
@@ -250,9 +250,9 @@ namespace
zstream->avail_out = BACKUP_FILE_HELPER_BLOCK_SIZE;
zstream->next_out = reinterpret_cast<unsigned char*>(aBuffer);
#if !defined Z_PREFIX
- const sal_uInt64 nRetval(inflate(zstream.get(), Z_NO_FLUSH));
+ const sal_Int64 nRetval(inflate(zstream.get(), Z_NO_FLUSH));
#else
- const sal_uInt64 nRetval(z_inflate(zstream.get(), Z_NO_FLUSH));
+ const sal_Int64 nRetval(z_inflate(zstream.get(), Z_NO_FLUSH));
#endif
if (Z_STREAM_ERROR == nRetval)
{
commit 6e5bb025c1cb72e6d24a271c33fa0136f6990c9c
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date: Wed Sep 28 18:14:51 2016 +0200
profilesafe: Added zip deflate/inflate
Stack of files can now deflate/inflate using zip
library, unfortunately have to use direct due to
Deflater/Inflater not being available, had to add
linking against zip.lib. Checked compressed and
uncompressed creation/usage of backup stack
Change-Id: I042cd808c023048a7d7b37c0cc6339820507be29
diff --git a/comphelper/Library_comphelper.mk b/comphelper/Library_comphelper.mk
index 59869a7..344e186 100644
--- a/comphelper/Library_comphelper.mk
+++ b/comphelper/Library_comphelper.mk
@@ -40,6 +40,7 @@ $(eval $(call gb_Library_use_externals,comphelper,\
boost_headers \
icuuc \
icu_headers \
+ zlib \
))
$(eval $(call gb_Library_use_libraries,comphelper,\
diff --git a/comphelper/source/misc/backupfilehelper.cxx b/comphelper/source/misc/backupfilehelper.cxx
index 8fed178..bf9a669 100644
--- a/comphelper/source/misc/backupfilehelper.cxx
+++ b/comphelper/source/misc/backupfilehelper.cxx
@@ -14,9 +14,10 @@
#include <comphelper/backupfilehelper.hxx>
#include <rtl/crc.h>
#include <deque>
+#include <zlib.h>
typedef std::shared_ptr< osl::File > FileSharedPtr;
-static const sal_uInt32 BACKUP_FILE_HELPER_BLOCK_SIZE = 1024;
+static const sal_uInt32 BACKUP_FILE_HELPER_BLOCK_SIZE = 16384;
namespace
{
@@ -86,38 +87,246 @@ namespace
namespace
{
- struct PackedFileEntry
+ class PackedFileEntry
{
private:
- sal_uInt32 mnSize; // size in bytes
- sal_uInt32 mnOffset; // offset in File (zero identifies new file)
- sal_uInt32 mnCrc32; // checksum
- FileSharedPtr maFile; // file where to find the data (at offset)
+ sal_uInt32 mnFullFileSize; // size in bytes of unpacked original file
+ sal_uInt32 mnPackFileSize; // size in bytes in file backup package (smaller if compressed, same if not)
+ sal_uInt32 mnOffset; // offset in File (zero identifies new file)
+ sal_uInt32 mnCrc32; // checksum
+ FileSharedPtr maFile; // file where to find the data (at offset)
+ bool mbDoCompress; // flag if this file is scheduled to be compredded when written
+
+ bool copy_content_straight(oslFileHandle& rTargetHandle)
+ {
+ if (maFile && osl::File::E_None == maFile->open(osl_File_OpenFlag_Read))
+ {
+ sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE];
+ sal_uInt64 nBytesTransfer(0);
+ sal_uInt64 nSize(getFullFileSize());
+
+ // set offset in source file - when this is zero, a new file is to be added
+ if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset())))
+ {
+ while (nSize != 0)
+ {
+ const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)BACKUP_FILE_HELPER_BLOCK_SIZE));
+
+ if (osl::File::E_None != maFile->read(reinterpret_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer)
+ {
+ break;
+ }
+
+ if (osl_File_E_None != osl_writeFile(rTargetHandle, reinterpret_cast<const void*>(aArray), nToTransfer, &nBytesTransfer) || nBytesTransfer != nToTransfer)
+ {
+ break;
+ }
+
+ nSize -= nToTransfer;
+ }
+ }
+
+ maFile->close();
+ return (0 == nSize);
+ }
+
+ return false;
+ }
+
+ bool copy_content_compress(oslFileHandle& rTargetHandle)
+ {
+ if (maFile && osl::File::E_None == maFile->open(osl_File_OpenFlag_Read))
+ {
+ sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE];
+ sal_uInt8 aBuffer[BACKUP_FILE_HELPER_BLOCK_SIZE];
+ sal_uInt64 nBytesTransfer(0);
+ sal_uInt64 nSize(getFullFileSize());
+ std::unique_ptr< z_stream > zstream(new z_stream);
+ memset(zstream.get(), 0, sizeof(*zstream));
+
+ if (Z_OK == deflateInit(zstream.get(), Z_BEST_COMPRESSION))
+ {
+ // set offset in source file - when this is zero, a new file is to be added
+ if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset())))
+ {
+ bool bOkay(true);
+
+ while (bOkay && nSize != 0)
+ {
+ const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)BACKUP_FILE_HELPER_BLOCK_SIZE));
+
+ if (osl::File::E_None != maFile->read(reinterpret_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer)
+ {
+ break;
+ }
+
+ zstream->avail_in = nToTransfer;
+ zstream->next_in = reinterpret_cast<unsigned char*>(aArray);
+
+ do {
+ zstream->avail_out = BACKUP_FILE_HELPER_BLOCK_SIZE;
+ zstream->next_out = reinterpret_cast<unsigned char*>(aBuffer);
+#if !defined Z_PREFIX
+ const sal_uInt64 nRetval(deflate(zstream.get(), nSize == nToTransfer ? Z_FINISH : Z_NO_FLUSH));
+#else
+ const sal_uInt64 nRetval(z_deflate(zstream.get(), nSize == nToTransfer ? Z_FINISH : Z_NO_FLUSH));
+#endif
+ if (Z_STREAM_ERROR == nRetval)
+ {
+ bOkay = false;
+ }
+ else
+ {
+ const sal_uInt64 nAvailable(BACKUP_FILE_HELPER_BLOCK_SIZE - zstream->avail_out);
+
+ if (osl_File_E_None != osl_writeFile(rTargetHandle, reinterpret_cast<const void*>(aBuffer), nAvailable, &nBytesTransfer) || nBytesTransfer != nAvailable)
+ {
+ bOkay = false;
+ }
+ }
+ } while (bOkay && 0 == zstream->avail_out);
+
+ if (!bOkay)
+ {
+ break;
+ }
+
+ nSize -= nToTransfer;
+ }
+
+#if !defined Z_PREFIX
+ deflateEnd(zstream.get());
+#else
+ z_deflateEnd(zstream.get());
+#endif
+ }
+ }
+
+ maFile->close();
+
+ // get compressed size and add to entry
+ if (mnFullFileSize == mnPackFileSize && mnFullFileSize == zstream->total_in)
+ {
+ mnPackFileSize = zstream->total_out;
+ }
+
+ return (0 == nSize);
+ }
+
+ return false;
+ }
+
+ bool copy_content_uncompress(oslFileHandle& rTargetHandle)
+ {
+ if (maFile && osl::File::E_None == maFile->open(osl_File_OpenFlag_Read))
+ {
+ sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE];
+ sal_uInt8 aBuffer[BACKUP_FILE_HELPER_BLOCK_SIZE];
+ sal_uInt64 nBytesTransfer(0);
+ sal_uInt64 nSize(getPackFileSize());
+ std::unique_ptr< z_stream > zstream(new z_stream);
+ memset(zstream.get(), 0, sizeof(*zstream));
+
+ if (Z_OK == inflateInit(zstream.get()))
+ {
+ // set offset in source file - when this is zero, a new file is to be added
+ if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset())))
+ {
+ bool bOkay(true);
+
+ while (bOkay && nSize != 0)
+ {
+ const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)BACKUP_FILE_HELPER_BLOCK_SIZE));
+
+ if (osl::File::E_None != maFile->read(reinterpret_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer)
+ {
+ break;
+ }
+
+ zstream->avail_in = nToTransfer;
+ zstream->next_in = reinterpret_cast<unsigned char*>(aArray);
+
+ do {
+ zstream->avail_out = BACKUP_FILE_HELPER_BLOCK_SIZE;
+ zstream->next_out = reinterpret_cast<unsigned char*>(aBuffer);
+#if !defined Z_PREFIX
+ const sal_uInt64 nRetval(inflate(zstream.get(), Z_NO_FLUSH));
+#else
+ const sal_uInt64 nRetval(z_inflate(zstream.get(), Z_NO_FLUSH));
+#endif
+ if (Z_STREAM_ERROR == nRetval)
+ {
+ bOkay = false;
+ }
+ else
+ {
+ const sal_uInt64 nAvailable(BACKUP_FILE_HELPER_BLOCK_SIZE - zstream->avail_out);
+
+ if (osl_File_E_None != osl_writeFile(rTargetHandle, reinterpret_cast<const void*>(aBuffer), nAvailable, &nBytesTransfer) || nBytesTransfer != nAvailable)
+ {
+ bOkay = false;
+ }
+ }
+ } while (bOkay && 0 == zstream->avail_out);
+
+ if (!bOkay)
+ {
+ break;
+ }
+
+ nSize -= nToTransfer;
+ }
+
+#if !defined Z_PREFIX
+ deflateEnd(zstream.get());
+#else
+ z_deflateEnd(zstream.get());
+#endif
+ }
+ }
+
+ maFile->close();
+ return (0 == nSize);
+ }
+
+ return false;
+ }
+
public:
PackedFileEntry(
- sal_uInt32 nSize,
+ sal_uInt32 nFullFileSize,
sal_uInt32 nOffset,
sal_uInt32 nCrc32,
- FileSharedPtr& rFile)
- : mnSize(nSize),
+ FileSharedPtr& rFile,
+ bool bDoCompress)
+ : mnFullFileSize(nFullFileSize),
+ mnPackFileSize(nFullFileSize),
mnOffset(nOffset),
mnCrc32(nCrc32),
- maFile(rFile)
+ maFile(rFile),
+ mbDoCompress(bDoCompress)
{
}
PackedFileEntry()
- : mnSize(0),
+ : mnFullFileSize(0),
+ mnPackFileSize(0),
mnOffset(0),
mnCrc32(0),
- maFile()
+ maFile(),
+ mbDoCompress(false)
+ {
+ }
+
+ sal_uInt32 getFullFileSize() const
{
+ return mnFullFileSize;
}
- sal_uInt32 getSize() const
+ sal_uInt32 getPackFileSize() const
{
- return mnSize;
+ return mnPackFileSize;
}
sal_uInt32 getOffset() const
@@ -142,10 +351,10 @@ namespace
sal_uInt8 aArray[4];
sal_uInt64 nBaseRead(0);
- // read and compute entry size
+ // read and compute full file size
if (osl::File::E_None == maFile->read(static_cast<void*>(aArray), 4, nBaseRead) && 4 == nBaseRead)
{
- mnSize = (sal_uInt32(aArray[0]) << 24) + (sal_uInt32(aArray[1]) << 16) + (sal_uInt32(aArray[2]) << 8) + sal_uInt32(aArray[3]);
+ mnFullFileSize = (sal_uInt32(aArray[0]) << 24) + (sal_uInt32(aArray[1]) << 16) + (sal_uInt32(aArray[2]) << 8) + sal_uInt32(aArray[3]);
}
else
{
@@ -157,6 +366,20 @@ namespace
{
mnCrc32 = (sal_uInt32(aArray[0]) << 24) + (sal_uInt32(aArray[1]) << 16) + (sal_uInt32(aArray[2]) << 8) + sal_uInt32(aArray[3]);
}
+ else
+ {
+ return false;
+ }
+
+ // read and compute packed size
+ if (osl::File::E_None == maFile->read(static_cast<void*>(aArray), 4, nBaseRead) && 4 == nBaseRead)
+ {
+ mnPackFileSize = (sal_uInt32(aArray[0]) << 24) + (sal_uInt32(aArray[1]) << 16) + (sal_uInt32(aArray[2]) << 8) + sal_uInt32(aArray[3]);
+ }
+ else
+ {
+ return false;
+ }
return true;
}
@@ -169,18 +392,18 @@ namespace
sal_uInt8 aArray[4];
sal_uInt64 nBaseWritten(0);
- // write size
- aArray[0] = sal_uInt8((mnSize & 0xff000000) >> 24);
- aArray[1] = sal_uInt8((mnSize & 0x00ff0000) >> 16);
- aArray[2] = sal_uInt8((mnSize & 0x0000ff00) >> 8);
- aArray[3] = sal_uInt8(mnSize & 0x000000ff);
+ // write full file size
+ aArray[0] = sal_uInt8((mnFullFileSize & 0xff000000) >> 24);
+ aArray[1] = sal_uInt8((mnFullFileSize & 0x00ff0000) >> 16);
+ aArray[2] = sal_uInt8((mnFullFileSize & 0x0000ff00) >> 8);
+ aArray[3] = sal_uInt8(mnFullFileSize & 0x000000ff);
if (osl_File_E_None != osl_writeFile(rHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) || 4 != nBaseWritten)
{
return false;
}
- // for each entry, write crc32
+ // write crc32
aArray[0] = sal_uInt8((mnCrc32 & 0xff000000) >> 24);
aArray[1] = sal_uInt8((mnCrc32 & 0x00ff0000) >> 16);
aArray[2] = sal_uInt8((mnCrc32 & 0x0000ff00) >> 8);
@@ -191,55 +414,51 @@ namespace
return false;
}
+ // write packed file size
+ aArray[0] = sal_uInt8((mnPackFileSize & 0xff000000) >> 24);
+ aArray[1] = sal_uInt8((mnPackFileSize & 0x00ff0000) >> 16);
+ aArray[2] = sal_uInt8((mnPackFileSize & 0x0000ff00) >> 8);
+ aArray[3] = sal_uInt8(mnPackFileSize & 0x000000ff);
+
+ if (osl_File_E_None != osl_writeFile(rHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) || 4 != nBaseWritten)
+ {
+ return false;
+ }
+
return true;
}
- bool copy_content(oslFileHandle& rTargetHandle, bool bInflate)
+ bool copy_content(oslFileHandle& rTargetHandle, bool bUncompress)
{
- if (maFile && osl::File::E_None == maFile->open(osl_File_OpenFlag_Read))
+ if (bUncompress)
{
- sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE];
- sal_uInt64 nBytesTransfer(0);
- sal_uInt64 nSize(getSize());
- const bool bNewFile(0 == getOffset());
-
- // set offset in source file - when this is zero, a new file is to be added
- if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset())))
+ if (getFullFileSize() == getPackFileSize())
{
- if (!bInflate)
- {
- // copy-back, deflate file
- }
- else if (bNewFile)
- {
- // new file gets added, inflate initially
- }
-
- while (nSize != 0)
- {
- const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)BACKUP_FILE_HELPER_BLOCK_SIZE));
-
- if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer)
- {
- break;
- }
-
- if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aArray), nToTransfer, &nBytesTransfer) || nBytesTransfer != nToTransfer)
- {
- break;
- }
-
- nSize -= nToTransfer;
- }
+ // not compressed, just copy
+ return copy_content_straight(rTargetHandle);
+ }
+ else
+ {
+ // compressed, need to uncompress on copy
+ return copy_content_uncompress(rTargetHandle);
+ }
+ }
+ else if (0 == getOffset())
+ {
+ if (mbDoCompress)
+ {
+ // compressed wanted, need to compress on copy
+ return copy_content_compress(rTargetHandle);
+ }
+ else
+ {
+ // not compressed, straight copy
+ return copy_content_straight(rTargetHandle);
}
-
- maFile->close();
-
- return (0 == nSize);
}
else
{
- return false;
+ return copy_content_straight(rTargetHandle);
}
}
};
@@ -288,13 +507,13 @@ namespace
// if there are entries (and less than max), read them
if (nEntries >= 1 && nEntries <= 10)
{
- // offset in souce file starts with 8Byte for header+numEntries and
- // 8byte for each entry (size and crc32)
- sal_uInt32 nOffset(8 + (8 * nEntries));
+ // offset in souce file starts with 8 Byte for header + numEntries and
+ // 12 byte for each entry (size, crc32 and PackedSize)
+ sal_uInt32 nOffset(8 + (12 * nEntries));
for (sal_uInt32 a(0); a < nEntries; a++)
{
- // create new entry, read header (size and crc) and
+ // create new entry, read header (size, crc and PackedSize),
// set offset and source file
PackedFileEntry aEntry;
@@ -304,7 +523,7 @@ namespace
maPackedFileEntryVector.push_back(aEntry);
// increase offset for next entry
- nOffset += aEntry.getSize();
+ nOffset += aEntry.getPackFileSize();
}
else
{
@@ -373,24 +592,56 @@ namespace
// write number of entries
if (osl_File_E_None == osl_writeFile(aHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) && 4 == nBaseWritten)
{
- // write headers
- for (auto& candidateA : maPackedFileEntryVector)
+ if (bRetval)
+ {
+ // write placeholder for headers. Due to the fact that
+ // PackFileSize for newly added files gets set during
+ // writing the content entry, write headers after content
+ // is written. To do so, write placeholders here. We know
+ // the number of entries to write
+ const sal_uInt32 nWriteSize(3 * maPackedFileEntryVector.size());
+ aArray[0] = aArray[1] = aArray[2] = aArray[3] = 0;
+
+ for (sal_uInt32 a(0); bRetval && a < nWriteSize; a++)
+ {
+ if (osl_File_E_None != osl_writeFile(aHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) || 4 != nBaseWritten)
+ {
+ bRetval = false;
+ }
+ }
+ }
+
+ if (bRetval)
+ {
+ // write contents - this may adapt PackFileSize for new
+ // files
+ for (auto& candidate : maPackedFileEntryVector)
+ {
+ if (!candidate.copy_content(aHandle, false))
+ {
+ bRetval = false;
+ break;
+ }
+ }
+ }
+
+ if (bRetval)
{
- if (!candidateA.write_header(aHandle))
+ // seek back to header start (at position 8)
+ if (osl_File_E_None != osl_setFilePos(aHandle, osl_Pos_Absolut, sal_Int64(8)))
{
- // error
bRetval = false;
- break;
}
}
if (bRetval)
{
- // write contents
- for (auto& candidateB : maPackedFileEntryVector)
+ // write headers
+ for (auto& candidate : maPackedFileEntryVector)
{
- if (!candidateB.copy_content(aHandle, true))
+ if (!candidate.write_header(aHandle))
{
+ // error
bRetval = false;
break;
}
@@ -442,7 +693,7 @@ namespace
// already backups there, check if different from last entry
const PackedFileEntry& aLastEntry = maPackedFileEntryVector.back();
- if (aLastEntry.getSize() != static_cast<sal_uInt32>(nFileSize))
+ if (aLastEntry.getFullFileSize() != static_cast<sal_uInt32>(nFileSize))
{
// different size, different file
bNeedToAdd = true;
@@ -475,12 +726,17 @@ namespace
// create a file entry for a new file. Offset is set to 0 to mark
// the entry as new file entry
+ // the compress flag decides if entries should be compressed when
+ // they get written to the target package
+ static bool bUseCompression(true);
+
maPackedFileEntryVector.push_back(
PackedFileEntry(
static_cast< sal_uInt32 >(nFileSize),
0,
nCrc32,
- rFileCandidate));
+ rFileCandidate,
+ bUseCompression));
mbChanged = true;
}
@@ -497,7 +753,10 @@ namespace
// already backups there, check if different from last entry
PackedFileEntry& aLastEntry = maPackedFileEntryVector.back();
- bRetval = aLastEntry.copy_content(rHandle, false);
+ // here the uncompress flag has to be determined, true
+ // means to add the file compressed, false means to add it
+ // uncompressed
+ bRetval = aLastEntry.copy_content(rHandle, true);
if (bRetval)
{
commit e883aa2a6f270179f60edf699886e0e4383678fa
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date: Wed Sep 28 12:31:44 2016 +0200
profilesafe: fixes to setPos and warnings
Change-Id: Ib286e2a3f25b0085a1e3ae4f50c9ff1ff3a5dcf5
diff --git a/comphelper/source/misc/backupfilehelper.cxx b/comphelper/source/misc/backupfilehelper.cxx
index b679431..8fed178 100644
--- a/comphelper/source/misc/backupfilehelper.cxx
+++ b/comphelper/source/misc/backupfilehelper.cxx
@@ -57,22 +57,23 @@ namespace
// set offset in source file - should be zero due to crc32 should
// only be needed to be created for new entries, gets loaded with old
// ones
- rCandidate->setPos(0, sal_Int64(nOffset));
-
- while (nSize != 0)
+ if (osl::File::E_None == rCandidate->setPos(osl_Pos_Absolut, sal_Int64(nOffset)))
{
- const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)BACKUP_FILE_HELPER_BLOCK_SIZE));
-
- if (osl::File::E_None == rCandidate->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) && nBytesTransfer == nToTransfer)
- {
- // add to crc and reduce size
- nCrc32 = rtl_crc32(nCrc32, static_cast<void*>(aArray), static_cast<sal_uInt32>(nBytesTransfer));
- nSize -= nToTransfer;
- }
- else
+ while (nSize != 0)
{
- // error - reset to zero again
- nSize = nCrc32 = 0;
+ const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)BACKUP_FILE_HELPER_BLOCK_SIZE));
+
+ if (osl::File::E_None == rCandidate->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) && nBytesTransfer == nToTransfer)
+ {
+ // add to crc and reduce size
+ nCrc32 = rtl_crc32(nCrc32, static_cast<void*>(aArray), static_cast<sal_uInt32>(nBytesTransfer));
+ nSize -= nToTransfer;
+ }
+ else
+ {
+ // error - reset to zero again
+ nSize = nCrc32 = 0;
+ }
}
}
@@ -174,7 +175,7 @@ namespace
aArray[2] = sal_uInt8((mnSize & 0x0000ff00) >> 8);
aArray[3] = sal_uInt8(mnSize & 0x000000ff);
- if (osl::File::E_None != osl_writeFile(rHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) || 4 != nBaseWritten)
+ if (osl_File_E_None != osl_writeFile(rHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) || 4 != nBaseWritten)
{
return false;
}
@@ -185,7 +186,7 @@ namespace
aArray[2] = sal_uInt8((mnCrc32 & 0x0000ff00) >> 8);
aArray[3] = sal_uInt8(mnCrc32 & 0x000000ff);
- if (osl::File::E_None != osl_writeFile(rHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) || 4 != nBaseWritten)
+ if (osl_File_E_None != osl_writeFile(rHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) || 4 != nBaseWritten)
{
return false;
}
@@ -200,35 +201,36 @@ namespace
sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE];
sal_uInt64 nBytesTransfer(0);
sal_uInt64 nSize(getSize());
-
- // set offset in source file - when this is zero, a new file is to be added
const bool bNewFile(0 == getOffset());
- maFile->setPos(0, sal_Int64(getOffset()));
- if (!bInflate)
- {
- // copy-back, deflate file
- }
- else if (bNewFile)
- {
- // new file gets added, inflate initially
- }
-
- while (nSize != 0)
+ // set offset in source file - when this is zero, a new file is to be added
+ if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset())))
{
- const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)BACKUP_FILE_HELPER_BLOCK_SIZE));
-
- if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer)
+ if (!bInflate)
{
- break;
+ // copy-back, deflate file
}
-
- if (osl::File::E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aArray), nToTransfer, &nBytesTransfer) || nBytesTransfer != nToTransfer)
+ else if (bNewFile)
{
- break;
+ // new file gets added, inflate initially
}
- nSize -= nToTransfer;
+ while (nSize != 0)
+ {
+ const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)BACKUP_FILE_HELPER_BLOCK_SIZE));
+
+ if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer)
+ {
+ break;
+ }
+
+ if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aArray), nToTransfer, &nBytesTransfer) || nBytesTransfer != nToTransfer)
+ {
+ break;
+ }
+
+ nSize -= nToTransfer;
+ }
}
maFile->close();
@@ -250,13 +252,13 @@ namespace
class PackedFile
{
private:
- const OUString& mrURL;
+ const OUString maURL;
PackedFileEntryVector maPackedFileEntryVector;
bool mbChanged;
public:
PackedFile(const OUString& rURL)
- : mrURL(rURL),
+ : maURL(rURL),
maPackedFileEntryVector(),
mbChanged(false)
{
@@ -328,7 +330,7 @@ namespace
if (maPackedFileEntryVector.empty())
{
// on error or no data get rid of pack file
- osl::File::remove(mrURL);
+ osl::File::remove(maURL);
}
}
@@ -339,7 +341,7 @@ namespace
if (maPackedFileEntryVector.empty())
{
// get rid of (now?) empty pack file
- osl::File::remove(mrURL);
+ osl::File::remove(maURL);
}
else if (mbChanged)
{
@@ -360,7 +362,7 @@ namespace
aArray[3] = 'K';
// write File_ID
- if (osl::File::E_None == osl_writeFile(aHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) && 4 == nBaseWritten)
+ if (osl_File_E_None == osl_writeFile(aHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) && 4 == nBaseWritten)
{
const sal_uInt32 nSize(maPackedFileEntryVector.size());
aArray[0] = sal_uInt8((nSize & 0xff000000) >> 24);
@@ -369,7 +371,7 @@ namespace
aArray[3] = sal_uInt8(nSize & 0x000000ff);
// write number of entries
- if (osl::File::E_None == osl_writeFile(aHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) && 4 == nBaseWritten)
+ if (osl_File_E_None == osl_writeFile(aHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) && 4 == nBaseWritten)
{
// write headers
for (auto& candidateA : maPackedFileEntryVector)
@@ -405,8 +407,8 @@ namespace
{
// copy over existing file by first deleting original
// and moving the temp file to old original
- osl::File::remove(mrURL);
- osl::File::move(aTempURL, mrURL);
+ osl::File::remove(maURL);
+ osl::File::move(aTempURL, maURL);
}
// delete temp file (in all cases - it may be moved already)
commit 14036cae3da93a80053b7e27b01f7fbf302d7317
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date: Wed Sep 28 11:38:27 2016 +0200
profilesafe: diverse adaptions
Use Vector for better mem performance for sorting,
defined static const for buffer size of manipulation,
prepare inflate/deflate usages
Change-Id: I864a6c2505dcf5e2c8ee265a5c04af01b65c3af4
diff --git a/comphelper/source/misc/backupfilehelper.cxx b/comphelper/source/misc/backupfilehelper.cxx
index 628ec2b..b679431 100644
--- a/comphelper/source/misc/backupfilehelper.cxx
+++ b/comphelper/source/misc/backupfilehelper.cxx
@@ -16,6 +16,7 @@
#include <deque>
typedef std::shared_ptr< osl::File > FileSharedPtr;
+static const sal_uInt32 BACKUP_FILE_HELPER_BLOCK_SIZE = 1024;
namespace
{
@@ -47,7 +48,7 @@ namespace
if (rCandidate && osl::File::E_None == rCandidate->open(osl_File_OpenFlag_Read))
{
- sal_uInt8 aArray[1024];
+ sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE];
sal_uInt64 nBytesTransfer(0);
sal_uInt64 nSize(0);
@@ -60,7 +61,7 @@ namespace
while (nSize != 0)
{
- const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)1024));
+ const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)BACKUP_FILE_HELPER_BLOCK_SIZE));
if (osl::File::E_None == rCandidate->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) && nBytesTransfer == nToTransfer)
{
@@ -192,20 +193,30 @@ namespace
return true;
}
- bool copy_content(oslFileHandle& rTargetHandle)
+ bool copy_content(oslFileHandle& rTargetHandle, bool bInflate)
{
if (maFile && osl::File::E_None == maFile->open(osl_File_OpenFlag_Read))
{
- sal_uInt8 aArray[1024];
+ sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE];
sal_uInt64 nBytesTransfer(0);
sal_uInt64 nSize(getSize());
// set offset in source file - when this is zero, a new file is to be added
+ const bool bNewFile(0 == getOffset());
maFile->setPos(0, sal_Int64(getOffset()));
+ if (!bInflate)
+ {
+ // copy-back, deflate file
+ }
+ else if (bNewFile)
+ {
+ // new file gets added, inflate initially
+ }
+
while (nSize != 0)
{
- const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)1024));
+ const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)BACKUP_FILE_HELPER_BLOCK_SIZE));
if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer)
{
@@ -376,7 +387,7 @@ namespace
// write contents
for (auto& candidateB : maPackedFileEntryVector)
{
- if (!candidateB.copy_content(aHandle))
+ if (!candidateB.copy_content(aHandle, true))
{
bRetval = false;
break;
@@ -484,7 +495,7 @@ namespace
// already backups there, check if different from last entry
PackedFileEntry& aLastEntry = maPackedFileEntryVector.back();
- bRetval = aLastEntry.copy_content(rHandle);
+ bRetval = aLastEntry.copy_content(rHandle, false);
if (bRetval)
{
diff --git a/configmgr/source/writemodfile.cxx b/configmgr/source/writemodfile.cxx
index 15c9ffa..381ab00 100644
--- a/configmgr/source/writemodfile.cxx
+++ b/configmgr/source/writemodfile.cxx
@@ -401,10 +401,10 @@ void writeNode(
}
// helpers to allow sorting of configmgr::Modifications::Node
-typedef std::pair< const rtl::OUString, configmgr::Modifications::Node > aPairEntry;
+typedef std::pair< const rtl::OUString, configmgr::Modifications::Node > ModNodePairEntry;
struct PairEntrySorter
{
- bool operator() (const aPairEntry* pValue1, const aPairEntry* pValue2) const
+ bool operator() (const ModNodePairEntry* pValue1, const ModNodePairEntry* pValue2) const
{
return pValue1->first.compareTo(pValue2->first) < 0;
}
@@ -472,19 +472,20 @@ void writeModifications(
// copy configmgr::Modifications::Node's to a sortable list. Use pointers
// to just reference the data instead of copying it
- std::list< const aPairEntry* > aPairEntryList;
+ std::vector< const ModNodePairEntry* > ModNodePairEntryVector;
+ ModNodePairEntryVector.reserve(modifications.children.size());
for (const auto& rCand : modifications.children)
{
- aPairEntryList.push_back(&rCand);
+ ModNodePairEntryVector.push_back(&rCand);
}
// sort the list
- aPairEntryList.sort(PairEntrySorter());
+ std::sort(ModNodePairEntryVector.begin(), ModNodePairEntryVector.end(), PairEntrySorter());
// now use the list to write entries in sorted order
// instead of random as from the unordered map
- for (const auto & i : aPairEntryList)
+ for (const auto & i : ModNodePairEntryVector)
{
writeModifications(
components, handle, pathRep, node, i->first,
@@ -637,19 +638,20 @@ void writeModFile(
// copy configmgr::Modifications::Node's to a sortable list. Use pointers
// to just reference the data instead of copying it
- std::list< const aPairEntry* > aPairEntryList;
+ std::vector< const ModNodePairEntry* > ModNodePairEntryVector;
+ ModNodePairEntryVector.reserve(data.modifications.getRoot().children.size());
for (const auto& rCand : data.modifications.getRoot().children)
{
- aPairEntryList.push_back(&rCand);
+ ModNodePairEntryVector.push_back(&rCand);
}
// sort the list
- aPairEntryList.sort(PairEntrySorter());
+ std::sort(ModNodePairEntryVector.begin(), ModNodePairEntryVector.end(), PairEntrySorter());
// now use the list to write entries in sorted order
// instead of random as from the unordered map
- for (const auto& j : aPairEntryList)
+ for (const auto& j : ModNodePairEntryVector)
{
writeModifications(
components, tmp, "", rtl::Reference< Node >(), j->first,
commit 14802959a0dc473f64fe3c6942b26a7398370fc6
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date: Fri Sep 23 18:21:54 2016 +0200
profilesafe: backups in single *.pack file
Enhanced helper classes for BackupFileHelper to
allow writing a stack of rescued last valid
configuration files to a single file package.
Added configuration values for enabling this and
defining the number of entries, added max entry
limitation. Using FileSize and CRC32 now to dectect
if config file did change. To make this work I added
sorting to writing the configuration so that with no
change the same configuration file is written (this
was not the case before)
Change-Id: I6a175d3d9cb5b947410e8cd00772a521dd81182f
diff --git a/comphelper/source/misc/backupfilehelper.cxx b/comphelper/source/misc/backupfilehelper.cxx
index 7a353b8..628ec2b 100644
--- a/comphelper/source/misc/backupfilehelper.cxx
+++ b/comphelper/source/misc/backupfilehelper.cxx
@@ -9,232 +9,657 @@
#include <sal/config.h>
-#include <comphelper/backupfilehelper.hxx>
#include <rtl/ustring.hxx>
+#include <rtl/bootstrap.hxx>
+#include <comphelper/backupfilehelper.hxx>
+#include <rtl/crc.h>
+#include <deque>
-namespace comphelper
-{
- sal_uInt16 BackupFileHelper::mnMaxAllowedBackups = 10;
- bool BackupFileHelper::mbExitWasCalled = false;
+typedef std::shared_ptr< osl::File > FileSharedPtr;
- 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)
+namespace
+{
+ OUString splitAtLastToken(const OUString& rSrc, sal_Unicode aToken, OUString& rRight)
{
- }
+ const sal_Int32 nIndex(rSrc.lastIndexOf(aToken));
+ OUString aRetval;
- void BackupFileHelper::setExitWasCalled()
- {
- mbExitWasCalled = true;
- }
+ if (-1 == nIndex)
+ {
+ aRetval = rSrc;
+ }
+ else if (nIndex > 0)
+ {
+ aRetval = rSrc.copy(0, nIndex);
+ }
- bool BackupFileHelper::getExitWasCalled()
- {
- return mbExitWasCalled;
+ if (rSrc.getLength() > nIndex + 1)
+ {
+ rRight = rSrc.copy(nIndex + 1);
+ }
+
+ return aRetval;
}
- bool BackupFileHelper::tryPush()
+ sal_uInt32 createCrc32(FileSharedPtr& rCandidate, sal_uInt32 nOffset)
{
- if (isDifferentOrNew())
+ sal_uInt32 nCrc32(0);
+
+ if (rCandidate && osl::File::E_None == rCandidate->open(osl_File_OpenFlag_Read))
{
- // 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();
+ sal_uInt8 aArray[1024];
+ sal_uInt64 nBytesTransfer(0);
+ sal_uInt64 nSize(0);
- // copy new one to now free 1st position
- osl::File::copy(mrBaseURL, getName(1));
+ rCandidate->getSize(nSize);
- return true;
+ // set offset in source file - should be zero due to crc32 should
+ // only be needed to be created for new entries, gets loaded with old
+ // ones
+ rCandidate->setPos(0, sal_Int64(nOffset));
+
+ while (nSize != 0)
+ {
+ const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)1024));
+
+ if (osl::File::E_None == rCandidate->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) && nBytesTransfer == nToTransfer)
+ {
+ // add to crc and reduce size
+ nCrc32 = rtl_crc32(nCrc32, static_cast<void*>(aArray), static_cast<sal_uInt32>(nBytesTransfer));
+ nSize -= nToTransfer;
+ }
+ else
+ {
+ // error - reset to zero again
+ nSize = nCrc32 = 0;
+ }
+ }
+
+ rCandidate->close();
}
- return false;
+ return nCrc32;
}
+}
- bool BackupFileHelper::isPopPossible()
+namespace
+{
+ struct PackedFileEntry
{
- return firstExists();
- }
+ private:
+ sal_uInt32 mnSize; // size in bytes
+ sal_uInt32 mnOffset; // offset in File (zero identifies new file)
+ sal_uInt32 mnCrc32; // checksum
+ FileSharedPtr maFile; // file where to find the data (at offset)
+
+ public:
+ PackedFileEntry(
+ sal_uInt32 nSize,
+ sal_uInt32 nOffset,
+ sal_uInt32 nCrc32,
+ FileSharedPtr& rFile)
+ : mnSize(nSize),
+ mnOffset(nOffset),
+ mnCrc32(nCrc32),
+ maFile(rFile)
+ {
+ }
- bool BackupFileHelper::tryPop()
- {
- if (firstExists())
+ PackedFileEntry()
+ : mnSize(0),
+ mnOffset(0),
+ mnCrc32(0),
+ maFile()
{
- // 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();
+ sal_uInt32 getSize() const
+ {
+ return mnSize;
+ }
- return true;
+ sal_uInt32 getOffset() const
+ {
+ return mnOffset;
}
- return false;
- }
+ sal_uInt32 getCrc32() const
+ {
+ return mnCrc32;
+ }
- rtl::OUString BackupFileHelper::getName(sal_uInt16 n)
- {
- if (maExt.isEmpty())
+ bool read_header(
+ FileSharedPtr& rFile,
+ sal_uInt32 nOffset)
{
- return OUString(maBase + "_" + OUString::number(n));
+ mnOffset = nOffset;
+ maFile = rFile;
+
+ if (maFile)
+ {
+ sal_uInt8 aArray[4];
+ sal_uInt64 nBaseRead(0);
+
+ // read and compute entry size
+ if (osl::File::E_None == maFile->read(static_cast<void*>(aArray), 4, nBaseRead) && 4 == nBaseRead)
+ {
+ mnSize = (sal_uInt32(aArray[0]) << 24) + (sal_uInt32(aArray[1]) << 16) + (sal_uInt32(aArray[2]) << 8) + sal_uInt32(aArray[3]);
+ }
+ else
+ {
+ return false;
+ }
+
+ // read and compute entry crc32
+ if (osl::File::E_None == maFile->read(static_cast<void*>(aArray), 4, nBaseRead) && 4 == nBaseRead)
+ {
+ mnCrc32 = (sal_uInt32(aArray[0]) << 24) + (sal_uInt32(aArray[1]) << 16) + (sal_uInt32(aArray[2]) << 8) + sal_uInt32(aArray[3]);
+ }
+
+ return true;
+ }
+
+ return false;
}
- return OUString(maBase + "_" + OUString::number(n) + "." + maExt);
- }
+ bool write_header(oslFileHandle& rHandle)
+ {
+ sal_uInt8 aArray[4];
+ sal_uInt64 nBaseWritten(0);
- bool BackupFileHelper::firstExists()
- {
- if (baseFileOpen() && splitBaseURL())
+ // write size
+ aArray[0] = sal_uInt8((mnSize & 0xff000000) >> 24);
+ aArray[1] = sal_uInt8((mnSize & 0x00ff0000) >> 16);
+ aArray[2] = sal_uInt8((mnSize & 0x0000ff00) >> 8);
+ aArray[3] = sal_uInt8(mnSize & 0x000000ff);
+
+ if (osl::File::E_None != osl_writeFile(rHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) || 4 != nBaseWritten)
+ {
+ return false;
+ }
+
+ // for each entry, write crc32
+ aArray[0] = sal_uInt8((mnCrc32 & 0xff000000) >> 24);
+ aArray[1] = sal_uInt8((mnCrc32 & 0x00ff0000) >> 16);
+ aArray[2] = sal_uInt8((mnCrc32 & 0x0000ff00) >> 8);
+ aArray[3] = sal_uInt8(mnCrc32 & 0x000000ff);
+
+ if (osl::File::E_None != osl_writeFile(rHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) || 4 != nBaseWritten)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ bool copy_content(oslFileHandle& rTargetHandle)
{
- // check if 1st copy exists
- osl::File aOneFile(getName(1));
- const osl::FileBase::RC aResult(aOneFile.open(osl_File_OpenFlag_Read));
+ if (maFile && osl::File::E_None == maFile->open(osl_File_OpenFlag_Read))
+ {
+ sal_uInt8 aArray[1024];
+ sal_uInt64 nBytesTransfer(0);
+ sal_uInt64 nSize(getSize());
+
+ // set offset in source file - when this is zero, a new file is to be added
+ maFile->setPos(0, sal_Int64(getOffset()));
+
+ while (nSize != 0)
+ {
+ const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)1024));
+
+ if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer)
+ {
+ break;
+ }
- return (osl::File::E_None == aResult);
+ if (osl::File::E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aArray), nToTransfer, &nBytesTransfer) || nBytesTransfer != nToTransfer)
+ {
+ break;
+ }
+
+ nSize -= nToTransfer;
+ }
+
+ maFile->close();
+
+ return (0 == nSize);
+ }
+ else
+ {
+ return false;
+ }
}
+ };
+}
- return false;
- }
+namespace
+{
+ typedef ::std::deque< PackedFileEntry > PackedFileEntryVector;
- void BackupFileHelper::pop()
+ class PackedFile
{
- for (sal_uInt16 a(2); a < mnMaxAllowedBackups + 1; a++)
+ private:
+ const OUString& mrURL;
+ PackedFileEntryVector maPackedFileEntryVector;
+ bool mbChanged;
+
+ public:
+ PackedFile(const OUString& rURL)
+ : mrURL(rURL),
+ maPackedFileEntryVector(),
+ mbChanged(false)
{
- const OUString aSourceName(getName(a));
+ FileSharedPtr aSourceFile(new osl::File(rURL));
- if (a > mnNumBackups + 1)
+ if (osl::File::E_None == aSourceFile->open(osl_File_OpenFlag_Read))
{
- // try to delete that file, it is out of scope
- osl::File::remove(aSourceName);
+ sal_uInt64 nBaseLen(0);
+ aSourceFile->getSize(nBaseLen);
+
+ // we need at least File_ID and num entries -> 8byte
+ if (8 < nBaseLen)
+ {
+ sal_uInt8 aArray[4];
+ sal_uInt64 nBaseRead(0);
+
+ // read and check File_ID
+ if (osl::File::E_None == aSourceFile->read(static_cast< void* >(aArray), 4, nBaseRead) && 4 == nBaseRead)
+ {
+ if ('P' == aArray[0] && 'A' == aArray[1] && 'C' == aArray[2] && 'K' == aArray[3])
+ {
+ // read and compute num entries in this file
+ if (osl::File::E_None == aSourceFile->read(static_cast<void*>(aArray), 4, nBaseRead) && 4 == nBaseRead)
+ {
+ sal_uInt32 nEntries((sal_uInt32(aArray[0]) << 24) + (sal_uInt32(aArray[1]) << 16) + (sal_uInt32(aArray[2]) << 8) + sal_uInt32(aArray[3]));
+
+ // if there are entries (and less than max), read them
+ if (nEntries >= 1 && nEntries <= 10)
+ {
+ // offset in souce file starts with 8Byte for header+numEntries and
+ // 8byte for each entry (size and crc32)
+ sal_uInt32 nOffset(8 + (8 * nEntries));
+
+ for (sal_uInt32 a(0); a < nEntries; a++)
+ {
+ // create new entry, read header (size and crc) and
+ // set offset and source file
+ PackedFileEntry aEntry;
+
+ if (aEntry.read_header(aSourceFile, nOffset))
+ {
+ // add to local data
+ maPackedFileEntryVector.push_back(aEntry);
+
+ // increase offset for next entry
+ nOffset += aEntry.getSize();
+ }
+ else
+ {
+ // error
+ nEntries = 0;
+ }
+ }
+
+ if (0 == nEntries)
+ {
+ // on read error clear local data
+ maPackedFileEntryVector.clear();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ aSourceFile->close();
}
- else
+
+ if (maPackedFileEntryVector.empty())
{
- // rename that file by decreasing index by one
- osl::File::move(aSourceName, getName(a - 1));
+ // on error or no data get rid of pack file
+ osl::File::remove(mrURL);
}
}
- }
- void BackupFileHelper::push()
- {
- for (sal_uInt16 a(0); a < mnMaxAllowedBackups; a++)
+ bool flush()
+ {
+ bool bRetval(true);
+
+ if (maPackedFileEntryVector.empty())
+ {
+ // get rid of (now?) empty pack file
+ osl::File::remove(mrURL);
+ }
+ else if (mbChanged)
+ {
+ // need to create a new pack file, do this in a temp file to which data
+ // will be copied from local file (so keep it here until this is done)
+ oslFileHandle aHandle;
+ OUString aTempURL;
+
+ // open target temp file
+ if (osl::File::E_None == osl::FileBase::createTempFile(nullptr, &aHandle, &aTempURL))
+ {
+ sal_uInt8 aArray[4];
+ sal_uInt64 nBaseWritten(0);
+
+ aArray[0] = 'P';
+ aArray[1] = 'A';
+ aArray[2] = 'C';
+ aArray[3] = 'K';
+
+ // write File_ID
+ if (osl::File::E_None == osl_writeFile(aHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) && 4 == nBaseWritten)
+ {
+ const sal_uInt32 nSize(maPackedFileEntryVector.size());
+ aArray[0] = sal_uInt8((nSize & 0xff000000) >> 24);
+ aArray[1] = sal_uInt8((nSize & 0x00ff0000) >> 16);
+ aArray[2] = sal_uInt8((nSize & 0x0000ff00) >> 8);
+ aArray[3] = sal_uInt8(nSize & 0x000000ff);
+
+ // write number of entries
+ if (osl::File::E_None == osl_writeFile(aHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) && 4 == nBaseWritten)
+ {
+ // write headers
+ for (auto& candidateA : maPackedFileEntryVector)
+ {
+ if (!candidateA.write_header(aHandle))
+ {
+ // error
+ bRetval = false;
+ break;
+ }
+ }
+
+ if (bRetval)
+ {
+ // write contents
+ for (auto& candidateB : maPackedFileEntryVector)
+ {
+ if (!candidateB.copy_content(aHandle))
+ {
+ bRetval = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // close temp file (in all cases)
+ osl_closeFile(aHandle);
+
+ if (bRetval)
+ {
+ // copy over existing file by first deleting original
+ // and moving the temp file to old original
+ osl::File::remove(mrURL);
+ osl::File::move(aTempURL, mrURL);
+ }
+
+ // delete temp file (in all cases - it may be moved already)
+ osl::File::remove(aTempURL);
+ }
+
+ return bRetval;
+ }
+
+ bool tryPush(FileSharedPtr& rFileCandidate)
{
- const sal_uInt16 nIndex(mnMaxAllowedBackups - a);
- const OUString aSourceName(getName(nIndex));
+ sal_uInt64 nFileSize(0);
+
+ if (rFileCandidate && osl::File::E_None == rFileCandidate->open(osl_File_OpenFlag_Read))
+ {
+ rFileCandidate->getSize(nFileSize);
+ rFileCandidate->close();
+ }
- if (nIndex >= mnNumBackups)
+ if (0 == nFileSize)
{
- // try to delete that file, it is out of scope
- osl::File::remove(aSourceName);
+ // empty file offered
+ return false;
+ }
+
+ bool bNeedToAdd(false);
+ sal_uInt32 nCrc32(0);
+
+ if (!maPackedFileEntryVector.empty())
+ {
+ // already backups there, check if different from last entry
+ const PackedFileEntry& aLastEntry = maPackedFileEntryVector.back();
+
+ if (aLastEntry.getSize() != static_cast<sal_uInt32>(nFileSize))
+ {
+ // different size, different file
+ bNeedToAdd = true;
+ }
+ else
+ {
+ // same size, check crc32
+ nCrc32 = createCrc32(rFileCandidate, 0);
+
+ if (nCrc32 != aLastEntry.getCrc32())
+ {
+ // different crc, different file
+ bNeedToAdd = true;
+ }
+ }
}
else
{
- // rename that file by increasing index by one
- osl::File::move(aSourceName, getName(nIndex + 1));
+ // no backup yet, add
+ bNeedToAdd = true;
+ }
+
+ if (bNeedToAdd)
+ {
+ // create crc32 if not yet done
+ if (0 == nCrc32)
+ {
+ nCrc32 = createCrc32(rFileCandidate, 0);
+ }
+
+ // create a file entry for a new file. Offset is set to 0 to mark
+ // the entry as new file entry
+ maPackedFileEntryVector.push_back(
+ PackedFileEntry(
+ static_cast< sal_uInt32 >(nFileSize),
+ 0,
+ nCrc32,
+ rFileCandidate));
+
+ mbChanged = true;
}
+
+ return bNeedToAdd;
}
- }
- bool BackupFileHelper::isDifferentOrNew()
- {
- if (baseFileOpen() && splitBaseURL())
+ bool tryPop(oslFileHandle& rHandle)
{
- osl::File aLastFile(getName(1));
- const osl::FileBase::RC aResult(aLastFile.open(osl_File_OpenFlag_Read));
- bool bDifferentOrNew(false);
+ bool bRetval(false);
- if (osl::File::E_None == aResult)
+ if (!maPackedFileEntryVector.empty())
{
- // exists, check for being equal
- bDifferentOrNew = !equalsBase(aLastFile);
+ // already backups there, check if different from last entry
+ PackedFileEntry& aLastEntry = maPackedFileEntryVector.back();
+
+ bRetval = aLastEntry.copy_content(rHandle);
+
+ if (bRetval)
+ {
+ maPackedFileEntryVector.pop_back();
+ mbChanged = true;
+ }
+
+ return bRetval;
}
- else if (osl::File::E_NOENT == aResult)
+
+ return false;
+ }
+
+ void tryReduceToNumBackups(sal_uInt16 nNumBackups)
+ {
+ while (maPackedFileEntryVector.size() > nNumBackups)
{
- // does not exist - also copy
- bDifferentOrNew = true;
+ maPackedFileEntryVector.pop_front();
+ mbChanged = true;
}
+ }
- return bDifferentOrNew;
+ bool empty()
+ {
+ return maPackedFileEntryVector.empty();
}
+ };
+}
- return false;
+namespace comphelper
+{
+ sal_uInt16 BackupFileHelper::mnMaxAllowedBackups = 10;
+ bool BackupFileHelper::mbExitWasCalled = false;
+
+ BackupFileHelper::BackupFileHelper(
+ const OUString& rBaseURL,
+ sal_uInt16 nNumBackups)
+ : mrBaseURL(rBaseURL),
+ mnNumBackups(::std::min(::std::max(nNumBackups, sal_uInt16(1)), mnMaxAllowedBackups)),
+ maBase(),
+ maName(),
+ maExt()
+ {
}
- bool BackupFileHelper::equalsBase(osl::File& rLastFile)
+ void BackupFileHelper::setExitWasCalled()
{
- sal_uInt64 nBaseLen(0);
- sal_uInt64 nLastLen(0);
- maBaseFile.getSize(nBaseLen);
- rLastFile.getSize(nLastLen);
+ mbExitWasCalled = true;
+ }
- if (nBaseLen == nLastLen)
+ bool BackupFileHelper::getExitWasCalled()
+ {
+ return mbExitWasCalled;
+ }
+
+ bool BackupFileHelper::getSecureUserConfig(sal_uInt16& rnSecureUserConfigNumCopies)
+ {
+ // init to not active
+ bool bRetval(false);
+ rnSecureUserConfigNumCopies = 0;
+ OUString sTokenOut;
+
+ if (rtl::Bootstrap::get("SecureUserConfig", sTokenOut))
+ {
+ bRetval = sTokenOut.toBoolean();
+ }
+
+ if (bRetval && rtl::Bootstrap::get("SecureUserConfigNumCopies", sTokenOut))
{
- // 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);
+ rnSecureUserConfigNumCopies = static_cast< sal_uInt16 >(sTokenOut.toUInt32());
+ }
- // both rewind on start
- maBaseFile.setPos(0, 0);
- rLastFile.setPos(0, 0);
+ return bRetval;
+ }
- 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)
+ rtl::OUString BackupFileHelper::getName()
+ {
+ return OUString(maBase + "/." + maName + ".pack");
+ }
+
+ bool BackupFileHelper::tryPush()
+ {
+ if (splitBaseURL() && baseFileExists())
+ {
+ PackedFile aPackedFile(getName());
+ FileSharedPtr aBaseFile(new osl::File(mrBaseURL));
+
+ if (aPackedFile.tryPush(aBaseFile))
{
- bDiffers = memcmp(aArrayOld, aArrayLast, nBytesReadBase);
+ // reduce to allowed number and flush
+ aPackedFile.tryReduceToNumBackups(mnNumBackups);
+ aPackedFile.flush();
+
+ return true;
}
+ }
- return !bDiffers;
+ return false;
+ }
+
+ bool BackupFileHelper::isPopPossible()
+ {
+ if (splitBaseURL() && baseFileExists())
+ {
+ PackedFile aPackedFile(getName());
+
+ return !aPackedFile.empty();
}
return false;
}
- bool BackupFileHelper::splitBaseURL()
+ bool BackupFileHelper::tryPop()
{
- if (maBase.isEmpty() && !mrBaseURL.isEmpty())
+ if (splitBaseURL() && baseFileExists())
{
- const sal_Int32 nIndex(mrBaseURL.lastIndexOf('.'));
+ PackedFile aPackedFile(getName());
- if (-1 == nIndex)
+ if (!aPackedFile.empty())
{
- maBase = mrBaseURL;
- }
- else if (nIndex > 0)
- {
- maBase = mrBaseURL.copy(0, nIndex);
+ oslFileHandle aHandle;
+ OUString aTempURL;
+
+ // open target temp file
+ if (osl::File::E_None == osl::FileBase::createTempFile(nullptr, &aHandle, &aTempURL))
+ {
+ bool bRetval(aPackedFile.tryPop(aHandle));
+
+ // close temp file (in all cases)
+ osl_closeFile(aHandle);
+
+ if (bRetval)
+ {
+ // copy over existing file by first deleting original
+ // and moving the temp file to old original
+ osl::File::remove(mrBaseURL);
+ osl::File::move(aTempURL, mrBaseURL);
+
+ // reduce to allowed number and flush
+ aPackedFile.tryReduceToNumBackups(mnNumBackups);
+ aPackedFile.flush();
+ }
+
+ // delete temp file (in all cases - it may be moved already)
+ osl::File::remove(aTempURL);
+
+ return bRetval;
+ }
}
+ }
- if (mrBaseURL.getLength() > nIndex + 1)
- {
- maExt = mrBaseURL.copy(nIndex + 1);
- }
+ return false;
+ }
+
+ bool BackupFileHelper::splitBaseURL()
+ {
+ if (maBase.isEmpty() && !mrBaseURL.isEmpty())
+ {
+ // split URL at extension and at last path separator
+ maBase = splitAtLastToken(splitAtLastToken(mrBaseURL, '.', maExt), '/', maName);
}
- return !maBase.isEmpty();
+ return !maBase.isEmpty() && !maName.isEmpty();
}
- bool BackupFileHelper::baseFileOpen()
+ bool BackupFileHelper::baseFileExists()
{
- if (!mbBaseFileIsOpen && !mrBaseURL.isEmpty())
+ if (!mrBaseURL.isEmpty())
{
- mbBaseFileIsOpen = (osl::File::E_None == maBaseFile.open(osl_File_OpenFlag_Read));
+ FileSharedPtr aBaseFile(new osl::File(mrBaseURL));
+
+ return (osl::File::E_None == aBaseFile->open(osl_File_OpenFlag_Read));
}
- return mbBaseFileIsOpen;
+ return false;
}
}
diff --git a/configmgr/source/components.cxx b/configmgr/source/components.cxx
index 7790ab0..54d8b3c 100644
--- a/configmgr/source/components.cxx
+++ b/configmgr/source/components.cxx
@@ -644,18 +644,22 @@ Components::~Components()
(*i)->setAlive(false);
}
- // test backup of registrymodifications
- static bool bFeatureSecureUserConfig(true);
-
if (!bExitWasCalled &&
- bFeatureSecureUserConfig &&
ModificationTarget::File == modificationTarget_ &&
!modificationFileUrl_.isEmpty())
{
- static sal_uInt16 nNumCopies(5);
- comphelper::BackupFileHelper aBackupFileHelper(modificationFileUrl_, nNumCopies);
+ // test backup of registrymodifications
+ sal_uInt16 nSecureUserConfigNumCopies(0);
+
+ // read configuration from soffice.ini
+ const bool bSecureUserConfig(comphelper::BackupFileHelper::getSecureUserConfig(nSecureUserConfigNumCopies));
- aBackupFileHelper.tryPush();
+ if (bSecureUserConfig)
+ {
+ comphelper::BackupFileHelper aBackupFileHelper(modificationFileUrl_, nSecureUserConfigNumCopies);
+
+ aBackupFileHelper.tryPush();
+ }
}
}
diff --git a/configmgr/source/writemodfile.cxx b/configmgr/source/writemodfile.cxx
index 1d20c18..15c9ffa 100644
--- a/configmgr/source/writemodfile.cxx
+++ b/configmgr/source/writemodfile.cxx
@@ -400,6 +400,16 @@ void writeNode(
}
}
+// helpers to allow sorting of configmgr::Modifications::Node
+typedef std::pair< const rtl::OUString, configmgr::Modifications::Node > aPairEntry;
+struct PairEntrySorter
+{
+ bool operator() (const aPairEntry* pValue1, const aPairEntry* pValue2) const
+ {
+ return pValue1->first.compareTo(pValue2->first) < 0;
+ }
+};
+
void writeModifications(
Components & components, TempFile &handle,
OUString const & parentPathRepresentation,
@@ -459,11 +469,26 @@ void writeModifications(
OUString pathRep(
parentPathRepresentation + "/" +
Data::createSegment(node->getTemplateName(), nodeName));
- for (const auto & i : modifications.children)
+
+ // copy configmgr::Modifications::Node's to a sortable list. Use pointers
+ // to just reference the data instead of copying it
+ std::list< const aPairEntry* > aPairEntryList;
+
+ for (const auto& rCand : modifications.children)
+ {
+ aPairEntryList.push_back(&rCand);
+ }
+
+ // sort the list
+ aPairEntryList.sort(PairEntrySorter());
+
+ // now use the list to write entries in sorted order
+ // instead of random as from the unordered map
+ for (const auto & i : aPairEntryList)
{
writeModifications(
- components, handle, pathRep, node, i.first,
- node->getMember(i.first), i.second);
+ components, handle, pathRep, node, i->first,
+ node->getMember(i->first), i->second);
}
}
}
@@ -601,9 +626,30 @@ void writeModFile(
//TODO: Do not write back information about those removed items that did not
// come from the .xcs/.xcu files, anyway (but had been added dynamically
// instead):
- for (Modifications::Node::Children::const_iterator j(
- data.modifications.getRoot().children.begin());
- j != data.modifications.getRoot().children.end(); ++j)
+
+ // For profilesafemode it is necessary to detect changes in the
+ // registrymodifications file, this is done based on file size in bytes and crc32.
+ // Unfortunately this write is based on writing unordered map entries, which creates
+ // valid and semantically equal XML-Files, bubt with different crc32 checksums. For
+ // the future usage it will be preferrable to have easily comparable config files
+ // which is guaranteed by writing the entries in sorted order. Indeed with this change
+ // (and in the recursive writeModifications call) the same config files get written
+
+ // copy configmgr::Modifications::Node's to a sortable list. Use pointers
+ // to just reference the data instead of copying it
+ std::list< const aPairEntry* > aPairEntryList;
+
+ for (const auto& rCand : data.modifications.getRoot().children)
+ {
+ aPairEntryList.push_back(&rCand);
+ }
+
+ // sort the list
+ aPairEntryList.sort(PairEntrySorter());
+
+ // now use the list to write entries in sorted order
+ // instead of random as from the unordered map
+ for (const auto& j : aPairEntryList)
{
writeModifications(
components, tmp, "", rtl::Reference< Node >(), j->first,
diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index b3514ef..16274bc 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -948,11 +948,13 @@ void Desktop::HandleBootstrapErrors(
else if ( aBootstrapError == BE_OFFICECONFIG_BROKEN )
{
// test restore of registrymodifications
- static bool bFeatureSecureUserConfig(true);
- static sal_uInt16 nNumCopies(5);
+ sal_uInt16 nSecureUserConfigNumCopies(0);
bool bFireOriginalError(true);
- if (bFeatureSecureUserConfig)
+ // read configuration from soffice.ini
+ const bool bSecureUserConfig(comphelper::BackupFileHelper::getSecureUserConfig(nSecureUserConfigNumCopies));
+
+ if (bSecureUserConfig)
{
// try to asccess user layer configuration file
OUString conf("${CONFIGURATION_LAYERS}");
@@ -977,7 +979,7 @@ void Desktop::HandleBootstrapErrors(
if (!aUser.isEmpty())
{
- comphelper::BackupFileHelper aBackupFileHelper(aUser, nNumCopies);
+ comphelper::BackupFileHelper aBackupFileHelper(aUser, nSecureUserConfigNumCopies);
if (aBackupFileHelper.isPopPossible())
{
diff --git a/include/comphelper/backupfilehelper.hxx b/include/comphelper/backupfilehelper.hxx
index f407d2b..2c6cc25 100644
--- a/include/comphelper/backupfilehelper.hxx
+++ b/include/comphelper/backupfilehelper.hxx
@@ -15,6 +15,7 @@
#include <comphelper/comphelperdllapi.h>
#include <rtl/ustring.hxx>
#include <osl/file.hxx>
+#include <memory>
namespace comphelper
{
@@ -45,12 +46,11 @@ namespace comphelper
{
private:
// internal data
- const OUString& mrBaseURL;
- sal_uInt16 mnNumBackups;
- OUString maBase;
- OUString maExt;
- osl::File maBaseFile;
- bool mbBaseFileIsOpen;
+ const OUString& mrBaseURL;
+ sal_uInt16 mnNumBackups;
+ OUString maBase;
+ OUString maName;
+ OUString maExt;
// internal flag if _exit() was called already - a hint to evtl.
// not create copies of potentially not well-defined data. This
@@ -67,6 +67,10 @@ namespace comphelper
public:
/** Constructor to handle Backups of the given file
*
+ * @param rxContext
+ * ComponentContext to use internally; needs to be handed
+ * over due to usages after DeInit() and thus no access
+ * anymore using comphelper::getProcessComponentContext()
* @param rBaseURL
* URL to an existing file that needs to be backed up
*
@@ -77,12 +81,21 @@ namespace comphelper
* It is used in tryPush() and tryPop() calls to cleanup/
* reduce the number of existing backups
*/
- BackupFileHelper(const OUString& rBaseURL, sal_uInt16 nNumBackups = 5);
+ BackupFileHelper(
+ const OUString& rBaseURL,
+ sal_uInt16 nNumBackups = 5);
- // allow to set flag when app had to call _exit()
+ // allow to set static global flag when app had to call _exit()
static void setExitWasCalled();
static bool getExitWasCalled();
+ // static helper to read config values - these are derived from
+ // soffice.ini due to cui not being available in all cases. The
+ // boolean SecureUserConfig is returned.
+ // Default for SecureUserConfig is false
+ // Default for SecureUserConfigNumCopies is 0 (zero)
+ static bool getSecureUserConfig(sal_uInt16& rnSecureUserConfigNumCopies);
+
/** tries to create a new backup, if there is none yet, or if the
* last differs from the base file. It will then put a new verion
* on the 'stack' of copies and evtl. delete the oldest backup.
@@ -113,14 +126,9 @@ namespace comphelper
private:
// internal helper methods
- rtl::OUString getName(sal_uInt16 n);
- bool firstExists();
- void pop();
- void push();
- bool isDifferentOrNew();
- bool equalsBase(osl::File& rLastFile);
bool splitBaseURL();
- bool baseFileOpen();
+ bool baseFileExists();
+ rtl::OUString getName();
};
}
commit 570b3ac181213f2aea7c85b3b2a8f0ccf2340ff6
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date: Thu Sep 15 15:51:21 2016 +0200
profilesafe: make dialog open on linux
Change-Id: Idacec97ec2f097af9bd22a8a67b410c7677d17f1
diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index c2fe950..b3514ef 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -981,6 +981,12 @@ void Desktop::HandleBootstrapErrors(
if (aBackupFileHelper.isPopPossible())
{
+ // for linux (and probably others?) we need to instantiate XDesktop2
+ // to be able to open a *.ui-file based dialog, so do this here locally.
+ // does no harm on win, so better always do this (in error case only anyways)
+ Reference< XComponentContext > xLocalContext = ::comphelper::getProcessComponentContext();
+ Reference< XDesktop2 > xDesktop = css::frame::Desktop::create(xLocalContext);
+
ScopedVclPtrInstance< MessageDialog > aQueryShouldRestore(
Application::GetDefDialogParent(),
"QueryTryToRestoreConfigurationDialog",
commit 8b34d407c7713fd702685fefda65e2f72331e1f4
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date: Thu Sep 15 12:27:28 2016 +0200
profilesafe: Added adaptions
Added code to detect/test exceptions, tested execution,
added code to detect if _exit() was already called on all
systems to avoid writing config and creating backup in that
state (win calls destructors of static objects on _exit(),
linux does not which is intended)
Change-Id: I01df80c714ee964646da23cc3b2b081b74ecfb4b
diff --git a/comphelper/source/misc/backupfilehelper.cxx b/comphelper/source/misc/backupfilehelper.cxx
index 778f0a0..7a353b8 100644
--- a/comphelper/source/misc/backupfilehelper.cxx
+++ b/comphelper/source/misc/backupfilehelper.cxx
@@ -15,6 +15,7 @@
namespace comphelper
{
sal_uInt16 BackupFileHelper::mnMaxAllowedBackups = 10;
+ bool BackupFileHelper::mbExitWasCalled = false;
BackupFileHelper::BackupFileHelper(
const OUString& rBaseURL,
@@ -28,6 +29,16 @@ namespace comphelper
{
}
+ void BackupFileHelper::setExitWasCalled()
+ {
+ mbExitWasCalled = true;
+ }
+
+ bool BackupFileHelper::getExitWasCalled()
+ {
+ return mbExitWasCalled;
+ }
+
bool BackupFileHelper::tryPush()
{
if (isDifferentOrNew())
diff --git a/configmgr/source/components.cxx b/configmgr/source/components.cxx
index b560b0d..7790ab0 100644
--- a/configmgr/source/components.cxx
+++ b/configmgr/source/components.cxx
@@ -614,25 +614,48 @@ Components::Components(
Components::~Components()
{
- flushModifications();
+ SAL_WARN("configmgr", "################# Components::~Components() #####################");
+
+ // get flag if _exit was already called which is a sign to not to secure user config
+ const bool bExitWasCalled(comphelper::BackupFileHelper::getExitWasCalled());
+
+#ifndef WNT
+ // we can add a SAL_WARN here for other systems where the destructor gets called after
+ // an _exit() call - which should not happen. Still safe - the getExitWasCalled() is
+ // used, but a hint that _exit behaves different on a system
+ SAL_WARN_IF(bExitWasCalled, "configmgr", "Components::~Components() called after _exit() call");
+#endif
+
+ if (bExitWasCalled)
+ {
+ osl::MutexGuard g(*lock_);
+
+ if (writeThread_.is())
+ {
+ writeThread_->join();
+ }
+ }
+ else
+ {
+ flushModifications();
+ }
+
for (WeakRootSet::iterator i(roots_.begin()); i != roots_.end(); ++i) {
(*i)->setAlive(false);
}
- // test backup of registrymodifications (currently off)
- static bool bFeatureSecureUserConfig(false);
+ // test backup of registrymodifications
+ static bool bFeatureSecureUserConfig(true);
- if (bFeatureSecureUserConfig && ModificationTarget::File == modificationTarget_ && !modificationFileUrl_.isEmpty())
+ if (!bExitWasCalled &&
+ bFeatureSecureUserConfig &&
+ ModificationTarget::File == modificationTarget_ &&
+ !modificationFileUrl_.isEmpty())
{
static sal_uInt16 nNumCopies(5);
comphelper::BackupFileHelper aBackupFileHelper(modificationFileUrl_, nNumCopies);
- aBackupFileHelper.tryPush();
- static bool bTryPop(false);
- if (bTryPop)
- {
- aBackupFileHelper.tryPop();
- }
+ aBackupFileHelper.tryPush();
}
}
diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index 7628c7a..c2fe950 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -81,6 +81,7 @@
#include <comphelper/configuration.hxx>
#include <comphelper/fileurl.hxx>
#include <comphelper/processfactory.hxx>
+#include <comphelper/backupfilehelper.hxx>
#include <unotools/bootstrap.hxx>
#include <unotools/configmgr.hxx>
#include <unotools/moduleoptions.hxx>
@@ -567,6 +568,14 @@ void Desktop::Init()
{
SetBootstrapError( BE_OFFICECONFIG_BROKEN, e.Message );
}
+
+ static bool bTryHardOfficeconfigBroken(false);
+
+ if (bTryHardOfficeconfigBroken)
+ {
+ SAL_WARN("configmgr", "################# Desktop::Init() #####################");
+ SetBootstrapError(BE_OFFICECONFIG_BROKEN, OUString());
+ }
}
if ( true )
@@ -938,15 +947,87 @@ void Desktop::HandleBootstrapErrors(
}
else if ( aBootstrapError == BE_OFFICECONFIG_BROKEN )
{
- OUString msg(
- GetMsgString(
+ // test restore of registrymodifications
+ static bool bFeatureSecureUserConfig(true);
+ static sal_uInt16 nNumCopies(5);
+ bool bFireOriginalError(true);
+
+ if (bFeatureSecureUserConfig)
+ {
+ // try to asccess user layer configuration file
+ OUString conf("${CONFIGURATION_LAYERS}");
+ rtl::Bootstrap::expandMacros(conf);
+ const OUString aTokenUser("user:");
+ sal_Int32 nStart(conf.indexOf(aTokenUser));
+ OUString aUser;
+
+ if (-1 != nStart)
+ {
+ nStart += aTokenUser.getLength();
+ sal_Int32 nEnd(conf.indexOf(' ', nStart));
+
+ if (-1 == nEnd)
+ {
+ nEnd = conf.getLength();
+ }
+
+ aUser = conf.copy(nStart, nEnd - nStart);
+ aUser.startsWith("!", &aUser);
+ }
+
+ if (!aUser.isEmpty())
+ {
+ comphelper::BackupFileHelper aBackupFileHelper(aUser, nNumCopies);
+
+ if (aBackupFileHelper.isPopPossible())
+ {
+ ScopedVclPtrInstance< MessageDialog > aQueryShouldRestore(
+ Application::GetDefDialogParent(),
+ "QueryTryToRestoreConfigurationDialog",
+ "desktop/ui/querytrytorestoreconfigurationdialog.ui");
+
+ if (aQueryShouldRestore.get())
+ {
+ if (!aErrorMessage.isEmpty())
+ {
+ OUString aPrimaryText(aQueryShouldRestore->get_primary_text());
+
+ aPrimaryText += "\n(\"" + aErrorMessage + "\")";
+ aQueryShouldRestore->set_primary_text(aPrimaryText);
+ }
+
+ if (RET_YES == aQueryShouldRestore->Execute())
+ {
+ aBackupFileHelper.tryPop();
+ bFireOriginalError = false;
+ }
+ }
+ }
+ }
+ }
+
+ // set flag at BackupFileHelper to be able to know if _exit was called and
+ // actions are executed after this
+ comphelper::BackupFileHelper::setExitWasCalled();
+
+ if (bFireOriginalError)
+ {
+ OUString msg(
+ GetMsgString(
STR_CONFIG_ERR_ACCESS_GENERAL,
("A general error occurred while accessing your central"
- " configuration.")));
- if (!aErrorMessage.isEmpty()) {
- msg += "\n(\"" + aErrorMessage + "\")";
+ " configuration.")));
+ if (!aErrorMessage.isEmpty()) {
+ msg += "\n(\"" + aErrorMessage + "\")";
+ }
+ FatalError(MakeStartupErrorMessage(msg));
+ }
+ else
+ {
+ // Already presented all information to the user.
+ // just do what FatalError does at it's end
+ _exit(EXITHELPER_FATAL_ERROR);
}
- FatalError(MakeStartupErrorMessage(msg));
}
else if ( aBootstrapError == BE_USERINSTALL_FAILED )
{
diff --git a/desktop/uiconfig/ui/querytrytorestoreconfigurationdialog.ui b/desktop/uiconfig/ui/querytrytorestoreconfigurationdialog.ui
new file mode 100644
index 0000000..4c332d1
--- /dev/null
+++ b/desktop/uiconfig/ui/querytrytorestoreconfigurationdialog.ui
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkMessageDialog" id="QueryTryToRestoreConfigurationDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes">LibreOffice Startup: General Configuration Error</property>
+ <property name="resizable">False</property>
+ <property name="type_hint">dialog</property>
+ <property name="skip_taskbar_hint">True</property>
+ <property name="message_type">question</property>
+ <property name="buttons">yes-no</property>
+ <property name="text" translatable="yes">A general error occurred during startup while accessing the central configuration.</property>
+ <property name="secondary_text" translatable="yes">A Backup of your configuration was detected. Restoring the configuration might solve this problem, but is not guaranteed to work. A restart of the Program is needed.
+
+Do you want to restore the configuration?</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="messagedialog-vbox5">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="messagedialog-action_area5">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/include/comphelper/backupfilehelper.hxx b/include/comphelper/backupfilehelper.hxx
index 3061254..f407d2b 100644
--- a/include/comphelper/backupfilehelper.hxx
+++ b/include/comphelper/backupfilehelper.hxx
@@ -14,6 +14,7 @@
#include <comphelper/comphelperdllapi.h>
#include <rtl/ustring.hxx>
+#include <osl/file.hxx>
namespace comphelper
{
@@ -51,6 +52,15 @@ namespace comphelper
osl::File maBaseFile;
bool mbBaseFileIsOpen;
+ // internal flag if _exit() was called already - a hint to evtl.
+ // not create copies of potentially not well-defined data. This
+ // may be used in destructors of static instances - which unfortunately
+ // get called on WNT but not on linux. Thus I thought about encapsulating
+ // in some '#ifdefs', but it's just more safe to always do it and
+ // allows to add a SAL_WARN when one of these destructors is called
+ // after _exit()
+ static bool mbExitWasCalled;
+
// internal upper limit (max) of allowed backups
static sal_uInt16 mnMaxAllowedBackups;
@@ -69,6 +79,10 @@ namespace comphelper
*/
BackupFileHelper(const OUString& rBaseURL, sal_uInt16 nNumBackups = 5);
+ // allow to set flag when app had to call _exit()
+ static void setExitWasCalled();
+ static bool getExitWasCalled();
+
/** tries to create a new backup, if there is none yet, or if the
* last differs from the base file. It will then put a new verion
* on the 'stack' of copies and evtl. delete the oldest backup.
commit 9e77585a42193f0496aa7b23afea4ccd65692113
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date: Thu Sep 1 16:16:39 2016 +0200
profilesafe: Implemented BackupFileHelper
Added helper class to allow easy creation/deployment
of backups of a file (here: registrymodifications). It
works like a 'stack' of backups, supüports easy push/pop
of backed-up versions.
Change-Id: Ie19e1209534f23a3dbd6106a5ca13b24b8fefe4d
diff --git a/comphelper/Library_comphelper.mk b/comphelper/Library_comphelper.mk
index 4d4e734..59869a7 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 0000000..778f0a0
--- /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);
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list