diff --git a/mozilla/netwerk/base/public/nsIFileStreams.idl b/mozilla/netwerk/base/public/nsIFileStreams.idl index 4a186d51bd4..c8b7c3d4503 100644 --- a/mozilla/netwerk/base/public/nsIFileStreams.idl +++ b/mozilla/netwerk/base/public/nsIFileStreams.idl @@ -47,6 +47,9 @@ interface nsISeekableStream : nsISupports void seek(in long whence, in long offset); unsigned long tell(); + + // truncate stream to the current offset + void setEOF(); }; [scriptable, uuid(616f5b48-da09-11d3-8cda-0060b0fc14a3)] diff --git a/mozilla/netwerk/base/src/nsBufferedStreams.cpp b/mozilla/netwerk/base/src/nsBufferedStreams.cpp index 3d8d98e33c0..55f2548da82 100644 --- a/mozilla/netwerk/base/src/nsBufferedStreams.cpp +++ b/mozilla/netwerk/base/src/nsBufferedStreams.cpp @@ -138,6 +138,19 @@ nsBufferedStream::Tell(PRUint32 *result) return NS_OK; } +NS_IMETHODIMP +nsBufferedStream::SetEOF() +{ + if (mStream == nsnull) + return NS_BASE_STREAM_CLOSED; + + nsresult rv; + nsCOMPtr ras = do_QueryInterface(mStream, &rv); + if (NS_FAILED(rv)) return rv; + + return ras->SetEOF(); +} + //////////////////////////////////////////////////////////////////////////////// // nsBufferedInputStream diff --git a/mozilla/netwerk/base/src/nsFileStreams.cpp b/mozilla/netwerk/base/src/nsFileStreams.cpp index 85f17d76e7c..5af2be19e76 100644 --- a/mozilla/netwerk/base/src/nsFileStreams.cpp +++ b/mozilla/netwerk/base/src/nsFileStreams.cpp @@ -20,6 +20,24 @@ * Contributor(s): */ +// file truncation support +#if defined(__linux) +#define _BSD_SOURCE 1 +#include +#elif defined(XP_MAC) +#include +#elif defined(XP_WIN) +#include +#else +// XXX add necessary include file for ftruncate (or equivalent) +#endif + +#if defined(XP_MAC) +#include "pprio.h" +#else +#include "private/pprio.h" +#endif + #include "nsFileStreams.h" #include "nsILocalFile.h" #include "nsXPIDLString.h" @@ -345,6 +363,46 @@ nsFileStream::Tell(PRUint32 *result) return NS_OK; } +NS_IMETHODIMP +nsFileStream::SetEOF() +{ + if (mFD == nsnull) + return NS_BASE_STREAM_CLOSED; + +#if defined(__linux) || defined(XP_MAC) || defined(XP_OS2) + // Some system calls require an EOF offset. + PRUint32 offset; + nsresult rv = Tell(&offset); + if (NS_FAILED(rv)) return rv; +#endif + +#if defined(__linux) + if (ftruncate(PR_FileDesc2NativeHandle(mFD), offset) != 0) { + NS_ERROR("ftruncate failed"); + return NS_ERROR_FAILURE; + } +#elif defined(XP_MAC) + if (::SetEOF(PR_FileDesc2NativeHandle(mFD), offset) != 0) { + NS_ERROR("SetEOF failed"); + return NS_ERROR_FAILURE; + } +#elif defined(XP_WIN) + if (!SetEndOfFile((HANDLE) PR_FileDesc2NativeHandle(mFD))) { + NS_ERROR("SetEndOfFile failed"); + return NS_ERROR_FAILURE; + } +#elif defined(XP_OS2) + if (DosSetFileSize((HFILE) PR_FileDesc2NativeHandle(mFD), offset) != NO_ERROR) { + NS_ERROR("DosSetFileSize failed"); + return NS_ERROR_FAILURE; + } +#else + // XXX not implemented +#endif + + return NS_OK; +} + //////////////////////////////////////////////////////////////////////////////// // nsFileInputStream diff --git a/mozilla/netwerk/base/src/nsFileTransport.cpp b/mozilla/netwerk/base/src/nsFileTransport.cpp index ea5da21125c..6f8b42c61c7 100644 --- a/mozilla/netwerk/base/src/nsFileTransport.cpp +++ b/mozilla/netwerk/base/src/nsFileTransport.cpp @@ -474,12 +474,19 @@ nsFileTransport::OpenOutputStream(PRUint32 aTransferOffset, NS_ASSERTION(aTransferCount == PRUint32(-1), "need to wrap output stream in one that truncates"); nsresult rv = mStreamIO->GetOutputStream(aResult); - if (NS_SUCCEEDED(rv) && aTransferOffset) { - nsCOMPtr seekable(do_QueryInterface(*aResult, &rv)); - if (NS_SUCCEEDED(rv) && seekable) { + if (NS_FAILED(rv)) return rv; + + nsCOMPtr seekable(do_QueryInterface(*aResult, &rv)); + if (seekable) { + if (aTransferOffset) rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, aTransferOffset); - } + if (NS_SUCCEEDED(rv)) + rv = seekable->SetEOF(); } + // a stream need not support nsISeekableStream unless a transfer offset + // greater than zero was requested. + else if (aTransferOffset == 0) + rv = NS_OK; return rv; } @@ -673,14 +680,12 @@ nsFileTransport::Process(void) if (mOffset > 0) { // if we need to set a starting offset, QI for the nsISeekableStream // and set it - nsCOMPtr ras = do_QueryInterface(source, &mStatus); - if (NS_FAILED(mStatus)) { - mXferState = END_READ; - return; + nsCOMPtr seekable = do_QueryInterface(source, &mStatus); + if (NS_SUCCEEDED(mStatus)) { + // for now, assume the offset is always relative to the start of the + // file (position 0) so use PR_SEEK_SET + mStatus = seekable->Seek(PR_SEEK_SET, mOffset); } - // for now, assume the offset is always relative to the start of the - // file (position 0) so use PR_SEEK_SET - mStatus = ras->Seek(PR_SEEK_SET, mOffset); if (NS_FAILED(mStatus)) { mXferState = END_READ; return; @@ -866,23 +871,24 @@ nsFileTransport::Process(void) return; } - if (mOffset > 0) { - // If we need to set a starting offset, QI for the nsISeekableStream - // and set it. - nsCOMPtr ras = do_QueryInterface(mSink, &mStatus); - if (NS_FAILED(mStatus)) { - mXferState = END_WRITE; - return; - } - // For now, assume the offset is always relative to the start of the - // file (position 0) so use PR_SEEK_SET. - mStatus = ras->Seek(PR_SEEK_SET, mOffset); - if (NS_FAILED(mStatus)) { - mXferState = END_WRITE; - return; - } - mOffset = 0; + // QI to a seekable stream so we can set EOF and Seek (if required) + nsCOMPtr seekable(do_QueryInterface(mSink, &mStatus)); + if (seekable) { + if (mOffset) + mStatus = seekable->Seek(nsISeekableStream::NS_SEEK_SET, mOffset); + if (NS_SUCCEEDED(mStatus)) + mStatus = seekable->SetEOF(); } + // a stream need not support nsISeekableStream unless a transfer offset + // greater than zero was requested. + else if (mOffset == 0) + mStatus = NS_OK; + + if (NS_FAILED(mStatus)) { + mXferState = END_WRITE; + return; + } + mOffset = 0; if (!mSinkWrapper) { // diff --git a/mozilla/netwerk/base/src/nsSocketTransport.cpp b/mozilla/netwerk/base/src/nsSocketTransport.cpp index d8258be20d4..c05870c7736 100644 --- a/mozilla/netwerk/base/src/nsSocketTransport.cpp +++ b/mozilla/netwerk/base/src/nsSocketTransport.cpp @@ -2329,6 +2329,12 @@ nsSocketIS::Tell(PRUint32 *offset) return NS_OK; } +NS_IMETHODIMP +nsSocketIS::SetEOF() +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + // //---------------------------------------------------------------------------- // nsSocketOS @@ -2456,6 +2462,12 @@ nsSocketOS::Tell(PRUint32 *offset) return NS_OK; } +NS_IMETHODIMP +nsSocketOS::SetEOF() +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + // //---------------------------------------------------------------------------- // nsSocketRequest