tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsFileStreams.h (9327B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #ifndef nsFileStreams_h__
      7 #define nsFileStreams_h__
      8 
      9 #include "mozilla/UniquePtr.h"
     10 #include "nsIFileStreams.h"
     11 #include "nsIFile.h"
     12 #include "nsICloneableInputStream.h"
     13 #include "nsIInputStream.h"
     14 #include "nsIOutputStream.h"
     15 #include "nsIRandomAccessStream.h"
     16 #include "nsISafeOutputStream.h"
     17 #include "nsISeekableStream.h"
     18 #include "nsILineInputStream.h"
     19 #include "nsCOMPtr.h"
     20 #include "nsIIPCSerializableInputStream.h"
     21 #include "nsReadLine.h"
     22 
     23 namespace mozilla {
     24 namespace ipc {
     25 class FileDescriptor;
     26 }  // namespace ipc
     27 }  // namespace mozilla
     28 
     29 ////////////////////////////////////////////////////////////////////////////////
     30 
     31 class nsFileStreamBase : public nsISeekableStream, public nsIFileMetadata {
     32 public:
     33  NS_DECL_THREADSAFE_ISUPPORTS
     34  NS_DECL_NSISEEKABLESTREAM
     35  NS_DECL_NSITELLABLESTREAM
     36  NS_DECL_NSIFILEMETADATA
     37 
     38  nsFileStreamBase() = default;
     39 
     40 protected:
     41  virtual ~nsFileStreamBase();
     42 
     43  nsresult Close();
     44  nsresult Available(uint64_t* aResult);
     45  nsresult Read(char* aBuf, uint32_t aCount, uint32_t* aResult);
     46  nsresult ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
     47                        uint32_t aCount, uint32_t* _retval);
     48  nsresult IsNonBlocking(bool* aNonBlocking);
     49  nsresult Flush();
     50  nsresult StreamStatus();
     51  nsresult Write(const char* aBuf, uint32_t aCount, uint32_t* result);
     52  nsresult WriteFrom(nsIInputStream* aFromStream, uint32_t aCount,
     53                     uint32_t* _retval);
     54  nsresult WriteSegments(nsReadSegmentFun aReader, void* aClosure,
     55                         uint32_t aCount, uint32_t* _retval);
     56 
     57  PRFileDesc* mFD{nullptr};
     58 
     59  /**
     60   * Flags describing our behavior.  See the IDL file for possible values.
     61   */
     62  int32_t mBehaviorFlags{0};
     63 
     64  enum {
     65    // This is the default value. It will be changed by Deserialize or Init.
     66    eUnitialized,
     67    // The opening has been deferred. See DEFER_OPEN.
     68    eDeferredOpen,
     69    // The file has been opened. mFD is not null.
     70    eOpened,
     71    // The file has been closed. mFD is null.
     72    eClosed,
     73    // Something bad happen in the Open() or in Deserialize(). The actual
     74    // error value is stored in mErrorValue.
     75    eError
     76  } mState{eUnitialized};
     77 
     78  struct OpenParams {
     79    nsCOMPtr<nsIFile> localFile;
     80    int32_t ioFlags = 0;
     81    int32_t perm = 0;
     82  };
     83 
     84  /**
     85   * Data we need to do an open.
     86   */
     87  OpenParams mOpenParams;
     88 
     89  nsresult mErrorValue{NS_ERROR_FAILURE};
     90 
     91  /**
     92   * Prepares the data we need to open the file, and either does the open now
     93   * by calling DoOpen(), or leaves it to be opened later by a call to
     94   * DoPendingOpen().
     95   */
     96  nsresult MaybeOpen(nsIFile* aFile, int32_t aIoFlags, int32_t aPerm,
     97                     bool aDeferred);
     98 
     99  /**
    100   * Cleans up data prepared in MaybeOpen.
    101   */
    102  void CleanUpOpen();
    103 
    104  /**
    105   * Open the file. This is called either from MaybeOpen (during Init)
    106   * or from DoPendingOpen (if DEFER_OPEN is used when initializing this
    107   * stream). The default behavior of DoOpen is to open the file and save the
    108   * file descriptor.
    109   */
    110  virtual nsresult DoOpen();
    111 
    112  /**
    113   * Based on mState, this method does the opening, return an error, or do
    114   * nothing. If the return value is not NS_OK, please, return it back to the
    115   * callee.
    116   */
    117  inline nsresult DoPendingOpen();
    118 };
    119 
    120 ////////////////////////////////////////////////////////////////////////////////
    121 
    122 // nsFileInputStream is cloneable only on the parent process because only there
    123 // it can open the same file multiple times.
    124 
    125 class nsFileInputStream : public nsFileStreamBase,
    126                          public nsIFileInputStream,
    127                          public nsILineInputStream,
    128                          public nsIIPCSerializableInputStream,
    129                          public nsICloneableInputStream {
    130 public:
    131  NS_DECL_ISUPPORTS_INHERITED
    132  NS_DECL_NSIFILEINPUTSTREAM
    133  NS_DECL_NSILINEINPUTSTREAM
    134  NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
    135  NS_DECL_NSICLONEABLEINPUTSTREAM
    136 
    137  NS_IMETHOD Close() override;
    138  NS_IMETHOD Tell(int64_t* aResult) override;
    139  NS_IMETHOD Available(uint64_t* _retval) override;
    140  NS_IMETHOD StreamStatus() override;
    141  NS_IMETHOD Read(char* aBuf, uint32_t aCount, uint32_t* _retval) override;
    142  NS_IMETHOD ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
    143                          uint32_t aCount, uint32_t* _retval) override {
    144    return nsFileStreamBase::ReadSegments(aWriter, aClosure, aCount, _retval);
    145  }
    146  NS_IMETHOD IsNonBlocking(bool* _retval) override {
    147    return nsFileStreamBase::IsNonBlocking(_retval);
    148  }
    149 
    150  // Overrided from nsFileStreamBase
    151  NS_IMETHOD Seek(int32_t aWhence, int64_t aOffset) override;
    152 
    153  nsFileInputStream() : mLineBuffer(nullptr) {}
    154 
    155  static nsresult Create(REFNSIID aIID, void** aResult);
    156 
    157 protected:
    158  virtual ~nsFileInputStream() = default;
    159 
    160  nsresult SeekInternal(int32_t aWhence, int64_t aOffset,
    161                        bool aClearBuf = true);
    162 
    163  mozilla::UniquePtr<nsLineBuffer<char>> mLineBuffer;
    164 
    165  /**
    166   * The file being opened.
    167   */
    168  nsCOMPtr<nsIFile> mFile;
    169  /**
    170   * The IO flags passed to Init() for the file open.
    171   */
    172  int32_t mIOFlags{0};
    173  /**
    174   * The permissions passed to Init() for the file open.
    175   */
    176  int32_t mPerm{0};
    177 
    178  /**
    179   * Cached position for Tell for automatically reopening streams.
    180   */
    181  int64_t mCachedPosition{0};
    182 
    183 protected:
    184  /**
    185   * Internal, called to open a file.  Parameters are the same as their
    186   * Init() analogues.
    187   */
    188  nsresult Open(nsIFile* file, int32_t ioFlags, int32_t perm);
    189 
    190  bool IsCloneable() const;
    191 };
    192 
    193 ////////////////////////////////////////////////////////////////////////////////
    194 
    195 class nsFileOutputStream : public nsFileStreamBase, public nsIFileOutputStream {
    196 public:
    197  NS_DECL_ISUPPORTS_INHERITED
    198  NS_DECL_NSIFILEOUTPUTSTREAM
    199  NS_FORWARD_NSIOUTPUTSTREAM(nsFileStreamBase::)
    200 
    201  static nsresult Create(REFNSIID aIID, void** aResult);
    202  nsresult InitWithFileDescriptor(const mozilla::ipc::FileDescriptor& aFd);
    203 
    204 protected:
    205  virtual ~nsFileOutputStream() = default;
    206 };
    207 
    208 ////////////////////////////////////////////////////////////////////////////////
    209 
    210 /**
    211 * A safe file output stream that overwrites the destination file only
    212 * once writing is complete. This protects against incomplete writes
    213 * due to the process or the thread being interrupted or crashed.
    214 */
    215 class nsAtomicFileOutputStream : public nsFileOutputStream,
    216                                 public nsISafeOutputStream {
    217 public:
    218  NS_DECL_ISUPPORTS_INHERITED
    219  NS_DECL_NSISAFEOUTPUTSTREAM
    220 
    221  nsAtomicFileOutputStream() = default;
    222 
    223  virtual nsresult DoOpen() override;
    224 
    225  NS_IMETHOD Close() override;
    226  NS_IMETHOD Write(const char* buf, uint32_t count, uint32_t* result) override;
    227  NS_IMETHOD Init(nsIFile* file, int32_t ioFlags, int32_t perm,
    228                  int32_t behaviorFlags) override;
    229 
    230 protected:
    231  virtual ~nsAtomicFileOutputStream() = default;
    232 
    233  nsCOMPtr<nsIFile> mTargetFile;
    234  nsCOMPtr<nsIFile> mTempFile;
    235 
    236  bool mTargetFileExists{true};
    237  nsresult mWriteResult{NS_OK};  // Internally set in Write()
    238 };
    239 
    240 ////////////////////////////////////////////////////////////////////////////////
    241 
    242 /**
    243 * A safe file output stream that overwrites the destination file only
    244 * once writing + flushing is complete. This protects against more
    245 * classes of software/hardware errors than nsAtomicFileOutputStream,
    246 * at the expense of being more costly to the disk, OS and battery.
    247 */
    248 class nsSafeFileOutputStream : public nsAtomicFileOutputStream {
    249 public:
    250  NS_IMETHOD Finish() override;
    251 };
    252 
    253 ////////////////////////////////////////////////////////////////////////////////
    254 
    255 class nsFileRandomAccessStream : public nsFileStreamBase,
    256                                 public nsIFileRandomAccessStream,
    257                                 public nsIInputStream,
    258                                 public nsIOutputStream {
    259 public:
    260  static nsresult Create(REFNSIID aIID, void** aResult);
    261 
    262  NS_DECL_ISUPPORTS_INHERITED
    263  NS_FORWARD_NSITELLABLESTREAM(nsFileStreamBase::)
    264  NS_FORWARD_NSISEEKABLESTREAM(nsFileStreamBase::)
    265  NS_DECL_NSIRANDOMACCESSSTREAM
    266  NS_DECL_NSIFILERANDOMACCESSSTREAM
    267  NS_FORWARD_NSIINPUTSTREAM(nsFileStreamBase::)
    268 
    269  // Can't use NS_FORWARD_NSIOUTPUTSTREAM due to overlapping methods
    270  // Close() and IsNonBlocking()
    271  NS_IMETHOD Flush() override { return nsFileStreamBase::Flush(); }
    272  NS_IMETHOD Write(const char* aBuf, uint32_t aCount,
    273                   uint32_t* _retval) override {
    274    return nsFileStreamBase::Write(aBuf, aCount, _retval);
    275  }
    276  NS_IMETHOD WriteFrom(nsIInputStream* aFromStream, uint32_t aCount,
    277                       uint32_t* _retval) override {
    278    return nsFileStreamBase::WriteFrom(aFromStream, aCount, _retval);
    279  }
    280  NS_IMETHOD WriteSegments(nsReadSegmentFun aReader, void* aClosure,
    281                           uint32_t aCount, uint32_t* _retval) override {
    282    return nsFileStreamBase::WriteSegments(aReader, aClosure, aCount, _retval);
    283  }
    284 
    285 protected:
    286  virtual ~nsFileRandomAccessStream() = default;
    287 };
    288 
    289 ////////////////////////////////////////////////////////////////////////////////
    290 
    291 #endif  // nsFileStreams_h__