mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 928321 - Implement a variant of safe-file-output-stream that doesn't flush by default. r=Yoric
This commit is contained in:
parent
56a6822193
commit
c4928abe6f
@ -997,6 +997,25 @@ NS_NewLocalFileOutputStream(nsIOutputStream **result,
|
||||
return rv;
|
||||
}
|
||||
|
||||
// returns a file output stream which can be QI'ed to nsISafeOutputStream.
|
||||
inline nsresult
|
||||
NS_NewAtomicFileOutputStream(nsIOutputStream **result,
|
||||
nsIFile *file,
|
||||
int32_t ioFlags = -1,
|
||||
int32_t perm = -1,
|
||||
int32_t behaviorFlags = 0)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIFileOutputStream> out =
|
||||
do_CreateInstance(NS_ATOMICLOCALFILEOUTPUTSTREAM_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = out->Init(file, ioFlags, perm, behaviorFlags);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
out.forget(result);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
// returns a file output stream which can be QI'ed to nsISafeOutputStream.
|
||||
inline nsresult
|
||||
NS_NewSafeLocalFileOutputStream(nsIOutputStream **result,
|
||||
|
@ -832,23 +832,23 @@ nsFileOutputStream::Init(nsIFile* file, int32_t ioFlags, int32_t perm,
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsSafeFileOutputStream
|
||||
// nsAtomicFileOutputStream
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED3(nsSafeFileOutputStream,
|
||||
NS_IMPL_ISUPPORTS_INHERITED3(nsAtomicFileOutputStream,
|
||||
nsFileOutputStream,
|
||||
nsISafeOutputStream,
|
||||
nsIOutputStream,
|
||||
nsIFileOutputStream)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSafeFileOutputStream::Init(nsIFile* file, int32_t ioFlags, int32_t perm,
|
||||
nsAtomicFileOutputStream::Init(nsIFile* file, int32_t ioFlags, int32_t perm,
|
||||
int32_t behaviorFlags)
|
||||
{
|
||||
return nsFileOutputStream::Init(file, ioFlags, perm, behaviorFlags);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSafeFileOutputStream::DoOpen()
|
||||
nsAtomicFileOutputStream::DoOpen()
|
||||
{
|
||||
// Make sure mOpenParams.localFile will be empty if we bail somewhere in
|
||||
// this function
|
||||
@ -896,7 +896,7 @@ nsSafeFileOutputStream::DoOpen()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSafeFileOutputStream::Close()
|
||||
nsAtomicFileOutputStream::Close()
|
||||
{
|
||||
nsresult rv = nsFileOutputStream::Close();
|
||||
|
||||
@ -911,9 +911,8 @@ nsSafeFileOutputStream::Close()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSafeFileOutputStream::Finish()
|
||||
nsAtomicFileOutputStream::Finish()
|
||||
{
|
||||
Flush();
|
||||
nsresult rv = nsFileOutputStream::Close();
|
||||
|
||||
// if there is no temp file, don't try to move it over the original target.
|
||||
@ -930,7 +929,7 @@ nsSafeFileOutputStream::Finish()
|
||||
// temp file we gave out was actually a reference to the target file.
|
||||
// since we succeeded in writing to the temp file (and hence succeeded
|
||||
// in writing to the target file), there is nothing more to do.
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
bool equal;
|
||||
if (NS_FAILED(mTargetFile->Equals(mTempFile, &equal)) || !equal)
|
||||
NS_ERROR("mTempFile not equal to mTargetFile");
|
||||
@ -959,7 +958,7 @@ nsSafeFileOutputStream::Finish()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSafeFileOutputStream::Write(const char *buf, uint32_t count, uint32_t *result)
|
||||
nsAtomicFileOutputStream::Write(const char *buf, uint32_t count, uint32_t *result)
|
||||
{
|
||||
nsresult rv = nsFileOutputStream::Write(buf, count, result);
|
||||
if (NS_SUCCEEDED(mWriteResult)) {
|
||||
@ -970,10 +969,20 @@ nsSafeFileOutputStream::Write(const char *buf, uint32_t count, uint32_t *result)
|
||||
|
||||
if (NS_FAILED(mWriteResult) && count > 0)
|
||||
NS_WARNING("writing to output stream failed! data may be lost");
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsSafeFileOutputStream
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSafeFileOutputStream::Finish()
|
||||
{
|
||||
(void) Flush();
|
||||
return nsAtomicFileOutputStream::Finish();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsFileStream
|
||||
|
||||
|
@ -225,23 +225,28 @@ public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class nsSafeFileOutputStream : public nsFileOutputStream,
|
||||
public nsISafeOutputStream
|
||||
/**
|
||||
* A safe file output stream that overwrites the destination file only
|
||||
* once writing is complete. This protects against incomplete writes
|
||||
* due to the process or the thread being interrupted or crashed.
|
||||
*/
|
||||
class nsAtomicFileOutputStream : public nsFileOutputStream,
|
||||
public nsISafeOutputStream
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSISAFEOUTPUTSTREAM
|
||||
|
||||
nsSafeFileOutputStream() :
|
||||
nsAtomicFileOutputStream() :
|
||||
mTargetFileExists(true),
|
||||
mWriteResult(NS_OK) {}
|
||||
|
||||
virtual ~nsSafeFileOutputStream()
|
||||
virtual ~nsAtomicFileOutputStream()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
virtual nsresult DoOpen();
|
||||
virtual nsresult DoOpen() MOZ_OVERRIDE;
|
||||
|
||||
NS_IMETHODIMP Close();
|
||||
NS_IMETHODIMP Write(const char *buf, uint32_t count, uint32_t *result);
|
||||
@ -253,6 +258,22 @@ protected:
|
||||
|
||||
bool mTargetFileExists;
|
||||
nsresult mWriteResult; // Internally set in Write()
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* A safe file output stream that overwrites the destination file only
|
||||
* once writing + flushing is complete. This protects against more
|
||||
* classes of software/hardware errors than nsAtomicFileOutputStream,
|
||||
* at the expense of being more costly to the disk, OS and battery.
|
||||
*/
|
||||
class nsSafeFileOutputStream : public nsAtomicFileOutputStream
|
||||
{
|
||||
public:
|
||||
|
||||
NS_IMETHOD Finish();
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -396,7 +396,17 @@
|
||||
{0x8c, 0xda, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \
|
||||
}
|
||||
|
||||
// component implementing nsISafeOutputStream
|
||||
// components implementing nsISafeOutputStream
|
||||
#define NS_ATOMICLOCALFILEOUTPUTSTREAM_CONTRACTID \
|
||||
"@mozilla.org/network/atomic-file-output-stream;1"
|
||||
#define NS_ATOMICLOCALFILEOUTPUTSTREAM_CID \
|
||||
{ /* 6EAE857E-4BA9-11E3-9B39-B4036188709B */ \
|
||||
0x6EAE857E, \
|
||||
0x4BA9, \
|
||||
0x11E3, \
|
||||
{0x9b, 0x39, 0xb4, 0x03, 0x61, 0x88, 0x70, 0x9b} \
|
||||
}
|
||||
|
||||
#define NS_SAFELOCALFILEOUTPUTSTREAM_CONTRACTID \
|
||||
"@mozilla.org/network/safe-file-output-stream;1"
|
||||
#define NS_SAFELOCALFILEOUTPUTSTREAM_CID \
|
||||
|
@ -102,6 +102,8 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(BackgroundFileSaverStreamListener, Init)
|
||||
#include "nsSyncStreamListener.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSyncStreamListener, Init)
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAtomicFileOutputStream)
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSafeFileOutputStream)
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFileStream)
|
||||
@ -705,6 +707,7 @@ NS_DEFINE_NAMED_CID(NS_LOADGROUP_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_LOCALFILEINPUTSTREAM_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_LOCALFILEOUTPUTSTREAM_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_PARTIALLOCALFILEINPUTSTREAM_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_ATOMICLOCALFILEOUTPUTSTREAM_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_SAFELOCALFILEOUTPUTSTREAM_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_LOCALFILESTREAM_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_URICHECKER_CID);
|
||||
@ -845,6 +848,7 @@ static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
|
||||
{ &kNS_LOCALFILEINPUTSTREAM_CID, false, nullptr, nsFileInputStream::Create },
|
||||
{ &kNS_LOCALFILEOUTPUTSTREAM_CID, false, nullptr, nsFileOutputStream::Create },
|
||||
{ &kNS_PARTIALLOCALFILEINPUTSTREAM_CID, false, nullptr, nsPartialFileInputStream::Create },
|
||||
{ &kNS_ATOMICLOCALFILEOUTPUTSTREAM_CID, false, nullptr, nsAtomicFileOutputStreamConstructor },
|
||||
{ &kNS_SAFELOCALFILEOUTPUTSTREAM_CID, false, nullptr, nsSafeFileOutputStreamConstructor },
|
||||
{ &kNS_LOCALFILESTREAM_CID, false, nullptr, nsFileStreamConstructor },
|
||||
{ &kNS_URICHECKER_CID, false, nullptr, nsURICheckerConstructor },
|
||||
@ -987,6 +991,7 @@ static const mozilla::Module::ContractIDEntry kNeckoContracts[] = {
|
||||
{ NS_LOCALFILEINPUTSTREAM_CONTRACTID, &kNS_LOCALFILEINPUTSTREAM_CID },
|
||||
{ NS_LOCALFILEOUTPUTSTREAM_CONTRACTID, &kNS_LOCALFILEOUTPUTSTREAM_CID },
|
||||
{ NS_PARTIALLOCALFILEINPUTSTREAM_CONTRACTID, &kNS_PARTIALLOCALFILEINPUTSTREAM_CID },
|
||||
{ NS_ATOMICLOCALFILEOUTPUTSTREAM_CONTRACTID, &kNS_ATOMICLOCALFILEOUTPUTSTREAM_CID },
|
||||
{ NS_SAFELOCALFILEOUTPUTSTREAM_CONTRACTID, &kNS_SAFELOCALFILEOUTPUTSTREAM_CID },
|
||||
{ NS_LOCALFILESTREAM_CONTRACTID, &kNS_LOCALFILESTREAM_CID },
|
||||
{ NS_URICHECKER_CONTRACT_ID, &kNS_URICHECKER_CID },
|
||||
|
@ -3,6 +3,20 @@
|
||||
* 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/. */
|
||||
|
||||
function write_atomic(file, str) {
|
||||
var stream = Cc["@mozilla.org/network/atomic-file-output-stream;1"]
|
||||
.createInstance(Ci.nsIFileOutputStream);
|
||||
stream.init(file, -1, -1, 0);
|
||||
do {
|
||||
var written = stream.write(str, str.length);
|
||||
if (written == str.length)
|
||||
break;
|
||||
str = str.substring(written);
|
||||
} while (1);
|
||||
stream.QueryInterface(Ci.nsISafeOutputStream).finish();
|
||||
stream.close();
|
||||
}
|
||||
|
||||
function write(file, str) {
|
||||
var stream = Cc["@mozilla.org/network/safe-file-output-stream;1"]
|
||||
.createInstance(Ci.nsIFileOutputStream);
|
||||
@ -43,4 +57,10 @@ function run_test()
|
||||
|
||||
write(file, "Second write");
|
||||
checkFile(file, "Second write");
|
||||
|
||||
write_atomic(file, "First write: Atomic");
|
||||
checkFile(file, "First write: Atomic");
|
||||
|
||||
write_atomic(file, "Second write: Atomic");
|
||||
checkFile(file, "Second write: Atomic");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user