From 7fce480440f57c7aeb013430593758d9d4e63d30 Mon Sep 17 00:00:00 2001 From: Eden Chuang Date: Mon, 21 Mar 2016 10:48:59 +0800 Subject: [PATCH] Bug 772528 - Remove nsFileInputStream::Seek() from nsPartialFileInputStream::Init(). r=baku --HG-- extra : rebase_source : 9050f4f38f64d9e7f8532377661e6d2e6052417e --- netwerk/base/nsFileStreams.cpp | 107 +++++++++++++++++++++++---------- netwerk/base/nsFileStreams.h | 7 ++- 2 files changed, 81 insertions(+), 33 deletions(-) diff --git a/netwerk/base/nsFileStreams.cpp b/netwerk/base/nsFileStreams.cpp index e15bd94f6a2e..c918fcf7aa9e 100644 --- a/netwerk/base/nsFileStreams.cpp +++ b/netwerk/base/nsFileStreams.cpp @@ -323,6 +323,8 @@ nsFileStreamBase::MaybeOpen(nsIFile* aFile, int32_t aIoFlags, mOpenParams.localFile = aFile; + // Following call open() at main thread. + // Main thread might be blocked, while open a remote file. return DoOpen(); } @@ -432,19 +434,23 @@ nsFileInputStream::Open(nsIFile* aFile, int32_t aIOFlags, int32_t aPerm) rv = MaybeOpen(aFile, aIOFlags, aPerm, mBehaviorFlags & nsIFileInputStream::DEFER_OPEN); + if (NS_FAILED(rv)) return rv; - if (mBehaviorFlags & DELETE_ON_CLOSE) { - // POSIX compatible filesystems allow a file to be unlinked while a - // file descriptor is still referencing the file. since we've already - // opened the file descriptor, we'll try to remove the file. if that - // fails, then we'll just remember the nsIFile and remove it after we - // close the file descriptor. - rv = aFile->Remove(false); - if (NS_SUCCEEDED(rv)) { - // No need to remove it later. Clear the flag. - mBehaviorFlags &= ~DELETE_ON_CLOSE; - } + // if defer open is set, do not remove the file here. + // remove the file while Close() is called. + if ((mBehaviorFlags & DELETE_ON_CLOSE) && + !(mBehaviorFlags & nsIFileInputStream::DEFER_OPEN)) { + // POSIX compatible filesystems allow a file to be unlinked while a + // file descriptor is still referencing the file. since we've already + // opened the file descriptor, we'll try to remove the file. if that + // fails, then we'll just remember the nsIFile and remove it after we + // close the file descriptor. + rv = aFile->Remove(false); + if (NS_SUCCEEDED(rv)) { + // No need to remove it later. Clear the flag. + mBehaviorFlags &= ~DELETE_ON_CLOSE; + } } return NS_OK; @@ -514,9 +520,6 @@ nsFileInputStream::Read(char* aBuf, uint32_t aCount, uint32_t* _retval) NS_IMETHODIMP nsFileInputStream::ReadLine(nsACString& aLine, bool* aResult) { - nsresult rv = DoPendingOpen(); - NS_ENSURE_SUCCESS(rv, rv); - if (!mLineBuffer) { mLineBuffer = new nsLineBuffer; } @@ -525,11 +528,19 @@ nsFileInputStream::ReadLine(nsACString& aLine, bool* aResult) NS_IMETHODIMP nsFileInputStream::Seek(int32_t aWhence, int64_t aOffset) +{ + return SeekInternal(aWhence, aOffset); +} + +nsresult +nsFileInputStream::SeekInternal(int32_t aWhence, int64_t aOffset, bool aClearBuf) { nsresult rv = DoPendingOpen(); NS_ENSURE_SUCCESS(rv, rv); - mLineBuffer = nullptr; + if (aClearBuf) { + mLineBuffer = nullptr; + } if (!mFD) { if (mBehaviorFlags & REOPEN_ON_REWIND) { rv = Open(mFile, mIOFlags, mPerm); @@ -699,19 +710,28 @@ nsPartialFileInputStream::Init(nsIFile* aFile, uint64_t aStart, nsresult rv = nsFileInputStream::Init(aFile, aIOFlags, aPerm, aBehaviorFlags); + + // aFile is a partial file, it must exist. NS_ENSURE_SUCCESS(rv, rv); - return nsFileInputStream::Seek(NS_SEEK_SET, mStart); + mDeferredSeek = true; + + return rv; } NS_IMETHODIMP nsPartialFileInputStream::Tell(int64_t *aResult) { int64_t tell = 0; - nsresult rv = nsFileInputStream::Tell(&tell); - if (NS_SUCCEEDED(rv)) { - *aResult = tell - mStart; - } + + nsresult rv = DoPendingSeek(); + NS_ENSURE_SUCCESS(rv, rv); + + rv = nsFileInputStream::Tell(&tell); + NS_ENSURE_SUCCESS(rv, rv); + + + *aResult = tell - mStart; return rv; } @@ -719,16 +739,23 @@ NS_IMETHODIMP nsPartialFileInputStream::Available(uint64_t* aResult) { uint64_t available = 0; - nsresult rv = nsFileInputStream::Available(&available); - if (NS_SUCCEEDED(rv)) { - *aResult = TruncateSize(available); - } + + nsresult rv = DoPendingSeek(); + NS_ENSURE_SUCCESS(rv, rv); + + rv = nsFileInputStream::Available(&available); + NS_ENSURE_SUCCESS(rv, rv); + + *aResult = TruncateSize(available); return rv; } NS_IMETHODIMP nsPartialFileInputStream::Read(char* aBuf, uint32_t aCount, uint32_t* aResult) { + nsresult rv = DoPendingSeek(); + NS_ENSURE_SUCCESS(rv, rv); + uint32_t readsize = (uint32_t) TruncateSize(aCount); if (readsize == 0 && mBehaviorFlags & CLOSE_ON_EOF) { Close(); @@ -736,16 +763,19 @@ nsPartialFileInputStream::Read(char* aBuf, uint32_t aCount, uint32_t* aResult) return NS_OK; } - nsresult rv = nsFileInputStream::Read(aBuf, readsize, aResult); - if (NS_SUCCEEDED(rv)) { - mPosition += readsize; - } + rv = nsFileInputStream::Read(aBuf, readsize, aResult); + NS_ENSURE_SUCCESS(rv, rv); + + mPosition += readsize; return rv; } NS_IMETHODIMP nsPartialFileInputStream::Seek(int32_t aWhence, int64_t aOffset) { + nsresult rv = DoPendingSeek(); + NS_ENSURE_SUCCESS(rv, rv); + int64_t offset; switch (aWhence) { case NS_SEEK_SET: @@ -765,10 +795,10 @@ nsPartialFileInputStream::Seek(int32_t aWhence, int64_t aOffset) return NS_ERROR_INVALID_ARG; } - nsresult rv = nsFileInputStream::Seek(NS_SEEK_SET, offset); - if (NS_SUCCEEDED(rv)) { - mPosition = offset - mStart; - } + rv = nsFileInputStream::Seek(NS_SEEK_SET, offset); + NS_ENSURE_SUCCESS(rv, rv); + + mPosition = offset - mStart; return rv; } @@ -828,6 +858,19 @@ nsPartialFileInputStream::Deserialize( return NS_SUCCEEDED(nsFileInputStream::Seek(NS_SEEK_SET, mStart)); } +nsresult +nsPartialFileInputStream::DoPendingSeek() +{ + if (!mDeferredSeek) { + return NS_OK; + } + + mDeferredSeek = false; + + // This is the first time to open the file, don't clear mLinebuffer. + // mLineBuffer might be already initialized by ReadLine(). + return nsFileInputStream::SeekInternal(NS_SEEK_SET, mStart, false); +} //////////////////////////////////////////////////////////////////////////////// // nsFileOutputStream diff --git a/netwerk/base/nsFileStreams.h b/netwerk/base/nsFileStreams.h index ad2c3c3b6a0f..00a020012ca6 100644 --- a/netwerk/base/nsFileStreams.h +++ b/netwerk/base/nsFileStreams.h @@ -143,6 +143,8 @@ protected: Close(); } + nsresult SeekInternal(int32_t aWhence, int64_t aOffset, bool aClearBuf=true); + nsAutoPtr > mLineBuffer; /** @@ -184,7 +186,7 @@ public: NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM nsPartialFileInputStream() - : mStart(0), mLength(0), mPosition(0) + : mStart(0), mLength(0), mPosition(0), mDeferredSeek(false) { } NS_IMETHOD Tell(int64_t *aResult) override; @@ -199,6 +201,8 @@ protected: ~nsPartialFileInputStream() { } + inline nsresult DoPendingSeek(); + private: uint64_t TruncateSize(uint64_t aSize) { return std::min(mLength - mPosition, aSize); @@ -207,6 +211,7 @@ private: uint64_t mStart; uint64_t mLength; uint64_t mPosition; + bool mDeferredSeek; }; ////////////////////////////////////////////////////////////////////////////////