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__