Microsoft-3D-Movie-Maker/kauai/SRC/FILEMAC.CPP
2022-05-03 16:31:19 -07:00

274 lines
6.1 KiB
C++

/* Copyright (c) Microsoft Corporation.
Licensed under the MIT License. */
/***************************************************************************
Author: ShonK
Project: Kauai
Reviewed:
Copyright (c) Microsoft Corporation
File management.
***************************************************************************/
#include "util.h"
#include <script.h>
ASSERTNAME
/***************************************************************************
Open or create the file. If the file is already open, sets the
permissions according to grffil. Note that the ffilDenyRead and
ffilDenyWrite do not work as in Windows. Effectively, this routine
picks one of the following combinations:
ffilWriteEnable | ffilDenyRead | ffilDenyWrite
ffilDenyWrite
***************************************************************************/
bool FIL::_FOpen(bool fCreate, ulong grffil)
{
AssertBaseThis(0);
AssertPo(&_fni, ffniFile);
short fref;
if (_el != elNil)
goto LFail;
//we just care about the permissions
if (grffil & ffilWriteEnable)
grffil = ffilWriteEnable | ffilDenyRead | ffilDenyWrite;
else
grffil = ffilDenyWrite;
//create the file if we need to
if (fCreate)
{
Assert(!_fOpen, "Creating an open file");
short cact, err;
for (cact = 0; ; cact++)
{
if ((err = FSpCreate(&_fni._fss, vftgCreator,
_fni._ftg, smSystemScript)) == noErr)
{
break;
}
if (cact > 0 || err != dupFNErr || FSpDelete(&_fni._fss) != noErr)
goto LFail;
}
}
else if (_fOpen && (~_grffil & grffil) == 0)
{
//permissions are already set high enough
return fTrue;
}
if (noErr != FSpOpenDF(&_fni._fss,
(grffil & ffilWriteEnable) ? fsRdWrPerm : fsRdPerm, &fref))
{
LFail:
if (!_fOpen)
_el = kelCritical;
return fFalse;
}
if (_fOpen && _fref != fref)
FSClose(_fref);
_fref = fref;
_fOpen = fTrue;
_grffil = _grffil & ~kgrffilPerm | grffil;
return fTrue;
}
/***************************************************************************
Close the file.
***************************************************************************/
void FIL::_Close(void)
{
AssertBaseThis(0);
if (_fOpen)
{
FSClose(_fref);
if (_fWrote)
FlushVol(pvNil, _fni._fss.vRefNum);
_fOpen = fFalse;
_fref = 0;
if (_grffil & ffilTemp)
FSpDelete(&_fni._fss);
}
_el = elNil;
}
/***************************************************************************
Flush the file (and its volume?).
***************************************************************************/
void FIL::Flush(void)
{
AssertThis(0);
FlushVol(pvNil, _fni._fss.vRefNum);
}
/***************************************************************************
Seek to the given fp.
***************************************************************************/
void FIL::_SetFpPos(FP fp)
{
AssertThis(0);
if (_el < kelSeek && SetFPos(_fref, fsFromStart, fp) != noErr)
{
_el = kelSeek;
PushErc(ercFileGeneral);
}
}
/***************************************************************************
Set the length of the file.
***************************************************************************/
bool FIL::FSetFpMac(FP fp)
{
AssertThis(0);
AssertIn(fp, 0, kcbMax);
if (_el >= kelWrite)
return fFalse;
_fWrote = fTrue;
Assert(_grffil & ffilWriteEnable, "file not open for write");
if (SetEOF(_fref, fp) != noErr)
{
_el = kelWrite;
PushErc(ercFileGeneral);
return fFalse;
}
return fTrue;
}
/***************************************************************************
Return the length of the file.
***************************************************************************/
FP FIL::FpMac(void)
{
AssertThis(0);
FP fp;
if (_el < kelSeek && GetEOF(_fref, &fp) != noErr)
{
_el = kelSeek;
PushErc(ercFileGeneral);
}
return _el < kelSeek ? fp : 0;
}
/***************************************************************************
Read a block from the file.
***************************************************************************/
bool FIL::FReadRgb(void *pv, long cb, FP fp)
{
AssertThis(0);
AssertIn(cb, 0, kcbMax);
AssertIn(fp, 0, klwMax);
AssertPvCb(pv, cb);
Debug( FP dfp = FpMac() - fp; )
_SetFpPos(fp);
if (_el >= kelRead)
return fFalse;
Assert(dfp >= cb, "read past EOF");
if (cb > 0 && FSRead(_fref, &cb, pv) != noErr)
{
_el = kelRead;
PushErc(ercFileGeneral);
return fFalse;
}
return fTrue;
}
/***************************************************************************
Write a block to the file.
***************************************************************************/
bool FIL::FWriteRgb(void *pv, long cb, FP fp)
{
AssertThis(0);
AssertIn(cb, 0, kcbMax);
AssertIn(fp, 0, klwMax);
AssertPvCb(pv, cb);
_SetFpPos(fp);
if (_el >= kelWrite)
return fFalse;
Assert(_grffil & ffilWriteEnable, "file not open for write");
_fWrote = fTrue;
if (cb > 0 && FSWrite(_fref, &cb, pv) != noErr)
{
_el = kelWrite;
PushErc(ercFileGeneral);
return fFalse;
}
return fTrue;
}
/***************************************************************************
Swap the names of the two files. They should be in the same directory.
***************************************************************************/
bool FIL::FSwapNames(PFIL pfil)
{
AssertThis(0);
AssertPo(pfil, 0);
FNI fni;
if (_el != elNil || pfil->_el != elNil)
return fFalse;
Assert(_fni.FSameDir(&pfil->_fni),
"trying to change directories with FSwapNames");
// swap the data
if (FSpExchangeFiles(&_fni._fss, &pfil->_fni._fss) != noErr)
{
PushErc(ercFileSwapNames);
return fFalse;
}
// swap the fni's
fni = _fni;
_fni = pfil->_fni;
pfil->_fni = fni;
AssertThis(0);
AssertPo(pfil, 0);
return fTrue;
}
/***************************************************************************
Rename the file.
***************************************************************************/
bool FIL::FRename(FNI *pfni)
{
AssertThis(0);
AssertPo(pfni, ffniFile);
if (_el != elNil)
return fFalse;
Assert(_fni.FSameDir(pfni), "trying to change directories with FRename");
if (FSpRename(&_fni._fss, pfni->_fss.name) != noErr)
{
PushErc(ercFileRename);
return fFalse;
}
CopySt((achar *)pfni->_fss.name, (achar *)_fni._fss.name);
AssertThis(0);
return fTrue;
}