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