Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / db / mork / src / morkFile.cpp
blob011056fa81baf10cc48225b78ab035f88ec34590
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
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/
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.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1999
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #ifndef _MDB_
39 #include "mdb.h"
40 #endif
42 #ifndef _MORK_
43 #include "mork.h"
44 #endif
46 #ifndef _MORKNODE_
47 #include "morkNode.h"
48 #endif
50 #ifndef _MORKENV_
51 #include "morkEnv.h"
52 #endif
54 #ifndef _MORKFILE_
55 #include "morkFile.h"
56 #endif
58 #ifdef MORK_WIN
59 #include "io.h"
60 #include <windows.h>
61 #endif
63 // #define MORK_CONFIG_USE_ORKINFILE 1
65 #ifdef MORK_CONFIG_USE_ORKINFILE
66 #ifndef _ORKINFILE_
67 #include "orkinFile.h"
68 #endif
69 #endif /*MORK_CONFIG_USE_ORKINFILE*/
71 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
74 // ````` ````` ````` ````` `````
75 // { ===== begin morkNode interface =====
77 /*public virtual*/ void
78 morkFile::CloseMorkNode(morkEnv* ev) // CloseFile() only if open
80 if ( this->IsOpenNode() )
82 this->MarkClosing();
83 this->CloseFile(ev);
84 this->MarkShut();
88 /*public virtual*/
89 morkFile::~morkFile() // assert CloseFile() executed earlier
91 MORK_ASSERT(mFile_Frozen==0);
92 MORK_ASSERT(mFile_DoTrace==0);
93 MORK_ASSERT(mFile_IoOpen==0);
94 MORK_ASSERT(mFile_Active==0);
97 /*public non-poly*/
98 morkFile::morkFile(morkEnv* ev, const morkUsage& inUsage,
99 nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
100 : morkObject(ev, inUsage, ioHeap, morkColor_kNone, (morkHandle*) 0)
101 , mFile_Frozen( 0 )
102 , mFile_DoTrace( 0 )
103 , mFile_IoOpen( 0 )
104 , mFile_Active( 0 )
106 , mFile_SlotHeap( 0 )
107 , mFile_Name( 0 )
108 , mFile_Thief( 0 )
110 if ( ev->Good() )
112 if ( ioSlotHeap )
114 nsIMdbHeap_SlotStrongHeap(ioSlotHeap, ev, &mFile_SlotHeap);
115 if ( ev->Good() )
116 mNode_Derived = morkDerived_kFile;
118 else
119 ev->NilPointerError();
123 NS_IMPL_ISUPPORTS_INHERITED1(morkFile, morkObject, nsIMdbFile)
124 /*public non-poly*/ void
125 morkFile::CloseFile(morkEnv* ev) // called by CloseMorkNode();
127 if ( this )
129 if ( this->IsNode() )
131 mFile_Frozen = 0;
132 mFile_DoTrace = 0;
133 mFile_IoOpen = 0;
134 mFile_Active = 0;
136 if ( mFile_Name )
137 this->SetFileName(ev, (const char*) 0);
139 nsIMdbHeap_SlotStrongHeap((nsIMdbHeap*) 0, ev, &mFile_SlotHeap);
140 nsIMdbFile_SlotStrongFile((nsIMdbFile*) 0, ev, &mFile_Thief);
142 this->MarkShut();
144 else
145 this->NonNodeError(ev);
147 else
148 ev->NilPointerError();
151 // } ===== end morkNode methods =====
152 // ````` ````` ````` ````` `````
154 nsIMdbFile*
155 morkFile::AcquireFileHandle(morkEnv* ev)
157 nsIMdbFile* outFile = 0;
159 #ifdef MORK_CONFIG_USE_ORKINFILE
160 return this;
161 #endif /*MORK_CONFIG_USE_ORKINFILE*/
162 MORK_USED_1(ev);
164 return outFile;
167 /*static*/ morkFile*
168 morkFile::OpenOldFile(morkEnv* ev, nsIMdbHeap* ioHeap,
169 const char* inFilePath, mork_bool inFrozen)
170 // Choose some subclass of morkFile to instantiate, in order to read
171 // (and write if not frozen) the file known by inFilePath. The file
172 // returned should be open and ready for use, and presumably positioned
173 // at the first byte position of the file. The exact manner in which
174 // files must be opened is considered a subclass specific detail, and
175 // other portions or Mork source code don't want to know how it's done.
177 return morkStdioFile::OpenOldStdioFile(ev, ioHeap, inFilePath, inFrozen);
180 /*static*/ morkFile*
181 morkFile::CreateNewFile(morkEnv* ev, nsIMdbHeap* ioHeap,
182 const char* inFilePath)
183 // Choose some subclass of morkFile to instantiate, in order to read
184 // (and write if not frozen) the file known by inFilePath. The file
185 // returned should be created and ready for use, and presumably positioned
186 // at the first byte position of the file. The exact manner in which
187 // files must be opened is considered a subclass specific detail, and
188 // other portions or Mork source code don't want to know how it's done.
190 return morkStdioFile::CreateNewStdioFile(ev, ioHeap, inFilePath);
193 void
194 morkFile::NewMissingIoError(morkEnv* ev) const
196 ev->NewError("file missing io");
199 /*static*/ void
200 morkFile::NonFileTypeError(morkEnv* ev)
202 ev->NewError("non morkFile");
205 /*static*/ void
206 morkFile::NilSlotHeapError(morkEnv* ev)
208 ev->NewError("nil mFile_SlotHeap");
211 /*static*/ void
212 morkFile::NilFileNameError(morkEnv* ev)
214 ev->NewError("nil mFile_Name");
217 void
218 morkFile::SetThief(morkEnv* ev, nsIMdbFile* ioThief)
220 nsIMdbFile_SlotStrongFile(ioThief, ev, &mFile_Thief);
223 void
224 morkFile::SetFileName(morkEnv* ev, const char* inName) // inName can be nil
226 nsIMdbHeap* heap = mFile_SlotHeap;
227 if ( heap )
229 char* name = mFile_Name;
230 if ( name )
232 mFile_Name = 0;
233 ev->FreeString(heap, name);
235 if ( ev->Good() && inName )
236 mFile_Name = ev->CopyString(heap, inName);
238 else
239 this->NilSlotHeapError(ev);
242 void
243 morkFile::NewFileDownError(morkEnv* ev) const
244 // call NewFileDownError() when either IsOpenAndActiveFile()
245 // is false, or when IsOpenActiveAndMutableFile() is false.
247 if ( this->IsOpenNode() )
249 if ( this->FileActive() )
251 if ( this->FileFrozen() )
253 ev->NewError("file frozen");
255 else
256 ev->NewError("unknown file problem");
258 else
259 ev->NewError("file not active");
261 else
262 ev->NewError("file not open");
265 void
266 morkFile::NewFileErrnoError(morkEnv* ev) const
267 // call NewFileErrnoError() to convert std C errno into AB fault
269 const char* errnoString = strerror(errno);
270 ev->NewError(errnoString); // maybe pass value of strerror() instead
273 // ````` ````` ````` ````` newlines ````` ````` ````` `````
275 #if defined(MORK_MAC)
276 static const char morkFile_kNewlines[] =
277 "\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015";
278 # define morkFile_kNewlinesCount 16
279 #else
280 # if defined(MORK_WIN) || defined(MORK_OS2)
281 static const char morkFile_kNewlines[] =
282 "\015\012\015\012\015\012\015\012\015\012\015\012\015\012\015\012";
283 # define morkFile_kNewlinesCount 8
284 # else
285 # if defined(MORK_UNIX) || defined(MORK_BEOS)
286 static const char morkFile_kNewlines[] =
287 "\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012";
288 # define morkFile_kNewlinesCount 16
289 # endif /* MORK_UNIX || MORK_BEOS */
290 # endif /* MORK_WIN */
291 #endif /* MORK_MAC */
293 mork_size
294 morkFile::WriteNewlines(morkEnv* ev, mork_count inNewlines)
295 // WriteNewlines() returns the number of bytes written.
297 mork_size outSize = 0;
298 while ( inNewlines && ev->Good() ) // more newlines to write?
300 mork_u4 quantum = inNewlines;
301 if ( quantum > morkFile_kNewlinesCount )
302 quantum = morkFile_kNewlinesCount;
304 mork_size quantumSize = quantum * mork_kNewlineSize;
305 mdb_size bytesWritten;
306 this->Write(ev->AsMdbEnv(), morkFile_kNewlines, quantumSize, &bytesWritten);
307 outSize += quantumSize;
308 inNewlines -= quantum;
310 return outSize;
313 NS_IMETHODIMP
314 morkFile::Eof(nsIMdbEnv* mev, mdb_pos* outPos)
316 mdb_err outErr = 0;
317 mdb_pos pos = -1;
318 morkEnv *ev = morkEnv::FromMdbEnv(mev);
319 pos = Length(ev);
320 outErr = ev->AsErr();
321 if ( outPos )
322 *outPos = pos;
323 return outErr;
326 NS_IMETHODIMP
327 morkFile::Get(nsIMdbEnv* mev, void* outBuf, mdb_size inSize,
328 mdb_pos inPos, mdb_size* outActualSize)
330 nsresult rv = NS_OK;
331 morkEnv *ev = morkEnv::FromMdbEnv(mev);
332 if ( ev )
334 mdb_pos outPos;
335 Seek(mev, inPos, &outPos);
336 if ( ev->Good() )
337 rv = Read(mev, outBuf, inSize, outActualSize);
339 return rv;
342 NS_IMETHODIMP
343 morkFile::Put(nsIMdbEnv* mev, const void* inBuf, mdb_size inSize,
344 mdb_pos inPos, mdb_size* outActualSize)
346 mdb_err outErr = 0;
347 *outActualSize = 0;
348 morkEnv *ev = morkEnv::FromMdbEnv(mev);
349 if ( ev )
351 mdb_pos outPos;
353 Seek(mev, inPos, &outPos);
354 if ( ev->Good() )
355 Write(mev, inBuf, inSize, outActualSize);
356 outErr = ev->AsErr();
358 return outErr;
361 // { ----- begin path methods -----
362 NS_IMETHODIMP
363 morkFile::Path(nsIMdbEnv* mev, mdbYarn* outFilePath)
365 mdb_err outErr = 0;
366 if ( outFilePath )
367 outFilePath->mYarn_Fill = 0;
368 morkEnv *ev = morkEnv::FromMdbEnv(mev);
369 if ( ev )
371 ev->StringToYarn(GetFileNameString(), outFilePath);
372 outErr = ev->AsErr();
374 return outErr;
377 // } ----- end path methods -----
379 // { ----- begin replacement methods -----
382 NS_IMETHODIMP
383 morkFile::Thief(nsIMdbEnv* mev, nsIMdbFile** acqThief)
385 mdb_err outErr = 0;
386 nsIMdbFile* outThief = 0;
387 morkEnv *ev = morkEnv::FromMdbEnv(mev);
388 if ( ev )
390 outThief = GetThief();
391 NS_IF_ADDREF(outThief);
392 outErr = ev->AsErr();
394 if ( acqThief )
395 *acqThief = outThief;
396 return outErr;
399 // } ----- end replacement methods -----
401 // { ----- begin versioning methods -----
403 // ````` ````` ````` ````` `````
404 // { ===== begin morkNode interface =====
406 /*public virtual*/ void
407 morkStdioFile::CloseMorkNode(morkEnv* ev) // CloseStdioFile() only if open
409 if ( this->IsOpenNode() )
411 this->MarkClosing();
412 this->CloseStdioFile(ev);
413 this->MarkShut();
417 /*public virtual*/
418 morkStdioFile::~morkStdioFile() // assert CloseStdioFile() executed earlier
420 if (mStdioFile_File)
421 CloseStdioFile(mMorkEnv);
422 MORK_ASSERT(mStdioFile_File==0);
425 /*public non-poly*/ void
426 morkStdioFile::CloseStdioFile(morkEnv* ev) // called by CloseMorkNode();
428 if ( this )
430 if ( this->IsNode() )
432 if ( mStdioFile_File && this->FileActive() && this->FileIoOpen() )
434 this->CloseStdio(ev);
437 mStdioFile_File = 0;
439 this->CloseFile(ev);
440 this->MarkShut();
442 else
443 this->NonNodeError(ev);
445 else
446 ev->NilPointerError();
449 // } ===== end morkNode methods =====
450 // ````` ````` ````` ````` `````
452 // compatible with the morkFile::MakeFile() entry point
454 /*static*/ morkStdioFile*
455 morkStdioFile::OpenOldStdioFile(morkEnv* ev, nsIMdbHeap* ioHeap,
456 const char* inFilePath, mork_bool inFrozen)
458 morkStdioFile* outFile = 0;
459 if ( ioHeap && inFilePath )
461 const char* mode = (inFrozen)? "rb" : "rb+";
462 outFile = new(*ioHeap, ev)
463 morkStdioFile(ev, morkUsage::kHeap, ioHeap, ioHeap, inFilePath, mode);
465 if ( outFile )
467 outFile->SetFileFrozen(inFrozen);
470 else
471 ev->NilPointerError();
473 return outFile;
476 /*static*/ morkStdioFile*
477 morkStdioFile::CreateNewStdioFile(morkEnv* ev, nsIMdbHeap* ioHeap,
478 const char* inFilePath)
480 morkStdioFile* outFile = 0;
481 if ( ioHeap && inFilePath )
483 const char* mode = "wb+";
484 outFile = new(*ioHeap, ev)
485 morkStdioFile(ev, morkUsage::kHeap, ioHeap, ioHeap, inFilePath, mode);
487 else
488 ev->NilPointerError();
490 return outFile;
495 NS_IMETHODIMP
496 morkStdioFile::BecomeTrunk(nsIMdbEnv* ev)
497 // If this file is a file version branch created by calling AcquireBud(),
498 // BecomeTrunk() causes this file's content to replace the original
499 // file's content, typically by assuming the original file's identity.
501 return Flush(ev);
504 NS_IMETHODIMP
505 morkStdioFile::AcquireBud(nsIMdbEnv * mdbev, nsIMdbHeap* ioHeap, nsIMdbFile **acquiredFile)
506 // AcquireBud() starts a new "branch" version of the file, empty of content,
507 // so that a new version of the file can be written. This new file
508 // can later be told to BecomeTrunk() the original file, so the branch
509 // created by budding the file will replace the original file. Some
510 // file subclasses might initially take the unsafe but expedient
511 // approach of simply truncating this file down to zero length, and
512 // then returning the same morkFile pointer as this, with an extra
513 // reference count increment. Note that the caller of AcquireBud() is
514 // expected to eventually call CutStrongRef() on the returned file
515 // in order to release the strong reference. High quality versions
516 // of morkFile subclasses will create entirely new files which later
517 // are renamed to become the old file, so that better transactional
518 // behavior is exhibited by the file, so crashes protect old files.
519 // Note that AcquireBud() is an illegal operation on readonly files.
521 NS_ENSURE_ARG(acquiredFile);
522 MORK_USED_1(ioHeap);
523 nsresult rv = NS_OK;
524 morkFile* outFile = 0;
525 morkEnv *ev = morkEnv::FromMdbEnv(mdbev);
527 if ( this->IsOpenAndActiveFile() )
529 FILE* file = (FILE*) mStdioFile_File;
530 if ( file )
532 //#ifdef MORK_WIN
533 // truncate(file, /*eof*/ 0);
534 //#else /*MORK_WIN*/
535 char* name = mFile_Name;
536 if ( name )
538 if ( MORK_FILECLOSE(file) >= 0 )
540 this->SetFileActive(morkBool_kFalse);
541 this->SetFileIoOpen(morkBool_kFalse);
542 mStdioFile_File = 0;
544 file = MORK_FILEOPEN(name, "wb+"); // open for write, discarding old content
545 if ( file )
547 mStdioFile_File = file;
548 this->SetFileActive(morkBool_kTrue);
549 this->SetFileIoOpen(morkBool_kTrue);
550 this->SetFileFrozen(morkBool_kFalse);
552 else
553 this->new_stdio_file_fault(ev);
555 else
556 this->new_stdio_file_fault(ev);
558 else
559 this->NilFileNameError(ev);
561 //#endif /*MORK_WIN*/
563 if ( ev->Good() && this->AddStrongRef(ev->AsMdbEnv()) )
565 outFile = this;
566 AddRef();
569 else if ( mFile_Thief )
571 rv = mFile_Thief->AcquireBud(ev->AsMdbEnv(), ioHeap, acquiredFile);
573 else
574 this->NewMissingIoError(ev);
576 else this->NewFileDownError(ev);
578 *acquiredFile = outFile;
579 return rv;
582 mork_pos
583 morkStdioFile::Length(morkEnv * ev) const
585 mork_pos outPos = 0;
587 if ( this->IsOpenAndActiveFile() )
589 FILE* file = (FILE*) mStdioFile_File;
590 if ( file )
592 long start = MORK_FILETELL(file);
593 if ( start >= 0 )
595 long fore = MORK_FILESEEK(file, 0, SEEK_END);
596 if ( fore >= 0 )
598 long eof = MORK_FILETELL(file);
599 if ( eof >= 0 )
601 long back = MORK_FILESEEK(file, start, SEEK_SET);
602 if ( back >= 0 )
603 outPos = eof;
604 else
605 this->new_stdio_file_fault(ev);
607 else this->new_stdio_file_fault(ev);
609 else this->new_stdio_file_fault(ev);
611 else this->new_stdio_file_fault(ev);
613 else if ( mFile_Thief )
614 mFile_Thief->Eof(ev->AsMdbEnv(), &outPos);
615 else
616 this->NewMissingIoError(ev);
618 else this->NewFileDownError(ev);
620 return outPos;
623 NS_IMETHODIMP
624 morkStdioFile::Tell(nsIMdbEnv* ev, mork_pos *outPos) const
626 nsresult rv = NS_OK;
627 NS_ENSURE_ARG(outPos);
628 morkEnv* mev = morkEnv::FromMdbEnv(ev);
629 if ( this->IsOpenAndActiveFile() )
631 FILE* file = (FILE*) mStdioFile_File;
632 if ( file )
634 long where = MORK_FILETELL(file);
635 if ( where >= 0 )
636 *outPos = where;
637 else
638 this->new_stdio_file_fault(mev);
640 else if ( mFile_Thief )
641 mFile_Thief->Tell(ev, outPos);
642 else
643 this->NewMissingIoError(mev);
645 else this->NewFileDownError(mev);
647 return rv;
650 NS_IMETHODIMP
651 morkStdioFile::Read(nsIMdbEnv* ev, void* outBuf, mork_size inSize, mork_num *outCount)
653 nsresult rv = NS_OK;
654 morkEnv* mev = morkEnv::FromMdbEnv(ev);
655 if ( this->IsOpenAndActiveFile() )
657 FILE* file = (FILE*) mStdioFile_File;
658 if ( file )
660 long count = (long) MORK_FILEREAD(outBuf, inSize, file);
661 if ( count >= 0 )
663 *outCount = (mork_num) count;
665 else this->new_stdio_file_fault(mev);
667 else if ( mFile_Thief )
668 mFile_Thief->Read(ev, outBuf, inSize, outCount);
669 else
670 this->NewMissingIoError(mev);
672 else this->NewFileDownError(mev);
674 return rv;
677 NS_IMETHODIMP
678 morkStdioFile::Seek(nsIMdbEnv* mdbev, mork_pos inPos, mork_pos *aOutPos)
680 mork_pos outPos = 0;
681 nsresult rv = NS_OK;
682 morkEnv *ev = morkEnv::FromMdbEnv(mdbev);
684 if ( this->IsOpenOrClosingNode() && this->FileActive() )
686 FILE* file = (FILE*) mStdioFile_File;
687 if ( file )
689 long where = MORK_FILESEEK(file, inPos, SEEK_SET);
690 if ( where >= 0 )
691 outPos = inPos;
692 else
693 this->new_stdio_file_fault(ev);
695 else if ( mFile_Thief )
696 mFile_Thief->Seek(mdbev, inPos, aOutPos);
697 else
698 this->NewMissingIoError(ev);
700 else this->NewFileDownError(ev);
702 *aOutPos = outPos;
703 return rv;
706 NS_IMETHODIMP
707 morkStdioFile::Write(nsIMdbEnv* mdbev, const void* inBuf, mork_size inSize, mork_size *aOutSize)
709 mork_num outCount = 0;
710 nsresult rv = NS_OK;
711 morkEnv *ev = morkEnv::FromMdbEnv(mdbev);
712 if ( this->IsOpenActiveAndMutableFile() )
714 FILE* file = (FILE*) mStdioFile_File;
715 if ( file )
717 fwrite(inBuf, 1, inSize, file);
718 if ( !ferror(file) )
719 outCount = inSize;
720 else
721 this->new_stdio_file_fault(ev);
723 else if ( mFile_Thief )
724 mFile_Thief->Write(mdbev, inBuf, inSize, &outCount);
725 else
726 this->NewMissingIoError(ev);
728 else this->NewFileDownError(ev);
730 *aOutSize = outCount;
731 return rv;
734 NS_IMETHODIMP
735 morkStdioFile::Flush(nsIMdbEnv* mdbev)
737 morkEnv *ev = morkEnv::FromMdbEnv(mdbev);
738 if ( this->IsOpenOrClosingNode() && this->FileActive() )
740 FILE* file = (FILE*) mStdioFile_File;
741 if ( file )
743 MORK_FILEFLUSH(file);
746 else if ( mFile_Thief )
747 mFile_Thief->Flush(mdbev);
748 else
749 this->NewMissingIoError(ev);
751 else this->NewFileDownError(ev);
752 return NS_OK;
755 // ````` ````` ````` ````` ````` ````` ````` `````
756 //protected: // protected non-poly morkStdioFile methods
758 void
759 morkStdioFile::new_stdio_file_fault(morkEnv* ev) const
761 FILE* file = (FILE*) mStdioFile_File;
763 int copyErrno = errno; // facilitate seeing error in debugger
765 // bunch of stuff not ported here
766 if ( !copyErrno && file )
768 copyErrno = ferror(file);
769 errno = copyErrno;
772 this->NewFileErrnoError(ev);
775 // ````` ````` ````` ````` ````` ````` ````` `````
776 //public: // public non-poly morkStdioFile methods
779 /*public non-poly*/
780 morkStdioFile::morkStdioFile(morkEnv* ev,
781 const morkUsage& inUsage, nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
782 : morkFile(ev, inUsage, ioHeap, ioSlotHeap)
783 , mStdioFile_File( 0 )
785 if ( ev->Good() )
786 mNode_Derived = morkDerived_kStdioFile;
789 morkStdioFile::morkStdioFile(morkEnv* ev, const morkUsage& inUsage,
790 nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap,
791 const char* inName, const char* inMode)
792 // calls OpenStdio() after construction
793 : morkFile(ev, inUsage, ioHeap, ioSlotHeap)
794 , mStdioFile_File( 0 )
796 if ( ev->Good() )
797 this->OpenStdio(ev, inName, inMode);
800 morkStdioFile::morkStdioFile(morkEnv* ev, const morkUsage& inUsage,
801 nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap,
802 void* ioFile, const char* inName, mork_bool inFrozen)
803 // calls UseStdio() after construction
804 : morkFile(ev, inUsage, ioHeap, ioSlotHeap)
805 , mStdioFile_File( 0 )
807 if ( ev->Good() )
808 this->UseStdio(ev, ioFile, inName, inFrozen);
811 void
812 morkStdioFile::OpenStdio(morkEnv* ev, const char* inName, const char* inMode)
813 // Open a new FILE with name inName, using mode flags from inMode.
815 if ( ev->Good() )
817 if ( !inMode )
818 inMode = "";
820 mork_bool frozen = (*inMode == 'r'); // cursory attempt to note readonly
822 if ( this->IsOpenNode() )
824 if ( !this->FileActive() )
826 this->SetFileIoOpen(morkBool_kFalse);
827 if ( inName && *inName )
829 this->SetFileName(ev, inName);
830 if ( ev->Good() )
832 FILE* file = MORK_FILEOPEN(inName, inMode);
833 if ( file )
835 mStdioFile_File = file;
836 this->SetFileActive(morkBool_kTrue);
837 this->SetFileIoOpen(morkBool_kTrue);
838 this->SetFileFrozen(frozen);
840 else
841 this->new_stdio_file_fault(ev);
844 else ev->NewError("no file name");
846 else ev->NewError("file already active");
848 else this->NewFileDownError(ev);
852 void
853 morkStdioFile::UseStdio(morkEnv* ev, void* ioFile, const char* inName,
854 mork_bool inFrozen)
855 // Use an existing file, like stdin/stdout/stderr, which should not
856 // have the io stream closed when the file is closed. The ioFile
857 // parameter must actually be of type FILE (but we don't want to make
858 // this header file include the stdio.h header file).
860 if ( ev->Good() )
862 if ( this->IsOpenNode() )
864 if ( !this->FileActive() )
866 if ( ioFile )
868 this->SetFileIoOpen(morkBool_kFalse);
869 this->SetFileName(ev, inName);
870 if ( ev->Good() )
872 mStdioFile_File = ioFile;
873 this->SetFileActive(morkBool_kTrue);
874 this->SetFileFrozen(inFrozen);
877 else
878 ev->NilPointerError();
880 else ev->NewError("file already active");
882 else this->NewFileDownError(ev);
886 void
887 morkStdioFile::CloseStdio(morkEnv* ev)
888 // Close the stream io if both and FileActive() and FileIoOpen(), but
889 // this does not close this instances (like CloseStdioFile() does).
890 // If stream io was made active by means of calling UseStdio(),
891 // then this method does little beyond marking the stream inactive
892 // because FileIoOpen() is false.
894 if ( mStdioFile_File && this->FileActive() && this->FileIoOpen() )
896 FILE* file = (FILE*) mStdioFile_File;
897 if ( MORK_FILECLOSE(file) < 0 )
898 this->new_stdio_file_fault(ev);
900 mStdioFile_File = 0;
901 this->SetFileActive(morkBool_kFalse);
902 this->SetFileIoOpen(morkBool_kFalse);
907 NS_IMETHODIMP
908 morkStdioFile::Steal(nsIMdbEnv* ev, nsIMdbFile* ioThief)
909 // If this file is a file version branch created by calling AcquireBud(),
910 // BecomeTrunk() causes this file's content to replace the original
911 // file's content, typically by assuming the original file's identity.
913 morkEnv *mev = morkEnv::FromMdbEnv(ev);
914 if ( mStdioFile_File && FileActive() && FileIoOpen() )
916 FILE* file = (FILE*) mStdioFile_File;
917 if ( MORK_FILECLOSE(file) < 0 )
918 new_stdio_file_fault(mev);
920 mStdioFile_File = 0;
922 SetThief(mev, ioThief);
923 return NS_OK;
927 #if defined(MORK_WIN)
929 void mork_fileflush(FILE * file)
931 fflush(file);
932 #ifndef WINCE
933 OSVERSIONINFOA vi = { sizeof(OSVERSIONINFOA) };
934 if ((GetVersionExA(&vi) && vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS))
936 // Win9x/ME
937 int fd = fileno(file);
938 HANDLE fh = (HANDLE)_get_osfhandle(fd);
939 FlushFileBuffers(fh);
941 #endif
944 #endif /*MORK_WIN*/
947 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789