Source code

Revision control

Other Tools

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