summaryrefslogtreecommitdiff
path: root/netwerk/base/nsFileStreams.h
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/base/nsFileStreams.h')
-rw-r--r--netwerk/base/nsFileStreams.h333
1 files changed, 333 insertions, 0 deletions
diff --git a/netwerk/base/nsFileStreams.h b/netwerk/base/nsFileStreams.h
new file mode 100644
index 0000000000..22ef91770c
--- /dev/null
+++ b/netwerk/base/nsFileStreams.h
@@ -0,0 +1,333 @@
+// /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+#ifndef nsFileStreams_h__
+#define nsFileStreams_h__
+
+#include "nsAutoPtr.h"
+#include "nsIFileStreams.h"
+#include "nsIFile.h"
+#include "nsIInputStream.h"
+#include "nsIOutputStream.h"
+#include "nsISafeOutputStream.h"
+#include "nsISeekableStream.h"
+#include "nsILineInputStream.h"
+#include "nsCOMPtr.h"
+#include "nsIIPCSerializableInputStream.h"
+#include "nsReadLine.h"
+#include <algorithm>
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsFileStreamBase : public nsISeekableStream,
+ public nsIFileMetadata
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSIFILEMETADATA
+
+ nsFileStreamBase();
+
+protected:
+ virtual ~nsFileStreamBase();
+
+ nsresult Close();
+ nsresult Available(uint64_t* _retval);
+ nsresult Read(char* aBuf, uint32_t aCount, uint32_t* _retval);
+ nsresult ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
+ uint32_t aCount, uint32_t* _retval);
+ nsresult IsNonBlocking(bool* _retval);
+ nsresult Flush();
+ nsresult Write(const char* aBuf, uint32_t aCount, uint32_t* _retval);
+ nsresult WriteFrom(nsIInputStream* aFromStream, uint32_t aCount,
+ uint32_t* _retval);
+ nsresult WriteSegments(nsReadSegmentFun aReader, void* aClosure,
+ uint32_t aCount, uint32_t* _retval);
+
+ PRFileDesc* mFD;
+
+ /**
+ * Flags describing our behavior. See the IDL file for possible values.
+ */
+ int32_t mBehaviorFlags;
+
+ /**
+ * Whether we have a pending open (see DEFER_OPEN in the IDL file).
+ */
+ bool mDeferredOpen;
+
+ struct OpenParams {
+ nsCOMPtr<nsIFile> localFile;
+ int32_t ioFlags;
+ int32_t perm;
+ };
+
+ /**
+ * Data we need to do an open.
+ */
+ OpenParams mOpenParams;
+
+ /**
+ * Prepares the data we need to open the file, and either does the open now
+ * by calling DoOpen(), or leaves it to be opened later by a call to
+ * DoPendingOpen().
+ */
+ nsresult MaybeOpen(nsIFile* aFile, int32_t aIoFlags, int32_t aPerm,
+ bool aDeferred);
+
+ /**
+ * Cleans up data prepared in MaybeOpen.
+ */
+ void CleanUpOpen();
+
+ /**
+ * Open the file. This is called either from MaybeOpen (during Init)
+ * or from DoPendingOpen (if DEFER_OPEN is used when initializing this
+ * stream). The default behavior of DoOpen is to open the file and save the
+ * file descriptor.
+ */
+ virtual nsresult DoOpen();
+
+ /**
+ * If there is a pending open, do it now. It's important for this to be
+ * inline since we do it in almost every stream API call.
+ */
+ inline nsresult DoPendingOpen();
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsFileInputStream : public nsFileStreamBase,
+ public nsIFileInputStream,
+ public nsILineInputStream,
+ public nsIIPCSerializableInputStream
+{
+public:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_NSIFILEINPUTSTREAM
+ NS_DECL_NSILINEINPUTSTREAM
+ NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
+
+ NS_IMETHOD Close() override;
+ NS_IMETHOD Tell(int64_t *aResult) override;
+ NS_IMETHOD Available(uint64_t* _retval) override;
+ NS_IMETHOD Read(char* aBuf, uint32_t aCount, uint32_t* _retval) override;
+ NS_IMETHOD ReadSegments(nsWriteSegmentFun aWriter, void *aClosure,
+ uint32_t aCount, uint32_t* _retval) override
+ {
+ return nsFileStreamBase::ReadSegments(aWriter, aClosure, aCount,
+ _retval);
+ }
+ NS_IMETHOD IsNonBlocking(bool* _retval) override
+ {
+ return nsFileStreamBase::IsNonBlocking(_retval);
+ }
+
+ // Overrided from nsFileStreamBase
+ NS_IMETHOD Seek(int32_t aWhence, int64_t aOffset) override;
+
+ nsFileInputStream()
+ : mLineBuffer(nullptr), mIOFlags(0), mPerm(0), mCachedPosition(0)
+ {}
+
+ static nsresult
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+protected:
+ virtual ~nsFileInputStream()
+ {
+ Close();
+ }
+
+ nsresult SeekInternal(int32_t aWhence, int64_t aOffset, bool aClearBuf=true);
+
+ nsAutoPtr<nsLineBuffer<char> > mLineBuffer;
+
+ /**
+ * The file being opened.
+ */
+ nsCOMPtr<nsIFile> mFile;
+ /**
+ * The IO flags passed to Init() for the file open.
+ */
+ int32_t mIOFlags;
+ /**
+ * The permissions passed to Init() for the file open.
+ */
+ int32_t mPerm;
+
+ /**
+ * Cached position for Tell for automatically reopening streams.
+ */
+ int64_t mCachedPosition;
+
+protected:
+ /**
+ * Internal, called to open a file. Parameters are the same as their
+ * Init() analogues.
+ */
+ nsresult Open(nsIFile* file, int32_t ioFlags, int32_t perm);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsPartialFileInputStream : public nsFileInputStream,
+ public nsIPartialFileInputStream
+{
+public:
+ using nsFileInputStream::Init;
+ using nsFileInputStream::Read;
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_NSIPARTIALFILEINPUTSTREAM
+ NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
+
+ nsPartialFileInputStream()
+ : mStart(0), mLength(0), mPosition(0), mDeferredSeek(false)
+ { }
+
+ NS_IMETHOD Tell(int64_t *aResult) override;
+ NS_IMETHOD Available(uint64_t *aResult) override;
+ NS_IMETHOD Read(char* aBuf, uint32_t aCount, uint32_t* aResult) override;
+ NS_IMETHOD Seek(int32_t aWhence, int64_t aOffset) override;
+
+ static nsresult
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+protected:
+ ~nsPartialFileInputStream()
+ { }
+
+ inline nsresult DoPendingSeek();
+
+private:
+ uint64_t TruncateSize(uint64_t aSize) {
+ return std::min<uint64_t>(mLength - mPosition, aSize);
+ }
+
+ uint64_t mStart;
+ uint64_t mLength;
+ uint64_t mPosition;
+ bool mDeferredSeek;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsFileOutputStream : public nsFileStreamBase,
+ public nsIFileOutputStream
+{
+public:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_NSIFILEOUTPUTSTREAM
+ NS_FORWARD_NSIOUTPUTSTREAM(nsFileStreamBase::)
+
+ static nsresult
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+protected:
+ virtual ~nsFileOutputStream()
+ {
+ Close();
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * 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
+
+ nsAtomicFileOutputStream() :
+ mTargetFileExists(true),
+ mWriteResult(NS_OK) {}
+
+ virtual nsresult DoOpen() override;
+
+ NS_IMETHOD Close() override;
+ NS_IMETHOD Write(const char *buf, uint32_t count, uint32_t *result) override;
+ NS_IMETHOD Init(nsIFile* file, int32_t ioFlags, int32_t perm, int32_t behaviorFlags) override;
+
+protected:
+ virtual ~nsAtomicFileOutputStream()
+ {
+ Close();
+ }
+
+ nsCOMPtr<nsIFile> mTargetFile;
+ nsCOMPtr<nsIFile> mTempFile;
+
+ 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() override;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsFileStream : public nsFileStreamBase,
+ public nsIInputStream,
+ public nsIOutputStream,
+ public nsIFileStream
+{
+public:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_NSIFILESTREAM
+ NS_FORWARD_NSIINPUTSTREAM(nsFileStreamBase::)
+
+ // Can't use NS_FORWARD_NSIOUTPUTSTREAM due to overlapping methods
+ // Close() and IsNonBlocking()
+ NS_IMETHOD Flush() override
+ {
+ return nsFileStreamBase::Flush();
+ }
+ NS_IMETHOD Write(const char* aBuf, uint32_t aCount, uint32_t* _retval) override
+ {
+ return nsFileStreamBase::Write(aBuf, aCount, _retval);
+ }
+ NS_IMETHOD WriteFrom(nsIInputStream* aFromStream, uint32_t aCount,
+ uint32_t* _retval) override
+ {
+ return nsFileStreamBase::WriteFrom(aFromStream, aCount, _retval);
+ }
+ NS_IMETHOD WriteSegments(nsReadSegmentFun aReader, void* aClosure,
+ uint32_t aCount, uint32_t* _retval) override
+ {
+ return nsFileStreamBase::WriteSegments(aReader, aClosure, aCount,
+ _retval);
+ }
+
+protected:
+ virtual ~nsFileStream()
+ {
+ Close();
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif // nsFileStreams_h__