Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

387 lines
11 KiB

#include "precomp.h"
#pragma hdrstop
EnableAssert
private void TidyBase(P1(AD *));
private void TidyFi(P1(AD *));
private void SortEd(P1(AD *));
private void CheckEd(P1(AD *));
F FTidyInit(pad)
AD *pad;
{
if (pad->flags&flagTidyCheckEd && !(pad->flags&(flagAll|flagRecursive)))
{
Error("-c should be specified with -a or -r\n");
return fFalse;
}
if (pad->flags&flagAll || pad->pecmd->gl&fglAll)
CreatePeekThread(pad);
Unreferenced(pad);
return fTrue;
}
F FTidyDir(pad)
AD *pad;
{
if (!FLoadStatus(pad, lckAll, flsNone))
return fFalse;
if (fVerbose)
PrErr("Tidy %&P/C\n", pad);
TidyBase(pad);
TidyFi(pad);
if (!FIsFreeEdValid(pad->psh)) {
SortEd(pad);
}
if (pad->flags&flagTidyCheckEd)
CheckEd(pad);
OpenLog(pad, fTrue);
AppendLog(pad, (FI far *)0, (char *)0, pad->szComment);
CloseLog();
FlushStatus(pad);
return fTrue;
}
private void TidyBase(pad)
/* This function removes unreferenced base files */
AD *pad;
{
char *pch;
short fFound;
int bi; // needs to be int to pass to PchGetW
IED ied;
FS far *rgfs;
register IFS ifs;
IFS ifsMac = pad->psh->ifiMac;
DE de;
FA fa;
char szFile[cchFileMax + 1];
PTH pthDir[cchPthMax], pthT[cchPthMax];
if (fVerbose)
PrErr("Removing unreferenced base files\n");
OpenDir(&de, SzPrint(pthDir, szEtcPZ, pad, (char *)NULL), faFiles);
while (FGetDirSz(&de, szFile, &fa) && *szFile == 'B')
{
pch = szFile + 1;
pch = PchGetW(pch, &bi);
/* check for legal file name */
if (szFile[0] == 'B' && *pch == '\0')
{
/* look for bi in rgfs */
fFound = fFalse;
for (ied = 0; !fFound && ied < pad->psh->iedMac; ied++)
{
rgfs = pad->mpiedrgfs[ied];
for (ifs = 0; ifs < ifsMac; ifs++)
{
if ((int)rgfs[ifs].bi == bi && rgfs[ifs].fm == fmMerge)
{
fFound = fTrue;
break;
}
}
}
if (!fFound)
/* remove file */
UnlinkPth(PthForBase(pad, bi, pthT), fxGlobal);
}
}
CloseDir(&de);
}
void TidyFi(pad)
/* This function will remove all FI for all files (not dirs) which are
* deleted. If someone is not ssynced it says who, and asks if it should
* delete anyway.
*/
AD *pad;
{
IFI ifi;
IED ied, iedMac = pad->psh->iedMac;
FI far *pfi;
char *sz = "N";
if (fVerbose)
PrErr("Compacting status file by removing unused file slots\n");
for (ifi = 0; ifi < pad->psh->ifiMac; ifi++)
{
pfi = pad->rgfi + ifi;
if (pfi->fDeleted && pfi->fk != fkDir)
{
int fUnSync = fFalse;
for (ied = 0; ied < iedMac; ied++)
{
if (PfsForPfi(pad, ied, pfi)->fm != fmNonExistent)
{
if (!fUnSync)
{
PrErr("The following directories are not in sync with %&C/F:\n", pad, pfi);
fUnSync = fTrue;
}
PrErr("\t%&E\n", pad, ied);
}
}
if (!fUnSync ||
(FCanPrompt() &&
(*(sz=SzQuery("Delete anyway (Y or N; ? = list again; CR = stop)? ")) == 'y' || *sz == 'Y')))
{
PurgeFi(pad, ifi);
ifi--; /* counteract next ++ */
}
else if (*sz == '?')
ifi--; /* to display the same one again */
else if (*sz == '\0')
/* user typed CR to prompt */
break;
}
}
}
void PurgeFi(AD *pad, IFI ifiToGo)
/* Remove indicated FI, and log removal */
{
IFI ifi, ifiMac = pad->psh->ifiMac;
IED ied, iedMac = pad->psh->iedMac;
FI far *rgfi = pad->rgfi;
FS far * far *mpiedrgfs = pad->mpiedrgfs;
char szComment[150];
AssertLoaded(pad);
SzPrint(szComment, "Removed file %&F", pad, rgfi + ifiToGo);
if (fVerbose)
PrErr("%s from %&P/C\n", szComment, pad);
pad->psh->ifiMac--;
for (ifi = ifiToGo; ifi < (IFI)(ifiMac-1); ifi++)
{
rgfi[ifi] = rgfi[ifi + 1];
for (ied = 0; ied < iedMac; ied++)
mpiedrgfs[ied][ifi] = mpiedrgfs[ied][ifi + 1];
}
/* write out to log */
OpenLog(pad, fTrue);
AppendLog(pad, (FI far *)0, (char *)0, szComment);
CloseLog();
}
private int CmpEd(P2(ED far *, ED far *));
private int CmpEd(ped1, ped2)
/* Return -1,0,1 if *ped1 <,=,> *ped2, where directories are ordered
* by nmOwner then by pthEd.
*/
ED far *ped1;
ED far *ped2;
{
int wCmp = NmCmpi(ped1->nmOwner, ped2->nmOwner, cchUserMax);
return (wCmp != 0) ? wCmp : NmCmpi(ped1->pthEd, ped2->pthEd, cchPthMax);
}
private void SortEd(pad)
/* use insertion sort to sort the ED by owner from:
page 65 of "Writing Efficient Programs," by Jon Bentley.
changed to used pointers and 0 based arrays. Mpiedrgfs array is sorted
sympathetically.
Why? I'm sure it ran quickly enough before, and would have been
a lot more readable! -Jan
*/
AD *pad;
{
register ED far *pedI;
register FS far * far *prgfsI;
FS far * far *prgfsJ, far *rgfsT;
ED far *pedJ, edT;
ED far *rged, far *pedMac;
if (fVerbose)
PrErr("Sorting ED\n");
AssertLoaded(pad);
rged = pad->rged;
pedMac = rged + pad->psh->iedMac;
for (pedI = &rged[1], prgfsI = &pad->mpiedrgfs[1]; pedI < pedMac; pedI++, prgfsI++)
{
pedJ = pedI;
prgfsJ = prgfsI;
edT = *pedJ;
rgfsT = *prgfsJ;
while (pedJ > rged && CmpEd(&edT, pedJ-1) < 0)
{
*pedJ = *(pedJ-1);
*prgfsJ = *(prgfsJ-1);
pedJ--;
prgfsJ--;
}
*pedJ = edT;
*prgfsJ = rgfsT;
}
}
static ED far *rgedPar = 0; /* parent directory's rged */
static IED iedParMac = 0; /* parent directory's ied. */
private void CheckEd(pad)
/* Check that subdirectories' rged conform to their parents'.
*
* The first time this routine is called, it saves a copy of the current
* directories' rged. Subsequent calls check the subdirectory's rged against
* the saved copy.
*/
AD *pad;
{
IED iedPar;
IED ied;
IED iedMac;
AssertLoaded(pad);
if (!rgedPar)
{
if (fVerbose)
PrErr("Checking ed (saving ed in %&P/C)\n", pad);
iedParMac = pad->psh->iedMac;
rgedPar = (ED far *)LpbAllocCb(sizeof(ED) * iedParMac, fFalse);
for (iedPar = 0; iedPar < iedParMac; iedPar++)
rgedPar[iedPar] = pad->rged[iedPar];
return;
}
if (fVerbose)
PrErr("Checking ed in %&P/C\n", pad);
/* Merge rgedPar and pad->rged together, discarding duplicates. */
ied = 0;
iedMac = pad->psh->iedMac;
iedPar = 0;
while (ied < iedMac || iedPar < iedParMac)
{
int wCmp; /* -1 if ed, 1 if edPar */
if (!(ied < iedMac))
wCmp = 1;
else if (!(iedPar < iedParMac))
wCmp = -1;
else
wCmp = CmpEd(pad->rged + ied, rgedPar + iedPar);
if (wCmp < 0)
PrErr("%&P/C extra ED (nmOwner=%&O, pthEd=%&E)\n",
pad, pad, ied, pad, ied);
else if (wCmp > 0)
{
char szOwner[cchUserMax + 1];
char szPthEd[cchPthMax + 1];
SzCopyNm(szOwner, rgedPar[iedPar].nmOwner, cchUserMax);
SzCopyNm(szPthEd, rgedPar[iedPar].pthEd, cchPthMax);
Error("%&P/C missing ED (nmOwner=%s, pthEd=%s)\n",
pad, szOwner, szPthEd);
}
ied += wCmp <= 0;
iedPar += wCmp >= 0;
}
}
private void LowerPth(P1(PTH far *));
private void LowerLpch(P2(char far *, int));
F FLowerInit(pad)
AD *pad;
{
if (pad->flags&flagAll || pad->pecmd->gl&fglAll)
CreatePeekThread(pad);
return fTrue;
}
F FLowerDir(pad)
/* Convert all paths and names in this dir's status file to lower case */
AD *pad;
{
IFI ifi, ifiMac;
IED ied, iedMac;
if (!FLoadStatus(pad, lckAll, flsNone))
return fFalse;
if (fVerbose)
PrErr("Change %&P/C to lowercase\n", pad);
for (ifi = 0, ifiMac = pad->psh->ifiMac; ifi < ifiMac; ifi++)
LowerLpch(pad->rgfi[ifi].nmFile, cchFileMax);
for (ied = 0, iedMac = pad->psh->iedMac; ied < iedMac; ied++) {
if (!FIsFreeEdValid(pad->psh) || !pad->rged[ied].fFreeEd) {
LowerPth(pad->rged[ied].pthEd);
LowerLpch(pad->rged[ied].nmOwner, cchUserMax);
}
}
/* Leave a log entry */
OpenLog(pad, fTrue);
AppendLog(pad, (FI far *)0, (char *)0, pad->szComment);
CloseLog();
FlushStatus(pad);
return fTrue;
}
private void LowerPth(pth)
/* converts pth to lower case */
PTH far *pth;
{
while (*pth)
{
if (isupper(*pth))
*pth = (PTH)tolower(*pth);
pth++;
}
}
private void LowerLpch(lpch, cchMac)
char far *lpch;
register int cchMac;
{
while (cchMac--)
{
if (isupper(*lpch))
*lpch = (char)tolower(*lpch);
++lpch;
}
}