Coverage Report

Created: 2018-09-25 14:53

/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__