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.
 
 
 
 
 
 

291 lines
11 KiB

#ifndef STFILE_INCLUDED
#define STFILE_INCLUDED
/* Must include slm.h, sys.h, and util.h first. */
/*
Status File
The status file is a binary record of the state of just one directory of
a project. Each directory is world unto itself, having all the necessary
information to operate on that directory as well as synchronize with the
master version of the same directory.
The format of the status file is:
sh
rgfi[sh.ifiMac] (at sh.posRgfi)
rged[sh.iedMac] (at sh.posRged)
rgfs[sh.ifiMac] (one for each ed; at rged[ied].posRgfs)
The rgfi and rgfs are in the same order; that is, there is a one to one
relationship between an ifi and an ifs; thus, the information in rgfi[ifi]
pertains to the same file as rged[ied].rgfs[ifi] (you get the picture). The
rgfi is sorted according to the file name (case insensitive for DOS).
When a file is deleted, we simply mark it deleted in the fs and set the
fDeleted bit in the fi. Later we may reuse the fi for a new file, shifting
the fi (and fs) about to make room if neccessary. This means that once an fi
(and the corresponding fs) is added, the contents are always valid!
When a directory is deleted, we actually remove the ed and shift up the
remainder.
A word on fm. Fm fall in exactly three class and transitions are well
defined:
1. IN - fmIn, fmCopyIn, fmAdd, fmGhost; the file is checked in for
the ed and should be read only for the user. In the cases
of fmAdd and fmGhost, there is no local copy of the file.
BI is nil.
2. OUT - fmOut, fmMerge, fmVerify; the file is checked out for the ed
and there may be a BI.
3. DELETED - fmNonExistent, fmDelIn, fmDelOut
the file is either non-existent or on its way to being so.
Locking
SLM currently accesses a status file in three different ways:
"read entire file, write nothing"
- commands like status which merely display information.
"read entire file, write a single ed's information"
- concurrent ssync; multiple executing SLMs can concurrently modify
their ed's fields.
"read entire file, write entire file"
- commands like in which may modify any other ed's information.
These following locking levels correspond to these types of access:
lckNil - no locking in effect.
lckEd - locking on a per-ed basis.
lckAll - entire file locked.
This locking variable is stored in the sh.lck field of the status file header.
These fields are also used for locking:
sh.fAdminLock - locked by the project administrator.
sh.nmLocker - (for lckAll or fAdminLock) the nm of the
user who has the status file locked.
rged[].fLocked - (for lckEd access) fTrue if this ed is locked.
When a user loads the status file with FLoadStatus, he specifies the type of
locking to apply to the file. FLoadStatus compares the current locking level
to the desired level and determines whether or not to grant the lock:
Current Desired lock:
sh.lck: lckNil lckEd lckAll
lckNil OK,- OK,lckEd OK,lckAll
lckEd OK,- OK,- (if this ED is DENIED,-
not already locked)
lckAll OK,- DENIED,- DENIED,-
(pairs are (OK/DENIED, new lck), '-' means no change.)
In addition, a lock will not be granted if fAdminLock unless the nmInvoker
matches the sh.nmLocker.
When FlushStatus is run, it takes different actions depending upon the
current in-memory sh.lck:
lckNil none.
lckEd write [ied,rgfs] record to a temporary file with mode
mmInstall1Ed.
lckAll set sh.lck to lckNil and write the entire status file with
mode mmInstall.
It is only when the script is run that the status file locking actually
changes. The possible script actions are
mmInstall1Ed Open, lockfile status file. Read sh and rged. Read ied and
rgfs from temporary file. Write rgfs. Clear rged[ied].fLocked.
Write rged[ied]. If no rged[].fLocked, clear sh.lck and write
sh. Unlock and close status file. Delete temporary file.
mmInstall Rename old status file to status.bak, rename new file to
status.slm.
Finally, the following actions are taken if AbortStatus is called:
lckNil none.
lckEd Open, lockfile status file. Read sh and rged. Clear
rged[ied].fLocked. Write rged[ied]. If no rged[].fLocked,
clear sh.lck and write sh. Unlock and close status file.
lckAll Open and lockfile status file, read sh, sh.lck to lckNil, clear
nmLocker (if !sh.fAdminLock), write sh, unlock and close file.
status file.
*/
typedef short LCK;
#define lckNil (LCK)0
#define lckEd (LCK)1
#define lckAll (LCK)2
#define lckMax (LCK)3
/* Load status flags */
typedef unsigned short LS;
#define flsNone 0 /* Do nothing special. */
#define flsJustFi (1<<0) /* Just load SH and FI. */
#define flsJustEd (1<<1) /* Just load SH and ED. */
#define flsExtraEd (1<<2) /* Make space for an extra ED. */
#define FlsFromCfiAdd(cfi) ((cfi) << 3) /* Make space for cfiAdd extra FI. */
#define CfiAddOfLs(ls) ((ls) >> 3) /* Extra cfiAdd from LS. */
/* max 2^15-1 enlisted directories */
typedef unsigned short IED;
typedef unsigned short IED2; /* for SLMCK version 2 status file */
#define iedMax ((IED)32767)
#define iedNil ((IED)-1)
typedef unsigned short IFS;
typedef unsigned short IFS2; /* for SLMCK version 2 status file */
typedef unsigned short IFI;
typedef unsigned short IFI2; /* for SLMCK version 2 status file */
#define ifiNil ((IFI)-1)
/* File Mode */
typedef unsigned short FM;
#define fmMin (FM)0
#define fmNonExistent (FM)0 /* fs unused */
#define fmIn (FM)1 /* file checked in */
#define fmOut (FM)2 /* file checked out */
#define fmAdd (FM)3 /* file to be added -> fmIn */
#define fmDelIn (FM)4 /* to be deleted (was in) -> fmNonExistent */
#define fmDelOut (FM)5 /* to be deleted (was out) -> fmNonExistent */
#define fmCopyIn (FM)6 /* new copy of file needed -> fmIn */
#define fmMerge (FM)7 /* merge with src directory -> fmOut */
#define fmVerify (FM)10 /* was merged; need verification -> fmOut */
#define fmConflict (FM)11 /* merged, conflicted; needs repair -> fmOut */
#define fmGhost (FM)12 /* ghosted, not copied locally */
#define fmMax 13
#define fmNil fmMax
#define FValidFm(fm) (((fm) <= fmMerge) || \
((fm) >= fmVerify && (fm) < fmMax))
extern char const * mpfmsz[];
/* BI - Base Id: unique number for producing the name of baseline files.
Base files are named:
$sroot/etc/$proj/$subdir/B<unique>
*/
typedef unsigned short BI;
#define biNil 4095
#define biMin 0
/* File kinds */
typedef unsigned short FK; /* file kind */
#define fkNil (FK)0 /* bad fk */
#define fkMin (FK)1
#define fkDir (FK)1 /* directory */
#define fkText (FK)2 /* ordinary text file */
#define fkAscii (FK)3 /* NYI future enhancement */
#define fkWord (FK)4 /* NYI future enhancement */
#define fkBinary (FK)5 /* backed up binary file */
#define fkUnrec (FK)6 /* not backed up file */
#define fkVersion (FK)7 /* automatically updated version.h */
#define fkObject (FK)8 /* NYI future enhancement */
#define fkUnicode (FK)9 /* Unicode text file */
#define fkUserMin (FK)16 /* NYI future enhancement */
#define fkMax (FK)26
extern char const * mpfksz[];
/* Status Header */
typedef struct
{
short magic;
short version;
IFI ifiMac; /* same as ifsMac */
IED iedMac; /* # of enlisted directories */
PV pv; /* project version */
BIT fRelease:1; /* true if project just released? */
BIT fAdminLock:1; /* locked by sadmin lock */
BIT fRobust:1; /* robust status file data checking */
BITS rgfSpare:13; /* remaining bits in word */
LCK lck; /* current locking level */
NM nmLocker[cchUserMax];/* name of locker */
short wSpare; /* was diNext */
BI biNext; /* next bi for base files */
PTH pthSSubDir[cchPthMax]; /* system project subdirectory */
short rgwSpare[4]; /* spare */
} SH;
/* fTrue if the status header lock information is consistent. */
#define FShLockInvariants(psh) \
((psh)->lck >= lckNil && (psh)->lck < lckMax && \
(!FEmptyNm((psh)->nmLocker) == (psh->lck == lckAll || psh->fAdminLock)))
/* File Information; sorted by name; max. 3276 in 64K */
typedef struct
{
NM nmFile[cchFileMax]; /* name of file */
FV fv; /* file version */
BITS fk:5; /* file kind */
BIT fDeleted:1; /* true if the file is not used. */
BIT fMarked:1; /* marked for processing (only in memory) */
BITS rgfSpare:9; /* spare */
BITS wSpare:16;
} FI;
/* Enlisted Directory; max. 574 in 64K */
typedef struct
{
PTH pthEd[cchPthMax]; /* path to user's root directory */
NM nmOwner[cchUserMax]; /* user who enlisted the directory */
BIT fLocked:1; /* ed is locked */
BIT fNewVer:1; /* ed is has new local version checked out */
BIT fFreeEd:1; /* ed is free and can be reused by enlist */
BITS rgfSpare:13;
BITS wSpare:16;
} ED;
#define FIsFreeEdValid(psh) ((psh)->version > VERSION_NO_FREE_ED)
/* File Status; rgfs same size and order as rgfi */
typedef struct
{
BITS fm:4; /* in, out, etc. */
BITS bi:12; /* saved base file or biNil */
FV fv;
} FS;
/* Positions of various structures in the status file. */
#define PosSh() (POS)0
#define PosRgfi(psh) ((long)sizeof(SH))
#define PosRged(psh) (PosRgfi(psh) + (long)(psh)->ifiMac * sizeof(FI))
#define PosEd(psh,ied) (PosRged(psh) + (long)(ied) * sizeof(ED))
#define PosRgrgfs(psh) (PosRged(psh) + (long)(psh)->iedMac * sizeof(ED))
#define PosRgfsIed(psh,ied) \
(PosRgrgfs(psh) + (long)(ied) * (psh)->ifiMac * sizeof(FS))
extern PTH pthStFile[];
extern PTH pthStBak[];
extern PTH pthUpdSlm[];
BOOL fSetTime;
#endif