<> <> <> <> <> <> DIRECTORY AlpFile, AlpineEnvironment, AlpineFile, AlpDirectory, AlpDirectoryExtras, AlpInstance, AlpTransaction, BasicTime, Buttons, IO, Rope, ViewerClasses, ViewerTools, YodelData; YodelPropertiesImpl: CEDAR PROGRAM IMPORTS AlpDirectory, AlpDirectoryExtras, AlpFile, AlpInstance, AlpTransaction, IO, Rope, ViewerTools, YodelData EXPORTS YodelData = BEGIN OPEN YodelData; ROPE: TYPE = Rope.ROPE; accessListToCommaROPE: PROC [accessList: AlpineEnvironment.AccessList] RETURNS [resultRope: ROPE _ NIL] = { 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: ROPE _ NIL, password: ROPE _ NIL , displayProperties: AlpineFile.PropertySet _ AlpineFile.allProperties, d: MyData] RETURNS [LIST OF REF ANY] = { fullFileName: ROPE; properties: LIST OF AlpineEnvironment.PropertyValuePair; resultRope: ROPE _ NIL; fileHandle: AlpFile.Handle; outcome: AlpTransaction.Outcome; failureName: ROPE _ "" ; readLockOption: AlpFile.LockOption = [read, IF d.breakLocks THEN wait ELSE fail]; { 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]]]]; [fileHandle, ] _ AlpDirectory.OpenFile[ transHandle: trans, access: readOnly, lock: readLockOption, name: fullFileName, createOptions: oldOnly]; properties _ AlpFile.ReadProperties[handle: fileHandle, lock: readLockOption ! AlpInstance.LockFailed => GOTO lockError; ]; { size: INT; size _ fileHandle.GetSize[]; ViewerTools.SetContents[viewer: d.oSize, contents: IO.PutFR["%g", IO.int[size]], paint: FALSE]; }; { keep: CARDINAL; [keep: keep] _ AlpDirectoryExtras.GetKeep[fileName: fullFileName, transHandle: trans]; ViewerTools.SetContents[viewer: d.oFileKeep, contents: IO.PutFR["%g", IO.card[keep]], paint: FALSE]; }; UNTIL properties = NIL DO property: AlpineEnvironment.PropertyValuePair _ properties.first ; properties _ properties.rest; BEGIN SELECT property.property FROM <> byteLength => { byteLength: INT _ NARROW[property, AlpineEnvironment.PropertyValuePair.byteLength].byteLength; ViewerTools.SetContents[viewer: d.oByteLength, contents: IO.PutFR["%g", IO.int[byteLength]], paint: FALSE]; }; <> createTime => { createTime: BasicTime.GMT _ NARROW[property, AlpineEnvironment.PropertyValuePair.createTime].createTime; <> <> <> }; <> 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: AlpineEnvironment.AccessList _ NARROW[property, AlpineEnvironment.PropertyValuePair.modifyAccess].modifyAccess; resultRope _ accessListToCommaROPE[modifyAccess]; ViewerTools.SetContents[viewer: d.oModifyAccess, contents: resultRope, paint: FALSE]; }; <> 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: AlpineEnvironment.AccessList _ NARROW[property, AlpineEnvironment.PropertyValuePair.readAccess].readAccess; resultRope _ accessListToCommaROPE[readAccess] ; ViewerTools.SetContents[viewer: d.oReadAccess, contents: resultRope, paint: FALSE]; }; <> stringName => { stringName: ROPE _ NARROW[property, AlpineEnvironment.PropertyValuePair.stringName].stringName; ViewerTools.SetContents[viewer: d.oStringName, contents: IO.PutFR["%g", IO.rope[stringName]], paint: FALSE]; }; version => { version: AlpineEnvironment.FileVersion _ NARROW[property, AlpineEnvironment.PropertyValuePair.version].version; ViewerTools.SetContents[viewer: d.oVersion, contents: IO.PutFR["%g", IO.int[version]], paint: FALSE]; }; ENDCASE; END; ENDLOOP; outcome _ AlpTransaction.Finish[trans, commit]; RETURN [CONS[NARROW["Examine of file successful ",ROPE],NIL]]; 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 = { resultList: LIST OF REF ANY _ NIL; d: MyData = NARROW[clientData]; p: ViewerClasses.Viewer = NARROW[parent]; server, user, file, password: ROPE; directory, restOfPattern: ROPE; parseError: BOOL; errorExplanation: ROPE; bangPos: INT; callExamine: YodelData.PerformProc = { RETURN[ExamineFile[trans, server, directory, restOfPattern, user, password, d.displayProperties, d]]; }; typeParseError: PROC [] = { d.out.PutF["\nBad name in Examine because %g\n", IO.rope[errorExplanation]]; }; d.stopFlag _ FALSE; [user, password, server, directory, file, parseError, errorExplanation] _ ParseSArgs[d]; IF parseError THEN { typeParseError[]; GOTO badParse;}; [directory, restOfPattern] _ DecomposePattern[server: server, pattern: file, user: user]; bangPos _ Rope.Find[restOfPattern, "!"]; IF bangPos < 0 THEN restOfPattern _ restOfPattern.Cat["!H"]; 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: ROPE _ NARROW[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]; EXITS badParse => {}; }; getAccessList: PROC [stream: IO.STREAM] RETURNS [outList: AlpineEnvironment.AccessList _ NIL] = { UNTIL IO.EndOf[stream] DO { token: ROPE _ IO.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: ROPE _ NIL, password: ROPE _ NIL , displayProperties: AlpineFile.PropertySet _ AlpineFile.allProperties, d: MyData] RETURNS [LIST OF REF ANY] = { fullFileName: ROPE; newProperties: LIST OF AlpineEnvironment.PropertyValuePair _ NIL ; properties: LIST OF AlpineEnvironment.PropertyValuePair; resultRope: ROPE _ NIL; fileHandle: AlpFile.Handle; outcome: AlpTransaction.Outcome; scratchStream: IO.STREAM _ NIL; failureName: ROPE _ "" ; readLockOption: AlpFile.LockOption = [read, IF d.breakLocks THEN wait ELSE fail]; writeLockOption: AlpFile.LockOption = [write, IF d.breakLocks THEN wait ELSE fail]; { 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]]]]; [fileHandle, ] _ AlpDirectory.OpenFile[ transHandle: trans, name: fullFileName, access: readWrite, lock: writeLockOption, createOptions: oldOnly]; properties _ AlpFile.ReadProperties[handle: fileHandle, lock: readLockOption ! 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]] ; <> fileHandle.SetSize[newSize]; }; { newKeepRope: ROPE; newKeep: LONG CARDINAL; newKeepRope _ ViewerTools.GetContents[viewer: d.oFileKeep]; scratchStream _ IO.RIS[newKeepRope, scratchStream]; newKeep _ NARROW[IO.GetCard[scratchStream]] ; [] _ AlpDirectory.SetKeep[fileName: fullFileName, transHandle: trans, keep: newKeep]; }; UNTIL properties = NIL DO property: AlpineEnvironment.PropertyValuePair _ properties.first ; properties _ properties.rest; { SELECT property.property FROM <> byteLength => { newByteLengthRope: ROPE; newByteLength: INT ; byteLength: INT _ NARROW[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 => { 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 => { 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 => { newOwnerRope: ROPE; newOwner: ROPE; newOwnerRope _ ViewerTools.GetContents[viewer: d.oOwner]; newOwner _ NARROW[newOwnerRope]; newProperties _ CONS[[owner[newOwner]], newProperties]; }; <> 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 => { newStringName: AlpineEnvironment.String; newStringNameRope: ROPE _ ViewerTools.GetContents[viewer: d.oStringName]; newStringName _ NARROW[newStringNameRope]; newProperties _ CONS[[stringName[newStringName]], newProperties]; }; ENDCASE; }; ENDLOOP; AlpFile.WriteProperties[handle: fileHandle, properties: newProperties, lock: writeLockOption ! AlpInstance.LockFailed => GOTO lockError]; outcome _ AlpTransaction.Finish[trans, commit]; RETURN [CONS[NARROW["Apply properties to file successful ",ROPE],NIL]]; 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= { resultList: LIST OF REF ANY _ NIL; d: MyData = NARROW[clientData]; p: ViewerClasses.Viewer = NARROW[parent]; server, user, file, password: ROPE; directory, restOfPattern: ROPE; parseError: BOOL; errorExplanation: ROPE; callApply: YodelData.PerformProc = { RETURN[ApplyToFile[trans, server, directory, restOfPattern, user, password, d.displayProperties, d]]; }; typeParseError: PROC [] = { d.out.PutF["\nBad pattern in Apply because %g\n", IO.rope[errorExplanation]]; }; d.stopFlag _ FALSE; [user, password, server, directory, file, parseError, errorExplanation] _ ParseSArgs[d]; IF parseError THEN { typeParseError[]; GOTO badParse;}; [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: ROPE _ NARROW[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]; EXITS badParse => {}; }; ReadQuota: PUBLIC PROC [trans: AlpTransaction.Handle, server: ROPE, directory: ROPE, user: ROPE _ NIL, password: ROPE _ NIL , d: MyData] RETURNS [LIST OF REF ANY] = { resultList: LIST OF REF ANY _ NIL; resultRope: ROPE _ NIL; 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 = { result: ROPE; resultList: LIST OF REF ANY _ NIL; d: MyData = NARROW[clientData]; server, user, file, password: ROPE; directory: ROPE; parseError: BOOL; errorExplanation: ROPE; callQuota: YodelData.PerformProc = { RETURN[ReadQuota[trans, server, directory.Substr[start: 1, len: directory.Size[]-2], user, password, d]] }; typeParseError: PROC [] = { d.out.PutF["\nBad name in Quota because %g\n", IO.rope[errorExplanation]]; }; [user, password, server, directory, file, parseError, errorExplanation] _ ParseSArgs[d]; IF parseError THEN { typeParseError[]; GOTO badParse;}; 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]]; EXITS badParse => {}; }; GetOwnerProperties: PUBLIC PROC [trans: AlpTransaction.Handle, server: ROPE, directory: ROPE, user: ROPE _ NIL, password: ROPE _ NIL , d: MyData] RETURNS [LIST OF REF ANY] = { resultList: LIST OF REF ANY _ NIL; resultRope: ROPE _ NIL; 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]; { keep: CARDINAL; keep _ AlpDirectoryExtras.GetDefaultKeep[volume: server, owner: directory, transHandle: trans]; ViewerTools.SetContents[viewer: d.oOwnerKeep, contents: IO.PutFR["%g", IO.card[keep]], paint: FALSE]; }; 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; }; <> <<(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 = { resultList: LIST OF REF ANY _ NIL; d: MyData = NARROW[clientData]; p: ViewerClasses.Viewer = NARROW[parent]; server, user, file, password: ROPE; directory: ROPE; parseError: BOOL; errorExplanation: ROPE; callGet: YodelData.PerformProc = { RETURN[GetOwnerProperties[trans, server, directory.Substr[start: 1, len: directory.Size[]-2], user, password, d]] }; typeParseError: PROC [] = { d.out.PutF["\nBad pattern in Get Owner Properties because %g\n", IO.rope[errorExplanation]]; }; d.stopFlag _ FALSE; [user, password, server, directory, file, parseError, errorExplanation] _ ParseSArgs[d]; IF parseError THEN { typeParseError[]; GOTO badParse;}; 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: ROPE _ NARROW[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]; EXITS badParse => {}; }; PutOwnerProperties: PUBLIC PROC [trans: AlpTransaction.Handle, server: ROPE, directory: ROPE, user: ROPE _ NIL, password: ROPE _ NIL , d: MyData] RETURNS [LIST OF REF ANY] = { resultList: LIST OF REF ANY _ NIL; resultRope: ROPE _ NIL; 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.STREAM _ NIL; 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]; { newDefaultKeepRope: ROPE _ ViewerTools.GetContents[viewer: d.oOwnerKeep]; newDefaultKeep: LONG CARDINAL; scratchStream _ IO.RIS[newDefaultKeepRope, scratchStream]; newDefaultKeep _ NARROW[IO.GetCard[scratchStream]]; AlpDirectory.SetDefaultKeep[volume: server, owner: directory, transHandle: trans, defaultKeep: newDefaultKeep]; }; 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 => { <> 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 = { resultList: LIST OF REF ANY _ NIL; d: MyData = NARROW[clientData]; p: ViewerClasses.Viewer = NARROW[parent]; server, user, file, password: ROPE; directory: ROPE; parseError: BOOL; errorExplanation: ROPE; callPut: YodelData.PerformProc = { RETURN[PutOwnerProperties[trans, server, directory.Substr[start: 1, len: directory.Size[]-2], user, password, d]] }; typeParseError: PROC [] = { d.out.PutF["\nBad pattern in Destroy Owner because %g\n", IO.rope[errorExplanation]]; }; d.stopFlag _ FALSE; [user, password, server, directory, file, parseError, errorExplanation] _ ParseSArgs[d]; IF parseError THEN { typeParseError[]; GOTO badParse;}; 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: ROPE _ NARROW[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]; EXITS badParse => {}; }; END. <> <>