summaryrefslogtreecommitdiff
path: root/linguistic
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@suse.com>2013-02-20 16:19:30 +0000
committerMichael Meeks <michael.meeks@suse.com>2013-02-20 16:21:28 +0000
commit28300209604ee1bb8e5050322b29e95a07f679d8 (patch)
tree17aa8303d9725259c9e2532b4fbc007fc9e809fa /linguistic
parent48a3e86ba752926631117b5e3a3d888e0a11e309 (diff)
fdo#42122 - truncate files that shrink to avoid dictionary corruption.
fixes a nasty apparently introduced by 7e01bc8d28ffefd4539a5eae2587e1f7da0999e7 Change-Id: I8227cb49a5dfa885d4dc38ce353a356bb5ed8a69
Diffstat (limited to 'linguistic')
-rw-r--r--linguistic/source/dicimp.cxx74
1 files changed, 59 insertions, 15 deletions
diff --git a/linguistic/source/dicimp.cxx b/linguistic/source/dicimp.cxx
index 2216a8ccd2ad..9dc63e332e11 100644
--- a/linguistic/source/dicimp.cxx
+++ b/linguistic/source/dicimp.cxx
@@ -386,33 +386,75 @@ static rtl::OString formatForSave(const uno::Reference< XDictionaryEntry > &xEnt
return aStr.makeStringAndClear();
}
+struct TmpDictionary
+{
+ OUString maURL, maTmpURL;
+ uno::Reference< ucb::XSimpleFileAccess3 > mxAccess;
+
+ void cleanTmpFile()
+ {
+ try
+ {
+ mxAccess->kill(maTmpURL);
+ }
+ catch (const uno::Exception &) { }
+ }
+ TmpDictionary(const OUString &rURL)
+ : maURL( rURL )
+ {
+ maTmpURL = maURL + ".tmp";
+ }
+ ~TmpDictionary()
+ {
+ cleanTmpFile();
+ }
+
+ uno::Reference< io::XStream > openTmpFile()
+ {
+ uno::Reference< io::XStream > xStream;
+
+ try
+ {
+ mxAccess = ucb::SimpleFileAccess::create(
+ comphelper::getProcessComponentContext());
+ xStream = mxAccess->openFileReadWrite(maTmpURL);
+ } catch (const uno::Exception &) { }
+
+ return xStream;
+ }
+
+ bool renameTmpToURL()
+ {
+ try
+ {
+ mxAccess->move(maTmpURL, maURL);
+ }
+ catch (const uno::Exception &)
+ {
+ DBG_ASSERT( 0, "failed to overwrite dict" );
+ return static_cast< sal_uLong >(-1);
+ }
+ return 0;
+ }
+};
sal_uLong DictionaryNeo::saveEntries(const OUString &rURL)
{
- MutexGuard aGuard( GetLinguMutex() );
+ MutexGuard aGuard( GetLinguMutex() );
if (rURL.isEmpty())
return 0;
DBG_ASSERT(!INetURLObject( rURL ).HasError(), "lng : invalid URL");
- uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
+ // lifecycle manage the .tmp file
+ TmpDictionary aTmpDictionary(rURL);
+ uno::Reference< io::XStream > xStream = aTmpDictionary.openTmpFile();
- // get XOutputStream stream
- uno::Reference< io::XStream > xStream;
- try
- {
- uno::Reference< ucb::XSimpleFileAccess3 > xAccess( ucb::SimpleFileAccess::create(xContext) );
- xStream = xAccess->openFileReadWrite( rURL );
- }
- catch (const uno::Exception &)
- {
- DBG_ASSERT( 0, "failed to get input stream" );
- }
if (!xStream.is())
return static_cast< sal_uLong >(-1);
- SvStreamPtr pStream = SvStreamPtr( utl::UcbStreamHelper::CreateStream( xStream ) );
sal_uLong nErr = sal::static_int_cast< sal_uLong >(-1);
+ SvStreamPtr pStream = SvStreamPtr( utl::UcbStreamHelper::CreateStream( xStream ) );
//
// Always write as the latest version, i.e. DIC_VERSION_7
@@ -449,9 +491,11 @@ sal_uLong DictionaryNeo::saveEntries(const OUString &rURL)
rtl::OString aOutStr = formatForSave(pEntry[i], eEnc);
pStream->WriteLine (aOutStr);
if (0 != (nErr = pStream->GetError()))
- return nErr;
+ break;
}
+ nErr = aTmpDictionary.renameTmpToURL();
+
//If we are migrating from an older version, then on first successful
//write, we're now converted to the latest version, i.e. DIC_VERSION_7
nDicVersion = DIC_VERSION_7;