netwerk/base/src/nsFileStreams.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial