DIRECTORY BasicTime USING [GMT], FS USING [Error], FSBackdoor USING [noVersion, Version], FSName USING [BangVersionFile], FSRemoteFileBackdoor USING [EnumerateForInfoProc, EnumerateForNamesProc], Rope USING [Compare, Concat, Equal, IsEmpty, IsPrefix, Match, ROPE, Substr], SunNFS USING [DirOpRes], SunNFSRemoteFile USING [caseFileNamePrefix, caseFileNamePrefixLen, CreateNameReader, CreateNameWriter, DecodeVersionFromNFSName, EachDirEntryProc, EncodeVersionInNFSName, EnumerateDirectory, GetRemoteDirChild, GetRemoteDirRoot, GMTFromSunTime, LookupThruSymLinks, NameReaderObject, NameWriterObject, ReadBaseComponent, ReadDirComponent, RemoteDirObject, ReportFSError, ReportNFSError, RetractComponent, RopeFromNameWriter, ServerHandle, UnPinRemoteDir, UnPinRemoteDirPath, VersionInfo, WriteBaseComponent, WriteDirComponent] ; SunNFSRemoteEnumImpl: CEDAR MONITOR IMPORTS FS, FSName, Rope, SunNFSRemoteFile EXPORTS SunNFSRemoteFile ~ { OPEN SunNFSRemoteFile; GMT: TYPE ~ BasicTime.GMT; NameReader: TYPE ~ REF NameReaderObject; NameWriter: TYPE ~ REF NameWriterObject; RemoteDirHandle: TYPE ~ REF RemoteDirObject; ROPE: TYPE ~ Rope.ROPE; Version: TYPE ~ FSBackdoor.Version; initialInfoSetSize: CARDINAL _ 16; InfoSet: TYPE ~ REF InfoSetObject; InfoSetObject: TYPE ~ RECORD [ size: CARDINAL, info: SEQUENCE maxSize: CARDINAL OF Info ]; maxMaxSize: CARDINAL _ (CARDINAL.LAST - SIZE[InfoSetObject[0]] - 10) / SIZE[Info]; -- the '10' is just for luck InfoKind: TYPE ~ { caseHint, file, subdirectory }; Info: TYPE ~ RECORD [ name: ROPE, -- not including version part kind: InfoKind, versionNum: CARDINAL ]; AddInfoToSet: PROC [set: InfoSet, info: Info] RETURNS [newSet: InfoSet] ~ { IF set = NIL THEN { set _ NEW[InfoSetObject[initialInfoSetSize]]; set.size _ 0 }; IF set.size < set.maxSize THEN { newSet _ set } ELSE { newSize: CARDINAL ~ MIN[2*set.maxSize, maxMaxSize]; newSet _ NEW[InfoSetObject[newSize]]; FOR i: CARDINAL IN [0 .. set.size) DO newSet.info[i] _ set.info[i]; ENDLOOP; newSet.size _ set.size; }; newSet.info[newSet.size] _ info; newSet.size _ newSet.size + 1; }; SortInfoSet: PROC [set: InfoSet] ~ { left, right, p, c, cRight: CARDINAL; temp: Info; Less: PROC [i, j: CARDINAL] RETURNS [BOOL] ~ INLINE { RETURN [ SELECT Rope.Compare[set.info[i].name, set.info[j].name, FALSE] FROM less => TRUE, greater => FALSE, ENDCASE => (set.info[i].versionNum < set.info[j].versionNum) ]; }; Swap: PROC [i, j: CARDINAL] ~ INLINE { temp _ set.info[i]; set.info[i] _ set.info[j]; set.info[j] _ temp; }; IF set.size < 2 THEN RETURN; left _ set.size/2; right _ set.size - 1; DO SELECT TRUE FROM (left > 0) => { left _ left - 1 }; (right > 0) => { Swap[0, right]; right _ right - 1 }; ENDCASE => EXIT; FOR p _ left, c DO IF (c _ 2*p+1) > right THEN EXIT; IF ((cRight _ c+1) <= right) AND Less[c, cRight] THEN c _ cRight; IF Less[c, p] THEN EXIT; Swap[p, c]; ENDLOOP; ENDLOOP; }; LocalEachFileProc: TYPE ~ PROC [file: ROPE, dH: RemoteDirHandle, component: ROPE, version: Version] RETURNS [continue: BOOL]; SunNFSEnumerateForInfo: PUBLIC FSRemoteFileBackdoor.EnumerateForInfoProc -- [h: ServerHandle, pattern: ROPE, proc: InfoProc] -- ~ { EachFile: LocalEachFileProc ~ { dirOpRes: SunNFS.DirOpRes _ LookupThruSymLinks[h, dH, EncodeVersionInNFSName[component, version]]; SELECT dirOpRes.status FROM ok => NULL; perm, acces, noent => RETURN[TRUE]; ENDCASE => ReportNFSError[dirOpRes.status, h]; SELECT dirOpRes.attributes.type FROM reg => NULL; ENDCASE => RETURN[TRUE]; RETURN [proc[file, dirOpRes.attributes.size, GMTFromSunTime[dirOpRes.attributes.mtime]]]; }; SunNFSEnumerate[h, pattern, EachFile]; }; SunNFSEnumerateForNames: PUBLIC FSRemoteFileBackdoor.EnumerateForNamesProc -- [h: ServerHandle, pattern: ROPE, proc: NameProc] -- ~ { EachFile: LocalEachFileProc -- [file: ROPE, ... ] RETURNS [continue: BOOL] -- ~ { RETURN [proc[file]]; }; SunNFSEnumerate[h, pattern, EachFile]; }; EnumerationAborted: PRIVATE ERROR ~ CODE; SunNFSEnumerate: PROC [h: ServerHandle, pattern: ROPE, proc: LocalEachFileProc] ~ { dH: RemoteDirHandle; nR: NameReader; nWPath, nWSuffix: NameWriter; patternPrefix, patternUpToVersionPart: ROPE; isPattern: BOOL; versionFromPattern: Version; vI: VersionInfo; callDepth: CARDINAL _ 0; EnumerateInner: PROC ~ { set: InfoSet _ NIL; EachName: EachDirEntryProc -- [entryName: ROPE] RETURNS [continue: BOOL _ TRUE] -- ~ { nameWithoutVersion: ROPE; thisVersion: Version; caseOK: BOOL; IF Rope.Equal[entryName, "."] OR Rope.Equal[entryName, ".."] THEN RETURN [TRUE]; IF Rope.IsPrefix[caseFileNamePrefix, entryName, TRUE] THEN { casedComponent, nameSuffix: ROPE; casedComponent _ Rope.Substr[entryName, caseFileNamePrefixLen]; WriteDirComponent[nWSuffix, casedComponent]; -- Ugh! Logically, this ought to be WriteBaseComponent[...], but I don't want leading '> characters for the pattern match! nameSuffix _ RopeFromNameWriter[nWSuffix]; IF Rope.Match[patternUpToVersionPart, nameSuffix, FALSE] THEN { set _ AddInfoToSet[set, [name~casedComponent, kind~caseHint, versionNum~0]]; }; RetractComponent[nWSuffix]; RETURN[TRUE]; }; [nameWithoutVersion, thisVersion, caseOK] _ DecodeVersionFromNFSName[entryName, TRUE]; SELECT TRUE FROM (NOT caseOK) => RETURN[TRUE]; (thisVersion # FSBackdoor.noVersion) => { IF (vI # bangNumber) OR (thisVersion = versionFromPattern) THEN { nameSuffix: ROPE; WriteDirComponent[nWSuffix, nameWithoutVersion]; -- Ugh! Logically, this ought to be WriteBaseComponent[...], but I don't want leading '> characters for the pattern match! nameSuffix _ RopeFromNameWriter[nWSuffix]; IF Rope.Match[patternUpToVersionPart, nameSuffix, FALSE] THEN { set _ AddInfoToSet[set, [name~nameWithoutVersion, kind~file, versionNum~thisVersion]]; }; RetractComponent[nWSuffix]; }; RETURN[TRUE]; }; ENDCASE => { addIt: BOOL; SELECT TRUE FROM (callDepth > 0) => addIt _ TRUE; (NOT isPattern) => addIt _ FALSE; ENDCASE => addIt _ Rope.IsPrefix[patternPrefix, entryName, FALSE]; IF addIt THEN { set _ AddInfoToSet[set, [name~entryName, kind~subdirectory, versionNum~CARDINAL.LAST]]; }; }; }; EnumerateDirectory[h, dH, EachName, FALSE ! FS.Error => { IF error.code = $accessDenied THEN { set _ NIL; CONTINUE } ELSE REJECT } ]; IF set # NIL THEN { i: CARDINAL _ 0; latestCaseHint, thisName, casedName: ROPE _ NIL; SortInfoSet[set]; WHILE i < set.size DO thisName _ set.info[i].name; casedName _ thisName; SELECT set.info[i].kind FROM caseHint => { latestCaseHint _ thisName; i _ i + 1; }; subdirectory => { callDepth _ callDepth + 1; IF latestCaseHint # NIL THEN { SELECT Rope.Compare[latestCaseHint, thisName, FALSE] FROM less => latestCaseHint _ NIL; equal => casedName _ latestCaseHint; ENDCASE; }; WriteDirComponent[nWPath, casedName]; WriteDirComponent[nWSuffix, casedName]; { gotChild: BOOL _ TRUE; [dHChild~dH] _ GetRemoteDirChild[h, dH, thisName, FALSE ! FS.Error => { gotChild _ FALSE; CONTINUE }]; IF gotChild THEN { EnumerateInner[]; dH _ UnPinRemoteDir[dH]; }; }; RetractComponent[nWSuffix]; RetractComponent[nWPath]; callDepth _ callDepth - 1; i _ i + 1; }; file => { it: CARDINAL; temp: ROPE; IF latestCaseHint # NIL THEN { SELECT Rope.Compare[latestCaseHint, thisName, FALSE] FROM less => latestCaseHint _ NIL; equal => casedName _ latestCaseHint; ENDCASE; }; SELECT vI FROM bangStar, bangNumber, bang, missing => { it _ i; i _ i + 1; }; bangH, bangL => { start: CARDINAL _ i; i _ i + 1; WHILE (i < set.size) AND (set.info[i].kind = file) AND Rope.Equal[thisName, set.info[i].name, FALSE] DO i _ i + 1; ENDLOOP; it _ (IF vI = bangH THEN i-1 ELSE start); }; ENDCASE => ERROR; temp _ FSName.BangVersionFile[casedName, [set.info[it].versionNum]]; WriteBaseComponent[nWPath, temp]; temp _ Rope.Concat["<", RopeFromNameWriter[nWPath]]; IF NOT proc[temp, dH, thisName, [set.info[it].versionNum]] THEN ERROR EnumerationAborted[]; RetractComponent[nWPath]; }; ENDCASE; ENDLOOP; }; }; { ENABLE { UNWIND => { IF dH # NIL THEN UnPinRemoteDirPath[dH]; dH _ NIL; }; EnumerationAborted => { CONTINUE; }; }; nR _ CreateNameReader[pattern]; nWPath _ CreateNameWriter[]; dH _ FollowDirPathForEnumeration[h, nR, nWPath]; [base~patternUpToVersionPart, vI~vI, version~versionFromPattern, isPattern~isPattern, patternHead~patternPrefix] _ ReadBaseComponent[nR~nR, case~FALSE, stripVersion~TRUE]; SELECT vI FROM missing => ReportFSError[illegalName, h, patternUpToVersionPart, "Enumerate, version part required"]; ENDCASE; nWSuffix _ CreateNameWriter[]; EnumerateInner[]; }; IF dH # NIL THEN UnPinRemoteDirPath[dH]; }; FollowDirPathForEnumeration: PROC [sH: ServerHandle, nR: NameReader, nW: NameWriter] RETURNS [dH: RemoteDirHandle] ~ { ENABLE UNWIND => { IF dH # NIL THEN UnPinRemoteDirPath[dH]; }; caseFileName: ROPE; component, casedComponent: ROPE; EachDirEntry: EachDirEntryProc -- [entryName: ROPE] RETURNS [continue: BOOL _ TRUE] -- ~ { IF Rope.Equal[entryName, caseFileName, FALSE] THEN { casedComponent _ Rope.Substr[entryName, caseFileNamePrefixLen]; continue _ FALSE; }; }; dH _ GetRemoteDirRoot[sH]; DO dHParent: RemoteDirHandle _ dH; component _ casedComponent _ ReadDirComponent[nR, FALSE]; IF Rope.IsEmpty[component] THEN EXIT; [dHChild~dH] _ GetRemoteDirChild[sH~sH, dH~dH, childName~component, create~FALSE]; caseFileName _ Rope.Concat[caseFileNamePrefix, component]; EnumerateDirectory[sH, dHParent, EachDirEntry]; WriteDirComponent[nW, casedComponent]; ENDLOOP; }; }...  SunNFSRemoteEnumImpl.mesa Copyright Σ 1987 by Xerox Corporation. All rights reserved. Demers, November 9, 1987 1:45:33 pm PST Copied Types Parameters Sets of Info Heapsort using as key ... Exported to SunNFSRemoteFile Select names to be included, add them to set. If vI = number the selection by version number was done before sorting. Main line code of EnumerateForInfo ... Κ ε˜codešœ™K™<™'K˜——šΟk ˜ Kšœ œœ˜Kšœœ ˜Kšœ œ˜&Kšœœ˜Kšœœ/˜IKšœœ4œ ˜LKšœœ ˜Kšœœφ˜ŒKšœ˜K˜—šΟnœœ˜#Kšœœ ˜*Kšœ˜K˜Kšœ˜head™ Kšœœ œ˜Kšœ œœ˜(Kšœ œœ˜(Kšœœœ˜,Kšœœœ˜Kšœ œ˜#—™ Kšœœ˜"—™ Kšœ œœ˜"šœœœ˜Kšœœ˜Kšœœ œœ˜(K˜—š œ œœœœœΟc˜oK˜—Kšœ œ$˜2šœœœ˜KšœœŸ˜)Jšœ˜Kšœ ˜K˜K˜—šž œœœ˜KKšœœœ œ4˜Qšœ˜Kšœ˜šœ˜Kšœ œœ˜3Kšœ œ˜%šœœœ˜%K˜Kšœ˜—K˜K˜——Kšœ ˜ K˜K˜K˜—šž œœ˜$K™:Kšœœ˜$Kšœ ˜ š žœœœœœœ˜5šœ˜šœ2œ˜CKšœœ˜ Kšœ œ˜Kšœ5˜<—K˜—K˜—šžœœœœ˜&Kšœ˜K˜K˜K˜—Kšœœœ˜K˜(š˜šœœ˜K˜"K˜5Kšœœ˜—šœ ˜Kšœœœ˜!Kšœœœ ˜AKšœ œœ˜K˜ Kšœ˜—Kšœ˜—K˜——™Kš œœœœ"œœ œ˜}K˜šžœœ+Ÿ6œ˜ƒšžœ˜Kšœb˜bšœ˜Kšœœ˜ Kšœœœ˜#Kšœ'˜.—šœ˜$Kšœœ˜ Kšœœœ˜—KšœS˜YK˜—K˜&K˜K˜—šžœœ,Ÿ6œ˜…šžœŸ1œ˜QKšœ˜K˜—K˜&K˜K˜—Kšžœœœœ˜)K˜šžœœœ˜SK˜K˜K˜Kšœ'œ˜,Kšœ œ˜K˜K˜Kšœ œ˜šžœœ˜Kšœœ˜šžœŸ7œ˜VK™-Kšœœ˜K˜Kšœœ˜ Kš œœœœœ˜Pšœ.œœ˜