(FILECREATED "11-Mar-85 15:47:34" {ERIS}<LISP>INTERMEZZO>SOURCES>SCAVENGEDSKDIRECTORY.;3 6333   

      changes to:  (FNS \LFScavFileName)
		   (VARS SCAVENGEDSKDIRECTORYCOMS)

      previous date: "28-Feb-85 20:15:51" {ERIS}<LISP>INTERMEZZO>SOURCES>SCAVENGEDSKDIRECTORY.;2)


(* Copyright (c) 1985 by Xerox Corporation. All rights reserved.)

(PRETTYCOMPRINT SCAVENGEDSKDIRECTORYCOMS)

(RPAQQ SCAVENGEDSKDIRECTORYCOMS ((DECLARE: EVAL@COMPILE DONTCOPY (FILES (LOADCOMP)
									LFDIRECTORY LFFILEMAP)
					   (FILES DECL))
				 (DECLARE: (LOCALVARS . T)
					   (IGNOREDECL . T))
				 (* * Directory (LFDIRECTORY)
				    level stuff)
				 (FNS SCAVENGEDSKDIRECTORY \LFScavFileName \LFScavVersion)
				 (GLOBALVARS \LFtopMonitor)
				 (* * Volume file map (LFFILEMAP)
				    level stuff)
				 (FNS \VFMGenerateFileIDs)))
(DECLARE: EVAL@COMPILE DONTCOPY 
(FILESLOAD (LOADCOMP)
	   LFDIRECTORY LFFILEMAP)

(FILESLOAD DECL)
)
(DECLARE: 
(DECLARE: DOEVAL@COMPILE DONTCOPY

(LOCALVARS . T)
)

(DECLARE: DOEVAL@COMPILE DONTEVAL@LOAD DONTCOPY 
(RESETSAVE COMPILEIGNOREDECL (QUOTE T))
)
)
(* * Directory (LFDIRECTORY) level stuff)

(DEFINEQ

(SCAVENGEDSKDIRECTORY
  [DLAMBDA ((volName (ONEOF ATOM STRINGP))
            (RETURNS (ONEOF NIL STRINGP)))
                                                             (* hts: "16-Feb-85 23:12")

          (* If your BTree is intact but your directory is smashed, this routine will scavenge your volume by building a new 
	  directory which associates all fileIDs in the BTree with a gensym filename)


    [WITH.MONITOR \LFtopMonitor
		  (PROG ((vol (\LFEntryPoint volName))
			 DIRECTORY LISPDIRECTORY LISPFILES)
		        (if (NOT (\PFPilotVolumeP vol))
			    then (ERROR "Non-pilot volume"))

          (* * Find the file ID's of the Lisp directory and all the Lisp files on the specified volume.)


		        (SETQ LISPDIRECTORY (\VFMGenerateFileIDs vol tLispDirectory))
		        (SETQ LISPFILES (\VFMGenerateFileIDs vol tLispFile))

          (* * If there are no Lisp files of any sort on the volume, abort)


		        (if (AND (NULL LISPDIRECTORY)
				 (NULL LISPFILES))
			    then (RETURN NIL))

          (* * This block throws away the old directory and builds a new one. It must be atomic.)


		        (UNINTERRUPTABLY

          (* * If there is an old directory, get rid of it.)


			    (\LFPurgeDirectory vol)

          (* * Create a fresh directory)


			    (\LFMakeVolumeDirectory vol)

          (* * For each file in volume file map, enter this fileID into the new directory)


			    [for fileID in LISPFILES
			       do (PROG ((stream (\LFOpenOldFile (create FileDescriptor
									 fileID ← fileID
									 volNum ←(\PFVolumeNumber
									   vol)
									 type ← tLispFile)
								 NIL NIL))
					 NAME&VERSION)
				        (SETQ NAME&VERSION (fetch (LeaderPage fileName)
							      of (fetch (DLIONSTREAM LEADERPAGE)
								    of stream)))
				        (\LFMakeDirEntry stream (create ExpandedName
									VOLNUM ←(\PFVolumeNumber
									  vol)
									CHARLIST ←(\LFScavFileName
									  NAME&VERSION)
									VERSION ←(\LFScavVersion
									  NAME&VERSION fileID))
							 (\LFGetDirectory vol])

          (* * Return the name of the new directory)


		        (RETURN (PACKFILENAME.STRING (QUOTE HOST)
						     (QUOTE DSK)
						     (QUOTE DIRECTORY)
						     (U-CASE (fetch (LogicalVolumeDescriptor LVlabel)
								of vol]])

(\LFScavFileName
  [DLAMBDA ((NAME&VERSION (ONEOF ATOM STRINGP))
            (RETURNS (LISTP OF SMALLP)))
                                                             (* edited: "11-Mar-85 15:09")

          (* * Extract the filename part of NAME&VERSION (ignore version number) and return it as a list of charcode)


    (PROG ((NAME (for C instring (MKSTRING NAME&VERSION) until (EQ C (CHARCODE ;)) collect C)))
          (RETURN (if (OR (NULL NAME)
			  (for C in NAME thereis (EQ (\LFCASEARRAYFETCH C)
						     0)))
		      then 

          (* * If there is an illegal char in the filename, or the filename is the empty string, gin up a random filename)


			   (CHCON (GENSYM (QUOTE TRASHEDFILENAME.)))
		    else 

          (* * Otherwise return the filename found)


			 NAME)))])

(\LFScavVersion
  [DLAMBDA ((NAME&VERSION (ONEOF ATOM STRINGP))
            (FILEID FIXP)
            (RETURNS SMALLP))
                                                             (* hts: "16-Feb-85 22:37")

          (* * Fetch the version number from NAME&VERSION. If it's garbled (ie, isn't a fixp) use the fileID as a version 
	  number instead (the fileID will at least give the file a unique version number and so avoid version number clashes))


    (OR (SMALLP (FILENAMEFIELD NAME&VERSION (QUOTE VERSION)))
	(SMALLP FILEID)
	(RAND 1 MAX.SMALLP))])
)
(DECLARE: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS \LFtopMonitor)
)
(* * Volume file map (LFFILEMAP) level stuff)

(DEFINEQ

(\VFMGenerateFileIDs
  [DLAMBDA ((vol LogicalVolumeDescriptor)
            (desiredType SMALLP)
            (RETURNS (LST OF FIXP)))
                                                             (* hts: "16-Feb-85 21:40")

          (* * Returns a list of the fileIDs of all the keys in the BTree with type = desiredType)


    [WITH.MONITOR \VFMmonitor (UNINTERRUPTABLY
                                  (\VFMContextSet vol)
				  (bind (currentKey ←(create Key))
				     until (PROGN (replace (Key filePage) of currentKey with MAX.FIXP)
						  (MESASETQ currentKey (fetch (Interval nextKey)
									  of (\VFMGet currentKey 0))
							    Key)
						  (EQP (fetch (Key fileID) of currentKey)
						       \VFMmaxID))
				     when (EQ (fetch (Key type) of currentKey)
					      desiredType)
				     collect (fetch (Key fileID) of currentKey)))]])
)
(PUTPROPS SCAVENGEDSKDIRECTORY COPYRIGHT ("Xerox Corporation" 1985))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (1141 5165 (SCAVENGEDSKDIRECTORY 1151 . 3661) (\LFScavFileName 3663 . 4565) (
\LFScavVersion 4567 . 5163)) (5282 6242 (\VFMGenerateFileIDs 5292 . 6240)))))
STOP