2020-09-30 17:12:29 +02:00

565 lines
12 KiB
C

/* sadmin dump utilities */
#include "precomp.h"
#pragma hdrstop
EnableAssert
/*** DUMP ***/
F
FDumpInit(
AD *pad
)
{
Unreferenced(pad);
if (pad->sz != NULL)
ValidateFileName(pad->sz, TRUE);
return fTrue;
}
private void PrWMf(MF *, char *, int);
private void PrNmMf(MF *, char *, NM far *, int);
F
FDumpDir(
AD *pad
)
{
MF *pmf;
IFI ifi;
IED ied;
register SH far *psh;
FI far *pfi;
ED far *ped;
FS far *pfs;
PTH pth[cchPthMax];
char szFile[cchFileMax + 1];
if (!FLoadStatus(pad, lckNil, flsNone))
return fFalse;
if (!FInitScript(pad, lckNil))
{
AbortStatus();
return fFalse;
}
if (fVerbose)
PrErr("dump %&P/C:\n", pad);
pmf = pad->sz ? PmfCreate(SzPrint(pth, "%&/U/Q/Z", pad, pad->sz),
permRW, fTrue, fxLocal) : &mfStdout;
PrMf(pmf, ";Dump of %&S/etc/P/C/status.slm on %s\n", pad,
SzTime(time((long *)0)));
psh = pad->psh;
PrWMf (pmf, "magic", psh->magic);
PrWMf (pmf, "version", psh->version);
PrWMf (pmf, "ifiMac", psh->ifiMac);
PrWMf (pmf, "iedMac", psh->iedMac);
PrMf (pmf, "%d %d %d\t; pv\n", psh->pv.rmj, psh->pv.rmm, psh->pv.rup);
PrNmMf(pmf, "pv.szName", psh->pv.szName, cchPvNameMax);
PrWMf (pmf, "fRelease", psh->fRelease);
PrWMf (pmf, "fAdminLock", psh->fAdminLock);
PrWMf (pmf, "fRobust", psh->fRobust);
PrWMf (pmf, "rgfSpare", psh->rgfSpare);
PrWMf (pmf, "lck", psh->lck);
PrNmMf(pmf, "nmLocker", psh->nmLocker, cchUserMax);
PrWMf (pmf, "wSpare", psh->wSpare);
PrWMf (pmf, "biNext", psh->biNext);
PrNmMf(pmf, "pthSSubDir", psh->pthSSubDir, cchPthMax);
PrMf (pmf, "%u %u %u %u\t; rgwSpare\n",
psh->rgwSpare[0], psh->rgwSpare[1],
psh->rgwSpare[2], psh->rgwSpare[3]);
PrMf(pmf, "\n;nmFile fv fk fD fM fS wSpare\n");
for (ifi = 0; ifi < psh->ifiMac; ifi++)
{
pfi = pad->rgfi + ifi;
SzCopyNm(szFile, pfi->nmFile, cchFileMax);
PrMf(pmf, "%-14s %5d %2d %1d %1d %1d %5u\n",
szFile, pfi->fv, pfi->fk, pfi->fDeleted,
pfi->fMarked, pfi->rgfSpare, pfi->wSpare);
}
for (ied = 0; ied < psh->iedMac; ied++)
{
ped = pad->rged + ied;
PrMf (pmf, "\n");
PrNmMf(pmf, "pthEd", ped->pthEd, cchPthMax);
PrNmMf(pmf, "nmOwner", ped->nmOwner, cchUserMax);
PrWMf (pmf, "fLocked", ped->fLocked);
PrWMf (pmf, "fNewVer", ped->fNewVer);
PrWMf (pmf, "wSpare", ped->wSpare);
if (FIsFreeEdValid(pad->psh))
PrWMf (pmf, "fFreeEd", ped->fFreeEd);
PrMf(pmf, ";fm fv bi (nmFile)\n");
for (ifi = 0; ifi < psh->ifiMac; ifi++)
{
pfi = pad->rgfi + ifi;
pfs = PfsForPfi(pad, ied, pfi);
PrMf(pmf, " %2d %5u %5u ; %&F\n",
pfs->fm, pfs->fv, pfs->bi, pad, pfi);
}
}
PrMf(pmf, "\n");
if (pmf != &mfStdout)
CloseMf(pmf);
FlushStatus(pad);
return fTrue;
}
private void
PrWMf(
MF *pmf,
char *szName,
int w
)
{
PrMf(pmf, "%7u\t; %s\n", w, szName);
}
private void
PrNmMf(
MF *pmf,
char *szName,
NM far *nm,
int cchMax
)
{
char szBuf[100];
AssertF(sizeof szBuf > cchMax);
SzCopyNm(szBuf, nm, cchMax);
PrMf(pmf, "%s\t; %s\n", szBuf, szName);
}
/*** UNDUMP ***/
private F FUndSh(SH *psh);
private void InitGet(PTH *);
private void FinishGet(void);
private void ErrorGet(char *);
private F FGetW(short *, F);
private F FGetNm(char *, int, F);
private F FGetEOF(void);
F FUndInit(pad)
AD *pad;
{
Unreferenced(pad);
return FCanQuery("status file not undumped\n") &&
FQueryUser("DANGER! Undump will destroy the existing status file.\n\
DANGER! If you don't know what you are doing, you may corrupt your project.\n\
DANGER! Are you sure you want to go through with this? ");
}
F
FUndDir(
AD *pad
)
{
PTH pth[cchPthMax];
SH sh;
FI fi;
ED ed;
FS fs;
IFI ifi;
IED ied;
InitGet(SzPrint(pth, "%&/U/Q/Z", pad, pad->sz));
ClearPbCb(&sh, sizeof(SH));
if (!FUndSh(&sh))
{
ErrorGet("reading status header");
return fFalse;
}
if ((pad->psh = PshAlloc(fFalse)) == 0)
return fFalse;
*pad->psh = sh;
pad->cfiAdd = 0;
pad->fExtraEd = fFalse;
pad->iedCur = iedNil;
if (!FAllocStatus(pad))
{
FreeStatus(pad);
return fFalse;
}
/* Load rgfi */
for (ifi = 0; ifi < sh.ifiMac; ifi++)
{
short fk;
short fDeleted;
short fMarked;
short fSpare;
short wSpare;
if (!(FGetNm(fi.nmFile, cchFileMax, fFalse) &&
FGetW(&fi.fv, fFalse) &&
FGetW(&fk, fFalse) &&
FGetW(&fDeleted, fFalse) && FIsF(fDeleted) &&
FGetW(&fMarked, fFalse) && FIsF(fMarked) &&
FGetW(&fSpare, fFalse) &&
FGetW(&wSpare, fTrue)))
{
ErrorGet("reading file info");
FreeStatus(pad);
return fFalse;
}
fi.fk = fk;
fi.fDeleted = fDeleted;
fi.fMarked = fMarked;
fi.rgfSpare = fSpare;
fi.wSpare = wSpare;
pad->rgfi[ifi] = fi;
}
/* Load rg(ed with rgfs) */
for (ied = 0; ied < sh.iedMac; ied++)
{
short fLocked;
short fNewVer;
short wSpare;
short fFreeEd;
if (!(FGetNm(ed.pthEd, cchPthMax, fTrue) &&
FGetNm(ed.nmOwner, cchUserMax, fFalse) &&
FGetW(&fLocked, fFalse) && FIsF(fLocked) &&
FGetW(&fNewVer, fFalse) && FIsF(fNewVer) &&
FGetW(&wSpare, fFalse) &&
(!FIsFreeEdValid(pad->psh) || (FGetW(&fFreeEd, fTrue) && FIsF(fFreeEd)))))
{
ErrorGet("reading enlisted directory info");
FreeStatus(pad);
return fFalse;
}
ed.fLocked = fLocked;
ed.fNewVer = fNewVer;
ed.rgfSpare = 0;
ed.wSpare = wSpare;
if (FIsFreeEdValid(pad->psh))
ed.fFreeEd = fFreeEd;
else
ed.fFreeEd = fFalse;
pad->rged[ied] = ed;
for (ifi = 0; ifi < sh.ifiMac; ifi++)
{
short fm;
short bi;
short fv;
if (!(FGetW(&fm, fFalse) && FValidFm(fm) &&
FGetW(&fv, fFalse) &&
FGetW(&bi, fTrue)))
{
ErrorGet("reading file status");
FreeStatus(pad);
return fFalse;
}
fs.fm = fm;
fs.bi = bi;
fs.fv = fv;
pad->mpiedrgfs[ied][ifi] = fs;
}
}
if (!FGetEOF())
{
ErrorGet("expecting EOF");
FreeStatus(pad);
return fTrue;
}
FinishGet();
if (fVerbose)
PrErr("undump %&P/C\n", pad);
/* Now pretend we had loaded this status file so we can write it
* back out.
*/
if (!FInitScript(pad, lckAll))
{
AbortStatus();
return fFalse;
}
/* Leave a log entry. */
OpenLog(pad, fTrue);
AppendLog(pad, (FI far *)0, (char *)0, pad->szComment);
CloseLog();
pad->fWLock = fTrue;
pad->psh->lck = lckAll;
NmCopySz(pad->psh->nmLocker, pad->nmInvoker, cchUserMax);
FlushStatus(pad);
return fTrue;
}
/* Undump the SH. The XENIX/68K C compiler couldn't stomach it as one
* big expression so we break it up into pieces.
*/
private F
FUndSh(
register SH *psh
)
{
short w;
short fRelease;
short fAdminLock;
short fRobust;
short rgfSpare;
short lck;
if (!(FGetW(&psh->magic, fTrue) && psh->magic == MAGIC &&
FGetW(&psh->version, fTrue) &&
(psh->version >= VERSION_COMPAT_MAC && psh->version <= VERSION) &&
FGetW((short *)&psh->ifiMac, fTrue) &&
FGetW((short *)&psh->iedMac, fTrue) &&
FGetW(&psh->pv.rmj, fFalse) &&
FGetW(&psh->pv.rmm, fFalse) &&
FGetW(&psh->pv.rup, fTrue) &&
(psh->pv.szName[cchPvNameMax] = 0,
FGetNm(psh->pv.szName, cchPvNameMax, fTrue))))
return fFalse;
if (!(FGetW(&fRelease, fTrue) && FIsF(fRelease) &&
FGetW(&fAdminLock, fTrue) && FIsF(fAdminLock) &&
FGetW(&fRobust, fTrue) && FIsF(fRobust) &&
FGetW(&rgfSpare, fTrue) &&
FGetW(&lck, fTrue) &&
lck >= lckNil && lck < lckMax &&
FGetNm(psh->nmLocker, cchUserMax, fTrue) &&
FGetW(&psh->wSpare, fTrue) &&
FGetW(&w, fTrue) &&
(psh->biNext = w, FGetNm(psh->pthSSubDir, cchPthMax, fTrue)) &&
FGetW(&psh->rgwSpare[0], fFalse) &&
FGetW(&psh->rgwSpare[1], fFalse) &&
FGetW(&psh->rgwSpare[2], fFalse) &&
FGetW(&psh->rgwSpare[3], fTrue)))
return fFalse;
psh->fRelease = fRelease;
psh->fAdminLock = fAdminLock;
psh->fRobust = fRobust;
psh->rgfSpare = rgfSpare;
psh->lck = lck;
return fTrue;
}
static int cLines;
static MF *pmfGet;
/* toy stdio to avoid a read system call per character */
static struct
{
int ich;
int ichMac;
char rgch[512];
} buf;
private void
InitGet(
PTH *pth
)
{
cLines = 1;
pmfGet = PmfOpen(pth, omAReadOnly, fxNil);
buf.ich = buf.ichMac = 0;
}
private void
FinishGet()
{
if (pmfGet)
CloseMf(pmfGet);
pmfGet = 0;
cLines = 0;
buf.ich = buf.ichMac = 0;
}
private void
ErrorGet(
char *szErr
)
{
Error("error %s near line %d\n", szErr, cLines);
FinishGet();
}
private char ChGetRaw(void);
private char ChGet(void);
private char ChGetNextNonWhite(void);
private void FlushLine(void);
private char
ChGetRaw()
{
if (buf.ich == buf.ichMac)
{
/* buffer empty */
buf.ich = 0;
buf.ichMac = CbReadMf(pmfGet, (char far *)buf.rgch, sizeof buf.rgch);
if (buf.ichMac == 0)
return 0;
}
return buf.rgch[buf.ich++];
}
private char
ChGet()
{
char ch;
ch = ChGetRaw();
while (ch == '\r')
ch = ChGetRaw();
if (ch == ';')
{
while ((ch = ChGetRaw()) != '\n' && ch != 0)
;
}
if (ch == '\n')
cLines++;
if (ch == '\\')
ch = '/';
return ch;
}
#define FWhiteCh(ch) ((ch) == ' ' || (ch) == '\t' || ch == '\n')
#define FDigitCh(ch) ((ch) >= '0' && (ch) <= '9')
private char
ChGetNextNonWhite()
{
char ch;
while (ch = ChGet(), FWhiteCh(ch))
;
return ch;
}
private void
FlushLine()
{
char ch;
while ((ch = ChGet()) != '\n' && ch != 0)
;
}
private F
FGetW(
short *pw,
F fFlushLine
)
{
char ch;
char rgch[20];
int ich;
int w;
if ((ch = ChGetNextNonWhite()) == 0)
return fFalse;
rgch[0] = ch;
for (ich = 1; ich < sizeof(rgch) && (ch = ChGet(), FDigitCh(ch)); ich++)
rgch[ich] = ch;
if (ich == sizeof(rgch) || (rgch[ich] = 0, *PchGetW(rgch, &w) != 0))
return fFalse;
*pw = w;
if (fFlushLine && ch != '\n')
FlushLine();
return fTrue;
}
/* (Always called on a new line), this function returns the first whitespace
* terminated string in nm.
*/
private F
FGetNm(
NM *nm,
int inmMax,
F fFlushLine
)
{
int inm;
char ch;
/* Skip over empty lines. */
while ((ch = ChGet()) == '\n')
;
/* Read characters up to next white space. */
inm = 0;
if (!FWhiteCh(ch))
{
nm[0] = ch;
for (inm = 1; inm < inmMax && (ch = ChGet()) != 0 &&
!FWhiteCh(ch); inm++)
nm[inm] = ch;
}
/* Zero rest of nm. */
for ( ; inm < inmMax; inm++)
nm[inm] = 0;
if (fFlushLine && ch != '\n')
FlushLine();
return fTrue;
}
private F
FGetEOF()
{
return ChGetNextNonWhite() == 0;
}