diff options
author | Michael Meeks <michael.meeks@suse.com> | 2013-02-20 16:19:30 +0000 |
---|---|---|
committer | Michael Meeks <michael.meeks@suse.com> | 2013-02-20 16:21:28 +0000 |
commit | 28300209604ee1bb8e5050322b29e95a07f679d8 (patch) | |
tree | 17aa8303d9725259c9e2532b4fbc007fc9e809fa /linguistic | |
parent | 48a3e86ba752926631117b5e3a3d888e0a11e309 (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.cxx | 74 |
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; |