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