VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/obsolete/nsIFileStream.cpp@ 4837

Last change on this file since 4837 was 1, checked in by vboxsync, 54 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.6 KB
Line 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 * Pierre Phaneuf <pp@ludusdesign.com>
24 *
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
36 *
37 * ***** END LICENSE BLOCK ***** */
38
39#include "nsIFileStream.h"
40#include "nsFileSpec.h"
41#include "nsCOMPtr.h"
42
43#include "prerror.h"
44
45#include "nsSegmentedBuffer.h"
46#include "nsInt64.h"
47
48#ifdef XP_MAC
49#include "pprio.h" // To get PR_ImportFile
50#else
51#include "prio.h"
52#endif
53
54#ifdef XP_MAC
55#include <Errors.h>
56#include <iostream>
57#endif
58
59//========================================================================================
60class FileImpl
61 : public nsIRandomAccessStore
62 , public nsIFileSpecOutputStream
63 , public nsIFileSpecInputStream
64 , public nsIOpenFile
65//========================================================================================
66{
67 public:
68 FileImpl(PRFileDesc* inDesc);
69 FileImpl(const nsFileSpec& inFile, int nsprMode, PRIntn accessMode);
70
71 // nsISupports interface
72 NS_DECL_ISUPPORTS
73
74 // nsIOpenFile interface
75 NS_IMETHOD Open(const nsFileSpec& inFile, int nsprMode, PRIntn accessMode);
76 NS_IMETHOD Close();
77 NS_IMETHOD GetIsOpen(PRBool* outOpen);
78
79 // nsIInputStream interface
80 NS_IMETHOD Available(PRUint32 *aLength);
81 NS_IMETHOD Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount);
82 NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval);
83 NS_IMETHOD IsNonBlocking(PRBool *aNonBlocking);
84
85 // nsIOutputStream interface
86 NS_IMETHOD Write(const char* aBuf, PRUint32 aCount, PRUint32 *aWriteCount);
87 NS_IMETHOD Flush();
88 NS_IMETHOD WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval);
89 NS_IMETHOD WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval);
90
91 // nsIRandomAccessStore interface
92 NS_DECL_NSISEEKABLESTREAM
93 NS_IMETHOD GetAtEOF(PRBool* outAtEOF);
94 NS_IMETHOD SetAtEOF(PRBool inAtEOF);
95
96 private:
97
98 ~FileImpl();
99
100 protected:
101
102 enum {
103 kOuputBufferSegmentSize = 4096,
104 kOuputBufferMaxSize = 4096
105 };
106
107 nsresult InternalFlush(PRBool syncFile);
108 nsresult AllocateBuffers(PRUint32 segmentSize, PRUint32 maxSize);
109
110 PRFileDesc* mFileDesc;
111 int mNSPRMode;
112 PRBool mFailed;
113 PRBool mEOF;
114 PRInt32 mLength;
115
116 PRBool mGotBuffers;
117 nsSegmentedBuffer mOutBuffer;
118 char* mWriteCursor;
119 char* mWriteLimit;
120
121}; // class FileImpl
122
123NS_IMPL_RELEASE(FileImpl)
124NS_IMPL_ADDREF(FileImpl)
125
126NS_IMPL_QUERY_HEAD(FileImpl)
127 NS_IMPL_QUERY_BODY(nsIOpenFile)
128 NS_IMPL_QUERY_BODY(nsISeekableStream)
129 NS_IMPL_QUERY_BODY(nsIRandomAccessStore)
130 NS_IMPL_QUERY_BODY(nsIOutputStream)
131 NS_IMPL_QUERY_BODY(nsIInputStream)
132 NS_IMPL_QUERY_BODY(nsIFileSpecInputStream)
133 NS_IMPL_QUERY_BODY(nsIFileSpecOutputStream)
134NS_IMPL_QUERY_TAIL(nsIOutputStream)
135
136
137//----------------------------------------------------------------------------------------
138FileImpl::FileImpl(PRFileDesc* inDesc)
139//----------------------------------------------------------------------------------------
140: mFileDesc(inDesc)
141, mNSPRMode(0)
142, mFailed(PR_FALSE)
143, mEOF(PR_FALSE)
144, mLength(-1)
145, mGotBuffers(PR_FALSE)
146{
147 mWriteCursor = nsnull;
148 mWriteLimit = nsnull;
149}
150
151
152//----------------------------------------------------------------------------------------
153FileImpl::FileImpl(const nsFileSpec& inFile, int nsprMode, PRIntn accessMode)
154//----------------------------------------------------------------------------------------
155: mFileDesc(nsnull)
156, mNSPRMode(-1)
157, mEOF(PR_FALSE)
158, mLength(-1)
159, mGotBuffers(PR_FALSE)
160{
161 mWriteCursor = nsnull;
162 mWriteLimit = nsnull;
163
164 nsresult rv = Open(inFile, nsprMode, accessMode); // this sets nsprMode
165
166 if (NS_FAILED(rv))
167 {
168 mFailed = PR_TRUE;
169#if DEBUG
170 char *fileName = inFile.GetLeafName();
171 printf("Opening file %s failed\n", fileName);
172 nsCRT::free(fileName);
173#endif
174 }
175 else
176 {
177 mFailed = PR_FALSE;
178 }
179}
180
181//----------------------------------------------------------------------------------------
182FileImpl::~FileImpl()
183//----------------------------------------------------------------------------------------
184{
185 nsresult rv = Close();
186 NS_ASSERTION(NS_SUCCEEDED(rv), "Close failed");
187}
188
189
190//----------------------------------------------------------------------------------------
191NS_IMETHODIMP FileImpl::Open(
192 const nsFileSpec& inFile,
193 int nsprMode,
194 PRIntn accessMode)
195//----------------------------------------------------------------------------------------
196{
197 if (mFileDesc)
198 if ((nsprMode & mNSPRMode) == nsprMode)
199 return NS_OK;
200 else
201 return NS_FILE_RESULT(PR_ILLEGAL_ACCESS_ERROR);
202
203 const int nspr_modes[]={
204 PR_WRONLY | PR_CREATE_FILE,
205 PR_WRONLY | PR_CREATE_FILE | PR_APPEND,
206 PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
207 PR_RDONLY,
208 PR_RDONLY | PR_APPEND,
209 PR_RDWR | PR_CREATE_FILE,
210 PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE,
211// "wb",
212// "ab",
213// "wb",
214// "rb",
215// "r+b",
216// "w+b",
217 0 };
218 const int* currentLegalMode = nspr_modes;
219 while (*currentLegalMode && nsprMode != *currentLegalMode)
220 ++currentLegalMode;
221 if (!*currentLegalMode)
222 return NS_FILE_RESULT(PR_ILLEGAL_ACCESS_ERROR);
223
224#ifdef XP_MAC
225 // Use the file spec to open the file, because one path can be common to
226 // several files on the Macintosh (you can have several volumes with the
227 // same name, see).
228 mFileDesc = 0;
229 OSErr err = inFile.Error();
230 if (err != noErr)
231 if (err != fnfErr || !(nsprMode & PR_CREATE_FILE))
232 return NS_FILE_RESULT(inFile.Error());
233 err = noErr;
234#if DEBUG
235 const OSType kCreator = 'CWIE';
236#else
237 const OSType kCreator = 'MOSS';
238#endif
239 // Resolve the alias to the original file.
240 nsFileSpec original = inFile;
241 PRBool ignoredResult;
242 original.ResolveSymlink(ignoredResult);
243 const FSSpec& spec = original.operator const FSSpec&();
244 if (nsprMode & PR_CREATE_FILE) {
245 // In order to get the right file type/creator, do it with an nsILocalFileMac
246 // Don't propagate any errors in doing this. If any error, just use FSpCreate.
247 FSSpec nonConstSpec = spec;
248 nsCOMPtr<nsILocalFileMac> macFile;
249 nsresult res = NS_NewLocalFileWithFSSpec(&nonConstSpec, PR_FALSE, getter_AddRefs(macFile));
250 if (NS_SUCCEEDED(res)) {
251 nsCOMPtr<nsIFile> asFile(do_QueryInterface(macFile, &res));
252 if (NS_SUCCEEDED(res)) {
253 res = asFile->Create(nsIFile::NORMAL_FILE_TYPE, 0);
254 if (res == NS_ERROR_FILE_ALREADY_EXISTS)
255 res = NS_OK;
256 }
257 }
258 if (NS_FAILED(res))
259 err = FSpCreate(&spec, kCreator, 'TEXT', 0);
260 }
261
262 if (err == dupFNErr)
263 err = noErr;
264 if (err != noErr)
265 return NS_FILE_RESULT(err);
266
267 SInt8 perm;
268 if (nsprMode & PR_RDWR)
269 perm = fsRdWrPerm;
270 else if (nsprMode & PR_WRONLY)
271 perm = fsWrPerm;
272 else
273 perm = fsRdPerm;
274
275 short refnum;
276 err = FSpOpenDF(&spec, perm, &refnum);
277
278 if (err == noErr && (nsprMode & PR_TRUNCATE))
279 err = ::SetEOF(refnum, 0);
280 if (err == noErr && (nsprMode & PR_APPEND))
281 err = SetFPos(refnum, fsFromLEOF, 0);
282 if (err != noErr)
283 return NS_FILE_RESULT(err);
284
285 if ((mFileDesc = PR_ImportFile(refnum)) == 0)
286 return NS_FILE_RESULT(PR_GetError());
287#else
288 // Platforms other than Macintosh...
289 // Another bug in NSPR: Mac PR_Open assumes a unix style path, but Win PR_Open assumes
290 // a windows path.
291 if ((mFileDesc = PR_Open((const char*)nsFileSpec(inFile), nsprMode, accessMode)) == 0)
292 return NS_FILE_RESULT(PR_GetError());
293#endif
294 mNSPRMode = nsprMode;
295 mLength = PR_Available(mFileDesc);
296 return NS_OK;
297} // FileImpl::Open
298
299
300//----------------------------------------------------------------------------------------
301NS_IMETHODIMP FileImpl::Available(PRUint32 *aLength)
302//----------------------------------------------------------------------------------------
303{
304 NS_PRECONDITION(aLength != nsnull, "null ptr");
305 if (!aLength)
306 return NS_ERROR_NULL_POINTER;
307 if (mLength < 0)
308 return NS_ERROR_UNEXPECTED;
309 *aLength = mLength;
310 return NS_OK;
311}
312
313//----------------------------------------------------------------------------------------
314NS_IMETHODIMP FileImpl::GetIsOpen(PRBool* outOpen)
315//----------------------------------------------------------------------------------------
316{
317 *outOpen = (mFileDesc != nsnull && !mFailed);
318 return NS_OK;
319}
320
321//----------------------------------------------------------------------------------------
322NS_IMETHODIMP FileImpl::Seek(PRInt32 whence, PRInt64 offset)
323//----------------------------------------------------------------------------------------
324{
325 if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc)
326 return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
327 mFailed = PR_FALSE; // reset on a seek.
328 mEOF = PR_FALSE; // reset on a seek.
329
330 // To avoid corruption, we flush during a seek. see bug number 18949
331 InternalFlush(PR_FALSE);
332
333 nsInt64 position = PR_Seek64(mFileDesc, 0, PR_SEEK_CUR);
334 nsInt64 available = PR_Available64(mFileDesc);
335 nsInt64 fileSize = position + available;
336 nsInt64 newPosition = offset;
337 switch (whence)
338 {
339 case NS_SEEK_CUR: newPosition += position; break;
340 case NS_SEEK_SET: ; break;
341 case NS_SEEK_END: newPosition += fileSize; break;
342 }
343 const nsInt64 zero = 0;
344 if (newPosition < zero)
345 {
346 newPosition = 0;
347 mFailed = PR_TRUE;
348 }
349 if (newPosition >= fileSize) // nb: not "else if".
350 {
351 newPosition = fileSize;
352 mEOF = PR_TRUE;
353 }
354 if (PR_Seek64(mFileDesc, newPosition, PR_SEEK_SET) < 0)
355 mFailed = PR_TRUE;
356 return NS_OK;
357} // FileImpl::Seek
358
359
360//----------------------------------------------------------------------------------------
361NS_IMETHODIMP FileImpl::Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount)
362//----------------------------------------------------------------------------------------
363{
364 NS_PRECONDITION(aBuf != nsnull, "null ptr");
365 if (!aBuf)
366 return NS_ERROR_NULL_POINTER;
367 NS_PRECONDITION(aReadCount != nsnull, "null ptr");
368 if (!aReadCount)
369 return NS_ERROR_NULL_POINTER;
370 if (!mFileDesc)
371 return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
372 if (mFailed)
373 return NS_ERROR_FAILURE;
374 PRInt32 bytesRead = PR_Read(mFileDesc, aBuf, aCount);
375 if (bytesRead < 0)
376 {
377 *aReadCount = 0;
378 mFailed = PR_TRUE;
379 return NS_FILE_RESULT(PR_GetError());
380 }
381 else if (bytesRead == 0)
382 {
383 mEOF = PR_TRUE;
384 }
385 *aReadCount = bytesRead;
386 return NS_OK;
387}
388
389NS_IMETHODIMP
390FileImpl::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval)
391{
392 NS_NOTREACHED("ReadSegments");
393 return NS_ERROR_NOT_IMPLEMENTED;
394}
395
396//----------------------------------------------------------------------------------------
397NS_IMETHODIMP FileImpl::Write(const char* aBuf, PRUint32 aCount, PRUint32 *aWriteCount)
398//----------------------------------------------------------------------------------------
399{
400 NS_PRECONDITION(aBuf != nsnull, "null ptr");
401 NS_PRECONDITION(aWriteCount != nsnull, "null ptr");
402
403 *aWriteCount = 0;
404
405#ifdef XP_MAC
406 // Calling PR_Write on stdout is sure suicide.
407 if (mFileDesc == PR_STDOUT || mFileDesc == PR_STDERR)
408 {
409 std::cout.write(aBuf, aCount);
410 *aWriteCount = aCount;
411 return NS_OK;
412 }
413#endif
414 if (!mFileDesc)
415 return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
416 if (mFailed)
417 return NS_ERROR_FAILURE;
418
419 if (!mGotBuffers)
420 {
421 nsresult rv = AllocateBuffers(kOuputBufferSegmentSize, kOuputBufferMaxSize);
422 if (NS_FAILED(rv))
423 return rv; // try to write non-buffered?
424 }
425
426 PRUint32 bufOffset = 0;
427 PRUint32 currentWrite = 0;
428 while (aCount > 0)
429 {
430 if (mWriteCursor == nsnull || mWriteCursor == mWriteLimit)
431 {
432 char* seg = mOutBuffer.AppendNewSegment();
433 if (seg == nsnull)
434 {
435 // buffer is full, try again
436 InternalFlush(PR_FALSE);
437 seg = mOutBuffer.AppendNewSegment();
438 if (seg == nsnull)
439 return NS_ERROR_OUT_OF_MEMORY;
440 }
441 mWriteCursor = seg;
442 mWriteLimit = seg + mOutBuffer.GetSegmentSize();
443 }
444
445 // move
446 currentWrite = mWriteLimit - mWriteCursor;
447
448 if (aCount < currentWrite)
449 currentWrite = aCount;
450
451 memcpy(mWriteCursor, (aBuf + bufOffset), currentWrite);
452
453 mWriteCursor += currentWrite;
454
455 aCount -= currentWrite;
456 bufOffset += currentWrite;
457 *aWriteCount += currentWrite;
458 }
459
460 return NS_OK;
461}
462
463static NS_METHOD
464nsWriteSegmentToFile(nsIInputStream* in,
465 void* closure,
466 const char* fromRawSegment,
467 PRUint32 toOffset,
468 PRUint32 count,
469 PRUint32 *writeCount)
470{
471 NS_NOTREACHED("nsWriteSegmentToFile");
472 return NS_ERROR_NOT_IMPLEMENTED;
473}
474
475NS_IMETHODIMP
476FileImpl::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *result)
477{
478 return inStr->ReadSegments(nsWriteSegmentToFile, nsnull, count, result);
479}
480
481NS_IMETHODIMP
482FileImpl::WriteSegments(nsReadSegmentFun reader, void * closure,
483 PRUint32 count, PRUint32 *result)
484{
485 NS_NOTREACHED("WriteSegments");
486 return NS_ERROR_NOT_IMPLEMENTED;
487}
488
489NS_IMETHODIMP
490FileImpl::IsNonBlocking(PRBool *aNonBlocking)
491{
492 *aNonBlocking = PR_FALSE;
493 return NS_OK;
494}
495
496//----------------------------------------------------------------------------------------
497NS_IMETHODIMP FileImpl::Tell(PRInt64* outWhere)
498//----------------------------------------------------------------------------------------
499{
500 if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc)
501 return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
502 *outWhere = PR_Seek64(mFileDesc, 0, PR_SEEK_CUR);
503 return NS_OK;
504} // FileImpl::Tell
505
506//----------------------------------------------------------------------------------------
507NS_IMETHODIMP FileImpl::Close()
508//----------------------------------------------------------------------------------------
509{
510 if ((mNSPRMode & PR_RDONLY) == 0)
511 InternalFlush(PR_FALSE);
512
513 if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc)
514 return NS_OK;
515 if (PR_Close(mFileDesc) == PR_SUCCESS)
516 mFileDesc = 0;
517 else
518 return NS_FILE_RESULT(PR_GetError());
519 return NS_OK;
520} // FileImpl::close
521
522//----------------------------------------------------------------------------------------
523NS_IMETHODIMP FileImpl::Flush()
524//----------------------------------------------------------------------------------------
525{
526 // for external callers, this will do a Sync as well as flush buffers.
527 return InternalFlush(PR_TRUE);
528} // FileImpl::flush
529
530
531//----------------------------------------------------------------------------------------
532NS_IMETHODIMP FileImpl::GetAtEOF(PRBool* outAtEOF)
533//----------------------------------------------------------------------------------------
534{
535 *outAtEOF = mEOF;
536 return NS_OK;
537}
538
539
540//----------------------------------------------------------------------------------------
541NS_IMETHODIMP FileImpl::SetAtEOF(PRBool inAtEOF)
542//----------------------------------------------------------------------------------------
543{
544 mEOF = inAtEOF;
545 return NS_OK;
546}
547
548//----------------------------------------------------------------------------------------
549NS_IMETHODIMP FileImpl::SetEOF()
550//----------------------------------------------------------------------------------------
551{
552 NS_NOTYETIMPLEMENTED("FileImpl::SetEOF");
553 return NS_ERROR_NOT_IMPLEMENTED;
554}
555
556//----------------------------------------------------------------------------------------
557nsresult FileImpl::AllocateBuffers(PRUint32 segmentSize, PRUint32 maxBufSize)
558//----------------------------------------------------------------------------------------
559{
560 nsresult rv = mOutBuffer.Init(segmentSize, maxBufSize);
561 if (NS_SUCCEEDED(rv))
562 mGotBuffers = PR_TRUE;
563
564 return rv;
565}
566
567// external callers of Flush will have sync get called,
568// but internal callers just want to flush the buffers to disk.
569nsresult FileImpl::InternalFlush(PRBool syncFile)
570{
571#ifdef XP_MAC
572 if (mFileDesc == PR_STDOUT || mFileDesc == PR_STDERR)
573 {
574 std::cout.flush();
575 return NS_OK;
576 }
577#endif
578 if (!mFileDesc)
579 return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
580
581 PRInt32 segCount = mOutBuffer.GetSegmentCount();
582 PRUint32 segSize = mOutBuffer.GetSegmentSize();
583
584 for (PRInt32 i = 0; i < segCount; i++)
585 {
586 char* seg = mOutBuffer.GetSegment(i);
587
588 // if it is the last buffer, it may not be completely full.
589 if(i == (segCount-1))
590 segSize = (mWriteCursor - seg);
591
592 PRInt32 bytesWrit = PR_Write(mFileDesc, seg, segSize);
593 if (bytesWrit != (PRInt32)segSize)
594 {
595 mFailed = PR_TRUE;
596 return NS_FILE_RESULT(PR_GetError());
597 }
598 }
599
600 if (mGotBuffers)
601 mOutBuffer.Empty();
602 mWriteCursor = nsnull;
603 mWriteLimit = nsnull;
604
605 // On unix, it seems to fail always.
606 if (syncFile && PR_Sync(mFileDesc) != PR_SUCCESS)
607 mFailed = PR_TRUE;
608
609 return NS_OK;
610}
611//----------------------------------------------------------------------------------------
612nsresult NS_NewTypicalInputFileStream(
613 nsISupports** aResult,
614 const nsFileSpec& inFile
615 /*Default nsprMode == PR_RDONLY*/
616 /*Default accessmode = 0666 (octal)*/)
617// Factory method to get an nsInputStream from a file, using most common options
618//----------------------------------------------------------------------------------------
619{
620 // This QueryInterface was needed because NS_NewIOFileStream
621 // does a cast from (void *) to (nsISupports *) thus causing a
622 // vtable problem on Windows, where we really didn't have the proper pointer
623 // to an nsIInputStream, this ensures that we do
624 nsISupports * supports;
625 nsIInputStream * inStr;
626
627 nsresult rv = NS_NewIOFileStream(&supports, inFile, PR_RDONLY, 0666);
628
629 *aResult = nsnull;
630 if (NS_SUCCEEDED(rv)) {
631 if (NS_SUCCEEDED(supports->QueryInterface(NS_GET_IID(nsIInputStream), (void**)&inStr))) {
632 *aResult = inStr;
633 }
634 NS_RELEASE(supports);
635 }
636 return rv;
637}
638
639//----------------------------------------------------------------------------------------
640nsresult NS_NewTypicalOutputFileStream(
641 nsISupports** aResult,
642 const nsFileSpec& inFile
643 /*default nsprMode= (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/
644 /*Default accessMode= 0666 (octal)*/)
645// Factory method to get an nsOutputStream to a file - most common case.
646//----------------------------------------------------------------------------------------
647{
648 // This QueryInterface was needed because NS_NewIOFileStream
649 // does a cast from (void *) to (nsISupports *) thus causing a
650 // vtable problem on Windows, where we really didn't have the proper pointer
651 // to an nsIOutputStream, this ensures that we do
652#if 1
653/* nsISupports * supports;
654 nsIOutputStream * outStr;
655
656 nsresult rv = NS_NewIOFileStream(
657 &supports,
658 inFile,
659 (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE),
660 0666);
661
662 *aResult = nsnull;
663 if (NS_SUCCEEDED(rv)) {
664 if (NS_SUCCEEDED(supports->QueryInterface(NS_GET_IID(nsIOutputStream), (void**)&outStr))) {
665 *aResult = outStr;
666 }
667 NS_RELEASE(supports);
668 }
669 return rv;
670 */
671
672 nsCOMPtr<nsISupports> supports;
673 nsIOutputStream * outStr;
674
675 nsresult rv = NS_NewIOFileStream(
676 getter_AddRefs(supports),
677 inFile,
678 (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE),
679 0666);
680
681 *aResult = nsnull;
682 if (NS_SUCCEEDED(rv)) {
683 if (NS_SUCCEEDED(supports->QueryInterface(NS_GET_IID(nsIOutputStream), (void**)&outStr))) {
684 *aResult = outStr;
685 }
686 }
687 return rv;
688#else
689 return NS_NewIOFileStream(
690 aResult,
691 inFile,
692 (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE),
693 0666);
694#endif
695}
696
697//----------------------------------------------------------------------------------------
698NS_COM_OBSOLETE nsresult NS_NewIOFileStream(
699 nsISupports** aResult,
700 const nsFileSpec& inFile,
701 PRInt32 nsprMode /*default = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/,
702 PRInt32 accessMode /*Default = 0666 (octal)*/)
703 // Factory method to get an object that implements both nsIInputStream
704 // and nsIOutputStream, associated with a file.
705//----------------------------------------------------------------------------------------
706{
707 NS_PRECONDITION(aResult != nsnull, "null ptr");
708 if (!aResult)
709 return NS_ERROR_NULL_POINTER;
710
711 FileImpl* stream = new FileImpl(inFile, nsprMode, accessMode);
712 if (! stream)
713 return NS_ERROR_OUT_OF_MEMORY;
714
715 NS_ADDREF(stream);
716 PRBool isOpened = PR_FALSE;
717 stream->GetIsOpen(&isOpened);
718 if (!isOpened)
719 {
720 NS_RELEASE(stream);
721 return NS_ERROR_FAILURE;
722 }
723
724 *aResult = (nsISupports*)(void*)stream;
725 return NS_OK;
726}
727
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use