(FILECREATED " 8-Jun-84 00:42:36" {ERIS}<LISPNEW>SOURCES>DLIONFS.;6 88088 changes to: (FNS \DFSGetVolumeInfo) previous date: " 5-Jun-84 13:48:14" {ERIS}<LISPNEW>SOURCES>DLIONFS.;4) (* Copyright (c) 1983, 1984 by Xerox Corporation) (PRETTYCOMPRINT DLIONFSCOMS) (RPAQQ DLIONFSCOMS ((DECLARE: EVAL@COMPILE DONTCOPY (COMS * DLIONFSCOMPILECOMS)) (INITRECORDS GadolKey) (* These provide the interface between this file and VolumeFileMap) (FNS \DFSTrimHelper \DFSFindVolumeNumber) (* These functions transfer pages to and from the disk) (FNS \PvTransferPage \PvTransferPageNoSwap \LvGetPage \LvPutPage \LvBasePageAddr) [DECLARE: DONTEVAL@LOAD (P (\LOCKFN (QUOTE \PvTransferPage)) (\LOCKFN (QUOTE \PvTransferPageNoSwap)) (\LOCKVAR (QUOTE \DFSWriteFlg] (* These functions are part of the volume file map (BTree) %. Most of this code has been gutted and moved to the file VolumeFileMap.) (FNS \DFSFindPageAddr) (* The following implement the device and directory level parts of the 1108 file system.) (FNS \DFSFindDirHole \DFSDEVICEP \DFSVOLUMEP \DFSGenFileID \DFSMakeStrPtr \DFSInit \DFSEnsureInitialized \DFSGetVolumeInfo \DFSGetBuffer \DFSGetPvName \DFSGetLvName \DFSGetLvNum \DFSHostNameP \DFSOpenDiskDevice \DFSCloseFile \DFSDirectoryNameP \DFSEventFn \DFSGetFileInfo \DFSGetFileName \DFSReadPages \DFSSetFileInfo \DFSTrimFile \DFSTruncateFile \DFSWritePages \DFSUnpackName \DFSUNAMELength \DFSZeroBuffer \DFSMakeVolumeDirectory \DFSOpenDirectory \DFSMakeLeaderPage \DFSOpenFileFromKey \DFSDeleteFile \DFSMakeDirEntry \DFSReadOnePage \DFSWriteOnePage \DFSCreateFile \DFSNewPages \DFSOpenFile \DFSUpdateAccessTimes \DFSExtendFile \DFSCompleteStream \DFSGetStreamForFile \DFSFileSpec \DFSMoveToLeader \DFSWriteLeaderPage \DFSReadLeaderPage \DFSVersions \DFSDirectorySearch \DFSFullFileName \DFSGenerateFiles \DFSNextFileFn \DFSFileInfoFn \DFSFreeDiskPages \DFSDsplyVolumes \DFSDeviceConflict \DFSCoreDeviceP \DFSDFSDeviceP) (* This function is a temporary check to make sure \DFSNewPages is doing the right thing.) (FNS \DFSCheck \DFSCheckEntry) (* These provide direct user interface to the file system.) (FNS MKDIR DFSVOLUMES DFSLISPVOLUMEP VOLUMEDISPLAY MAKEPILOT SCAVENGEVOLUME CURRENTVOLUME) (GLOBALVARS \DFSReadVolumes \DFSInitialized \DFSWriteFlg \DFSCheck) (FILES VOLUMEFILEMAP VOLUMEALLOCATIONMAP) (FNS \DFSAtLoad) (P (\DFSAtLoad)))) (DECLARE: EVAL@COMPILE DONTCOPY (RPAQQ DLIONFSCOMPILECOMS ((RECORDS PhysVolumeDscr SubVolumeDscr LogicalVolumeDscr) (RECORDS FILEGENOBJ DLIONSTREAM DLIONDISK DFSUnpackedName DFSLeaderPage DFSFileSpec DFSGenerateFileState DFSDirSearchState) (CONSTANTS (DFSPilotVolume 0) (DFSLispVolume 3) (hardMicrocode 0) (nullVolumePage 0) (SubVolumeEntrySize 13)) (MACROS FADDR UCASECHAR BETWEEN) (MACROS LvPagePtr SubVolumeEntryPtr LvDevicePtr LvNum LVEqual SwapIn&Dirty MarkerPageAddr) (* The following are for diagnostic purposes.) (FNS DsplyPvPage DsplyLvPage DsplyPage DsplyWords ShowIntervals DsplySubVolEntry DsplyFileStream))) [DECLARE: EVAL@COMPILE (BLOCKRECORD PhysVolumeDscr ((Seal WORD) (* Validation) (Version WORD) (NameLength WORD) (PvID 5 WORD) (BootingInfo 36 WORD) (* Defines 4 PILOT file types) (Name 40 BYTE) (* Ascii name of the volume) (SubVolCount WORD) (SubVolMrkID 5 WORD) (* Marker pages belong to this Pseudo File) (BadPageCount SWAPPEDFIXP) (MaxBadPages SWAPPEDFIXP) (OnLineCount WORD) (SubVolumes 78 WORD) (* See SubVolumeDscr record for description of each of six entries stored here) (Fill1 99 WORD) (LocalTimeParmValid WORD) (LocalTimeParm 2 WORD) (CheckSum WORD)) (SYSTEM)) (BLOCKRECORD SubVolumeDscr ((LvID 5 WORD) (* Logical Volume ID) (LvSize SWAPPEDFIXP) (* Size for the complete voluem..may span packs some day) (LvPage SWAPPEDFIXP) (* Typically 0) (PvPage SWAPPEDFIXP) (* Disk Address of the beginning of the volume See LogicalVolumeDscr Record NIL) (NPages SWAPPEDFIXP) (* Number of Pages of Volume in this Phisycal Volume) ) (SYSTEM)) (BLOCKRECORD LogicalVolumeDscr ((Seal WORD) (* Validation) (Version WORD) (LvID 5 WORD) (* ID of This Volume) (NameLength WORD) (* Length of th ASCII name of this volume) (Name 40 BYTE) (* Volume name in AScII) (Type WORD) (VolumeSize SWAPPEDFIXP) (* Number of pages in this volume) (BootingInfo 54 WORD) (* Defines 6 PILOT file types) (TreeDepth WORD) (Changing WORD) (FreePageCount SWAPPEDFIXP) (* Number of free pages remaining) (VAMStart SWAPPEDFIXP) (VFMStart SWAPPEDFIXP) (* Relative address of the start of the volume file map) (LowerBound SWAPPEDFIXP) (RootFileID 30 WORD) (FreeSpaceID 5 WORD) (VAMID 5 WORD) (VFMID 5 WORD) (VolumeRootDirectory 5 WORD) (VolNum WORD) (IntervalCache 96 WORD) (* One entry for each level of the B-Tree) (Fill 6 WORD) (VFMLowKey 7 WORD) (CheckSum WORD)) (SYSTEM)) ] [DECLARE: EVAL@COMPILE (RECORD FILEGENOBJ (NEXTFILEFN FILEINFOFN . GENFILESTATE)) (ACCESSFNS DLIONSTREAM ((FID (fetch F1 of DATUM) (replace F1 of DATUM with NEWVALUE)) (TRANSFERKEY (fetch F2 of DATUM) (replace F2 of DATUM with NEWVALUE)) (DIRINFO (fetch F4 of DATUM) (replace F4 of DATUM with NEWVALUE)) (DIRHOLEPTR (fetch F5 of DATUM) (replace F5 of DATUM with NEWVALUE)) (LastAllocated (fetch FW6 of DATUM) (replace FW6 of DATUM with NEWVALUE))) (CREATE (create STREAM))) (ACCESSFNS DLIONDISK ((VolNum (\DFSFindVolumeNumber (fetch DEVICEINFO of DATUM))) (DirectoryStream (ELT \DirStreams (LvNum DATUM)) (SETA \DirStreams (LvNum DATUM) NEWVALUE))) (CREATE (create FDEV))) (RECORD DFSUnpackedName ((VERSION PARTNUM . ESCFLAG) . CHARPAIRS)) (BLOCKRECORD DFSLeaderPage ((TimeCreate FIXP) (TimeWrite FIXP) (TimeRead FIXP) (FileKey 7 WORD) (AllocatedPages FIXP) (EofPage FIXP) (EOffSet WORD) (NameLength WORD) (FileName 100 BYTE) (AuthorLength WORD) (AuthorName 30 BYTE))) (RECORD DFSFileSpec (UNAME FSDIRPTR) [ACCESSFNS DFSFileSpec ((DFSNAME (\DFSFullFileName (fetch UNAME of DATUM]) (RECORD DFSGenerateFileState (DIROFD HOSTNAME ENTRYSTART GENSTREAM . SEARCHSTATE)) (RECORD DFSDirSearchState (DIRPTR . CHARLIST)) ] (DECLARE: EVAL@COMPILE (RPAQQ DFSPilotVolume 0) (RPAQQ DFSLispVolume 3) (RPAQQ hardMicrocode 0) (RPAQQ nullVolumePage 0) (RPAQQ SubVolumeEntrySize 13) (CONSTANTS (DFSPilotVolume 0) (DFSLispVolume 3) (hardMicrocode 0) (nullVolumePage 0) (SubVolumeEntrySize 13)) ) (DECLARE: EVAL@COMPILE (PUTPROPS FADDR MACRO ((Parm Fld) (LOCF (fetch Fld of Parm)))) (PUTPROPS UCASECHAR MACRO [(C) (COND ((ILESSP C (CHARCODE a)) C) (T (IDIFFERENCE C (IDIFFERENCE (CHARCODE a) (CHARCODE A]) (PUTPROPS BETWEEN MACRO (OPENLAMBDA (V LO HI) (AND (IGEQ V LO) (ILEQ V HI)))) ) (DECLARE: EVAL@COMPILE (PUTPROPS LvPagePtr MACRO ((I) (ELT \LogicalVolumes I))) (PUTPROPS SubVolumeEntryPtr MACRO ((LVNum) (* edited: " 7-JUN-83 14:02") (\ADDBASE (FADDR \PhysVolumePage (PhysVolumeDscr SubVolumes)) (ITIMES (SUB1 LVNum) SubVolumeEntrySize)))) (PUTPROPS LvDevicePtr MACRO ((VolNum) (ELT \DFSDevices VolNum))) (PUTPROPS LvNum MACRO ((DEV) (fetch (DLIONDISK VolNum) of DEV))) (PUTPROPS LVEqual MACRO ((a b) (MESAEQUAL (fetch (LogicalVolumeDescriptor vID) of a) (fetch (LogicalVolumeDescriptor vID) of b) ID))) (PUTPROPS SwapIn&Dirty MACRO (OPENLAMBDA (page) (\PUTBASE page 0 (\GETBASE page 0)))) (PUTPROPS MarkerPageAddr MACRO [(vol) (fetch (SubVolumeDscr NPages) of (SubVolumeEntryPtr ( \DFSFindVolumeNumber vol]) ) (* The following are for diagnostic purposes.) (DEFINEQ (DsplyPvPage [LAMBDA NIL (* sg: " 8-JUN-83 19:26") (INSPECT \PhysVolumePage (QUOTE PhysVolumeDscr]) (DsplyLvPage [LAMBDA (I) (* sg: " 8-JUN-83 19:25") (INSPECT (LvPagePtr I) (QUOTE LogicalVolumeDscr]) (DsplyPage [LAMBDA (VolNum PageAddr) (* SDG "14-NOV-83 13:45") (DsplyWords (\LvGetPage VolNum PageAddr) 256]) (DsplyWords [LAMBDA (Start Number) (* hts: " 3-Apr-84 16:04") (for I from 0 to (SUB1 Number) do (PRIN1 (\GETBASE Start I)) (PRIN1 " ") (if (ZEROP (IREMAINDER (ADD1 I) 10)) then (TERPRI))) (TERPRI]) (ShowIntervals [LAMBDA (vol) (* hts: " 4-Apr-84 16:20") (bind interval for I from 0 to 5 do (printout T I ":" T "key: ") (SETQ interval (PROG ((newCopy (create Intervals))) (\BLT newCopy (\ADDBASE (fetch (LogicalVolumeDescriptor interval) of vol) (IPLUS (ITIMES (IDIFFERENCE I 0) 16))) (MESASIZE Intervals)) (RETURN newCopy))) (DsplyWords (fetch (Interval key) of interval) (MESASIZE Key)) (printout T "volumePage: " (fetch (Interval volumePage) of interval) T) (printout T "nextKey: ") (DsplyWords (fetch (Interval nextKey) of interval) (MESASIZE Key]) (DsplySubVolEntry [LAMBDA (Vol) (* edited: " 8-JUN-83 19:57") (INSPECT (SubVolumeEntryPtr Vol) (QUOTE SubVolumeDscr]) (DsplyFileStream [LAMBDA (File) (* SDG "10-AUG-83 15:50") (INSPECT (GETSTREAM File) (QUOTE DLIONSTREAM)) (INSPECT (GETSTREAM File]) ) ) (* These provide the interface between this file and VolumeFileMap) (DEFINEQ (\DFSTrimHelper [LAMBDA (volNum key targetFileSize actualFileSize) (* hts: "24-May-84 20:35") (* Shortens or deletes a file by taking entries out of the BTree and out of the allocation map Removes the pages of the file between targetFileSize & actualFileSize) (if (NOT (EQP targetFileSize actualFileSize)) then (bind (group ←(create PageGroup (SETQ filePage targetFileSize) (SETQ volumePage nullVolumePage) (SETQ nextFilePage actualFileSize))) (filePtr ←(create FileDescriptor (SETQ fileID (fetch (Key fileID) of key)) (SETQ volumeID (fetch (LogicalVolumeDescriptor vID) of (LvPagePtr volNum))) (SETQ location (QUOTE local)) (SETQ immutable NIL) (SETQ temporary NIL) (SETQ size actualFileSize) (SETQ type 0))) until (PROGN (\DFSVFMDeletePageGroup (LvPagePtr volNum) filePtr group) (\DFSVAMFreePageGroup (LvPagePtr volNum) filePtr group) (if (ZEROP (fetch (PageGroup filePage) of group)) then (replace (PageGroup nextFilePage) of group with 0) (\DFSVFMDeletePageGroup (LvPagePtr volNum) filePtr group) (\DFSVAMFreePageGroup (LvPagePtr volNum) filePtr group) T else (EQP (fetch (PageGroup filePage) of group) targetFileSize))) do (replace (FileDescriptor size) of filePtr with (fetch (PageGroup filePage) of group)) (replace (PageGroup nextFilePage) of group with (fetch (PageGroup filePage) of group)) (replace (PageGroup filePage) of group with targetFileSize)) (\DFSDsplyVolumes]) (\DFSFindVolumeNumber [LAMBDA (vol) (* hts: "18-May-84 21:51") (* vol: LogicalVolumeDescriptor; RETURNS: FIXP in 1..6) (* Converts vol into a logical volume number, becuase the page reading and writing routines expect a logical volume number rather than the logical volume itself. Should be changed later.) (OR [FIXP (for volNum from 1 to 6 thereis (LVEqual vol (LvPagePtr volNum] (SHOULDNT (QUOTE cantFindLogicalVolume]) ) (* These functions transfer pages to and from the disk) (DEFINEQ (\PvTransferPage [LAMBDA (absoluteDiskAddress BUFFER WRITEFLG) (* hts: "23-May-84 16:17") (* This function modifies the IOCB that controls the Dlion rigid disk. The IOCB was originally stolen from the booting process, and is now inherited by Lisp. It modifies the IOCB to select read/write and the sector/head number to read/write to.) (UNINTERRUPTABLY (SwapIn&Dirty BUFFER) (SETQ \DFSWriteFlg WRITEFLG) (* Call the page reading/writing routine in a special stack environment which will not page fault on frame extension) (\MISCAPPLY*(FUNCTION \PvTransferPageNoSwap) absoluteDiskAddress BUFFER) (* absoluteDiskAddress is just barely a smallp for the Quantum; will have to worry about unboxed arith when we go to large Trident drives) )]) (\PvTransferPageNoSwap [LAMBDA (absoluteDiskAddress buffer) (* hts: "11-May-84 22:56") (* Calls \DL.XFERDISK in a special stack environment that is guaranteed not to page fault. \DFSWriteFlg is passed as a global because \MISCAPPLY* allows only two args to be passed.) (\DL.XFERDISK absoluteDiskAddress buffer \DFSWriteFlg]) (\LvGetPage [LAMBDA (VolNum PageAddr Buffer) (* hts: "23-May-84 16:23") (* Reads a page from the disk and puts the result in Buffer. The page read is the PageAddr'th page of the VolNum'th logical volume.) (* Steve: you should modify this routine to deal with labels correctly. If label is non-NIL, I expect it to be checked.) (if (NOT (FIXP VolNum)) then (SETQ VolNum (\DFSFindVolumeNumber VolNum))) (if (NOT Buffer) then (SETQ Buffer (\DFSGetBuffer))) (* If Buffer does not exist, create a new one.) (\PvTransferPage (IPLUS (\LvBasePageAddr VolNum) PageAddr) Buffer) (* Read the page off the disk) Buffer]) (\LvPutPage [LAMBDA (VolNum PageAddr PagePtr) (* hts: "20-May-84 21:29") (* Writes the contents of PagePtr onto the disk at the PageAddr'th page of the VolNum'th logical volume.) (if (NOT (FIXP VolNum)) then (SETQ VolNum (\DFSFindVolumeNumber VolNum))) (\PvTransferPage (IPLUS (\LvBasePageAddr VolNum) PageAddr) PagePtr T) NIL]) (\LvBasePageAddr [LAMBDA (LVNum) (* SDG "14-NOV-83 13:43") (fetch (SubVolumeDscr PvPage) of (SubVolumeEntryPtr LVNum]) ) (DECLARE: DONTEVAL@LOAD (\LOCKFN (QUOTE \PvTransferPage)) (\LOCKFN (QUOTE \PvTransferPageNoSwap)) (\LOCKVAR (QUOTE \DFSWriteFlg)) ) (* These functions are part of the volume file map (BTree) %. Most of this code has been gutted and moved to the file VolumeFileMap.) (DEFINEQ (\DFSFindPageAddr [LAMBDA (vol file filePage noCheck) (* hts: "20-May-84 21:39") (PROG ((result (\DFSVFMGetPageGroup vol file filePage))) (* GetPageGroup returns a dotted pair whose CAR is NIL iff the fileID was not found, and whose CDR contains a PageGroup indicating the desired pages) (if (NULL (CAR result)) then (SHOULDNT (QUOTE keyNotFound))) [if (ZEROP (fetch (PageGroup volumePage) of (CDR result))) then (if noCheck then (RETURN NIL) else (SHOULDNT (QUOTE keyNotFound] (* Gives a zero volume page iff the fileID is found, but the page specified isn't. noCheck is T only when called to see if the file should be extended.) (RETURN (IPLUS (fetch (PageGroup volumePage) of (CDR result)) filePage (IMINUS (fetch (PageGroup filePage) of (CDR result]) ) (* The following implement the device and directory level parts of the 1108 file system.) (DEFINEQ (\DFSFindDirHole [LAMBDA (WDS DIRSTREAM) (* hts: " 5-Jun-84 13:14") (* Swiped wholesale from mod44io) (* Returns the byte address of a directory hole of size WDS. The directory file is positioned just after the 2-byte length field of the hole.) (PROG ((PTR (OR (fetch DIRHOLEPTR of DIRSTREAM) 0)) T1 C) NEXT(\SETFILEPTR DIRSTREAM PTR) (COND ((\EOFP DIRSTREAM) (GO END)) ((ILESSP 3 (SETQ C (\BIN DIRSTREAM))) (SETQ T1 (\BIN DIRSTREAM)) (* Already occupied) ) [(IGREATERP WDS (SETQ T1 (IPLUS (LLSH C 8) (\BIN DIRSTREAM] (T (\SETFILEPTR DIRSTREAM PTR) (* Hole is large enough) [COND ((IGREATERP T1 WDS) (* Too large, so break it apart.) (SETQ T1 (IDIFFERENCE T1 WDS)) (\WOUT DIRSTREAM T1) (\SETFILEPTR DIRSTREAM (SETQ PTR (IPLUS PTR T1 T1] (GO END))) (SETQ PTR (IPLUS PTR T1 T1)) (GO NEXT) END (\WOUT DIRSTREAM WDS) (RETURN PTR]) (\DFSDEVICEP [LAMBDA (DirSpec) (* hts: "22-May-84 16:50") (PROG (LvNum) (if (NEQ (MACHINETYPE) (QUOTE DANDELION)) then (RETURN NIL)) (\DFSEnsureInitialized) (SETQ LvNum (\DFSGetLvNum (MKSTRING DirSpec))) (RETURN (OR (AND LvNum (LvDevicePtr LvNum)) (AND (EQ (QUOTE DSK) (MKATOM (U-CASE DirSpec))) (PROGN (* Special case for DSK (should really be handled in mod44io): if there is no logical volume for DSK, create a coredevice for it) (printout NIL "Warning: There is no lisp logical volume called DSK." T "Creating coredevice {DSK}." T "{DSK} files will be core files." T "They will not be part of the local file system." T) (\GETDEVICEFROMNAME (COREDEVICE (QUOTE DSK]) (\DFSVOLUMEP [LAMBDA (DirSpec) (* hts: "11-May-84 22:35") (\DFSEnsureInitialized) (\DFSGetLvNum (MKSTRING DirSpec]) (\DFSGenFileID [LAMBDA NIL (* hts: "13-May-84 16:20") (PROG (NewKey) (SETQ NewKey (create Key filePage ← 0)) (\PUTBASE NewKey 0 (CADDR \MY.NSHOSTNUMBER)) (\PUTBASE NewKey 1 (CADDDR \MY.NSHOSTNUMBER)) (\PUTBASE NewKey 2 (IMOD (CLOCK 0) 1000)) (\BLT (\ADDBASE NewKey 3) (DAYTIME) 2) (RETURN NewKey]) (\DFSMakeStrPtr [LAMBDA (Addr Len) (* SDG "17-JUN-83 14:16") (PROG ((STR "Test3")) (\PUTBASEPTR STR 0 Addr) (\PUTBASE STR 2 Len) (RETURN STR]) (\DFSInit [LAMBDA NIL (* hts: " 5-Jun-84 12:17") (UNINTERRUPTABLY (OR (EQ (MACHINETYPE) (QUOTE DANDELION)) (ERROR (QUOTE attemptToRunDFSOnNon1108))) (OR \DFSReadVolumes (\DFSGetVolumeInfo)) (\DFSVAMInit) (\DFSVFMInit) (SETQ \DFSDevices (ARRAY 6)) (SETQ \DirStreams (ARRAY 6)) (for volNum from 1 to (fetch (PhysVolumeDscr SubVolCount) of \PhysVolumePage) when (EQ (fetch (LogicalVolumeDescriptor type) of (LvPagePtr volNum)) DFSLispVolume) do (if (NOT (\DFSDeviceConflict (MKATOM (\DFSGetLvName volNum)) (QUOTE smashDFSDevice))) then (\DFSOpenDiskDevice volNum))) (* Create a lisp file device for every logical volume marked to be a lisp logical volume) (SETQ \DFSMachineId \MY.NSHOSTNUMBER) (SETQ \DFSInitialized T) (\DFSDsplyVolumes))]) (\DFSEnsureInitialized [LAMBDA NIL (* hts: "11-May-84 22:43") (if (NOT (AND (BOUNDP (QUOTE \DFSInitialized)) \DFSInitialized)) then (\DFSInit]) (\DFSGetVolumeInfo [LAMBDA NIL (* edited: " 8-Jun-84 00:35") [if (NOT (BOUNDP \PhysVolumePage)) then (SETQ \PhysVolumePage (NCREATE (QUOTE VMEMPAGEP] (\PvTransferPage 0 \PhysVolumePage NIL) (if (NOT (BOUNDP (QUOTE \LogicalVolumes))) then (SETQ \LogicalVolumes (ARRAY 6))) (for volNum from 1 to (fetch (PhysVolumeDscr SubVolCount) of \PhysVolumePage) do [if (NULL (ELT \LogicalVolumes volNum)) then (SETA \LogicalVolumes volNum (NCREATE (QUOTE VMEMPAGEP] (\LvGetPage volNum 0 (ELT \LogicalVolumes volNum)) (* Cache the logical volume pages)) (SETQ \DFSReadVolumes T) (* Note that this routine has been run) ]) (\DFSGetBuffer [LAMBDA NIL (* SDG "14-NOV-83 15:56") (NCREATE (QUOTE VMEMPAGEP]) (\DFSGetPvName [LAMBDA NIL (* SDG "14-NOV-83 14:41") (\DFSMakeStrPtr (FADDR \PhysVolumePage (PhysVolumeDscr Name)) (fetch (PhysVolumeDscr NameLength) of \PhysVolumePage]) (\DFSGetLvName [LAMBDA (VolNum) (* hts: " 2-May-84 14:59") (U-CASE (\DFSMakeStrPtr (FADDR (LvPagePtr VolNum) (LogicalVolumeDscr Name)) (fetch (LogicalVolumeDscr NameLength) of (LvPagePtr VolNum]) (\DFSGetLvNum [LAMBDA (LvName) (* hts: " 3-May-84 09:08") (SETQ LvName (U-CASE LvName)) (for I from 1 to (fetch (PhysVolumeDscr SubVolCount) of \PhysVolumePage) do (if (STREQUAL (\DFSGetLvName I) LvName) then (RETURN I]) (\DFSHostNameP [LAMBDA NIL (* SDG "30-JUN-83 15:23") NIL]) (\DFSOpenDiskDevice [LAMBDA (VolNum) (* hts: "17-May-84 10:51") (UNINTERRUPTABLY (PROG ((volumeName (MKATOM (\DFSGetLvName VolNum))) DEV) (SETQ DEV (create FDEV DEVICENAME ← volumeName FDBINABLE ← T FDBOUTABLE ← T FDEXTENDABLE ← T RESETABLE ← T RANDOMACCESSP ← T NODIRECTORIES ← T PAGEMAPPED ← T CLOSEFILE ←(FUNCTION \DFSCloseFile) DELETEFILE ←(FUNCTION \DFSDeleteFile) GETFILEINFO ←(FUNCTION \DFSGetFileInfo) GETFILENAME ←(FUNCTION \DFSGetFileName) OPENFILE ←(FUNCTION \DFSOpenFile) READPAGES ←(FUNCTION \DFSReadPages) SETFILEINFO ←(FUNCTION \DFSSetFileInfo) TRUNCATEFILE ←(FUNCTION \DFSTruncateFile) WRITEPAGES ←(FUNCTION \DFSWritePages) REOPENFILE ←(FUNCTION \DFSOpenFile) GENERATEFILES ←(FUNCTION \DFSGenerateFiles) EVENTFN ←(FUNCTION \DFSEventFn) DEVICEINFO ←(LvPagePtr VolNum) DIRECTORYNAMEP ←(FUNCTION \DFSDirectoryNameP) HOSTNAMEP ←(FUNCTION \DFSHostNameP) BIN ←(FUNCTION \PAGEDBIN) BOUT ←(FUNCTION \PAGEDBOUT) PEEKBIN ←(FUNCTION \PAGEDPEEKBIN) BACKFILEPTR ←(FUNCTION \PAGEDBACKFILEPTR) SETFILEPTR ←(FUNCTION \PAGEDSETFILEPTR) GETFILEPTR ←(FUNCTION \PAGEDGETFILEPTR) GETEOFPTR ←(FUNCTION \PAGEDGETEOFPTR) EOFP ←(FUNCTION \PAGEDEOFP) BLOCKIN ←(FUNCTION \PAGEDBINS) BLOCKOUT ←(FUNCTION \PAGEDBOUTS) FLUSHOUTPUT ←(FUNCTION \PAGED.FLUSHOUTPUT))) (SETA \DFSDevices VolNum DEV) (if (EQ DFSLispVolume (fetch (LogicalVolumeDescriptor type) of (LvPagePtr VolNum))) then (replace (DLIONDISK DirectoryStream) of DEV with (\DFSOpenDirectory DEV))) (\DEFINEDEVICE volumeName DEV) (printout NIL "Created local disk device {" volumeName "}" T) (RETURN DEV)))]) (\DFSCloseFile [LAMBDA (STREAM) (* hts: " 5-Jun-84 10:37") (* Update EOF in leader page) (UNINTERRUPTABLY (PROG ((BUFFER (\DFSGetBuffer))) (RELEASECPAGE STREAM) (\CLEARMAP STREAM) (if (NEQ (fetch ACCESS of STREAM) (QUOTE INPUT)) then (\DFSTrimFile STREAM) (SETQ BUFFER (\DFSReadLeaderPage STREAM BUFFER)) (replace (DFSLeaderPage EofPage) of BUFFER with (fetch (STREAM EPAGE) of STREAM)) (replace (DFSLeaderPage EOffSet) of BUFFER with (fetch (STREAM EOFFSET) of STREAM)) (replace (DFSLeaderPage AllocatedPages) of BUFFER with (IPLUS (fetch (STREAM EPAGE) of STREAM) (if (ZEROP (fetch EOFFSET of STREAM)) then 1 else 2))) (\DFSWriteLeaderPage STREAM BUFFER)) (RETURN STREAM)))]) (\DFSDirectoryNameP [LAMBDA (DirSpec) (* hts: " 5-Jun-84 12:13") (UNINTERRUPTABLY (PROG ((Volume (FILENAMEFIELD DirSpec (QUOTE HOST))) LvNum) (SETQ LvNum (\DFSVOLUMEP Volume)) (RETURN (if (AND LvNum (fetch DirectoryStream of (LvDevicePtr LvNum)) (\DFSUnpackName DirSpec)) then T else NIL))))]) (\DFSEventFn [LAMBDA (Dev Event) (* hts: " 5-Jun-84 11:57") (UNINTERRUPTABLY (SELECTQ Event ((AFTERLOGOUT AFTERSYSOUT AFTERMAKESYS AFTERSAVEVM) (OR \DFSReadVolumes (\DFSGetVolumeInfo)) (PROG (LvNum) (if [NOT (AND (EQUAL \DFSMachineId \MY.NSHOSTNUMBER) [SETQ LvNum (\DFSGetLvNum (MKSTRING (fetch (FDEV DEVICENAME) of Dev] (EQ DFSLispVolume (fetch (LogicalVolumeDescriptor type) of (LvPagePtr LvNum] then (replace (FDEV REOPENFILE) of Dev with (FUNCTION NILL)) (* ensure that no local files from another machine (or the same machine with changed logical volumes) will be reopened) (\REMOVEDEVICE Dev) (printout NIL "Device {" (fetch (FDEV DEVICENAME) of Dev) "} has disappeared." T) (SETQ \DFSInitialized NIL) (* Make the 1108 file system reinitialize itself) )) (if (NOT (EQ (MACHINETYPE) (QUOTE DANDELION))) then (\OPENDISKDEVICE 0) (* Open mod44 disk))) (BEFORELOGOUT (if (fetch DirectoryStream of Dev) then (\FLUSH.OPEN.STREAMS Dev)) (SETQ \DFSReadVolumes NIL)) NIL))]) (\DFSGetFileInfo [LAMBDA (STREAM ATTRIBUTE DEV) (* hts: " 5-Jun-84 10:41") (* Get the value of the ATTRIBUTE for a model44 file. If STREAM is a filename, then the file is not open.) (UNINTERRUPTABLY [PROG (BUFFER STREAMPASSED) (SETQ STREAMPASSED (type? STREAM STREAM)) (RETURN (if [OR STREAMPASSED (SETQ STREAM (\DFSGetStreamForFile STREAM (QUOTE OLD) (QUOTE INPUT) DEV NIL (\DFSGetBuffer] then (SETQ BUFFER (\DFSGetBuffer)) (if (NEQ ATTRIBUTE (QUOTE LENGTH)) then (\LvGetPage (fetch (DLIONDISK VolNum) of DEV) (\DFSFindPageAddr (fetch (FDEV DEVICEINFO) of DEV) (create FileDescriptor fileID ←(fetch (Key fileID) of (fetch (DLIONSTREAM FID) of STREAM)) volumeID ←(fetch ( LogicalVolumeDescriptor vID) of (fetch (FDEV DEVICEINFO) of DEV)) location ←(QUOTE local) immutable ← NIL temporary ← NIL type ← 0) 0) BUFFER)) (SELECTQ ATTRIBUTE (LENGTH (if (NOT STREAMPASSED) then (SETQ STREAM (\DFSCompleteStream STREAM BUFFER)) else (\UPDATEOF STREAM)) (IPLUS (fetch (STREAM EOFFSET) of STREAM) (ITIMES (fetch (STREAM EPAGE) of STREAM) 512))) (WRITEDATE (GDATE (fetch (DFSLeaderPage TimeWrite) of BUFFER))) (READDATE (GDATE (fetch (DFSLeaderPage TimeRead) of BUFFER))) (CREATIONDATE (GDATE (fetch (DFSLeaderPage TimeCreate) of BUFFER))) (IWRITEDATE (fetch (DFSLeaderPage TimeWrite) of BUFFER)) (IREADDATE (fetch (DFSLeaderPage TimeRead) of BUFFER)) (ICREATIONDATE (fetch (DFSLeaderPage TimeCreate) of BUFFER)) [AUTHOR (PROG ((AuthorStart (FADDR BUFFER (DFSLeaderPage AuthorName)) ) (AuthorLength (fetch (DFSLeaderPage AuthorLength) of BUFFER))) (RETURN (if (IGREATERP AuthorLength 0) then [PACK (for I from 0 to (SUB1 AuthorLength) collect (CHARACTER (\GETBASEBYTE AuthorStart I] else (QUOTE ????] NIL])]) (\DFSGetFileName [LAMBDA (FileName Recog Dev) (* hts: " 5-Jun-84 10:42") (UNINTERRUPTABLY (fetch DFSNAME of (\DFSFileSpec FileName Recog (fetch DirectoryStream of Dev))))]) (\DFSReadPages [LAMBDA (Stream FirstPage Buffers) (* hts: " 5-Jun-84 11:53") (UNINTERRUPTABLY (for Buffer inside Buffers as Page from FirstPage sum (\DFSReadOnePage Stream Page Buffer)))]) (\DFSSetFileInfo [LAMBDA (Stream Attribute Value Device) (* hts: " 5-Jun-84 11:54") (UNINTERRUPTABLY [PROG ((BUFFER (\DFSGetBuffer)) STREAMPASSED) (SETQ STREAMPASSED (type? STREAM Stream)) (RETURN (COND ((OR STREAMPASSED (SETQ Stream (\DFSGetStreamForFile Stream (QUOTE OLD) (QUOTE INPUT) Device NIL BUFFER))) (\DFSReadLeaderPage Stream BUFFER) (SELECTQ Attribute (CREATIONDATE (replace (DFSLeaderPage TimeCreate) of BUFFER with (IDATE Value))) (ICREATIONDATE (replace (DFSLeaderPage TimeCreate) of BUFFER with Value)) [AUTHOR (PROG ((AuthorStart (FADDR BUFFER (DFSLeaderPage AuthorName))) (Value (CHCON Value)) AuthorLength) (SETQ AuthorLength (LENGTH Value)) (replace (DFSLeaderPage AuthorLength) of BUFFER with AuthorLength) (for I from 0 to (SUB1 AuthorLength) as C in Value do (\PUTBASEBYTE AuthorStart I C] (SETQ Value NIL)) (\DFSWriteLeaderPage Stream BUFFER) Value])]) (\DFSTrimFile [LAMBDA (Stream actualPages) (* hts: "24-May-84 20:33") (PROG ((Buffer (\DFSGetBuffer)) (DEV (fetch DEVICE of Stream)) VolNum Key desiredPages actualPages) (FLUSHMAP Stream) (SETQ VolNum (fetch (DLIONDISK VolNum) of DEV)) (SETQ Key (fetch FID of Stream)) (SETQ desiredPages (IPLUS (fetch EPAGE of Stream) (if (ZEROP (fetch EOFFSET of Stream)) then 1 else 2))) (SETQ actualPages (fetch (DLIONSTREAM LastAllocated) of Stream)) (\DFSTrimHelper VolNum Key desiredPages actualPages) (* \DFSTrimHelper will take the requisite pages out of the BTree. desiredPages is the desired number of pages in the file, and actualPages is the number of pages actually in the file.) (RETURN Stream]) (\DFSTruncateFile [LAMBDA (STREAM LP EP UpdateNow) (* SDG "29-JUN-83 13:00") NIL]) (\DFSWritePages [LAMBDA (Stream FirstPage Buffers) (* hts: " 5-Jun-84 13:41") (UNINTERRUPTABLY (for Buffer inside Buffers as Page from FirstPage do (\DFSWriteOnePage Stream Page Buffer)))]) (\DFSUnpackName [LAMBDA (NAME) (* edited: "10-Jan-84 17:28") (* Unpacks file name into a DFSUnpackedName of the form ((VERSION VOLNUM . ESCFLAG) . CHARPAIRS) where VERSION is the version indicator (either a positive integer or one of OLD, OLDEST, NEW) PARTNUM is the logical volume number and ESCFLAG indicates that NAME terminated in escape, and the CHARPAIRS is a list of pairs the first element of which is the char actually specified in name, and the second is the upper/lower case alternative for alphabetics.) (* changed to generate a file not found error in the case that a directory is specified - rrb.) (PROG (J C END NEGATEDVERSION VERSION RESULT VOLNUM) (COND ([OR (NOT NAME) (EQ NAME T) (NEQ (NTHCHARCODE NAME 1) (CHARCODE {)) (NOT (SETQ J (STRPOS "}" NAME))) (NOT (SETQ VOLNUM (\DFSGetLvNum (SUBSTRING NAME 2 (SUB1 J] (RETURN))) (SETQ END (SETQ RESULT (create DFSUnpackedName PARTNUM ← VOLNUM))) (* End is the cell whose CDR can be smashed.) (add J 1) COLLECTNAME (COND ((NOT (SETQ C (NTHCHARCODE NAME J))) (GO RET)) (T [RPLACD END (SETQ END (LIST (COND [(BETWEEN C (CHARCODE A) (CHARCODE Z)) (LIST C (IPLUS C (IDIFFERENCE (CHARCODE a) (CHARCODE A] [(BETWEEN C (CHARCODE a) (CHARCODE z)) (LIST C (IDIFFERENCE C (IDIFFERENCE (CHARCODE a) (CHARCODE A] ((BETWEEN C (CHARCODE 0) (CHARCODE 9)) (LIST C)) (T (SELCHARQ C ((; !) (GO SEMI)) ((< >) (LIST C)) ((ESCAPE *) (replace ESCFLAG of RESULT with T) (SETQ C (NTHCHARCODE NAME (add J 1))) (GO TERM)) (%. (* Omit trailing dots) (SELCHARQ (NTHCHARCODE NAME (ADD1 J)) (NIL (GO RET)) ((; !) (add J 1) (GO SEMI)) (LIST C))) (($ + -) (LIST C)) (GO ERR] (add J 1) (GO COLLECTNAME))) SEMI[SELCHARQ (SETQ C (NTHCHARCODE NAME (add J 1))) ((H h) (SETQQ VERSION OLD) (SELCHARQ (SETQ C (NTHCHARCODE NAME (add J 1))) (NIL (GO RET)) ((; !) (GO SEMI)) (GO ERR))) ((L l) (SETQQ VERSION OLDEST) (SELCHARQ (SETQ C (NTHCHARCODE NAME (add J 1))) (NIL (GO RET)) ((; !) (GO SEMI)) (GO ERR))) ((N n) (SETQQ VERSION NEW) (SELCHARQ (SETQ C (NTHCHARCODE NAME (add J 1))) (NIL (GO RET)) ((; !) (GO SEMI)) (GO ERR))) [(T t S s A a P p) (* Various Tenex crocks. Not implemented, but don't complain about them) (PROG NIL SKIP(SELCHARQ (NTHCHARCODE NAME (add J 1)) ((; !) (GO SEMI)) (NIL (GO RET)) (GO SKIP] [- (COND (VERSION (GO ERR)) (T (SETQ NEGATEDVERSION T) (SETQ VERSION 0) (SETQ C (NTHCHARCODE NAME (add J 1))) (GO COLLECTVERSION] (NIL (GO ERR)) (COND (VERSION (GO ERR)) (T (SETQ VERSION 0) (GO COLLECTVERSION] COLLECTVERSION (COND ((AND C (BETWEEN C (CHARCODE 0) (CHARCODE 9))) [SETQ VERSION (IPLUS (ITIMES VERSION 10) (IDIFFERENCE C (CHARCODE 0] (SETQ C (NTHCHARCODE NAME (add J 1))) (GO COLLECTVERSION))) (COND [NEGATEDVERSION (SETQ VERSION (SELECTQ VERSION (1 (QUOTE NEW)) (2 (QUOTE OLDEST)) (GO ERR] ((ZEROP VERSION) (SETQQ VERSION OLD)) ((IGREATERP VERSION 65535) (GO ERR))) TERM(SELCHARQ C (NIL (GO RET)) ((; !) (GO SEMI)) (GO ERR)) ERR (* BAD FILE NAME) (RETURN NIL) RET (replace VERSION of RESULT with VERSION) (RETURN RESULT]) (\DFSUNAMELength [LAMBDA (UNAME) (* edited: "16-SEP-83 14:59") (LENGTH (fetch CHARPAIRS of UNAME]) (\DFSZeroBuffer [LAMBDA (Buffer) (* SDG " 5-AUG-83 20:27") (for I from 0 to 255 do (\PUTBASE Buffer I 0]) (\DFSMakeVolumeDirectory [LAMBDA (dev) (* hts: "15-May-84 20:07") (PROG ((vol (LvPagePtr (LvNum dev))) (key (\DFSGenFileID)) (buffer (\DFSGetBuffer)) [dirName (\DFSUnpackName (PACK* (QUOTE {) (fetch DEVICENAME of dev) (QUOTE }) (QUOTE DIRECTORY;1] file) [SETQ dirName (\DFSUnpackName (PACK* (QUOTE {) (fetch DEVICENAME of dev) (QUOTE }) (QUOTE DIRECTORY;1] (SETQ file (create FileDescriptor fileID ←(fetch (Key fileID) of key) volumeID ←(fetch (LogicalVolumeDescriptor vID) of vol) location ←(QUOTE local) immutable ← NIL temporary ← NIL type ← 0)) (\DFSNewPages vol file (create PageGroup filePage ← 0 volumePage ← 0 nextFilePage ← 50)) (UNINTERRUPTABLY (SETQ buffer (\DFSMakeLeaderPage dirName key 20 buffer)) (\LvPutPage vol (fetch (PageGroup volumePage) of (CDR (\DFSVFMGetPageGroup vol file 0))) buffer)) (* Make and put a leader page for the directory file) (UNINTERRUPTABLY (MESASETQ (fetch (LogicalVolumeDescriptor volumeRootDirectory) of vol) (fetch (Key fileID) of key) ID) (\LvPutPage vol 0 vol)) (* Record the ID of the directory file) (UNINTERRUPTABLY (replace (DLIONDISK DirectoryStream) of dev with (\DFSOpenDirectory dev))) (printout NIL "Created directory for device {" (fetch DEVICENAME of dev) "}" T) (RETURN key]) (\DFSOpenDirectory [LAMBDA (dev) (* hts: "15-May-84 20:07") (UNINTERRUPTABLY (PROG (DirStream DirKey) [SETQ DirKey (create Key fileID ←(fetch (LogicalVolumeDescriptor volumeRootDirectory) of (fetch DEVICEINFO of dev] (SETQ DirStream (\DFSOpenFileFromKey dev (\DFSUnpackName (PACK* (QUOTE {) (fetch DEVICENAME of dev) (QUOTE }) (QUOTE DIRECTORY.;1))) (QUOTE BOTH) NIL DirKey (\DFSGetBuffer))) (SETQ DirStream (\OPENFILE DirStream (QUOTE BOTH))) [replace MAXBUFFERS of DirStream with (IMAX 20 (ADD1 (fetch EPAGE of DirStream] (RETURN DirStream)))]) (\DFSMakeLeaderPage [LAMBDA (Name Key Pages LeaderPage Info) (* hts: "16-May-84 10:20") (PROG ([CurrentTime (IDATE (CADR (FASSOC (QUOTE CREATIONDATE) Info] [Author (CHCON (OR (CADR (FASSOC (QUOTE AUTHOR) Info)) (USERNAME] AuthorStart LeaderNameStart) (SETQ LeaderPage (OR LeaderPage (\DFSGetBuffer))) (\DFSZeroBuffer LeaderPage) (SETQ AuthorStart (LOCF (fetch (DFSLeaderPage AuthorName) of LeaderPage))) (SETQ LeaderNameStart (ITIMES (IDIFFERENCE [CDR (LOC (LOCF (fetch (DFSLeaderPage FileName) of LeaderPage] (CDR (LOC LeaderPage))) 2)) (replace TimeCreate of LeaderPage with CurrentTime) (replace TimeWrite of LeaderPage with CurrentTime) (\BLT (FADDR LeaderPage (DFSLeaderPage FileKey)) Key 7) (replace (DFSLeaderPage AllocatedPages) of LeaderPage with Pages) (replace (DFSLeaderPage EofPage) of LeaderPage with 0) (replace (DFSLeaderPage EOffSet) of LeaderPage with 0) (replace (DFSLeaderPage NameLength) of LeaderPage with (\DFSMoveToLeader Name LeaderPage LeaderNameStart)) (replace (DFSLeaderPage AuthorLength) of LeaderPage with (LENGTH Author)) (for I from 0 to (SUB1 (fetch (DFSLeaderPage AuthorLength) of LeaderPage)) as C in Author do (\PUTBASEBYTE AuthorStart I C)) (RETURN LeaderPage]) (\DFSOpenFileFromKey [LAMBDA (Dev Name Access DirInfo Key Buffer) (* hts: "11-May-84 16:21") (PROG (STREAM) (if (NULL Key) then (RETURN)) (SETQ STREAM (create DLIONSTREAM)) (replace FULLFILENAME of STREAM with (\DFSFullFileName Name)) (replace DEVICE of STREAM with Dev) (replace FID of STREAM with Key) (replace TRANSFERKEY of STREAM with (create Key fileID ←(fetch FID of STREAM))) (replace DIRINFO of STREAM with (OR DirInfo -1)) (\DFSCompleteStream STREAM Buffer) (RETURN STREAM]) (\DFSDeleteFile [LAMBDA (FileName Dev) (* hts: " 5-Jun-84 10:40") (UNINTERRUPTABLY (PROG ((Buffer (\DFSGetBuffer)) (VolNum (fetch VolNum of Dev)) Stream DirStream Key actualPages) (SETQ Stream (\DFSGetStreamForFile FileName (QUOTE OLDEST) (QUOTE BOTH) Dev NIL Buffer NIL)) (if (OR (NOT Stream) (bind (NAME ←(fetch FULLFILENAME of Stream)) find ST in \OPENFILES suchthat (EQ (fetch FULLFILENAME of ST) NAME))) then (RETURN)) (SETQ Key (fetch FID of Stream)) (SETQ actualPages (fetch (DLIONSTREAM LastAllocated) of Stream)) (\DFSTrimHelper VolNum Key 0 actualPages) (* Take the entire file out of the BTree and out of the allocation map) (SETQ DirStream (fetch DirectoryStream of Dev)) (\SETFILEPTR DirStream (fetch (DLIONSTREAM DIRINFO) of Stream)) (\BOUT DirStream (LOGAND 3 (\PEEKBIN DirStream))) (FLUSHMAP DirStream) (replace FID of Stream with NIL) (replace (DLIONSTREAM TRANSFERKEY) of Stream with NIL) (RETURN (fetch FULLFILENAME of Stream))))]) (\DFSMakeDirEntry [LAMBDA (FID UNAME FDEV) (* hts: " 5-Jun-84 13:14") (* Makes a directory entry for a new file) (UNINTERRUPTABLY (PROG ((DirStream (fetch (DLIONDISK DirectoryStream) of FDEV)) (NC (\DFSUNAMELength UNAME)) POS SIZE LeaderPage) (SETQ SIZE (FOLDHI (IPLUS NC 16) BYTESPERWORD)) (* The 16 is 1 word marker, 5 words fileID, 1 byte string length (for filename), 1 byte !, and 1 word version number) (SETQ POS (\DFSFindDirHole SIZE DirStream)) (for I from 0 to 4 do (\WOUT DirStream (\GETBASE FID I))) (\BOUT DirStream NC) (* This byte says # chars in filename (exclusive of ! and version #)) [for C in (fetch CHARPAIRS of UNAME) do (\BOUT DirStream (UCASECHAR (CAR C] (\BOUT DirStream (CHARCODE !)) (\WOUT DirStream (fetch VERSION of UNAME)) (\SETFILEPTR DirStream POS) (\BOUT DirStream (LOGOR 4 (\PEEKBIN DirStream))) (* When everything is ready, finally change the type from hole to file.) (FLUSHMAP DirStream) (SETQ LeaderPage (\DFSReadLeaderPage DirStream (\DFSGetBuffer))) (replace EofPage of LeaderPage with (fetch EPAGE of DirStream)) (replace EOffSet of LeaderPage with (fetch EOFFSET of DirStream)) (\DFSWriteLeaderPage DirStream LeaderPage) (RETURN POS)))]) (\DFSReadOnePage [LAMBDA (Stream Page Buffer) (* hts: "20-May-84 21:13") (PROG ((VolNum (LvNum (fetch (STREAM DEVICE) of Stream))) (Key (fetch TRANSFERKEY of Stream))) (if (OR (ILESSP Page (fetch EPAGE of Stream)) (AND (EQUAL Page (fetch EPAGE of Stream)) (IGREATERP (fetch EOFFSET of Stream) 0))) then (\LvGetPage VolNum (\DFSFindPageAddr (LvPagePtr VolNum) (create FileDescriptor fileID ←(fetch (Key fileID) of Key) volumeID ←(fetch ( LogicalVolumeDescriptor vID) of (LvPagePtr VolNum)) location ←(QUOTE local) immutable ← NIL temporary ← NIL type ← 0) (ADD1 Page)) Buffer) (BLOCK) (RETURN 256) else (\DFSZeroBuffer Buffer) (BLOCK) (RETURN 0]) (\DFSWriteOnePage [LAMBDA (Stream Page Buffer) (* hts: "20-May-84 21:52") (PROG ((vol (fetch (FDEV DEVICEINFO) of (fetch (STREAM DEVICE) of Stream))) (Key (fetch TRANSFERKEY of Stream)) filePtr volumePage) (SETQ Page (ADD1 Page)) (SETQ filePtr (create FileDescriptor fileID ←(fetch (Key fileID) of Key) volumeID ←(fetch (LogicalVolumeDescriptor vID) of vol) location ←(QUOTE local) immutable ← NIL temporary ← NIL type ← 0)) (SETQ volumePage (\DFSFindPageAddr vol filePtr Page T)) (if (NULL volumePage) then (* if this page is beyond the last allocated page of the file, extend the file another chunk) (\DFSExtendFile Stream Page Key) (SETQ volumePage (\DFSFindPageAddr vol filePtr Page T))) (\LvPutPage vol volumePage Buffer) (BLOCK]) (\DFSCreateFile [LAMBDA (fileName dev buffer pages info) (* hts: "15-May-84 19:58") (PROG ((vol (LvPagePtr (LvNum dev))) (key (\DFSGenFileID)) (initialAlloc (OR pages 64)) buffer file) (* Why the fuck is buffer here as well as an arg??? Why is buffer passed in at all??) [if (NLISTP fileName) then (SETQ fileName (fetch UNAME of (\DFSFileSpec fileName (QUOTE NEW) (fetch DirectoryStream of dev] (SETQ file (create FileDescriptor fileID ←(fetch (Key fileID) of key) volumeID ←(fetch (LogicalVolumeDescriptor vID) of vol) location ←(QUOTE local) immutable ← NIL temporary ← NIL type ← 0)) (\DFSNewPages vol file (create PageGroup filePage ← 0 volumePage ← 0 nextFilePage ← initialAlloc)) (UNINTERRUPTABLY (SETQ buffer (\DFSMakeLeaderPage fileName key initialAlloc buffer info)) (\LvPutPage vol (fetch (PageGroup volumePage) of (CDR (\DFSVFMGetPageGroup vol file 0))) buffer)) (* Create leader page for the new file and put it) (\DFSMakeDirEntry key fileName dev) (* Enter the new file in the directory) (RETURN key]) (\DFSNewPages [LAMBDA (vol file group) (* hts: "18-May-84 23:57") (* Attempts to allocate needed pages for file. Returns a list of intervals allocated. Interval represented as dotted pair (startPage . #ofPages)) (PROG ((lastPageAllocated (fetch (PageGroup filePage) of group)) currentGroup) (until (EQP lastPageAllocated (fetch (PageGroup nextFilePage) of group)) do (SETQ currentGroup (create PageGroup filePage ← lastPageAllocated volumePage ← 0 nextFilePage ←(fetch (PageGroup nextFilePage) of group))) (\DFSVAMAllocPageGroup vol file currentGroup) (* Allocate as many pages of the desired group as possible) (\DFSVFMInsertPageGroup vol file currentGroup) (* Stick the newly allocated group into the volume file map BTree) (if \DFSCheck then (\DFSCheck vol file currentGroup)) (SETQ lastPageAllocated (fetch (PageGroup nextFilePage) of currentGroup))) (\DFSDsplyVolumes]) (\DFSOpenFile [LAMBDA (NAME ACCESS RECOG OTHERINFO FDEV OLDSTREAM) (* hts: " 5-Jun-84 11:40") (* Open a Model44 file. Gets the physical end of file and sets up ofd) (UNINTERRUPTABLY (PROG ([PAGESTIMATE (AND (NEQ ACCESS (QUOTE INPUT)) (for X in OTHERINFO when (EQ (CAR (LISTP X)) (QUOTE LENGTH)) do (RETURN (ADD1 (FOLDHI (CADR X) BYTESPERPAGE] (BUFFER (\DFSGetBuffer)) STREAM) (OR (SETQ STREAM (if (NOT (type? STREAM NAME)) then (\DFSGetStreamForFile NAME RECOG ACCESS FDEV (AND (NEQ ACCESS (QUOTE INPUT)) (OR PAGESTIMATE T)) BUFFER NIL PAGESTIMATE OTHERINFO) else (\DFSCompleteStream NAME BUFFER))) (RETURN NIL)) (if (EQ ACCESS (QUOTE OUTPUT)) then (* File is EMPTY even if it is old) (replace EPAGE of STREAM with (replace EOFFSET of STREAM with 0))) (* Leader page is read in during STREAM initialization) (if (AND (NOT OLDSTREAM) (NOT (FMEMB (QUOTE DON'T.CHANGE.DATE) OTHERINFO))) then (\DFSUpdateAccessTimes STREAM ACCESS BUFFER) (* For REOPENFILE op, don't change dates) (* Resets validation) (* We write out accumulated changes to leader page) ) (\DFSWriteLeaderPage STREAM BUFFER) (RETURN STREAM)))]) (\DFSUpdateAccessTimes [LAMBDA (STREAM ACCESS BUF) (* edited: "10-Jan-84 17:21") (* The leader page of STREAM has been read into buffer. Set the "last read" and/or "last written" times in the BUF according to access, which is assumed to be either INPUT, OUTPUT, BOTH, or APPEND.) (PROG ((DT (DAYTIME))) (\DFSReadLeaderPage STREAM BUF) (SELECTQ ACCESS ((OUTPUT BOTH APPEND) (replace TimeWrite of BUF with DT)) NIL) (SELECTQ ACCESS ((INPUT BOTH) (replace TimeRead of BUF with DT)) NIL]) (\DFSExtendFile [LAMBDA (stream page key) (* hts: "15-May-84 20:11") (PROG [[vol (LvPagePtr (fetch VolNum of (fetch DEVICE of stream] (leader (\DFSReadLeaderPage stream (\DFSGetBuffer))) (allocate (MAX 64 (IDIFFERENCE page (fetch LastAllocated of stream] (\DFSNewPages vol (create FileDescriptor fileID ←(fetch (Key fileID) of key) volumeID ←(fetch (LogicalVolumeDescriptor vID) of vol) location ←(QUOTE local) immutable ← NIL temporary ← NIL type ← 0) (create PageGroup filePage ←(fetch LastAllocated of stream) volumePage ← 0 nextFilePage ←(IPLUS (fetch LastAllocated of stream) allocate))) (UNINTERRUPTABLY (add (fetch AllocatedPages of leader) allocate) (replace EofPage of leader with page) (replace LastAllocated of stream with (fetch AllocatedPages of leader)) (\DFSWriteLeaderPage stream leader)) (* Fix up leader page and stream) ]) (\DFSCompleteStream [LAMBDA (STREAM SCRBUFF) (* hts: "13-May-84 13:42") (* Completes the fields of a file handle that describes an existing file by reading in its leader page which it leaves for its caller) (PROG ((Leader (\DFSReadLeaderPage STREAM SCRBUFF))) (* Get the page number and the number of bytes on the last page of the file specified by fHandle. If the last page number hint is wrong in the leader page, then find the real last page and change the hint.) (* UPDATEVALIDATION STREAM BUF) (* Validation is low order bits of creation and write dates) (replace LastAllocated of STREAM with (fetch AllocatedPages of Leader)) (replace EPAGE of STREAM with (fetch EofPage of Leader)) (replace EOFFSET of STREAM with (fetch EOffSet of Leader))) STREAM]) (\DFSGetStreamForFile [LAMBDA (NAME RECOG ACCESS FDEV CREATEFLG SCRBUFF FAST PAGES OTHERINFO) (* hts: "12-May-84 00:35") (* Creates a STREAM for dsk file NAME, creating it if necessary when CREATEFLG is true. SCRBUFF is a scratch buffer for manipluating the leader page. If FAST is true, does not fill in any fields of STREAM that would require reading the file, e.g., the length and full map) (PROG ((DIROFD (fetch (DLIONDISK DirectoryStream) of FDEV)) FS STREAM FileKey) (SETQ FS (\DFSFileSpec NAME RECOG (fetch DirectoryStream of FDEV))) (RETURN (if (NULL DIROFD) then (* Non-existent device) NIL elseif (for OpenFile in \OPENFILES thereis (EQUAL (fetch DFSNAME of FS) (fetch FULLNAME of OpenFile))) elseif (fetch FSDIRPTR of FS) then (\SETFILEPTR DIROFD (IPLUS 2 (fetch FSDIRPTR of FS))) (SETQ STREAM (create DLIONSTREAM)) (SETQ FileKey (create Key)) (for I from 0 to 4 do (\PUTBASE FileKey I (\WIN DIROFD))) (replace FULLFILENAME of STREAM with (fetch DFSNAME of FS)) (replace DEVICE of STREAM with FDEV) (replace FID of STREAM with FileKey) (replace TRANSFERKEY of STREAM with (create Key fileID ←(fetch FID of STREAM))) (replace DIRINFO of STREAM with (fetch FSDIRPTR of FS)) (\DFSCompleteStream STREAM SCRBUFF) STREAM elseif (NULL (CAR (fetch VERSION of FS))) then NIL elseif (IGREATERP (CAR (fetch VERSION of FS)) MAX.SMALLP) then (ERROR "Version number limit is 65535 on 1108 File System") elseif CREATEFLG then (SETQ FileKey (\DFSCreateFile (fetch UNAME of FS) FDEV SCRBUFF PAGES OTHERINFO)) (\DFSOpenFileFromKey FDEV (fetch UNAME of FS) ACCESS NIL FileKey SCRBUFF]) (\DFSFileSpec [LAMBDA (NAME RECOG DIROFD) (* hts: "14-May-84 09:45") (* This returns a full file specification, with all the information needed to do open, delete, etc. A filespec is a (packedname unpackedname dirptr) triple, with the true version number smashed into the uname. The dirptr is NIL if the file does not currently exist in the directory.) (PROG (DP V L (UNAME (\DFSUnpackName NAME))) [if (NULL DIROFD) then (printout NIL "No LISP directory on volume " (\DFSGetLvName (fetch PARTNUM of UNAME)) T) (RETURN (create DFSFileSpec UNAME ← NIL)) elseif (NULL UNAME) then (* BAD FILE NAME) (RETURN (create DFSFileSpec UNAME ← NIL)) elseif [AND (SETQ L (\DFSVersions UNAME DIROFD (SELECTQ RECOG ((NEW OLD/NEW) T) NIL))) (SETQ V (SELECTQ (OR (fetch VERSION of UNAME) RECOG) ((OLD OLD/NEW) (CAR (LAST L))) [NEW (* A new version, so the DIRPTR is NIL) (LIST (ADD1 (CAAR (LAST L] (OLDEST (CAR L)) (SASSOC (fetch VERSION of UNAME) L] then (SETQ DP (CDR V)) (SETQ V (CAR V)) else (SETQ DP NIL) (* Since file doesnt exist, recognition mode takes precedence over version number) (SETQ V (SELECTQ (OR RECOG (fetch VERSION of UNAME)) ((NEW OLD/NEW) (if (fetch ESCFLAG of UNAME) then NIL elseif (FIXP (fetch VERSION of UNAME)) else 1)) ((OLD OLDEST) NIL) (FIXP (fetch VERSION of UNAME] (* We may have to zap a version number that was specified but not found) (replace VERSION of UNAME with V) (RETURN (create DFSFileSpec UNAME ← UNAME FSDIRPTR ← DP]) (\DFSMoveToLeader [LAMBDA (UNAME SCRBUFF StartPos) (* SDG "10-AUG-83 23:21") (for POS from StartPos as C in (fetch CHARPAIRS of UNAME) do (\PUTBASEBYTE SCRBUFF POS (UCASECHAR (CAR C))) finally [COND ((OR (CDR (fetch VERSION of UNAME)) (NEQ (CAR (fetch VERSION of UNAME)) (CHARCODE 1))) (\PUTBASEBYTE SCRBUFF POS (CHARCODE !)) (for old POS from (ADD1 POS) as C in (fetch VERSION of UNAME) do (\PUTBASEBYTE SCRBUFF POS C] (\PUTBASEBYTE SCRBUFF POS (CHARCODE %.)) (OR (EVENP (add POS 1) BYTESPERWORD) (\PUTBASEBYTE SCRBUFF POS 0)) (* Fill out the last word) (RETURN (IDIFFERENCE POS StartPos]) (\DFSWriteLeaderPage [LAMBDA (Stream Buffer) (* hts: "20-May-84 21:29") (PROG ((vol (fetch (FDEV DEVICEINFO) of (fetch DEVICE of Stream))) (Key (fetch FID of Stream))) (\LvPutPage vol (\DFSFindPageAddr vol (create FileDescriptor fileID ←(fetch (Key fileID) of Key) volumeID ←(fetch (LogicalVolumeDescriptor vID) of vol) location ←(QUOTE local) immutable ← NIL temporary ← NIL type ← 0) 0) Buffer]) (\DFSReadLeaderPage [LAMBDA (Stream Buffer) (* hts: "20-May-84 21:30") (PROG ((vol (fetch (FDEV DEVICEINFO) of (fetch DEVICE of Stream))) (Key (fetch FID of Stream))) (RETURN (\LvGetPage vol (\DFSFindPageAddr vol (create FileDescriptor fileID ←(fetch (Key fileID) of Key) volumeID ←(fetch ( LogicalVolumeDescriptor vID) of vol) location ←(QUOTE local) immutable ← NIL temporary ← NIL type ← 0) 0) Buffer]) (\DFSVersions [LAMBDA (UNAME STREAM HMIN) (* hts: "23-Apr-84 18:46") (* UNAME is a value of \UNPACKFILENAME. STREAM is the directory ofd. HMIN=T means look for a hole big enough for UNAME, a number N means look for that size hole, NIL means don't look. Returns a list of (version . fileptr) pairs sorted by increasing version. Ptr is a pointer to the beginning of the directory slot for the file. If the UNAME had an escape which matches unambiguously, the UNAME is smashed with the completion characters.) (PROG ((LEN1 (IPLUS 13 (\DFSUNAMELength UNAME))) (ESC (fetch ESCFLAG of UNAME)) (TLIST (CONS 0 (fetch CHARPAIRS of UNAME))) (FIXEDVERSION (FIXP (fetch VERSION of UNAME))) LASTBANG PTR NCHARSLEFT RESULT V END CHARLIST L1 OLDESCLIST L2) (* 13 in LEN1 calc is 12 for 6 word block plus 1 for char count) (if (AND FIXEDVERSION (OR ESC (ZEROP FIXEDVERSION))) then (SETQ FIXEDVERSION NIL)) (if (EQ HMIN T) then (* 3 is ! plus two chars for version number) (SETQ HMIN (FOLDHI (IPLUS LEN1 3) BYTESPERWORD))) S (if (NULL (SETQ NCHARSLEFT (\DFSDirectorySearch STREAM TLIST HMIN))) then [if (AND ESC OLDESCLIST) then (NCONC UNAME (for X in (DREVERSE OLDESCLIST) collect (CONS X] (RETURN RESULT)) (SETQ PTR (\GETFILEPTR STREAM)) (from NCHARSLEFT to 1 by -1 first (SETQ CHARLIST NIL) do (push CHARLIST (\BIN STREAM))) (OR (EQ (\BIN STREAM) (CHARCODE !)) (SHOULDNT (QUOTE badDirectoryEntry))) (SETQ V (\WIN STREAM)) (* Read version number) (if (NULL ESC) then (if CHARLIST then (GO NEXT)) (* Everything but version has to match exactly if there was no Escape) elseif (EQ ESC T) then (* Escape, first time.) (SETQ OLDESCLIST CHARLIST) (SETQ ESC 0) (* 0 means ESC but not first time. Used for ambiguity checking.) else (* ESC is 0) (* Make sure that the rest of the name is the same) (OR (for (L1 ← CHARLIST) by (CDR L1) as (L2 ← OLDESCLIST) by (CDR L2) do (if (NULL L1) then (RETURN (NULL L2)) elseif [OR (NULL L2) (AND (NEQ (CAR L1) (CAR L2)) (NEQ (CAR L1) (LOGXOR (CAR L2) 32] then (RETURN NIL))) (RETURN))) (* * Name matches. V is the version number. Cons up a piece of the result. If UNAME has an explicit version, insist on it now) (SETQ PTR (IDIFFERENCE PTR LEN1)) (* \DFSVFMFind beginning of the directory entry) (* \DFSVFMMerge new element into RESULT) (if FIXEDVERSION then (if (EQ V FIXEDVERSION) then (RETURN (LIST (CONS V PTR))) else (GO NEXT)) elseif (OR (NULL RESULT) (IGREATERP (CAAR RESULT) V)) then (SETQ RESULT (CONS (CONS V PTR) RESULT)) (GO NEXT)) (SETQ END RESULT) INS (while (AND (CDR END) (IGREATERP V (CAADR END))) do (SETQ END (CDR END))) (RPLACD END (CONS (CONS V PTR) (CDR END))) NEXT(AND HMIN (fetch DIRHOLEPTR of STREAM) (SETQ HMIN NIL)) (* Stop looking if found a hole) (GO S]) (\DFSDirectorySearch [LAMBDA (STREAM TLIST HMIN) (* hts: "23-Apr-84 18:46") (* Finds next directory entry for which TLIST::1 is a prefix of the filename. Returns NIL if no entry found, else the length of the remaining chars in the entry. Leaves the directory positioned after the char matching the last char of TLIST::1 - STREAM is the ofd of the directory file - TLIST is a list of the form (POS . CHARPAIRS), where POS at entry is a fileptr in the directory file at which to start searching and CHARPAIRS is like the characters pairs of a uname. At exit, TLIST is smashed so that POS is the fileptr just beyond the found entry. - if HMIN~=NIL, sets STREAM's DIRHOLEPTR to NIL or the fileptr of the first hole of at least HMIN words.) (PROG ((NEXT (CAR TLIST)) (CHARPAIRS (CDR TLIST)) THISNAMELENGTH TARGETLENGTH PTR L CHPAIR TYP ENTRYLENGTH CH) (if HMIN then (replace DIRHOLEPTR of STREAM with NIL)) (SETQ TARGETLENGTH (LENGTH CHARPAIRS)) NEXT(\SETFILEPTR STREAM (SETQ PTR NEXT)) (if (\EOFP STREAM) then (RETURN)) (* * Format of a directory entry is - Type (0 = hole, 1 = file), 6 bits - Length of entry in words, 10 bits - FP 5 words - Name as a string) (SETQ TYP (\BIN STREAM)) (SETQ ENTRYLENGTH (IPLUS (LLSH (LOGAND TYP 3) 8) (\BIN STREAM))) (SETQ NEXT (IPLUS (UNFOLD ENTRYLENGTH BYTESPERWORD) PTR)) (if (NEQ 1 (LRSH TYP 2)) then (* Not a file) (if (AND HMIN (ILEQ HMIN ENTRYLENGTH)) then (replace DIRHOLEPTR of STREAM with PTR) (SETQ HMIN NIL)) (GO NEXT)) (\SETFILEPTR STREAM (IPLUS PTR 12)) (if (ILESSP (SETQ THISNAMELENGTH (\BIN STREAM)) TARGETLENGTH) then (GO NEXT)) (SETQ L CHARPAIRS) READ(if (NULL L) then (RPLACA TLIST NEXT) (RETURN (IDIFFERENCE THISNAMELENGTH TARGETLENGTH))) (SETQ CHPAIR (CAR L)) (SETQ CH (\BIN STREAM)) (if (OR (EQ CH (CAR CHPAIR)) (EQ CH (CADR CHPAIR))) then (SETQ L (CDR L)) (GO READ) else (GO NEXT]) (\DFSFullFileName [LAMBDA (UNAME) (* SDG "14-NOV-83 16:11") (PROGN (* Produces a Lisp style file-name of the form "name.[ext];ver") (AND (fetch VERSION of UNAME) (PACK* (COND ((fetch PARTNUM of UNAME) (PACK* "{" (\DFSGetLvName (fetch PARTNUM of UNAME)) "}")) (T (SHOULDNT))) (PACKC (NCONC (for X in (fetch CHARPAIRS of UNAME) collect (UCASECHAR (CAR X))) (APPEND [COND ((FASSOC (CHARCODE %.) (fetch CHARPAIRS of UNAME)) (CHARCODE (;))) (T (CHARCODE (%. ;] (CHCON (fetch VERSION of UNAME]) (\DFSGenerateFiles [LAMBDA (FDEV PATTERN DESIREDPROPS OPTIONS) (* hts: " 5-Jun-84 11:56") (* Returns a file-generator object that will generate AT LEAST all files in the sys-dir of FDEV whose names match PATTERN. Clients might need to provide additional filtering. For M44, the generate state consists of the HOSTNAME (DSK) followed by a "search state", a directory pointer and a character list of the sort that \SEARCHDIR1 expects. DIRPTR is the position of the next file to be considered in the directory.) (UNINTERRUPTABLY [PROG ((DIROFD (fetch DirectoryStream of FDEV)) [HOSTNAME (U-CASE (FILENAMEFIELD PATTERN (QUOTE HOST] [DIRECTORY (U-CASE (FILENAMEFIELD PATTERN (QUOTE DIRECTORY] CHARLIST) [OR DIROFD (RETURN (create FILEGENOBJ NEXTFILEFN ←(FUNCTION NILL] (SETQ PATTERN (PACKFILENAME (QUOTE HOST) NIL (QUOTE BODY) PATTERN)) [SETQ CHARLIST (for C in (UNPACK PATTERN) as I from 1 collect (SETQ C (CHCON1 C)) (COND [(AND (IGEQ C (CHARCODE a)) (ILEQ C (CHARCODE z))) (LIST C (IPLUS (IDIFFERENCE C (CHARCODE a)) (CHARCODE A] [(AND (IGEQ C (CHARCODE A)) (ILEQ C (CHARCODE Z))) (LIST C (IPLUS (IDIFFERENCE C (CHARCODE A)) (CHARCODE a] ((FMEMB C (CHARCODE (ESCAPE * ; ?))) (* \SEARCHDIR1 currently only checks prefixes, so we truncate at the first * or escape. Also ignore version specifications, because of the alternative representations of version 1) (RETURN $$VAL)) ([AND (EQ C (CHARCODE %.)) (FMEMB (NTHCHARCODE PATTERN (ADD1 I)) (CHARCODE (ESCAPE * ? ; NIL] (* We don't require a dot match unless it separates a real extension. The client must filter for various combinations of version numbers.) (RETURN $$VAL)) (T (LIST C] (RETURN (create FILEGENOBJ NEXTFILEFN ←(FUNCTION \DFSNextFileFn) FILEINFOFN ←(FUNCTION \DFSFileInfoFn) GENFILESTATE ←(create DFSGenerateFileState DIROFD ← DIROFD HOSTNAME ← HOSTNAME GENSTREAM ← DESIREDPROPS SEARCHSTATE ←(create DFSDirSearchState DIRPTR ← 0 CHARLIST ← CHARLIST])]) (\DFSNextFileFn [LAMBDA (GENFILESTATE NAMEONLY SCRATCHLIST) (* bvm: " 6-May-84 22:47") (* GENFILESTATE is the state information from the file-generator object created by \DFSGenerateFiles This function returns the list of character codes of the next file generated by the generator, smashing them into SCRATCHLIST. Returns NIL if no files left. It updates GENFILESTATE so that it will get the following satisfactory file on the next call to this function. - If NOVERSION, returns the filenames without the semi-colon and version number) (COND ((EQ (CAR GENFILESTATE) (QUOTE \DFSFileInfoFn)) (* Old style) (SETQ GENFILESTATE (CDR GENFILESTATE)) (swap NAMEONLY SCRATCHLIST))) (PROG ((DIROFD (fetch DIROFD of GENFILESTATE)) TEMP LEN GETVERSION SAWDOT SAWVERSION NAMESTART) [COND ((SETQ TEMP (\SEARCHDIR1 DIROFD (fetch SEARCHSTATE of GENFILESTATE))) [SETQ TEMP (SCRATCHLIST SCRATCHLIST [COND ((NULL NAMEONLY) (ADDTOSCRATCHLIST (CHARCODE {)) (for C in (CHCON (fetch HOSTNAME of GENFILESTATE)) do (ADDTOSCRATCHLIST C)) (ADDTOSCRATCHLIST (CHARCODE }] [\SETFILEPTR DIROFD (SETQ NAMESTART (IDIFFERENCE (GETFILEPTR DIROFD) (SETQ LEN (LENGTH (fetch CHARLIST of (fetch SEARCHSTATE of GENFILESTATE] (COND (NIL (replace ENTRYSTART of GENFILESTATE with (IDIFFERENCE NAMESTART 13)) (replace DIRINFO of (fetch GENSTREAM of GENFILESTATE) with NIL))) (* Read all the characters from the directory) (for I from 1 to (IPLUS TEMP LEN 1) do (SETQ TEMP (\BIN DIROFD)) (COND ((EQ TEMP (CHARCODE !)) (SETQ SAWVERSION T) (COND (NAMEONLY (RETURN))) [COND ((NOT SAWDOT) (ADDTOSCRATCHLIST (CHARCODE "."] (SETQ TEMP (CHARCODE ;))) [(AND (IGEQ TEMP (CHARCODE a)) (ILEQ TEMP (CHARCODE z))) (SETQ TEMP (IPLUS (IDIFFERENCE TEMP (CHARCODE a)) (CHARCODE A] ((EQ TEMP (CHARCODE ".")) (SETQ SAWDOT T))) (COND ((LISTP TEMP) (for C in TEMP do (ADDTOSCRATCHLIST C))) (T (ADDTOSCRATCHLIST TEMP))) finally (for C in (CHCON (\WIN DIROFD)) do (ADDTOSCRATCHLIST C))) (COND ((AND (NOT NAMEONLY) (NOT SAWVERSION)) (* No version found--insert ;1) (OR SAWDOT (ADDTOSCRATCHLIST (CHARCODE %.))) (ADDTOSCRATCHLIST (CHARCODE ;)) (ADDTOSCRATCHLIST (CHARCODE 1] (COND ((fetch GENSTREAM of GENFILESTATE) (* Temporary for \DFSFileInfoFn) (replace ENTRYSTART of GENFILESTATE with (PACKC TEMP] (RETURN TEMP]) (\DFSFileInfoFn [LAMBDA (GENFILESTATE ATTRIBUTE) (* bvm: " 6-May-84 22:36") (GETFILEINFO (fetch GENSTREAM of GENFILESTATE) ATTRIBUTE]) (\DFSFreeDiskPages [LAMBDA (volName recompute) (* hts: "22-May-84 10:17") (PROG ((volNum (\DFSGetLvNum (MKSTRING volName))) vol) (if (NULL volNum) then (ERROR (CONCAT "Volume " volName " not on local disk"))) (SETQ vol (LvPagePtr volNum)) (if recompute then (\DFSVAMRecomputeFreePageCount vol) (\DFSDsplyVolumes)) (RETURN (fetch (LogicalVolumeDscr FreePageCount) of vol]) (\DFSDsplyVolumes [LAMBDA NIL (* hts: "23-May-84 09:08") (PROG NIL (if (NOT \DFSDISPLAY) then (RETURN NIL) elseif (NULL \VolumeDsplyWindow) then (SETQ \VolumeDsplyWindow (CREATEW (create REGION WIDTH ← 290 HEIGHT ←(IPLUS 45 (ITIMES 15 (fetch (PhysVolumeDscr SubVolCount) of \PhysVolumePage))) LEFT ← 100 BOTTOM ← 50) "1108 InterLisp File System")) [WINDOWPROP \VolumeDsplyWindow (QUOTE CLOSEFN) (FUNCTION (LAMBDA (W) (SETQ \DFSDISPLAY NIL] (WINDOWPROP \VolumeDsplyWindow (QUOTE RESHAPEFN) (QUOTE DON'T)) else (CLEARW \VolumeDsplyWindow)) (printout \VolumeDsplyWindow # (DSPFONT \DFSfixedFont \VolumeDsplyWindow) "Physical Volume: " # (DSPFONT \DFSfixedBold \VolumeDsplyWindow) (\DFSGetPvName) # (DSPFONT \DFSfixedFont \VolumeDsplyWindow) T "Logical Volumes:" T) (for I from 1 to (fetch (PhysVolumeDscr SubVolCount) of \PhysVolumePage) do (printout \VolumeDsplyWindow # (DSPFONT \DFSfixedFont \VolumeDsplyWindow) (if (EQ (fetch (LogicalVolumeDscr Type) of (LvPagePtr I)) DFSLispVolume) then "* " else " ") I " " # (DSPFONT \DFSfixedBold \VolumeDsplyWindow) (\DFSGetLvName I) " " # (DSPFONT \DFSfixedFont \VolumeDsplyWindow) .FR 18 (fetch (LogicalVolumeDscr VolumeSize) of (LvPagePtr I)) " Pages" .FR 31 (fetch (LogicalVolumeDscr FreePageCount) of (LvPagePtr I)) " Free" .FONT DEFAULTFONT T]) (\DFSDeviceConflict [LAMBDA (deviceName smashDFSDevice) (* hts: "21-May-84 19:59") (* Resolves device name conflicts appropriately before creating DlionFS device) (PROG ((deviceEntry (FASSOC deviceName \DEVICENAMETODEVICE)) newDeviceName device (conflictingDevice NIL)) (SETQ device (CDR deviceEntry)) (if device then (if (\DFSCoreDeviceP device) then (SETQ conflictingDevice "coredevice")) (if (AND (NOT smashDFSDevice) (\DFSDFSDeviceP device)) then (SETQ conflictingDevice "local file device")) (if conflictingDevice then (printout NIL "{" deviceName "} is already a " conflictingDevice "." T "Do you wish to smash it? ") (if (EQ (QUOTE N) (ASKUSER)) then (RETURN T))) (printout NIL "Supplanted old device {" deviceName "}" T) (RETURN NIL]) (\DFSCoreDeviceP [LAMBDA (dev) (* hts: "11-May-84 21:48") (* Returns NIL iff dev is not a coredevice. There probably is a better way to do this.) (EQ (FUNCTION \CORE.CLOSEFILE) (fetch (FDEV CLOSEFILE) of dev]) (\DFSDFSDeviceP [LAMBDA (dev) (* hts: "11-May-84 21:51") (* Returns NIL iff dev is not a DLIONFS device.) (EQ (FUNCTION \DFSCloseFile) (fetch (FDEV CLOSEFILE) of dev]) ) (* This function is a temporary check to make sure \DFSNewPages is doing the right thing.) (DEFINEQ (\DFSCheck [LAMBDA (vol file group) (* hts: "19-May-84 00:06") (* First check to make sure all the pages in the interval have been allocated.) (OR [for page from (fetch (PageGroup volumePage) of group) to [IPLUS (fetch (PageGroup volumePage) of group) (SUB1 (IDIFFERENCE (fetch (PageGroup nextFilePage) of group) (fetch (PageGroup filePage) of group] never (ZEROP (\DFSVAMUpdateVAM vol NIL page (QUOTE read] (SHOULDNT (QUOTE wrongPageAllocated))) (* Then invalidate interval cache) (\DFSCheckEntry (\DFSVFMGetPageGroup vol file 0)) (\DFSCheckEntry (\DFSVFMGetPageGroup vol file (fetch (PageGroup filePage) of group))) (\DFSCheckEntry (\DFSVFMGetPageGroup vol file 0)) (\DFSCheckEntry (\DFSVFMGetPageGroup vol file (SUB1 (fetch (PageGroup nextFilePage) of group]) (\DFSCheckEntry [LAMBDA (foundGroup) (* hts: "18-May-84 23:56") (OR [AND (CAR foundGroup) (NEQ 0 (fetch (PageGroup volumePage) of (CDR foundGroup] (SHOULDNT (QUOTE missingPagesInBTree]) ) (* These provide direct user interface to the file system.) (DEFINEQ (MKDIR [LAMBDA (VolName) (* hts: " 5-Jun-84 10:23") (PROG ((volNum (\DFSVOLUMEP VolName)) vol markerPage) (* \DFSVOLUMEP returns the volume number associated with VolName, it there is such) (if (NULL volNum) then (ERROR (CONCAT "Volume " VolName " not on local disk"))) (SETQ vol (LvPagePtr volNum)) (if (\DFSDeviceConflict VolName) then (RETURN NIL) else (UNINTERRUPTABLY (replace (LogicalVolumeDescriptor type) of vol with DFSPilotVolume) (\DFSVFMInitMap vol) (\DFSOpenDiskDevice volNum) (\DFSMakeVolumeDirectory (LvDevicePtr volNum)) (replace (LogicalVolumeDescriptor type) of vol with DFSLispVolume) (\LvPutPage vol 0 vol) (SETQ markerPage (\LvGetPage vol (MarkerPageAddr vol))) (replace (LogicalSubVolumeMarker type) of (fetch (SubVolumeMarkerPage logical) of markerPage) with DFSLispVolume) (replace (LogicalSubVolumeMarker volumeRootDirectory) of markerPage with (fetch (LogicalVolumeDescriptor volumeRootDirectory) of vol)) (* This should be of (fetch (SubVolumeMarkerPage logical) of markerPage) rather than of markerPage, but can't be because of a bug in dtdeclare not fixed in lispnew.) (\LvPutPage vol (MarkerPageAddr vol) markerPage) (\DFSDsplyVolumes)) (RETURN VolName]) (DFSVOLUMES [LAMBDA NIL (* hts: " 5-Jun-84 12:18") (SELECTQ (MACHINETYPE) [DANDELION (UNINTERRUPTABLY (\DFSEnsureInitialized) (for I from 1 to (fetch SubVolCount of \PhysVolumePage) collect (MKATOM (\DFSGetLvName I))))] NIL]) (DFSLISPVOLUMEP [LAMBDA (VOL) (* hts: " 5-Jun-84 12:19") (SELECTQ (MACHINETYPE) [DANDELION (UNINTERRUPTABLY [PROG ((volNum (\DFSVOLUMEP VOL))) (RETURN (AND volNum (LvDevicePtr volNum])] NIL]) (VOLUMEDISPLAY [LAMBDA (NewState) (* hts: " 5-Jun-84 12:19") (* If newState = OFF, turns volume display window off; if ON, turns it on; if anything else, doesn't do anything. Returns old state (oneof {ON, OFF})) (UNINTERRUPTABLY (\DFSEnsureInitialized) (PROG [(oldState (SELECTQ \DFSDISPLAY (T (QUOTE ON)) (NIL (QUOTE OFF)) (SHOULDNT] (SELECTQ NewState (ON (if \VolumeDsplyWindow then (CLOSEW \VolumeDsplyWindow)) (* If there already was a volume display window, shut it (which will set \DFSDISPLAY to NIL.)) (SETQ \DFSDISPLAY T) (\DFSDsplyVolumes)) (OFF (if \VolumeDsplyWindow then (CLOSEW \VolumeDsplyWindow))) NIL) (RETURN oldState)))]) (MAKEPILOT [LAMBDA (VOL) (* hts: "21-May-84 17:58") (PROG [(volNum (\DFSVOLUMEP VOL)) vol (device (CDR (FASSOC VOL \DEVICENAMETODEVICE] (if (NOT volNum) then (ERROR (CONCAT VOL " is not a local disk volume"))) (UNINTERRUPTABLY (SETQ vol (LvPagePtr volNum)) (replace (LogicalVolumeDescriptor type) of vol with DFSPilotVolume) (\LvPutPage vol 0 vol) (\DFSDsplyVolumes) (if device then (\REMOVEDEVICE device) (SETA \DFSDevices volNum NIL)))]) (SCAVENGEVOLUME [LAMBDA (VOL) (* hts: "23-May-84 10:35") (* VOL: atom (which is a lisp logical volume name)) (* 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) (PROG ((volNum (\DFSVOLUMEP VOL)) vol device (oldDirectoryID (create ID))) (if (NOT (DFSLISPVOLUMEP VOL)) then (ERROR (CONCAT VOL " is not a lisp local disk volume"))) (UNINTERRUPTABLY (SETQ vol (LvPagePtr volNum)) (SETQ device (LvDevicePtr volNum)) (MESASETQ oldDirectoryID (fetch (LogicalVolumeDescriptor volumeRootDirectory) of vol) ID) (\DFSMakeVolumeDirectory device) (* Create a fresh directory) [for fileID in (\DFSVFMGenerateFileIDs vol) do (COND ((MESAEQUAL fileID (fetch (LogicalVolumeDescriptor volumeRootDirectory) of vol) ID) (* fileID is the ID of the directory we just created; don't make a directory entry for it) ) ((MESAEQUAL fileID oldDirectoryID ID) (\DFSTrimHelper volNum (create Key fileID ← fileID) 0 50) (* fileID is the ID of the old (smashed) directory; chop it out of the BTree and don't make a directory entry for it) ) (T (\DFSMakeDirEntry fileID (fetch UNAME of (\DFSFileSpec (PACKFILENAME (QUOTE HOST) (fetch (FDEV DEVICENAME) of device) (QUOTE NAME) (GENSYM)) (QUOTE NEW) (fetch DirectoryStream of device))) device) (* Enter this fileID into the directory with a gensym filename) ])]) (CURRENTVOLUME [LAMBDA NIL (* hts: " 5-Jun-84 12:22") (UNINTERRUPTABLY (\DFSEnsureInitialized) [MKATOM (\DFSGetLvName (for volNum to 6 thereis (EQP (fetch (DiskFileID da) of (FMESAELT (fetch ( PhysicalVolumeDescriptor bootingInfo) of \PhysVolumePage) PVBootFiles hardMicrocode)) (fetch (DiskFileID da) of (FMESAELT (fetch ( LogicalVolumeDescriptor bootingInfo) of (LvPagePtr volNum)) LVBootFiles hardMicrocode])]) ) (DECLARE: DOEVAL@COMPILE DONTCOPY (ADDTOVAR GLOBALVARS \DFSReadVolumes \DFSInitialized \DFSWriteFlg \DFSCheck) ) (FILESLOAD VOLUMEFILEMAP VOLUMEALLOCATIONMAP) (DEFINEQ (\DFSAtLoad [LAMBDA NIL (* hts: " 5-Jun-84 12:16") (UNINTERRUPTABLY (SETQ \DFSfixedFont (FONTCREATE (QUOTE GACHA) 10 (QUOTE MRR))) (SETQ \DFSfixedBold (FONTCREATE (QUOTE GACHA) 10 (QUOTE BRR))) (SETQ \VolumeDsplyWindow) (SETQ \DFSDISPLAY) (SETQ \DFSReadVolumes) (SETQ \DFSCheck) (if (EQ (MACHINETYPE) (QUOTE DANDELION)) then (\DFSEnsureInitialized)))]) ) (\DFSAtLoad) (PUTPROPS DLIONFS COPYRIGHT ("Xerox Corporation" 1983 1984)) (DECLARE: DONTCOPY (FILEMAP (NIL (8838 10833 (DsplyPvPage 8848 . 9008) (DsplyLvPage 9010 . 9177) (DsplyPage 9179 . 9345) (DsplyWords 9347 . 9647) (ShowIntervals 9649 . 10446) (DsplySubVolEntry 10448 . 10630) ( DsplyFileStream 10632 . 10831)) (10912 13342 (\DFSTrimHelper 10922 . 12735) (\DFSFindVolumeNumber 12737 . 13340)) (13407 16306 (\PvTransferPage 13417 . 14351) (\PvTransferPageNoSwap 14353 . 14737) ( \LvGetPage 14739 . 15625) (\LvPutPage 15627 . 16119) (\LvBasePageAddr 16121 . 16304)) (16583 17556 ( \DFSFindPageAddr 16593 . 17554)) (17655 79384 (\DFSFindDirHole 17665 . 18858) (\DFSDEVICEP 18860 . 19754) (\DFSVOLUMEP 19756 . 19938) (\DFSGenFileID 19940 . 20383) (\DFSMakeStrPtr 20385 . 20611) ( \DFSInit 20613 . 21554) (\DFSEnsureInitialized 21556 . 21777) (\DFSGetVolumeInfo 21779 . 22645) ( \DFSGetBuffer 22647 . 22788) (\DFSGetPvName 22790 . 23039) (\DFSGetLvName 23041 . 23318) (\DFSGetLvNum 23320 . 23653) (\DFSHostNameP 23655 . 23774) (\DFSOpenDiskDevice 23776 . 25595) (\DFSCloseFile 25597 . 26650) (\DFSDirectoryNameP 26652 . 27076) (\DFSEventFn 27078 . 28529) (\DFSGetFileInfo 28531 . 31010) (\DFSGetFileName 31012 . 31256) (\DFSReadPages 31258 . 31516) (\DFSSetFileInfo 31518 . 32733) ( \DFSTrimFile 32735 . 33666) (\DFSTruncateFile 33668 . 33790) (\DFSWritePages 33792 . 34051) ( \DFSUnpackName 34053 . 38422) (\DFSUNAMELength 38424 . 38587) (\DFSZeroBuffer 38589 . 38766) ( \DFSMakeVolumeDirectory 38768 . 40536) (\DFSOpenDirectory 40538 . 41338) (\DFSMakeLeaderPage 41340 . 42937) (\DFSOpenFileFromKey 42939 . 43652) (\DFSDeleteFile 43654 . 44952) (\DFSMakeDirEntry 44954 . 46644) (\DFSReadOnePage 46646 . 47564) (\DFSWriteOnePage 47566 . 48584) (\DFSCreateFile 48586 . 49998) (\DFSNewPages 50000 . 51341) (\DFSOpenFile 51343 . 53139) (\DFSUpdateAccessTimes 53141 . 53786) ( \DFSExtendFile 53788 . 54962) (\DFSCompleteStream 54964 . 56062) (\DFSGetStreamForFile 56064 . 58281) (\DFSFileSpec 58283 . 60437) (\DFSMoveToLeader 60439 . 61272) (\DFSWriteLeaderPage 61274 . 61870) ( \DFSReadLeaderPage 61872 . 62471) (\DFSVersions 62473 . 66459) (\DFSDirectorySearch 66461 . 68850) ( \DFSFullFileName 68852 . 69636) (\DFSGenerateFiles 69638 . 72091) (\DFSNextFileFn 72093 . 75208) ( \DFSFileInfoFn 75210 . 75395) (\DFSFreeDiskPages 75397 . 75908) (\DFSDsplyVolumes 75910 . 77686) ( \DFSDeviceConflict 77688 . 78720) (\DFSCoreDeviceP 78722 . 79080) (\DFSDFSDeviceP 79082 . 79382)) ( 79484 80777 (\DFSCheck 79494 . 80521) (\DFSCheckEntry 80523 . 80775)) (80846 87353 (MKDIR 80856 . 82458) (DFSVOLUMES 82460 . 82835) (DFSLISPVOLUMEP 82837 . 83144) (VOLUMEDISPLAY 83146 . 84062) ( MAKEPILOT 84064 . 84692) (SCAVENGEVOLUME 84694 . 86728) (CURRENTVOLUME 86730 . 87351)) (87514 87992 ( \DFSAtLoad 87524 . 87990))))) STOP