1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/base/src/nsFileStreams.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,321 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef nsFileStreams_h__ 1.10 +#define nsFileStreams_h__ 1.11 + 1.12 +#include "nsAutoPtr.h" 1.13 +#include "nsIFileStreams.h" 1.14 +#include "nsIFile.h" 1.15 +#include "nsIInputStream.h" 1.16 +#include "nsIOutputStream.h" 1.17 +#include "nsISafeOutputStream.h" 1.18 +#include "nsISeekableStream.h" 1.19 +#include "nsILineInputStream.h" 1.20 +#include "nsCOMPtr.h" 1.21 +#include "nsIIPCSerializableInputStream.h" 1.22 +#include "nsReadLine.h" 1.23 +#include <algorithm> 1.24 + 1.25 + 1.26 +//////////////////////////////////////////////////////////////////////////////// 1.27 + 1.28 +class nsFileStreamBase : public nsISeekableStream, 1.29 + public nsIFileMetadata 1.30 +{ 1.31 +public: 1.32 + NS_DECL_THREADSAFE_ISUPPORTS 1.33 + NS_DECL_NSISEEKABLESTREAM 1.34 + NS_DECL_NSIFILEMETADATA 1.35 + 1.36 + nsFileStreamBase(); 1.37 + virtual ~nsFileStreamBase(); 1.38 + 1.39 +protected: 1.40 + nsresult Close(); 1.41 + nsresult Available(uint64_t* _retval); 1.42 + nsresult Read(char* aBuf, uint32_t aCount, uint32_t* _retval); 1.43 + nsresult ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, 1.44 + uint32_t aCount, uint32_t* _retval); 1.45 + nsresult IsNonBlocking(bool* _retval); 1.46 + nsresult Flush(); 1.47 + nsresult Write(const char* aBuf, uint32_t aCount, uint32_t* _retval); 1.48 + nsresult WriteFrom(nsIInputStream* aFromStream, uint32_t aCount, 1.49 + uint32_t* _retval); 1.50 + nsresult WriteSegments(nsReadSegmentFun aReader, void* aClosure, 1.51 + uint32_t aCount, uint32_t* _retval); 1.52 + 1.53 + PRFileDesc* mFD; 1.54 + 1.55 + /** 1.56 + * Flags describing our behavior. See the IDL file for possible values. 1.57 + */ 1.58 + int32_t mBehaviorFlags; 1.59 + 1.60 + /** 1.61 + * Whether we have a pending open (see DEFER_OPEN in the IDL file). 1.62 + */ 1.63 + bool mDeferredOpen; 1.64 + 1.65 + struct OpenParams { 1.66 + nsCOMPtr<nsIFile> localFile; 1.67 + int32_t ioFlags; 1.68 + int32_t perm; 1.69 + }; 1.70 + 1.71 + /** 1.72 + * Data we need to do an open. 1.73 + */ 1.74 + OpenParams mOpenParams; 1.75 + 1.76 + /** 1.77 + * Prepares the data we need to open the file, and either does the open now 1.78 + * by calling DoOpen(), or leaves it to be opened later by a call to 1.79 + * DoPendingOpen(). 1.80 + */ 1.81 + nsresult MaybeOpen(nsIFile* aFile, int32_t aIoFlags, int32_t aPerm, 1.82 + bool aDeferred); 1.83 + 1.84 + /** 1.85 + * Cleans up data prepared in MaybeOpen. 1.86 + */ 1.87 + void CleanUpOpen(); 1.88 + 1.89 + /** 1.90 + * Open the file. This is called either from MaybeOpen (during Init) 1.91 + * or from DoPendingOpen (if DEFER_OPEN is used when initializing this 1.92 + * stream). The default behavior of DoOpen is to open the file and save the 1.93 + * file descriptor. 1.94 + */ 1.95 + virtual nsresult DoOpen(); 1.96 + 1.97 + /** 1.98 + * If there is a pending open, do it now. It's important for this to be 1.99 + * inline since we do it in almost every stream API call. 1.100 + */ 1.101 + inline nsresult DoPendingOpen(); 1.102 +}; 1.103 + 1.104 +//////////////////////////////////////////////////////////////////////////////// 1.105 + 1.106 +class nsFileInputStream : public nsFileStreamBase, 1.107 + public nsIFileInputStream, 1.108 + public nsILineInputStream, 1.109 + public nsIIPCSerializableInputStream 1.110 +{ 1.111 +public: 1.112 + NS_DECL_ISUPPORTS_INHERITED 1.113 + NS_DECL_NSIFILEINPUTSTREAM 1.114 + NS_DECL_NSILINEINPUTSTREAM 1.115 + NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM 1.116 + 1.117 + NS_IMETHOD Close(); 1.118 + NS_IMETHOD Tell(int64_t *aResult); 1.119 + NS_IMETHOD Available(uint64_t* _retval); 1.120 + NS_IMETHOD Read(char* aBuf, uint32_t aCount, uint32_t* _retval); 1.121 + NS_IMETHOD ReadSegments(nsWriteSegmentFun aWriter, void *aClosure, 1.122 + uint32_t aCount, uint32_t* _retval) 1.123 + { 1.124 + return nsFileStreamBase::ReadSegments(aWriter, aClosure, aCount, 1.125 + _retval); 1.126 + } 1.127 + NS_IMETHOD IsNonBlocking(bool* _retval) 1.128 + { 1.129 + return nsFileStreamBase::IsNonBlocking(_retval); 1.130 + } 1.131 + 1.132 + // Overrided from nsFileStreamBase 1.133 + NS_IMETHOD Seek(int32_t aWhence, int64_t aOffset); 1.134 + 1.135 + nsFileInputStream() 1.136 + : mLineBuffer(nullptr), mIOFlags(0), mPerm(0), mCachedPosition(0) 1.137 + {} 1.138 + 1.139 + virtual ~nsFileInputStream() 1.140 + { 1.141 + Close(); 1.142 + } 1.143 + 1.144 + static nsresult 1.145 + Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); 1.146 + 1.147 +protected: 1.148 + nsAutoPtr<nsLineBuffer<char> > mLineBuffer; 1.149 + 1.150 + /** 1.151 + * The file being opened. 1.152 + */ 1.153 + nsCOMPtr<nsIFile> mFile; 1.154 + /** 1.155 + * The IO flags passed to Init() for the file open. 1.156 + */ 1.157 + int32_t mIOFlags; 1.158 + /** 1.159 + * The permissions passed to Init() for the file open. 1.160 + */ 1.161 + int32_t mPerm; 1.162 + 1.163 + /** 1.164 + * Cached position for Tell for automatically reopening streams. 1.165 + */ 1.166 + int64_t mCachedPosition; 1.167 + 1.168 +protected: 1.169 + /** 1.170 + * Internal, called to open a file. Parameters are the same as their 1.171 + * Init() analogues. 1.172 + */ 1.173 + nsresult Open(nsIFile* file, int32_t ioFlags, int32_t perm); 1.174 +}; 1.175 + 1.176 +//////////////////////////////////////////////////////////////////////////////// 1.177 + 1.178 +class nsPartialFileInputStream : public nsFileInputStream, 1.179 + public nsIPartialFileInputStream 1.180 +{ 1.181 +public: 1.182 + using nsFileInputStream::Init; 1.183 + using nsFileInputStream::Read; 1.184 + NS_DECL_ISUPPORTS_INHERITED 1.185 + NS_DECL_NSIPARTIALFILEINPUTSTREAM 1.186 + NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM 1.187 + 1.188 + nsPartialFileInputStream() 1.189 + : mStart(0), mLength(0), mPosition(0) 1.190 + { } 1.191 + 1.192 + NS_IMETHOD Tell(int64_t *aResult); 1.193 + NS_IMETHOD Available(uint64_t *aResult); 1.194 + NS_IMETHOD Read(char* aBuf, uint32_t aCount, uint32_t* aResult); 1.195 + NS_IMETHOD Seek(int32_t aWhence, int64_t aOffset); 1.196 + 1.197 + static nsresult 1.198 + Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); 1.199 + 1.200 +private: 1.201 + uint64_t TruncateSize(uint64_t aSize) { 1.202 + return std::min<uint64_t>(mLength - mPosition, aSize); 1.203 + } 1.204 + 1.205 + uint64_t mStart; 1.206 + uint64_t mLength; 1.207 + uint64_t mPosition; 1.208 +}; 1.209 + 1.210 +//////////////////////////////////////////////////////////////////////////////// 1.211 + 1.212 +class nsFileOutputStream : public nsFileStreamBase, 1.213 + public nsIFileOutputStream 1.214 +{ 1.215 +public: 1.216 + NS_DECL_ISUPPORTS_INHERITED 1.217 + NS_DECL_NSIFILEOUTPUTSTREAM 1.218 + NS_FORWARD_NSIOUTPUTSTREAM(nsFileStreamBase::) 1.219 + 1.220 + virtual ~nsFileOutputStream() 1.221 + { 1.222 + Close(); 1.223 + } 1.224 + 1.225 + static nsresult 1.226 + Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); 1.227 +}; 1.228 + 1.229 +//////////////////////////////////////////////////////////////////////////////// 1.230 + 1.231 +/** 1.232 + * A safe file output stream that overwrites the destination file only 1.233 + * once writing is complete. This protects against incomplete writes 1.234 + * due to the process or the thread being interrupted or crashed. 1.235 + */ 1.236 +class nsAtomicFileOutputStream : public nsFileOutputStream, 1.237 + public nsISafeOutputStream 1.238 +{ 1.239 +public: 1.240 + NS_DECL_ISUPPORTS_INHERITED 1.241 + NS_DECL_NSISAFEOUTPUTSTREAM 1.242 + 1.243 + nsAtomicFileOutputStream() : 1.244 + mTargetFileExists(true), 1.245 + mWriteResult(NS_OK) {} 1.246 + 1.247 + virtual ~nsAtomicFileOutputStream() 1.248 + { 1.249 + Close(); 1.250 + } 1.251 + 1.252 + virtual nsresult DoOpen() MOZ_OVERRIDE; 1.253 + 1.254 + NS_IMETHODIMP Close(); 1.255 + NS_IMETHODIMP Write(const char *buf, uint32_t count, uint32_t *result); 1.256 + NS_IMETHODIMP Init(nsIFile* file, int32_t ioFlags, int32_t perm, int32_t behaviorFlags); 1.257 + 1.258 +protected: 1.259 + nsCOMPtr<nsIFile> mTargetFile; 1.260 + nsCOMPtr<nsIFile> mTempFile; 1.261 + 1.262 + bool mTargetFileExists; 1.263 + nsresult mWriteResult; // Internally set in Write() 1.264 + 1.265 +}; 1.266 + 1.267 +//////////////////////////////////////////////////////////////////////////////// 1.268 + 1.269 +/** 1.270 + * A safe file output stream that overwrites the destination file only 1.271 + * once writing + flushing is complete. This protects against more 1.272 + * classes of software/hardware errors than nsAtomicFileOutputStream, 1.273 + * at the expense of being more costly to the disk, OS and battery. 1.274 + */ 1.275 +class nsSafeFileOutputStream : public nsAtomicFileOutputStream 1.276 +{ 1.277 +public: 1.278 + 1.279 + NS_IMETHOD Finish(); 1.280 +}; 1.281 + 1.282 +//////////////////////////////////////////////////////////////////////////////// 1.283 + 1.284 +class nsFileStream : public nsFileStreamBase, 1.285 + public nsIInputStream, 1.286 + public nsIOutputStream, 1.287 + public nsIFileStream 1.288 +{ 1.289 +public: 1.290 + NS_DECL_ISUPPORTS_INHERITED 1.291 + NS_DECL_NSIFILESTREAM 1.292 + NS_FORWARD_NSIINPUTSTREAM(nsFileStreamBase::) 1.293 + 1.294 + // Can't use NS_FORWARD_NSIOUTPUTSTREAM due to overlapping methods 1.295 + // Close() and IsNonBlocking() 1.296 + NS_IMETHOD Flush() 1.297 + { 1.298 + return nsFileStreamBase::Flush(); 1.299 + } 1.300 + NS_IMETHOD Write(const char* aBuf, uint32_t aCount, uint32_t* _retval) 1.301 + { 1.302 + return nsFileStreamBase::Write(aBuf, aCount, _retval); 1.303 + } 1.304 + NS_IMETHOD WriteFrom(nsIInputStream* aFromStream, uint32_t aCount, 1.305 + uint32_t* _retval) 1.306 + { 1.307 + return nsFileStreamBase::WriteFrom(aFromStream, aCount, _retval); 1.308 + } 1.309 + NS_IMETHOD WriteSegments(nsReadSegmentFun aReader, void* aClosure, 1.310 + uint32_t aCount, uint32_t* _retval) 1.311 + { 1.312 + return nsFileStreamBase::WriteSegments(aReader, aClosure, aCount, 1.313 + _retval); 1.314 + } 1.315 + 1.316 + virtual ~nsFileStream() 1.317 + { 1.318 + Close(); 1.319 + } 1.320 +}; 1.321 + 1.322 +//////////////////////////////////////////////////////////////////////////////// 1.323 + 1.324 +#endif // nsFileStreams_h__