forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			300 lines
		
	
	
	
		
			9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			300 lines
		
	
	
	
		
			9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // /* -*- 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 "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>
 | |
| 
 | |
| 
 | |
| ////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| 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;
 | |
| 
 | |
|     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;
 | |
| 
 | |
|     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);
 | |
| 
 | |
|     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);
 | |
| 
 | |
| 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__
 | 
