DIRECTORY
BasicTime USING [GMT, nullGMT],
File USING [Error, FP, GetProperties, Handle, PropertyStorage, RC, WriteProperties],
FSBackdoor USING [ProduceError, Version],
FSFileOps,
FSReport USING [FileError],
GVBasics USING [MakeKey, Password],
PrincOps USING [ByteBltBlock],
PrincOpsUtils USING [ByteBlt],
Rope USING [Length, NewText, ROPE, Text];
FSPropertiesImpl:
CEDAR
MONITOR
IMPORTS File, FSBackdoor, FSReport, GVBasics, PrincOpsUtils, Rope
EXPORTS FSFileOps
= BEGIN
PropertiesObject:
TYPE =
RECORD [
validation: GVBasics.Password,
bytes: INT,
keep: CARDINAL,
created: BasicTime.GMT,
version: FSBackdoor.Version,
nameBody: TextRep];
TextRep:
TYPE =
RECORD[length:
CARDINAL, chars:
PACKED
ARRAY [0 .. 0)
OF
CHARACTER];
Properties: TYPE = LONG POINTER TO PropertiesObject;
Exported to FSFileOps
GetProps:
PUBLIC
PROC [f: File.Handle]
RETURNS [bytes:
INT, keep:
CARDINAL, created: BasicTime.
GMT] =
BEGIN
InnerGet:
ENTRY
PROC =
TRUSTED
BEGIN ENABLE UNWIND => NULL;
pPtr: Properties = LOOPHOLE[File.GetProperties[f], Properties];
IF pPtr.validation = validation
THEN
BEGIN
bytes ← pPtr.bytes;
keep ← pPtr.keep;
created ← pPtr.created;
END
ELSE invalidPP ← TRUE; -- invalid property page
END;
fileRC: File.RC ← ok;
invalidPP: BOOLEAN ← FALSE;
InnerGet[ ! File.Error => {fileRC ← why; CONTINUE} ];
IF invalidPP THEN InvalidPropertyPage[];
IF fileRC # ok THEN FSReport.FileError[fileRC];
END;
GetNameBodyAndVersion:
PUBLIC
PROC [f: File.Handle]
RETURNS [nameBody: Rope.Text, version: FSBackdoor.Version] =
BEGIN
InnerGetNameBodyAndVersion:
ENTRY
PROC =
TRUSTED
BEGIN ENABLE UNWIND => NULL;
pPtr: Properties = LOOPHOLE[File.GetProperties[f], Properties];
IF pPtr.validation = validation
THEN
BEGIN
nameBody ← GetText[@pPtr.nameBody];
version ← pPtr.version;
END
ELSE invalidPP ← TRUE; -- invalid property page
END;
fileRC: File.RC ← ok;
invalidPP: BOOLEAN ← FALSE;
InnerGetNameBodyAndVersion[
! File.Error => {fileRC ← why; CONTINUE} ];
IF invalidPP THEN InvalidPropertyPage[];
IF fileRC # ok THEN FSReport.FileError[fileRC];
END;
InitializePropertyStorage:
PUBLIC
PROC [fp: File.
FP, propStorage: File.PropertyStorage] =
TRUSTED
{ LOOPHOLE[propStorage, Properties].validation ← validation };
SetProps:
PUBLIC
PROC [f: File.Handle, bytes:
INT, keep:
CARDINAL, created: BasicTime.
GMT, nameBody: Rope.Text, version: FSBackdoor.Version] =
BEGIN
InnerSet:
ENTRY
PROC =
TRUSTED
BEGIN ENABLE UNWIND => NULL;
pPtr: Properties = LOOPHOLE[File.GetProperties[f], Properties];
IF pPtr.validation = validation
THEN
BEGIN
IF bytes # -1 THEN pPtr.bytes ← bytes;
pPtr.keep ← keep;
IF created # BasicTime.nullGMT THEN pPtr.created ← created;
pPtr.version ← version;
PutText[nameBody, @(pPtr.nameBody)];
File.WriteProperties[f];
END
ELSE invalidPP ← TRUE; -- invalid property page here is a bug
END;
fileRC: File.RC ← ok;
invalidPP: BOOLEAN ← FALSE;
InnerSet[ ! File.Error => {fileRC ← why; CONTINUE} ];
IF invalidPP THEN ERROR;
IF fileRC # ok THEN FSReport.FileError[fileRC];
END;
SetBytesAndCreated:
PUBLIC
PROC [f: File.Handle, bytes:
INT, created: BasicTime.
GMT] =
BEGIN
InnerSetBytesAndCreated:
ENTRY
PROC =
TRUSTED
BEGIN ENABLE UNWIND => NULL;
pPtr: Properties = LOOPHOLE[File.GetProperties[f], Properties];
IF pPtr.validation = validation
THEN
BEGIN
IF bytes # -1 THEN pPtr.bytes ← bytes;
IF created # BasicTime.nullGMT THEN pPtr.created ← created;
File.WriteProperties[f];
END
ELSE invalidPP ← TRUE; -- invalid property page
END;
fileRC: File.RC ← ok;
invalidPP: BOOLEAN ← FALSE;
InnerSetBytesAndCreated[ ! File.Error => {fileRC ← why; CONTINUE} ];
IF invalidPP THEN InvalidPropertyPage[];
IF fileRC # ok THEN FSReport.FileError[fileRC];
END;
SetKeep:
PUBLIC
PROC [f: File.Handle, keep:
CARDINAL] =
BEGIN
InnerSetKeep:
ENTRY
PROC =
TRUSTED
BEGIN ENABLE UNWIND => NULL;
pPtr: Properties = LOOPHOLE[File.GetProperties[f], Properties];
IF pPtr.validation = validation
THEN
BEGIN
pPtr.keep ← keep;
File.WriteProperties[f];
END
ELSE invalidPP ← TRUE; -- invalid property page
END;
fileRC: File.RC ← ok;
invalidPP: BOOLEAN ← FALSE;
InnerSetKeep[ ! File.Error => {fileRC ← why; CONTINUE} ];
IF invalidPP THEN InvalidPropertyPage[];
IF fileRC # ok THEN FSReport.FileError[fileRC];
END;
Validation stuff for leader pages; changing the stamp will require all nucleus volumes to be erased.
validation: GVBasics.Password ← ALL[0];
ComputeValidation:
PROC =
BEGIN
stamp: Rope.ROPE = "August 19, 1983 1:16 pm"; -- DON'T CHANGE THIS!!! --
validation ← GVBasics.MakeKey[stamp];
END;