-- Yodel: File and Owner Property commands
-- Hauser, March 19, 1985 4:42:49 pm PST

-- YodelProperties.mesa
-- Last Edited by: Hagmann, April 4, 1984 4:25:35 pm PST

DIRECTORY
AlpFile,
AlpineEnvironment,
AlpineFile,
AlpineInterimDirectory,
AlpInstance,
AlpTransaction ,
BasicTime,
Buttons,
IO,
Rope,
ViewerClasses,
ViewerTools,
YodelData;

YodelProperties: CEDAR PROGRAM
IMPORTS AlpineInterimDirectory, AlpFile, AlpInstance, AlpTransaction, IO, Rope, ViewerTools, YodelData

EXPORTS YodelData

=

BEGIN OPEN YodelData;




ROPE: TYPE = Rope.ROPE;
accessListToCommaROPE: PROC [ accessList: AlpineEnvironment.AccessList]
RETURNS [resultRope: ROPENIL] = {
IF accessList = NIL THEN resultRope ← Rope.Concat[resultRope,"*none*"]
ELSE {
UNTIL accessList = NIL DO
accessItem: AlpineEnvironment.RName ← accessList.first;
resultRope ← Rope.Concat[resultRope,accessItem];
accessList ← accessList.rest;
IF accessList # NIL THEN resultRope ← Rope.Concat[resultRope,", "];
ENDLOOP;
}
};
ExamineFile: PUBLIC PROC [trans: AlpTransaction.Handle,
server: ROPE, directory: ROPE, file: ROPE,
user: ROPENIL, password: ROPENIL ,
displayProperties: AlpineFile.PropertySet ← AlpineFile.allProperties,
d: MyData]
RETURNS [LIST OF REF ANY] = {
fullFileName: ROPE;
resultList: LIST OF REF ANYNIL;
universalFile: AlpineEnvironment.UniversalFile;
createdFile: BOOLEAN;
properties: LIST OF AlpineEnvironment.PropertyValuePair;
resultRope: ROPENIL;
fileHandle: AlpFile.Handle;
outcome: AlpTransaction.Outcome;
failureName: ROPE ← "" ;
{
ENABLE UNWIND => IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort];
IF trans = NIL THEN GOTO notAlpineFile;
IF d.assertWheel THEN trans.AssertAlpineWheel[TRUE];
fullFileName ← Rope.Concat["[",Rope.Concat[server,Rope.Concat["]",
  Rope.Concat[directory,file]]]];
[universalFile, createdFile] ← AlpineInterimDirectory.OpenUnderTrans[
transHandle: trans,
fileName: fullFileName,
createOptions: oldOnly];
[fileHandle]← AlpFile.Open[transHandle: trans,
universalFile: universalFile,
access: readOnly,
lock: [read, fail]
];
properties ← AlpFile.ReadProperties[handle: fileHandle, lock: [read, fail]
! AlpInstance.LockFailed => GOTO lockError;
];
{
size: INT;
size ← fileHandle.GetSize[];
ViewerTools.SetContents[viewer: d.oSize,
contents: IO.PutFR["%g", IO.int[size]],
paint: FALSE];
};
UNTIL properties = NIL DO
property: AlpineEnvironment.PropertyValuePair ← properties.first ;
properties ← properties.rest;
BEGIN
SELECT property.property FROM
     -- byteLength
byteLength => {
byteLength: INTNARROW[property,
AlpineEnvironment.PropertyValuePair.byteLength].byteLength;
ViewerTools.SetContents[viewer: d.oByteLength,
contents: IO.PutFR["%g", IO.int[byteLength]],
paint: FALSE];
};
     -- createTime
createTime => {
createTime: BasicTime.GMTNARROW[property,
AlpineEnvironment.PropertyValuePair.createTime].createTime;
-- ViewerTools.SetContents[viewer: d.oCreateTime,
-- contents: IO.PutFR["%g", IO.time[createTime]],
-- paint: FALSE];
};
    -- highWaterMark
highWaterMark => {
highWaterMark: AlpineEnvironment.PageCount ← NARROW[property,
AlpineEnvironment.PropertyValuePair.highWaterMark].highWaterMark;
ViewerTools.SetContents[viewer: d.oHighWaterMark,
contents: IO.PutFR["%g", IO.int[highWaterMark]],
paint: FALSE];
};
    -- modifyAccess
modifyAccess => {
modifyAccess: AlpineEnvironment.AccessList ← NARROW[property,
AlpineEnvironment.PropertyValuePair.modifyAccess].modifyAccess;
resultRope ← accessListToCommaROPE[modifyAccess];
ViewerTools.SetContents[viewer: d.oModifyAccess,
contents: resultRope,
paint: FALSE];
};
    -- owner
owner => {
owner: AlpineEnvironment.OwnerName ← NARROW[property,
AlpineEnvironment.PropertyValuePair.owner].owner;
ViewerTools.SetContents[viewer: d.oOwner,
contents: IO.PutFR["%g", IO.rope[owner]],
paint: FALSE];
};
    -- readAccess
readAccess => {
readAccess: AlpineEnvironment.AccessList ← NARROW[property,
AlpineEnvironment.PropertyValuePair.readAccess].readAccess;
resultRope ← accessListToCommaROPE[readAccess] ;
ViewerTools.SetContents[viewer: d.oReadAccess,
contents: resultRope,
paint: FALSE];
};
     -- stringName
stringName => {
stringName: ROPENARROW[property,
AlpineEnvironment.PropertyValuePair.stringName].stringName;
ViewerTools.SetContents[viewer: d.oStringName,
contents: IO.PutFR["%g", IO.rope[stringName]],
paint: FALSE];
};
-- bogus (Well, you see that if you don't use all the
-- variants from
PropertyValuePair somewhere, then
-- the compiler has this fatal error in pass 4.)
     -- version
version => {
version: AlpineEnvironment.FileVersion ← NARROW[property,
AlpineEnvironment.PropertyValuePair.version].version;
-- bogus (Well, you see that if you don't use all the
-- variants from
PropertyValuePair somewhere, then
-- the compiler has this fatal error in pass 4.)

};

ENDCASE;
END;
ENDLOOP;

outcome ← AlpTransaction.Finish[trans, commit];
RETURN [resultList];

EXITS
lockError => {
outcome ← AlpTransaction.Finish[trans, abort];
ViewerTools.SetContents[viewer: d.oByteLength, contents: "", paint: FALSE];
ViewerTools.SetContents[viewer: d.oHighWaterMark, contents: "", paint: FALSE];
ViewerTools.SetContents[viewer: d.oModifyAccess, contents: "", paint: FALSE];
ViewerTools.SetContents[viewer: d.oOwner, contents: "", paint: FALSE];
ViewerTools.SetContents[viewer: d.oReadAccess, contents: "", paint: FALSE];
ViewerTools.SetContents[viewer: d.oStringName, contents: "", paint: FALSE];
RETURN[CONS[
NARROW["lock prevents access to file",ROPE]
,NIL]];
 };
notAlpineFile => {
RETURN[CONS[
NARROW["Cannot Examine a non-Alpine file",ROPE]
,NIL]];
 };
};
};



ExamineProc: PUBLIC Buttons.ButtonProc=
BEGIN
  resultList: LIST OF REF ANYNIL;
  d: MyData = NARROW[clientData];
  p: ViewerClasses.Viewer = NARROW[parent];
  server, user, file, password: ROPE;
  directory, restOfPattern: ROPE;

  callExamine: YodelData.PerformProc = {

RETURN[ExamineFile[trans, server, directory, restOfPattern, user, password,
d.displayProperties, d]];
};


  d.stopFlag ← FALSE;

  [user, password, server, directory, file] ← ParseSArgs[d];

  [directory, restOfPattern] ← DecomposePattern[server: server, pattern: file, user: user];

  d.out.PutF["\nExamine of [%g]%g%g\n",
IO.rope[server], IO.rope[directory], IO.rope[restOfPattern]];
  resultList ← PerformOp[performProc: callExamine,
  server: server, user: user, password: password];
DO
  nowRope: ROPENARROW[IF resultList = NIL THEN NIL ELSE resultList.first];
IF resultList = NIL THEN EXIT;
  resultList ← resultList.rest;
  d.out.PutF[" %g\n", IO.rope[nowRope]];
ENDLOOP;
  CreateButtons[d, p.parent.parent];
END;


getAccessList: PROC [stream: IO.STREAM]
RETURNS [outList: AlpineEnvironment.AccessList ← NIL] = {
UNTIL IO.EndOf[stream] DO {
token: ROPEIO.GetTokenRope[stream, IO.IDProc
! IO.EndOfStream => GOTO endList].token;
IF (token # NIL) AND Rope.Fetch[token] # ', THEN
outList ← CONS[NARROW[token, AlpineEnvironment.RName], outList];
};
ENDLOOP;
EXITS
endList => RETURN;
};


ApplyToFile: PUBLIC PROC [trans: AlpTransaction.Handle,
server: ROPE, directory: ROPE, file: ROPE,
user: ROPENIL, password: ROPENIL ,
displayProperties: AlpineFile.PropertySet ← AlpineFile.allProperties,
d: MyData]
RETURNS [LIST OF REF ANY] = {

fullFileName: ROPE;
resultList: LIST OF REF ANYNIL;
universalFile: AlpineEnvironment.UniversalFile;
createdFile: BOOLEAN;
newProperties: LIST OF AlpineEnvironment.PropertyValuePair ← NIL ;
properties: LIST OF AlpineEnvironment.PropertyValuePair;
resultRope: ROPENIL;
fileHandle: AlpFile.Handle;
fileID: AlpineEnvironment.FileID;
outcome: AlpTransaction.Outcome;
scratchStream: IO.STREAMNIL;
failureName: ROPE ← "" ;
{
ENABLE UNWIND => IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort];
IF trans = NIL THEN GOTO notAlpineFile;
IF d.assertWheel THEN trans.AssertAlpineWheel[TRUE];
fullFileName ← Rope.Concat["[",Rope.Concat[server,Rope.Concat["]",
  Rope.Concat[directory,file]]]];
[universalFile, createdFile] ← AlpineInterimDirectory.OpenUnderTrans[
transHandle: trans,
fileName: fullFileName,
createOptions: oldOnly];
[fileHandle, fileID]← AlpFile.Open[transHandle: trans,
universalFile: universalFile,
access: readWrite,
lock: [write, fail]
];
properties ← AlpFile.ReadProperties[handle: fileHandle, lock: [read, fail]
! AlpInstance.LockFailed => GOTO lockError;
];
{
newSizeRope: ROPE;
newSize: INT;
size: INT;
size ← fileHandle.GetSize[];
newSizeRope ← ViewerTools.GetContents[viewer: d.oSize];
scratchStream ← IO.RIS[newSizeRope, scratchStream];
newSize ← NARROW[IO.GetInt[scratchStream]] ;
-- newSize ← MAX[newSize,size];
fileHandle.SetSize[newSize];
};
UNTIL properties = NIL DO
property: AlpineEnvironment.PropertyValuePair ← properties.first ;
properties ← properties.rest;
BEGIN
SELECT property.property FROM
     -- byteLength
byteLength => {
newByteLengthRope: ROPE;
newByteLength: INT ;
byteLength: INTNARROW[property,
AlpineEnvironment.PropertyValuePair.byteLength].byteLength;
newByteLengthRope ← ViewerTools.GetContents[viewer: d.oByteLength];
scratchStream ← IO.RIS[newByteLengthRope, scratchStream];
newByteLength ← IO.GetInt[scratchStream] ;
newProperties ← CONS[[byteLength[newByteLength]], newProperties];
};
    -- highWaterMark
highWaterMark => {
newHighWaterMark: INT ;
newHighWaterMarkRope: ROPE
ViewerTools.GetContents[viewer: d.oHighWaterMark];
scratchStream ← IO.RIS[newHighWaterMarkRope, scratchStream];
newHighWaterMark ← NARROW[IO.GetInt[scratchStream]] ;
newProperties ← CONS[[highWaterMark[newHighWaterMark]], newProperties];
};
    -- modifyAccess
modifyAccess => {
newModifyAccess: AlpineEnvironment.AccessList ← NIL ;
newModifyAccessRope: ROPE
ViewerTools.GetContents[viewer: d.oModifyAccess];
scratchStream ← IO.RIS[newModifyAccessRope, scratchStream];
newModifyAccess ← getAccessList[scratchStream];
newProperties ← CONS[[modifyAccess[newModifyAccess]], newProperties];
};
    -- owner
owner => {
newOwnerRope: ROPE;
newOwner: ROPE;
newOwnerRope ← ViewerTools.GetContents[viewer: d.oOwner];
newOwner ← NARROW[newOwnerRope];
newProperties ← CONS[[owner[newOwner]], newProperties];
};
    -- readAccess
readAccess => {
newReadAccess: AlpineEnvironment.AccessList ← NIL ;
newReadAccessRope: ROPE
ViewerTools.GetContents[viewer: d.oReadAccess];
scratchStream ← IO.RIS[newReadAccessRope, scratchStream];
newReadAccess ← getAccessList[scratchStream];
newProperties ← CONS[[readAccess[newReadAccess]], newProperties];
};
     -- stringName
stringName => {
newStringName: AlpineEnvironment.String;
newStringNameRope: ROPE
ViewerTools.GetContents[viewer: d.oStringName];
newStringName ← NARROW[newStringNameRope];
newProperties ← CONS[[stringName[newStringName]], newProperties];
};

ENDCASE;
END;
ENDLOOP;
AlpFile.WriteProperties[handle: fileHandle, properties: newProperties,
lock: [read, fail]
! AlpInstance.LockFailed => GOTO lockError;
];

outcome ← AlpTransaction.Finish[trans, commit];
RETURN [resultList];

EXITS
lockError => {
outcome ← AlpTransaction.Finish[trans, abort];
ViewerTools.SetContents[viewer: d.oByteLength, contents: "", paint: FALSE];
ViewerTools.SetContents[viewer: d.oHighWaterMark, contents: "", paint: FALSE];
ViewerTools.SetContents[viewer: d.oModifyAccess, contents: "", paint: FALSE];
ViewerTools.SetContents[viewer: d.oOwner, contents: "", paint: FALSE];
ViewerTools.SetContents[viewer: d.oReadAccess, contents: "", paint: FALSE];
ViewerTools.SetContents[viewer: d.oStringName, contents: "", paint: FALSE];
RETURN[CONS[
NARROW["lock prevents access to file",ROPE]
,NIL]];
 };
notAlpineFile => {
RETURN[CONS[
NARROW["Cannot Apply to a non-Alpine file",ROPE]
,NIL]];
};
};
};



ApplyProc: PUBLIC Buttons.ButtonProc=
BEGIN
  resultList: LIST OF REF ANYNIL;
  d: MyData = NARROW[clientData];
  p: ViewerClasses.Viewer = NARROW[parent];
  server, user, file, password: ROPE;
  directory, restOfPattern: ROPE;

  callApply: YodelData.PerformProc = {

RETURN[ApplyToFile[trans, server, directory, restOfPattern, user, password,
d.displayProperties, d]];
};


  d.stopFlag ← FALSE;

  [user, password, server, directory, file] ← ParseSArgs[d];

  [directory, restOfPattern] ← DecomposePattern[server:server, pattern: file, user: user];

  d.out.PutF["\nApply changes to [%g]%g%g\n",
IO.rope[server], IO.rope[directory], IO.rope[restOfPattern]];
  resultList ← PerformOp[performProc: callApply,
  server: server, user: user, password: password];
DO
  nowRope: ROPENARROW[IF resultList = NIL THEN NIL ELSE resultList.first];
IF resultList = NIL THEN EXIT;
  resultList ← resultList.rest;
  d.out.PutF[" %g\n", IO.rope[nowRope]];
ENDLOOP;
  CreateButtons[d, p.parent.parent];
END;



ReadQuota: PUBLIC PROC [trans: AlpTransaction.Handle,
server: ROPE, directory: ROPE,
user: ROPENIL, password: ROPENIL ,
d: MyData]
RETURNS [LIST OF REF ANY] = {

resultList: LIST OF REF ANYNIL;

resultRope: ROPENIL;
outcome: AlpTransaction.Outcome;
properties: LIST OF AlpineEnvironment.OwnerPropertyValuePair;
pageLimit, spaceInUse: AlpineEnvironment.PageCount;
failureName: ROPE ← "" ;
{

IF trans = NIL THEN GOTO notAlpineFile;
IF d.assertWheel THEN trans.AssertAlpineWheel[TRUE];
properties ← AlpTransaction.ReadOwnerProperties[
handle: trans,
volumeGroupID: AlpTransaction.GetNextVolumeGroup[handle: trans,
previousGroup: AlpineEnvironment.nullVolumeGroupID, lock: [none, fail]],
owner: directory,
desiredProperties: [quota: TRUE, spaceInUse: TRUE]];
outcome ← AlpTransaction.Finish[trans, commit];
UNTIL properties = NIL DO -- because ReadOwnerProperties does not sort them yet ...
WITH properties.first SELECT FROM
q: AlpineEnvironment.OwnerPropertyValuePair.quota => pageLimit ← q.quota;
s: AlpineEnvironment.OwnerPropertyValuePair.spaceInUse => spaceInUse ← s.spaceInUse;
ENDCASE ;
properties ← properties.rest;
ENDLOOP;
RETURN [CONS[NARROW[
IO.PutFR["Page Limit is %g and Space in Use is %g",
IO.int[pageLimit], IO.int[spaceInUse]],ROPE]
,NIL]];
EXITS
 notAlpineFile => {
RETURN[CONS[
NARROW["Cannot get the quota for a non-Alpine server",ROPE]
,NIL]];
 };

};
};



QuotaProc: PUBLIC Buttons.ButtonProc=
BEGIN
  result: ROPE;
  resultList: LIST OF REF ANYNIL;
  d: MyData = NARROW[clientData];
  server, user, file, password: ROPE;
  directory: ROPE;

  callQuota: YodelData.PerformProc = {

RETURN[ReadQuota[trans, server,
  directory.Substr[start: 1, len: directory.Size[]-2],
  user,
  password,
  d]]
};


  [user, password, server, directory, file] ← ParseSArgs[d];

  d.out.PutF["\nQuota for [%g]%g\n", IO.rope[server], IO.rope[directory]];
  resultList ← PerformOp[performProc: callQuota,
  server: server, user: user, password: password ];
  result ← NARROW[IF resultList = NIL THEN NIL ELSE resultList.first];
  d.out.PutF[" %g\n", IO.rope[result]];

END;

GetOwnerProperties: PUBLIC PROC [trans: AlpTransaction.Handle, server: ROPE,
directory: ROPE, user: ROPENIL, password: ROPENIL , d: MyData]
RETURNS [LIST OF REF ANY] = {
resultList: LIST OF REF ANYNIL;
resultRope: ROPENIL;
outcome: AlpTransaction.Outcome;
properties: LIST OF AlpineEnvironment.OwnerPropertyValuePair;
rootProperties: LIST OF AlpineEnvironment.PropertyValuePair;
failureName: ROPE ← "" ;
rootFile: AlpineEnvironment.UniversalFile ← AlpineEnvironment.nullUniversalFile ;
fileHandle: AlpFile.Handle;
{
ENABLE UNWIND => IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort];
IF trans = NIL THEN GOTO notAlpineFile;
IF d.assertWheel THEN trans.AssertAlpineWheel[TRUE];
properties ← AlpTransaction.ReadOwnerProperties[
handle: trans,
volumeGroupID: AlpTransaction.GetNextVolumeGroup[handle: trans,
previousGroup: AlpineEnvironment.nullVolumeGroupID, lock: [none, fail]],
owner: directory];
UNTIL properties = NIL DO -- because ReadOwnerProperties does not sort them yet ...
WITH properties.first SELECT FROM
q: AlpineEnvironment.OwnerPropertyValuePair.createAccessList => {
createList: AlpineEnvironment.AccessList ← q.createAccessList;
resultRope: ROPE ← accessListToCommaROPE[createList];
ViewerTools.SetContents[viewer: d.oCreateAccessList, contents: resultRope, paint: FALSE];
};
s: AlpineEnvironment.OwnerPropertyValuePair.modifyAccessList => {
modifyList: AlpineEnvironment.AccessList ← s.modifyAccessList;
};
filler to use all the variants so the compiler won't blow up
(this is the cedar version of the "don't delete this line" comment
r: AlpineEnvironment.OwnerPropertyValuePair.rootFile => {
rootFile ← r.rootFile ;
};
t: AlpineEnvironment.OwnerPropertyValuePair.quota => {};
u: AlpineEnvironment.OwnerPropertyValuePair.spaceInUse => {};
ENDCASE ;
properties ← properties.rest;
ENDLOOP;
IF rootFile = AlpineEnvironment.nullUniversalFile THEN {
RETURN [CONS[NARROW[
"Could not find root file on owner property list",ROPE]
,NIL]];
};
[fileHandle]← AlpFile.Open[transHandle: trans,
universalFile: rootFile,
access: readOnly,
lock: [read, fail]
];
rootProperties ← AlpFile.ReadProperties[handle: fileHandle, lock: [read, fail]
! AlpInstance.LockFailed => GOTO lockError;
];
UNTIL rootProperties = NIL DO
property: AlpineEnvironment.PropertyValuePair ← rootProperties.first ;
SELECT property.property FROM
modifyAccess => {
modifyAccess: AlpineEnvironment.AccessList ← NARROW[property,
AlpineEnvironment.PropertyValuePair.modifyAccess].modifyAccess;
resultRope ← accessListToCommaROPE[modifyAccess];
ViewerTools.SetContents[viewer: d.oRootModifyAccess,
contents: resultRope,
paint: FALSE];
};
readAccess => {
readAccess: AlpineEnvironment.AccessList ← NARROW[property,
AlpineEnvironment.PropertyValuePair.readAccess].readAccess;
resultRope ← accessListToCommaROPE[readAccess];
ViewerTools.SetContents[viewer: d.oRootReadAccess,
contents: resultRope,
paint: FALSE];
};
ENDCASE;
rootProperties ← rootProperties.rest;
ENDLOOP;
outcome ← AlpTransaction.Finish[trans, commit];
RETURN [CONS[NARROW[
"Owner Properties access successful",ROPE]
,NIL]];
EXITS
notAlpineFile => {
RETURN[CONS[
NARROW["Cannot get owner properties for a non-Alpine server",ROPE]
,NIL]];
};
lockError => {
RETURN[CONS[
NARROW["Lock prevents access to root file",ROPE]
,NIL]];
};
};
};


GetOwnerPropertiesProc: PUBLIC Buttons.ButtonProc=
BEGIN
  resultList: LIST OF REF ANYNIL;
  d: MyData = NARROW[clientData];
  p: ViewerClasses.Viewer = NARROW[parent];
  server, user, file, password: ROPE;
  directory: ROPE;
  callGet: YodelData.PerformProc = {

RETURN[GetOwnerProperties[trans,
server,
  directory.Substr[start: 1, len: directory.Size[]-2],
  user,
  password,
  d]]
};

  d.stopFlag ← FALSE;
  [user, password, server, directory, file] ← ParseSArgs[d];
  d.out.PutF["\nGet Properties for [%g]%g\n", IO.rope[server], IO.rope[directory]];
  resultList ← PerformOp[performProc: callGet,
  server: server, user: user, password: password];
DO
  nowRope: ROPENARROW[IF resultList = NIL THEN NIL ELSE resultList.first];
IF resultList = NIL THEN EXIT;
  resultList ← resultList.rest;
  d.out.PutF[" %g\n", IO.rope[nowRope]];
ENDLOOP;
  CreateButtons[d, p.parent.parent];
END;

PutOwnerProperties: PUBLIC PROC [trans: AlpTransaction.Handle,
server: ROPE, directory: ROPE, user: ROPENIL, password: ROPENIL , d: MyData]
RETURNS [LIST OF REF ANY] = {
resultList: LIST OF REF ANYNIL;
resultRope: ROPENIL;
rootFileHandle: AlpFile.Handle;
outcome: AlpTransaction.Outcome;
rootUniversalFile: AlpineEnvironment.UniversalFile;
properties: LIST OF AlpineEnvironment.OwnerPropertyValuePair;
rootNewProperties: LIST OF AlpineEnvironment.PropertyValuePair ← NIL ;
fooNewProperties, newProperties: LIST OF AlpineEnvironment.OwnerPropertyValuePair ← NIL ;
scratchStream: IO.STREAMNIL;
failureName: ROPE ← "" ;
{
ENABLE UNWIND => IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort];
IF trans = NIL THEN GOTO notAlpineFile;
IF d.assertWheel THEN trans.AssertAlpineWheel[TRUE];
properties ← AlpTransaction.ReadOwnerProperties[
handle: trans,
volumeGroupID: AlpTransaction.GetNextVolumeGroup[handle: trans,
previousGroup: AlpineEnvironment.nullVolumeGroupID, lock: [none, fail]],
owner: directory];
UNTIL properties = NIL DO -- because ReadOwnerProperties does not sort them yet ...
WITH properties.first SELECT FROM
q: AlpineEnvironment.OwnerPropertyValuePair.createAccessList => {
createList: AlpineEnvironment.AccessList ← q.createAccessList;
newCreateList: AlpineEnvironment.AccessList ← NIL ;
newCreateListRope: ROPE ←ViewerTools.GetContents[viewer: d.oCreateAccessList];
scratchStream ← IO.RIS[newCreateListRope, scratchStream];
newCreateList ← getAccessList[scratchStream];
newProperties ← CONS[[createAccessList[newCreateList]], newProperties];
scratchStream ← IO.RIS[ViewerTools.GetContents[viewer: d.oRootReadAccess], scratchStream];
rootNewProperties ← CONS[[readAccess[getAccessList[scratchStream]]], rootNewProperties];
scratchStream ← IO.RIS[ViewerTools.GetContents[viewer: d.oRootModifyAccess], scratchStream];
rootNewProperties ← CONS[[modifyAccess[getAccessList[scratchStream]]], rootNewProperties];
};
s: AlpineEnvironment.OwnerPropertyValuePair.modifyAccessList => {
The compiler insists that I leave this code here.
modifyList: AlpineEnvironment.AccessList ← s.modifyAccessList;
newModifyList: AlpineEnvironment.AccessList ← NIL ;
fooNewProperties ← CONS[[modifyAccessList[newModifyList]], newProperties];
};
r: AlpineEnvironment.OwnerPropertyValuePair.rootFile => {
rootUniversalFile ← r.rootFile;
};
ENDCASE;
properties ← properties.rest;
ENDLOOP;
AlpTransaction.WriteOwnerProperties[
handle: trans,
volumeGroupID: AlpTransaction.GetNextVolumeGroup[handle: trans,
previousGroup: AlpineEnvironment.nullVolumeGroupID, lock: [none, wait]],
owner: directory,
overCommitQuotasIfNeeded: TRUE,
properties: newProperties];
[rootFileHandle]← AlpFile.Open[transHandle: trans,
universalFile: rootUniversalFile,
access: readWrite,
lock: [write, fail]];
AlpFile.WriteProperties[handle: rootFileHandle, properties: rootNewProperties,
lock: [read, fail]
! AlpInstance.LockFailed => GOTO lockError;
];
outcome ← AlpTransaction.Finish[trans, commit];
RETURN [CONS[NARROW[
"Put of owner properties successful",ROPE]
,NIL]];
EXITS
lockError => {
outcome ← AlpTransaction.Finish[trans, abort];
RETURN[CONS[
NARROW["lock prevents access to root file",ROPE]
,NIL]];
};
notAlpineFile => {
RETURN[CONS[
NARROW["Cannot put owner properties for a non-Alpine server",ROPE]
,NIL]];
};
};
};
PutOwnerPropertiesProc: PUBLIC Buttons.ButtonProc=
BEGIN
  resultList: LIST OF REF ANYNIL;
  d: MyData = NARROW[clientData];
  p: ViewerClasses.Viewer = NARROW[parent];
  server, user, file, password: ROPE;
  directory: ROPE;
  callPut: YodelData.PerformProc = {
RETURN[PutOwnerProperties[trans,
server,
  directory.Substr[start: 1, len: directory.Size[]-2],
  user,
  password,
  d]]
};
  d.stopFlag ← FALSE;
  [user, password, server, directory, file] ← ParseSArgs[d];
  d.out.PutF["\nPut Properties for [%g]%g\n", IO.rope[server], IO.rope[directory]];
  resultList ← PerformOp[performProc: callPut,
  server: server, user: user, password: password];
DO
  nowRope: ROPENARROW[IF resultList = NIL THEN NIL ELSE resultList.first];
IF resultList = NIL THEN EXIT;
  resultList ← resultList.rest;
  d.out.PutF[" %g\n", IO.rope[nowRope]];
ENDLOOP;
  CreateButtons[d, p.parent.parent];
END;
END.