{Begin SubSec File System} {Title File System} {Text Typically, the most machine-dependent part of any computer language implementation is the I/O system. Regardless of efforts to create consistant interfaces, the fact remains that different physical machines offer different disks, printers, etc., and languages have to be extended to take advantage of these. In the case of implementing Interlisp on the Xerox 1100 family machines, the biggest change was the addition of facilities for using the high-resolution display, described elsewhere. Other changes have had to be made to accomodate using files on a local disk or on a file server, and sending files to remote printers. Every effort has been made to keep these interfaces compatible with Interlisp-10 conventions, to reduce the amount of work necessary when transferring programs. However, in some situations the user may wish to take advantage of the special extensions offered by Interlisp-D. This section contains information about a variety of extensions to Interlisp-D that accomodate the different I/O environment. {Begin SubSec File Names} {Title File Names} {Text "Full" file names inside of Interlisp-D look similar to Tenex/Tops-20 file names. Full file names begin with a device/host name (in braces) to identify the machine (or device) on which the file resides. Files on the local disk belong to device/host {lisp DSK}, e.g., {lisp {bracket DSK}FOO.BAR;3}. Files on the 1108 Floppy disk are on device {lisp FLOPPY}. {fn PACKFILENAME} and {fn UNPACKFILENAME} are still the appropriate way for programs to manipulate filenames. The device/host of a file may be accessed using the new field name {lisp HOST}. Xerox 1100s and Xerox 1132s, have separately bootable "partitions". Interlisp-D can access partitions other than the one which was booted. If the other partition is password-protected, Interlisp insists on the correct password before accessing any files. Partitions are denoted by {lisp {bracket DSK1}} for Partition 1, {lisp {bracket DSK2}} for Partition 2, etc. {pacom DIR}, {fn DIRECTORY}, etc. all work for other partitions. }{End SubSec File Names} {Begin SubSec Renaming Files} {Title Renaming Files} {Text Interlisp-D implements {lisp (RENAMEFILE {arg OLD} {arg NEW})} even when {arg OLD} and {arg NEW} are on different file servers or devices. In this case, it merely copies {arg OLD} to {arg NEW} and then deletes {arg OLD}. While this procedure is quite general, it can be unnecessarily slow when renaming a file to the same device. Each individual device or server protocol can implement a direct {lisp RENAMEFILE} operation, speeding this process. Currently, direct (fast) {lisp RENAMEFILE} is implemented for PUP-FTP, NS filing, the {lisp DSK} device, and the {lisp FLOPPY} device. }{End SubSec Renaming Files} {Begin SubSec End Of Line Convention} {Title End Of Line Convention} {Text While all versions of Interlisp use ASCII for internal representation of alphabetic and numeric characters, there are still some differences in the {it end of line} conventions. In Interlisp-D, end of line is represented internally by the carriage return character (15Q), whereas the internal representation in Interlisp-10 is the {lisp EOL} character (37Q). The {fn CHARCODE} macro ({PageRef Fn CHARCODE}) is the appropriate way to code programs to be independent of the {lisp EOL} convention: in all systems {lisp (CHARCODE EOL)} is always the appropriate end-of-line character. {lisp (CHARCODE CR)} and {lisp (CHARCODE TENEXEOL)} provide the system-dependent character codes. }{End SubSec End Of Line Convention} {Begin SubSec Using Files with Processes} {Title Using Files with Processes} {Text Currently, Interlisp-D does not provide interlocks to keep multiple processes from trying to access the same file. Therefore, the user has to be careful not to have two processes manipulating the same file at the same time. For example, it will not work to have one process {fn TCOMPL} a file while another process is running {fn LISTFILES} on it. }{End SubSec Using Files with Processes} {Begin SubSec Miscellaneous File Manipulation} {Title Miscellaneous File Manipulation} {Text {FnDef {Name COPYFILE} {Args FROMFILE TOFILE} {Text Copies a file to a new file. The source and destination may be any servers/devices. {fn COPYFILE} attempts to preserve the {lisp TYPE} and {lisp CREATIONDATE} where possible. {fn COPYFILE} always tries to create the new file with the same file type as the original file. If the original file's file type is unknown, {fn COPYFILE} infers the type (file type is {lisp BINARY} if any of its 8-bit bytes have their high bit on). Note: {fn COPYFILE} uses the FTP file transfer protocol whenever possible. Using the FTP protocol for such file transfers is much more efficient for some file servers. }} {FnDef {Name DISKFREEPAGES} {Args {anonarg} {anonarg}} {Text Returns an estimate of the number of pages free on the local disk (current partition). This number is only a "hint", but is usually quite accurate. }} {FnDef {Name DISKPARTITION} {Args} {Text Returns the number of the current partition (1 or 2 on Xerox 1100, 1-5 on Xerox 1132). }} }{End SubSec Miscellaneous File Manipulation} {Begin SubSec Connecting to Directories} {Title Connecting to Directories} {Text Interlisp has a notion of a "connected" directory, which is used as the default when you give a filename lacking an explicit device/host (and directory). The default is changed by using the programmer's assistant command {lisp CONN} or the function {lisp CNDIR}. {Def {Type PACom} {Name CONN} {Args directory} {NoParens} {Text In Interlisp-D, {arg directory} can be of the form {bracket {arg host}}<{arg directory}>. Either part of the argument is optional; if the directory is omitted, the default for devices that have directories is the value of {lisp ({fn USERNAME})}; if the host is omitted, connection will be made to another directory on the same host as before. If {lisp CONN} is given with no arguments, connects to the value of {var LOGINHOST/DIR}. Note that {lisp CONN} does not require or provide any directory access privileges, as does the command of the same name in Interlisp-10. Access privileges are checked when a file is opened. }} {FnDef {Name CNDIR} {Args HOST/DIR} {Text Programmatic form of {lisp CONN}. Connects to the directory {arg HOST/DIR}. Returns the fullname of the now-connected directory. }} {FnDef {Name /CNDIR} {Args HOST/DIR} {Text Undoable form of {fn CNDIR}. {lisp CONN} is implemented via {fn /CNDIR}. }} {VarDef {Name LOGINHOST/DIR} {Text {lisp CONN} with no argument connects to the value of the variable {var LOGINHOST/DIR}, initially {lisp {bracket DSK}}, but usually reset in the user's greeting file. }} {FnDef {Name DIRECTORYNAME} {Args FLG STRPTR} {Text If {arg FLG} is {lisp T}, returns the currently connected host and directory name. If {arg FLG} is {lisp NIL}, returns the value of {var LOGINHOST/DIR}. If {arg STRPTR} is {lisp T}, the value is returned as an atom, otherwise it is returned as a string. }} {FnDef {Name DIRECTORYNAMEP} {Args DIRNAME HOSTNAME} {Text Returns {lisp T} if {arg DIRNAME} is recognized as a valid directory. {arg DIRNAME} may include an explicit hostname. }} {VarDef {Name DIRECTORIES} {Text Global variable containing the list of directories searched (in order) by {fn SPELLFILE} and {fn FINDFILE} ({PageRef Fn SPELLFILE}) when not given an explicit {arg DIRLST} argument. In this list, the atom {lisp NIL} stands for the login directory ({var LOGINHOST/DIR}), and the atom {lisp T} stands for the currently connected directory. {note Check this. True? should we document this here?} }} }{End SubSec Connecting to Directories} {Begin SubSec Streams} {Title Streams} {Text In Interlisp-D, the basic handle on an open file is a datatype called a {lisp STREAM},{index STREAM (Data Type)} whose basic operations are "input" and "output". All I/O functions (e.g., {fn PRINT}, {fn PRIN1}, {fn COPYBYTES}, {fn FULLNAME}) accept streams, and any other arguments (e.g. file names, {lisp NIL}, {lisp T}) are first coerced to streams before any other action is taken. Thus I/O functions will operate more efficiently if given streams directly. The following functions provide user access to streams: {FnDef {FnName OPENSTREAM} {FnArgs FILE ACCESS RECOG BYTESIZE MACHINE.DEPENDENT.PARAMETERS} {Text Opens and returns a {lisp STREAM} for {arg FILE}, interpreting the other arguments in the same manner as {fn OPENFILE} ({PageRef Fn OPENFILE}). }} {FnDef {Name GETSTREAM} {Args FILE ACCESS} {Text Takes a designator which can be used as a "file" argument for a file already open for {arg ACCESS} (e.g., a full/partial file name, {lisp NIL}, a window, etc.) and returns the corresponding stream. If {arg FILE} is a stream, it is simply returned. {arg ACCESS} is interpreted the same as in {fn OPENP} ({PageRef Fn OPENP}). }} {FnDef {Name STREAMP} {Args X} {Text Returns {arg X} if {arg X} is a {lisp STREAM}, otherwise {lisp NIL}. }} {FnDef {Name FORCEOUTPUT} {Args STREAM WAITFORFINISH} {Text Forces any buffered output data in {arg STREAM} to be transmitted. If {arg WAITFORFINISH} is non-{lisp NIL}, this doesn't return until the data has been forced out. }} The following two functions provide the most primitive binary input and output on streams: {FnDef {Name BIN} {Args STREAM} {Text Returns the next byte from {arg STREAM}; thus, this operation is similar to {lisp (CHCON1 (READC {arg STREAM}))}. Depending on the kind of stream, {fn BIN} may be a microcoded operation. }} {FnDef {Name BOUT} {Args STREAM BYTE} {Text Outputs a single 8-bit byte to {arg STREAM}, i.e., similar to {lisp (PRIN3 (CHARACTER {arg BYTE}))}. }} {fn BIN} and {fn BOUT} will also accept a file designator, in which case they coerce it to a stream via {fn GETSTREAM}. However, {fn BIN} executes in microcode only when given a stream directly. {Begin Note} document DFOR10? [Warning: these functions are currently not supported in Interlisp-10. A compatibility package for Interlisp-10 is planned but not yet available. Please contact the Interlisp-D maintainers if you have requirements to transport code which uses binary I/O to Interlisp-10.] {End Note} }{End SubSec Streams} {Begin SubSec Temporary Files and the CORE Device} {Title Temporary Files and the CORE Device} {Text The local {lisp DSK} device and most file servers do not support the temporary or scratch files that are available in Interlisp-10. Files that are created do not disappear when some later event such as logout occurs and instead must be deleted by specific action on the part of the user. For this reason, the {lisp ;S} and {lisp ;T} suffixes in file names are simply ignored when output is directed to a particular host or device. However, Interlisp-D does support a notion of core-resident files, and in many cases these provide a reasonable substitute for Interlisp-10 scratch files. Core-resident files are on the device {lisp CORE}{index CORE (core device)} (e.g. {lisp {bracket CORE}<FOO>FIE.DCOM;5)}. The directory for this device and all files on it are represented completely within the user's virtual memory. These files are treated as ordinary files by all file operations; their only distinguishing feature is that all trace of them disappears when the virtual memory is abandoned. {note is the vmem space reclaimed if a core-resident file is deleted? (yes - Ron)} In Interlisp-D, the function {fn PACKFILENAME} is defined to default the device name to {lisp CORE} if the file has the {lisp TEMPORARY} attribute and no explicit host is provided. Interlisp-D is initialized with the single core-resident device {lisp CORE}, but the function {fn COREDEVICE} may be used to create any number of logically distinct core devices. {FnDef {Name COREDEVICE} {Args NAME} {Text Creates a new device for core-resident files and assigns {arg NAME} as its device name. Thus, after performing {lisp (COREDEVICE 'FOO)}, one can execute {lisp (OUTFILE '{bracket FOO}BAR)} to open a file on that device. }} If the directory information associated with {lisp CORE} devices is not needed, the device {lisp NODIRCORE}{index NODIRCORE (core device)} can be used to open core-resident files which "disappear" when they are closed. Note that {lisp {bracket NODIRCORE}} files do not have names, so the only way to manipulate them is to pass around the value that {fn OPENFILE} returned when the file was opened. Another useful device is the null device,{index NULL (Device)} {lisp {bracket NULL}}. Input and output streams can be opened on the null device, and passed to I/O functions. Any input operations from a null device input stream cause a end-of-file error. Any output operations to a null device output stream are no-ops. {note how to create new device structures? document?} }{End SubSec Temporary Files and the CORE Device} }{End SubSec File System} {Begin SubSec File Servers} {Title File Servers} {Text A file server is a shared resource on a local communications network which provides large amounts of file storage. Different file servers honor a variety of access protocols. Interlisp-D supports three such protocols, known respectively as PUP-FTP, PUP-Leaf, and NS Filing. Leaf is a random access protocol. It has been integrated into the Interlisp-D file system to allow files on a file server to be treated in much the same way files are accessed on the local disk. Except where noted in this section, the standard file operations ({fn OPENFILE}, {fn INFILEP}, {fn CLOSEF}, etc.) all work for remote files. This section explains how to make use of remote files and what differences exist between them and other files. {Begin SubSec File Server File Names} {Title File Server File Names} {Text The full name of a file on a file server host includes the name of the host in braces, and a directory specification in angle brackets, e.g., {lisp {bracket PHYLUM}<LISP>FOO.DCOM;3}. These names are not necessarily the syntax by which the actual device/server knows the files (e.g. some file servers use "{lisp !}" instead of "{lisp ;}"), but Lisp presents a uniform set of naming conventions. The user can "connect" to a directory on a file server using the {pacom CONN} command ({PageRef PACom CONN}), after which any filename supplied that does not include the host name and/or directory will use the "connected" host and/or directory. Specifically, if the host is omitted, then the connected host is used, and if the directory is also omitted, the connected directory is used as well. If an explicit host is supplied, no defaulting of the directory occurs. Interlisp supports file access to Xerox 803x file servers, using the Filing Protocol built on Xerox Network Systems protocols. From inside Interlisp-D, one accesses files on NS servers similarly to PUP servers: any device with a colon in its name is presumed to be accessible with NS protocols rather than PUP, e.g., {lisp {bracket STARFILE:}}. The general format of NS fileserver device names is {lisp {bracket {arg SERVERNAME}:{arg DOMAIN}:{arg ORGANIZATION}}}; the device specification for an 8000-series product must contain the ClearingHouse domain and organization. If domain and organization are not supplied directly, then they are obtained from the defaults, which themselves are found by a search for the nearest ClearingHouse. The Interlisp-D software that supports access to NS fileservers uses IFS-style pathnames and does the appropriate mapping in software. One important difference, however, is that fileserver, directory, and file names may have spaces in them. NS file servers are modeled after the Star world, and have "File Drawers" rather than directories; "File Folders" are like sub-directories. The functions {fn DIRECTORY}, {fn FILEBROWSER}, {fn INFILE}, {fn COPYFILE}, {fn LOAD}, and {fn MAKEFILE} are working now with NS file servers. {VarDef {Name NETWORKOSTYPES} {Text Files servers on different machines have different login protocols, file name formats, etc. For proper service from file servers other than Xerox file servers, the user should add entries to the association-list {var NETWORKOSTYPES} associating the host name (all uppercase) with its operating system type, currently one of {lisp TENEX}, {lisp TOPS20}, {lisp UNIX}, or {lisp VMS}. For example {lisp (ADDTOVAR NETWORKOSTYPES (MAXC2 . TENEX))} will inform Interlisp that the file server {lisp MAXC2} is a {lisp TENEX} file server. }} }{End SubSec File Server File Names} {Begin SubSec Logging In} {Title Logging In} {Text Most file servers require a user name and password for access. When a file server requests this information, Interlisp-D first gives the name and password from the Alto Executive. If the file server doesn't recognize that name/password, Interlisp-D prompts the user for a name and password to use. It suggests a default name (the one on the disk), which the user can accept by typing a space, or replace by typing a new name or backspacing over it. Interlisp-D saves names and passwords for each host, so the user can login to different file servers using different names. {note how about protection violation interaction -- ron} {FnDef {Name LOGIN} {Args HOSTNAME {anonarg} {anonarg} {anonarg}} {Text Forces Interlisp-D to ask for the login name and password to be used when accessing host {arg HOSTNAME}. Any previous login information for {arg HOSTNAME} is overriden. If {arg HOSTNAME} is {lisp NIL}, it overrides login information for all hosts. Password information vanishes when {fn LOGOUT}, {fn SYSOUT}, or {fn MAKESYS} is executed. Returns the login user name. }} {FnDef {Name SETPASSWORD} {Args HOST USER PASSWORD DIRECTORY} {Text Sets the values in the internal password database as if typed in via LOGIN. }} {note Need to expand explanation of passwords, and how Interlisp stores/forgets them. From Intermezzo release notes: File operations to files protected against owner produces "PROTECTION VIOLATION" error instead of hanging If Interlisp is prevented from executing a file operation because of file protection, it tries to connect to the appropriate directory. If a password is needed to connect to the directory, the user is prompted to supply a password. However, if the file is even protected against the person connected to the directory, then Interlisp used to just hang forever. Now, Interlisp detects this condition, and generates a "PROTECTION VIOLATION" error instead of hanging.} }{End SubSec Logging In} {Begin SubSec Abnormal Conditions} {Title Abnormal Conditions} {Text If Interlisp-D tries to access a file and does not get a response from the file server in a reasonable period of time, it prints a message that the file server is not responding, and keeps trying. If the file server has actually crashed, this may continue indefinitely. A {lisp CTRL-E} or similar interrupt aborts out of this state. If the file server crashes but is restarted before the user attempts to do anything, file operations will usually proceed normally, except for a brief pause while Interlisp-D tries to reestablish any connections it had open before the crash. It will inform the user of any problems that arise in so doing. The most likely problem occurs when a file has been opened for output but has not yet been written to (or not enough has been written so that Interlisp-D has written to the file server). In this case the file server will think the file is not there when Interlisp-D tries to reestablish the connection. A similar situation arises if the system has been idle (or at least has not accessed the file server) for a sufficiently long period. In this case, the file server will time out the connection. Normally, Interlisp-D will attempt to recover gracefully as described above. {fn LOGOUT} closes any Leaf connections that are currently open. On return, it attempts to reestablish connections for any files that were open before logging out. If a file has disappeared or been modified, Interlisp-D reports this fact. If it is desired to break the Leaf connection without logging out, call {lisp (BREAKCONNECTION {arg HOST})}.{index BREAKCONNECTION FN} Any subsequent reference to files on that host will reestablish the connection. The main reason for doing this occurs if Interlisp-D is interrupted while a file is being opened, leaving the file server thinking the file is open and Lisp thinking it is closed, and then getting a file busy when Interlisp-D next tries to open it. {note BREAKCONNECTION should be documented below. Are there any other user-level Leaf functions?} On rare occasions, the Ethernet may appear completely unresponsive, due to Interlisp having gotten into a bad state. Typing {lisp (RESTART.ETHER)} will reinitialize Lisp's Ethernet driver(s), just as when the Lisp system is started up following a {fn LOGOUT}, {fn SYSOUT}, etc (see {PageRef Fn RESTART.ETHER}) }{End SubSec Abnormal Conditions} {Begin SubSec Caveats} {Title Caveats} {Text Leaf does not currently support directory enumeration except for one minor case (in the version field). Hence, {fn DIRECTORY} or {fn FILDIR} cannot be used on a Leaf file server to get a list of files. {fn INFILEP} and {fn GETFILEINFO} currently have to open the file for input in order to obtain their information, and hence the file's read date will change, even though the semantics of these functions do not imply it. This differs from the operation of {lisp DSK}, and from Interlisp-10 file operations. Interlisp supports simultaneous access to the same server from different processes and permits overlapping of Lisp computation with file server operations, allowing for improved performance. However, as a corollary of this, a file is not closed the instant that {fn CLOSEF} returns; Interlisp closes the file "in the background". It is therefore very important that the user exits Interlisp via {lisp (LOGOUT)}, or {lisp (LOGOUT T)}, rather than boot the machine or exit via Raid. }{End SubSec Caveats} {Begin SubSec New Functionality} {Title New Functionality} {Text Certain file servers treat text and binary files differently. Files on file servers can have the attribute {lisp TYPE}, with value {lisp TEXT} or {lisp BINARY}, for use with {fn GETFILEINFO} and {fn SETFILEINFO}. The file type defaults to the value of {var DEFAULTFILETYPE},{index DEFAULTFILETYPE Var} initially {lisp TEXT}. {fn OPENFILE} accepts {lisp (TYPE TEXT)} or {lisp (TYPE BINARY)} as an element of its argument {arg PARAMETERS}. {note who cares? -- Ron I do! This can be important info for OPENFILE of a new file -- bvm} Another allowed element of {arg PARAMETERS} is {lisp DON'T.CHANGE.DATE}, which means not to change the file's creation date when a file is opened (meaningful only for files being opened for output). Interlisp-D includes an implementation of the PupFtp protocol, which supports transferring files sequentially only. In those cases where sequential access (as opposed to random access) to a file is appropriate, the use of PupFtp generally results in considerable speed improvement over Leaf, particularly for writing files on a Xerox IFS. The system tries to use PupFtp where possible for {fn SYSOUT} and for the destination file of a {fn COPYFILE}. One can indicate that a file is going to be accessed only sequentially by including the keyword {lisp SEQUENTIAL}{index SEQUENTIAL (File Attribute)} in the list of {arg PARAMETERS} passed to {fn OPENFILE}; the PupFtp will be used, if possible. If for some reason your file server supports PupFtp but you do not wish {fn COPYFILE} or {fn SYSOUT} to use it, you can set the internal variable {var \FTPAVAILABLE}{index \FTPAVAILABLE Var} to {lisp NIL}. }{End SubSec New Functionality} }{End SubSec File Servers}