summaryrefslogtreecommitdiffstats
path: root/netwerk/base/nsFileStreams.h
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/base/nsFileStreams.h')
-rw-r--r--netwerk/base/nsFileStreams.h288
1 files changed, 288 insertions, 0 deletions
diff --git a/netwerk/base/nsFileStreams.h b/netwerk/base/nsFileStreams.h
new file mode 100644
index 0000000000..c694d1b366
--- /dev/null
+++ b/netwerk/base/nsFileStreams.h
@@ -0,0 +1,288 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "mozilla/UniquePtr.h"
+#include "nsIFileStreams.h"
+#include "nsIFile.h"
+#include "nsICloneableInputStream.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>
+
+namespace mozilla {
+namespace ipc {
+class FileDescriptor;
+} // namespace ipc
+} // namespace mozilla
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsFileStreamBase : public nsISeekableStream, public nsIFileMetadata {
+ public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSITELLABLESTREAM
+ 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;
+
+ enum {
+ // This is the default value. It will be changed by Deserialize or Init.
+ eUnitialized,
+ // The opening has been deferred. See DEFER_OPEN.
+ eDeferredOpen,
+ // The file has been opened. mFD is not null.
+ eOpened,
+ // The file has been closed. mFD is null.
+ eClosed,
+ // Something bad happen in the Open() or in Deserialize(). The actual
+ // error value is stored in mErrorValue.
+ eError
+ } mState;
+
+ struct OpenParams {
+ nsCOMPtr<nsIFile> localFile;
+ int32_t ioFlags;
+ int32_t perm;
+ };
+
+ /**
+ * Data we need to do an open.
+ */
+ OpenParams mOpenParams;
+
+ nsresult mErrorValue;
+
+ /**
+ * 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();
+
+ /**
+ * Based on mState, this method does the opening, return an error, or do
+ * nothing. If the return value is not NS_OK, please, return it back to the
+ * callee.
+ */
+ inline nsresult DoPendingOpen();
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+// nsFileInputStream is cloneable only on the parent process because only there
+// it can open the same file multiple times.
+
+class nsFileInputStream : public nsFileStreamBase,
+ public nsIFileInputStream,
+ public nsILineInputStream,
+ public nsIIPCSerializableInputStream,
+ public nsICloneableInputStream {
+ public:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_NSIFILEINPUTSTREAM
+ NS_DECL_NSILINEINPUTSTREAM
+ NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
+ NS_DECL_NSICLONEABLEINPUTSTREAM
+
+ 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() = default;
+
+ void SerializeInternal(mozilla::ipc::InputStreamParams& aParams,
+ FileDescriptorArray& aFileDescriptors);
+
+ nsresult SeekInternal(int32_t aWhence, int64_t aOffset,
+ bool aClearBuf = true);
+
+ mozilla::UniquePtr<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);
+
+ bool IsCloneable() const;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+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);
+ nsresult InitWithFileDescriptor(const mozilla::ipc::FileDescriptor& aFd);
+
+ protected:
+ virtual ~nsFileOutputStream() = default;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * 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() = default;
+
+ 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() = default;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif // nsFileStreams_h__