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