[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A Lisp Machine generally has access to many file systems. While it may have its own file system on its own disks, usually a community of Lisp Machine users want to have a shared file system accessible by any of the Lisp Machines over a network. These shared file systems can be implemented by any computer that is capable of providing file system service. A file server computer may be a special-purpose computer that does nothing but service file system requests from computers on a network, or it might be an existing time-sharing system.
Programs need to use names to designate files within these file systems. The main difficulty in dealing with names of files is that different file systems have different naming formats for files. For example, in the ITS file system, a typical name looks like:
DSK: GEORGE; FOO QFASL |
PS:<GEORGE>FOO.QFASL |
The functions and flavors described in this chapter exist to solve this problem. They provide an interface through which a program can deal with names of files and manipulate them without depending on anything about their syntax. This lets a program deal with multiple remote file servers simultaneously, using a uniform set of conventions.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
All file systems dealt with by the Lisp Machine are mapped into a common model, in which files are named by something called a pathname. A pathname always has six components, described below. These components are the common interface that allows programs to work the same way with different file systems; the mapping of the pathname components into the concepts peculiar to each file system is taken care of by the pathname software. This mapping is described for each file system later in this chapter.
These are the components of a pathname. They will be clarified by an example below.
host
device
directory
name
type
version
As an example, consider a Lisp program named CONCH. If it belongs to GEORGE, who uses the FISH machine, the host would be the host-object for the machine FISH, the device would be the default probably, and the directory would be GEORGE. On this directory would be a number of files related to the CONCH program. The source code for this program would live in a set of files with name CONCH, type LISP, and versions 1, 2, 3, etc. The compiled form of the program would live in files named CONCH with type QFASL; each would have the same version number as the source file that it came from. If the program had a documentation file, it would have type INFO.
Note that a pathname is not necessarily the name of a specific file. Rather, it is a way to get to a file; a pathname need not correspond to any file that actually exists, and more than one pathname can refer to the same file. For example, the pathname with a version of "newest" will refer to the same file as a pathname with the same components except a certain number as the version. In systems with links, multiple file names, logical devices, etc. two pathnames that look quite different may really turn out to address the same file. To get from a pathname to a file requires doing a file system operation such as open.
A pathname is an instance of a flavor (see (flavor)); exactly which flavor depends on what the host of the pathname is. One of the messages handled by host objects is the :pathname-flavor operation, which returns the name of the flavor to use for pathnames on that host. And one of the differences between flavors of host is how they handle this operation.
If p is a pathname, then (typep p 'fs:pathname) will return t. (fs is the file-system package.) There are functions for manipulating pathnames, and there are also messages that can be sent to them. These are described later in this chapter.
Two important operations of the pathname system are parsing and merging. Parsing is the conversion of a string--which might be something typed in by the user when asked to supply the name of a file--into a pathname object. This involves finding out what host the pathname is for, then using the file name syntax conventions of that host to parse the string into the standard pathname components. Merging is the operation which takes a pathname with missing components and supplies values for those components from a set of defaults.
Since each kind of file server can have its own character string representation of names of its files, there has to be a different parser for each of these representations, capable of examining such a character string and figuring out what each component is. The parsers all work differently. How can the parsing operation know which parser to use? The first thing that the parser does is to figure out which host this filename belongs to. A filename character string may specify a host explicitly, by having the name of the host, followed by a colon, either at the beginning or the end of the string. For example, the following strings all specify hosts explicitly:
AI: COMMON; GEE WHIZ ; This specifies host AI. COMMON; GEE WHIZ AI: ; So does this. AI: ARC: USERS1; FOO BAR ; So does this. ARC: USERS1; FOO BAR AI: ; So does this. EE:PS:<COMMON>GEE.WHIZ.5 ; This specifies host EE. PS:<COMMON>GEE.WHIZ.5 EE: ; So does this. |
Pathnames are kept unique, like symbols, so that there is only one object with a given set of components. This is useful because a pathname object has a property list (see (plist)) on which you can store properties describing the file or family of files which the pathname represents. The uniqueness implies that any time the same components are typed in, the program will get the same pathname object, and find there the properties it ought to find.
.setq pathname-plist-warning page
If you wish to store properties that refer to a specific file rather than to a family of files, simply use the file's pathname. To avoid problems with links, logical hosts, multiple names for the same file, and different versions that access the same file (such as :newest versus the version number itself), use the pathname you get by sending :truename to a stream rather than the pathname you open. By following this convention you will avoid problems where two references to two unequal pathnames that describe the same file fail to communicate properties correctly.
To get a unique pathname object representing a family of files, send the message :generic-pathname to a pathname for any file in the family (see (generic-pathname)).
A pathname can be converted into a string, which is in the file name syntax of its host's file system, except that the name of the host followed by a colon is inserted at the front. prin1 of a pathname (~S in format) prints it like a Lisp object (using the "#" syntax so it can be read back in), while princ of a pathname (~A in format) prints it like a file name of the host file system. The string function, applied to a pathname, returns the string that princ would print. Thus pathnames may be used as arguments to functions like string-append.
Not all of the components of a pathname need to be specified. If a component of a pathname is missing, its value is nil. Before a file server can do anything interesting with a file, such as opening the file, all the missing components of a pathname must be filled in from defaults. But pathnames with missing components are often handed around inside the machine, since almost all pathnames typed by users do not specify all the components explicitly. The host is not allowed to be missing from any pathname; since the behavior of a pathname is host-dependent to some extent, it has to know what its host is. All pathnames have host attributes, even if the string being parsed does not specify one explicitly.
A component of a pathname can also be the special symbol :unspecific. This means that the component has been explicitly determined not to be there, as opposed to being missing. One way this can occur is with generic pathnames, which refer not to a file but to a whole family of files. The version, and usually the type, of a generic pathname are :unspecific. Another way :unspecific is used has to do with mapping of pathnames into file systems such as ITS that do not have all six components. A component that is really not there will be :unspecific in the pathname. When a pathname is converted to a string, nil and :unspecific both cause the component not to appear in the string. The difference occurs in the merging operation, where nil will be replaced with the default for that component, while :unspecific overrides any defaults.
A component of a pathname can also be the special symbol :wild. This is only useful when the pathname is being used with a directory primitive such as fs:directory-list (see (fs:directory-list-fun)), where it means that this pathname component matches anything. The printed representation of a pathname usually designates :wild with an asterisk; however, this is host-dependent.
What values are allowed for components of a pathname depends, in general, on the pathname's host. However, in order for pathnames to be usable in a system-independent way certain global conventions are adhered to. These conventions are stronger for the type and version than for the other components, since the type and version are actually understood by many programs, while the other components are usually just treated as something supplied by the user which just needs to be remembered.
The type is always a string (unless it is one of the special symbols nil, :unspecific, and :wild). Many programs that deal with files have an idea of what type they want to use. For example, Lisp source programs are "lisp", compiled Lisp programs are "qfasl", text files are "text", tags files are "tags", etc. Just what characters are allowed in the type, and how many, is system dependent.
The version is either a number (specifically, a positive fixnum), or a special symbol. nil, :unspecific, and :wild have been explained above. :newest refers to the largest version number that exists when reading a file, or that number plus one when writing a new file. :oldest refers to the smallest version number that exists. Some file systems may define other special version symbols, such as :installed for example, or may allow negative numbers.
The device, directory, and name are more system-dependent. These can be strings (with host-dependent rules on allowed characters and length), or they can be structured. A structured component is a list of strings. This is used for file system features such as hierarchical directories. The system is arranged so that programs do not need to know about structured components unless they do host-dependent operations. Giving a string as a pathname component to a host that wants a structured value converts the string to the appropriate form. Giving a structured component to a host that does not understand them converts it to a string by taking the first element and ignoring the rest.
Some host file systems have features that do not fit into this pathname model. For instance, directories might be accessible as files, there might be complicated structure in the directories or names, or there might be relative directories, such as "<" in Multics. These features appear in the parsing of strings into pathnames, which is one reason why the strings are written in host-dependent syntax. Pathnames for hosts with these features are also likely to handle additional messages besides the common ones documented in this chapter, for the benefit of host-dependent programs which want to access those features. However, note that once your program depends on any such features, it will only work for certain file servers and not others; in general, it is a good idea to make your program work just as well no matter what file server is being used.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When the user is asked to type in a pathname, it is of course unreasonable to require the user to type a complete pathname, containing all components. Instead there are defaults, so that components not specified by the user can be supplied automatically by the system. Each program that deals with pathnames typically has its own set of defaults.
The system defines an object called a defaults a-list. Functions are provided to create one, get the default pathname out of one, merge a pathname with one, and store a pathname back into one. A defaults a-list can remember more than one default pathname if defaults are being kept separately for each host; this is controlled by the variable fs:*defaults-are-per-host*. The main primitive for using defaults is the function fs:merge-pathname-defaults (see (fs:merge-pathname-defaults-fun)).
In place of a defaults a-list, you may use just a pathname. Defaulting one pathname from another is useful for cases such as a program that has an input file and an output file, and asks the user for the name of both, letting the unsupplied components of one name default from the other. Unspecified components of the output pathname will come from the input pathname, except that the type should default not to the type of the input but to the appropriate default type for output from this program.
The implementation of a defaults a-list is an association list of host names and default pathnames. The host name nil is special and holds the defaults for all hosts, when defaults are not per-host.
.setq pathname-merging-rules page The merging operation takes as input a pathname, a defaults a-list (or another pathname), a default type, and a default version, and returns a pathname. Basically, the missing components in the pathname are filled in from the defaults a-list. However, if a name is specified but the type or version is not, then the type or version is treated specially.
The full details of the merging rules are as follows. First, if the pathname explicitly specifies a host and does not supply a device, then the device will be the default file device for that host. Next, if the pathname does not specify a host, device, directory, or name, that component comes from the defaults.
If the value of fs:*always-merge-type-and-version* is non-nil, the type and version are merged just like the other components. Otherwise, the merging rules for the type and version are more complicated, and depend on whether the pathname specifies a name. If the pathname doesn't specify a name, then the type and version, if not provided, will come from the defaults, just like the other components. However, if the pathname does specify a name, then the type and version are not affected by the defaults. The reason for this is that the type and version "belong to" some other filename, and are thought to be unlikely to have anything to do with the new one you are typing in. Instead, the type and version,if not specified, come from the default type and default version arguments to the merging operation. If the default type and default version arguments were omitted, the value of fs:*name-specified-default-type* (initially, "LISP") is used as the default type, and :newest is used as the default version.
The following special variables are parts of the pathname interface that are relevant to defaults.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
.setq generic-pathname section-page
A generic pathname stands for a whole family of files. The property list of a generic pathname is used to remember information about the family, some of which (such as the package) comes from the 7-*- line (see (file-property-list)) of a source file in the family. Several types of files with that name, in that directory, belong together. They are different members of the same family; for example, they might be source code and compiled code. However, there may be several other types of files which form a logically distinct group even thought they have this same name; TEXT and PRESS for example. The exact mapping is done on a per host basis since it can sometimes be affected by host naming conventions.
The generic pathname of pathname p usually has the same host, device, directory, and name as p does. However, it has a version of :unspecific. The type of the generic pathname is obtained by sending a :generic-base-type <type of p> message to the host of p. The default response to this message is to return the associated type from fs:*generic-base-type-alist* if there is one, else <type of p>. (The old variable, fs:*known-types*, is discontinued). However ITS presents special problems. One cannot distinguish multiple generic base types in this same way since the type component does not exist as such; it is derived from the second filename, which unfortunately is also sometimes used as a version number. Thus, on ITS, the type of a generic pathname is always :unspecific if there is any association for the type of the pathname on fs:generic-base-type-alist*.
Since generic pathnames are primarily useful for storing properties, it is important that they be as standardized and conceptualized as possible. For this reason, generic pathnames are defined to be "backtranslated", ie the generic pathname of a pathname which is (or could be) the result of a logical host translation has the host and directory of the logical pathname. For example, the generic pathname of AI:LMWIN;STREAM > would be SYS:WINDOW;STREAM LISP if AI is the system host. On the other hand, a pathname specifying a logical host but a directory that, strictly speaking, is not defined for that host will have a generic pathname of the forward translated host. For example SYS:RG;FOO might have a generic pathname of AI:RG;FOO.
All version numbers of a particular pathname share the same identical generic pathname. If the values of particular properties have changed between versions, it is possible for confusion to result. One means to deal with this problem have the property be a list associating version number with the actual desired property. Then it is relatively easy to determine which versions have which values for the property in question and select one appropriately. But usually in the applications for which generic pathnames are used this is not necessary.
The :generic-pathname message to a pathname returns its corresponding generic pathname. See (pathname-generic-pathname-method).
(("TEXT" . "TEXT") ("DOC" . "TEXT") ("PRESS" . "TEXT") ("XGP" . "TEXT") ("LISP" . :UNSPECIFIC) ("QFASL" . :UNSPECIFIC) (NIL . :UNSPECIFIC)) |
Some users may need to add to this list.
The system records certain properties on generic pathnames automatically.
:warnings
:definitions
Each definition is a cons whose car is the symbol or function spec defined and whose cdr is the type of definition (usually one of the symbols defun, defvar, defflavor and defstruct).
:systems
:file-id-package-alist
(package file-information) |
Some additional properties are put on the generic pathname by reading the attribute list of the file (see (fs:file-read-attributes-list-fun)). It is not completely clear that this is the right place to store these properties, so it may change in the future. Any property name can appear in the attributes list and get onto the generic pathname, but here are the typical ones.
:mode
:base
:package
:fonts
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
These functions are what programs use to parse and default file names that have been typed in or otherwise supplied by the user.
This function does not do defaulting, even though it has an argument named defaults; it only does parsing. The host and defaults arguments are there because in order to parse a string into a pathname, it is necessary to know what host it is for so that it can be parsed with the file name syntax peculiar to that host. If thing does not contain a manifest host name, then if host is non-nil, it is the host name to use, as a string. If thing is a string, a manifest host name may be at the beginning or the end, and consists of the name of a host followed by a colon. If host is nil then the host name is obtained from the default pathname in defaults. If defaults is not supplied, the default defaults (fs:*default-pathname-defaults*) are used.
Note that if host is specified, and thing contains a host name, an error is signalled if they are not the same host.
If defaults is a pathname, rather than a defaults a-list, then the defaults are taken from its components. This is how you merge two pathnames (in Maclisp that operation is called mergef).
defaults defaults to the value of fs:*default-pathname-defaults* if unsupplied. default-type defaults to the value of fs:*name-specified-default-type*. default-version defaults to :newest.
.need 1500 This function yields a pathname given its components.
.need 1500 These functions are used to manipulate defaults a-lists directly.
If fs:*defaults-are-per-host* is nil (its default value), this gets the one relevant default from the a-list. If it is t, this gets the default for host if one is specified, otherwise for the host most recently used.
If defaults is not specified, the default defaults are used.
This function has an additional optional argument internal-p, which users should never supply.
.need 1500 These functions return useful information.
.need 1500 These functions are useful for poking around.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This section documents the messages a user may send to a pathname object. Pathnames handle some additional messages which are only intended to be sent by the file system itself, and therefore are not documented here. Someone who wanted to add a new host to the system would need to understand those internal messages. This section also does not document messages which are peculiar to pathnames of a particular host; those would be documented under that host.
The operations :new-name, etc., are equivalent to :new-pathname specifying only one component to be changed.
.need 1500 Messages to get a path name string out of a pathname object:
.need 1500 Messages to move around through a hierarchy of directories:
The special symbol :root can be used as the directory component of a pathname on file systems which have a root directory.
.need 1500 Messages to manipulate the property list of a pathname:
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This section lists the host file systems supported, gives an example of the pathname syntax for each system, and discusses any special idiosyncracies. More host types will no doubt be added in the future.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
An ITS pathname looks like "HOST: DEVICE: DIR; FOO 69". The primary device is DSK: but other devices such as ML:, ARC:, DVR:, or PTR: may be used.
ITS does not exactly fit the virtual file system model, in that a file name has two components (FN1 and FN2) rather than three (name, type, and version). Consequently to map any virtual pathname into an ITS filename, it is necessary to choose whether the FN2 will be the type or the version. The rule is that usually the type goes in the FN2 and the version is ignored; however, certain types (LISP and TEXT) are ignored and instead the version goes in the FN2. Also if the type is :unspecific the FN2 is the version.
Given an ITS filename, it is converted into a pathname by making the FN2 the version if it is "<", ">", or a number. Otherwise the FN2 becomes the type. ITS pathnames allow the special version symbols :oldest and :newest, which correspond to "<" and ">" respectively. If a version is specified, the type is always :unspecific. If a type is specified, the version is :newest unless the type is a normally-ignored type (such as LISP) in which case the version is :unspecific so that it does not override the type.
Each component of an ITS pathname is mapped to upper case and truncated to six characters.
Special characters (space, colon, and semicolon) in a component of an ITS pathname can be quoted by prefixing them with right horseshoe (7) or equivalence sign (7). Right horseshoe is the same character code in the Lisp Machine character set as control-Q in the ITS character set.
An ITS pathname can have a structured name, which is a list of two strings, the FN1 and the FN2. In this case there is neither a type nor a version.
An ITS pathname with an FN2 but no FN1 (i.e. a type and/or version but no name) is represented with the placeholder FN1 7"", because ITS pathname syntax provides no way to write an FN2 without an FN1 before it.
The ITS init file naming convention is "homedir; user program".
("lisp" "text" nil :unspecific) |
On an its-pathname, :type-and-version returns the type and version thus extracted (not the same as the type and version of the pathname). :new-type-and-version returns a new pathname constructed from the specified new type and new version.
On any other type of pathname, these operations simply return or set both the type component and the version component.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A pathname on TOPS-20 (better known as Twenex) looks like
"HOST:DEVICE:
TOPS-20 pathnames are mapped to upper case. Special characters (including lowercase letters) are quoted with the circle-x (7) character, which has the same character code in the Lisp Machine character set as control-V in the TOPS-20 character set.
If you specify a period after the name, but nothing after that, then the type is :unspecific, which translates into an empty extension on the TOPS-20 system. If you omit the period, you have allowed the type to be defaulted.
TOPS-20 pathnames allow the special version symbols :oldest and :newest. In the string form of a pathname, these are expressed as ".-2" and ".0" respectively for the version.
The directory component of a TOPS-20 pathname may be structured. The directory <FOO.BAR> is represented as the list ("FOO" "BAR").
The TOPS-20 init file naming convention is "<user>program.INIT".
When there is an attempt to display a TOPS-20 file name in the who-line and there isn't enough room to show the entire name, the name is truncated and followed by a center-dot character to indicate that there is more to the name than can be displayed.
Tenex pathnames are almost the same as TOPS-20 pathnames, except that the version is preceeded by a semi-colon instead of a period, the default device is DSK instead of PS, and the quoting requirements are slightly different.
VMS pathnames are basically like TOPS-20 pathnames, with a few complexities. The primary device is SYS$SYSDISK.
First of all, only alphanumeric characters are allowed in filenames (though $ and underscore can appear in device names).
Secondly, a version number is preceded by ";" rather than by ".".
Thirdly, file types ("extensions") are limited to three characters. Because much Lisp Machine software uses specific types (such as "LISP") which are longer, the system provides a set of translations between specific standard system types and three-letter abbreviations. The longer, standard names actually appear as the type components of pathnames, and are used with the :type and :new-type operations. The abbreviations appear in printed representations of pathnames, and are used when a file is opened.
The type name translations are an alist in the value of fs:*vms-file-type-alist*. The standard translations are:
lisp lsp; text txt; midas mid; qfasl qfs; press prs; (pdir) pdr; patch-directory pdr; qwabl qwb; babyl bab; mail mai; xmail xml; init ini; unfasl unf; cwarns cwn; output out.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A Unix pathname is a sequence of directory or file names separated by slashes. The last name is the filename; preceding ones are directory names (but directories are files anyway). There are no devices or versions. Alphabetic case is always significant in Unix pathnames.
Unix allows you to specify a pathname relative to your default directory by using just a filename, or starting with the first subdirectory name; or you can specify it starting from the root directory by starting with a slash. In addition, you can start with ".." as a directory name one or more times, to refer upward in the hierarchy from the default directory.
Unix pathnames on the Lisp Machine provide all these features too, but the canonicalization to a simple descending list of directory names starting from the root is done on the Lisp Machine itself when you merge the specified pathname with the defaults.
If a pathname string starts with a slash, the pathname object that results from parsing it is called "absolute". Otherwise the pathname object is called "relative".
In an absolute pathname object, the directory component is either a symbol (nil, :unspecific or :root), a string, or a list of strings. A single string is used when there is only one level of directory in the pathname.
A relative pathname has a directory which is a list of the symbol :relative followed by some strings. When the pathname is merged with defaults, the strings in the list are appended to the strings in the default directory. The result of merging is always an absolute pathname.
In a relative pathname's string form, the string ".." can be used as a directory name. It is translated to the symbol :up when the string is parsed. That symbol is processed when the relative pathname is merged with the defaults.
Restrictions on the length of Unix pathnames require abbreviations for the standard Zetalisp pathname types, just as for VMS. On Unix the abbreviations are all one or two characters. The alist of abbreviations is stored in fs:*unix-file-type-alist*, and the default set is:
lisp l, text tx; qfasl qf; midas md; press pr; (pdir) pd; patch-directory pd; qwabl qw; babyl bb; mail ma; xmail xm; init in; unfasl uf; cwarns cw; output ot.
The Multics file system is much like the Unix one; there are absolute and relative pathnames, absolute ones start with a directory delimiter, and here are no devices or versions. Alphabetic case is significant.
There are differences in details. Diretory names are terminated, and absolute pathnames begun, with the character ">". The containing directory is referred to by the character "<", which is complete in itself. It does not require a delimiter. Thus, "<<FOO>BAR" refers to subdirectory FOO, file BAR in the superdirectory of the superdirectory of the default directory.
The limits on filename sizes are very large, so there is no translation of type components.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
There are two file systems that run in the MIT Lisp Machine system. They have different pathname syntax. Both can be accessed either locally, or remotely like any other file server.
The Local-File system uses host name LM for the machine you are on. A Local-File system on another machine can be accessed using the name of that machine as a host name, provided that machine is known as a file server.
The remainder of the pathname for the Local-File system looks like "DIRECTORY; NAME.TYPE#VERSION". There is no restriction on the length of names, and letters are mapped to upper case.
The Local-File system on the Filecomputer at MIT is called FS.
The LMFILE system is primarily for use as a file server. At MIT, it runs on the filecomputer, and is accessed remotely with host name FC.
The remainder of an LMFILE pathname looks like "DIRECTORY; NAME TYPE#VERSION". However, the directory and name can be composed of any number of subnames, separated by backslashes. This is how subdirectories are specified. "FOO;BAR\X" refers to the same file as "FOO\BAR;X", but the two ways of specifying the file have different consequences in defaulting, getting directory listings, etc.
Case is significant in LMFILE pathnames; however, when you open a file, the LMFILE system ignores the case when it matches your pathname against the existing files. As a result, the case you use matters when you create or rename a file, and appears in directory listings, but it is ignored when you refer to an existing file, and you cannot have two files whose names differ only in case.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
There is another kind of pathname that doesn't correspond to any particular file server. It is called a "logical" pathname, and its host is called a "logical" host. Every logical pathname can be translated into a corresponding "physical" pathname; there is a mapping from logical hosts into physical hosts used to effect this translation.
The reason for having logical pathnames is to make it easy to keep bodies of software on more than one file system. An important example is the body of software that constitutes the Lisp Machine system. Every site has a copy of all of the sources of the programs that are loaded into the initial Lisp environment. Some sites may store the sources on an ITS file system, while others might store them on a TOPS-20. However, there is software that wants to deal with the pathnames of these files in such a way that the software will work correctly no matter which site it is run at. The way this is accomplished is that there is a logical host called SYS, and all pathnames for system software files are actually logical pathnames with host SYS. At each site, SYS is defined as a logical host, but translation will work differently at one site than at another. At a site where the sources are stored on a certain TOPS-20, for example, pathnames of the SYS host will be translated into pathnames for that TOPS-20.
Here is how translation is done. For each logical host, there is a mapping that takes the name of a directory on the logical host, and produces a device and a directory for the corresponding physical host. To translate a logical pathname, the system finds the mapping for that pathname's host and looks up that pathname's directory in the mapping. If the directory is found, a new pathname is created whose host is the physical host, and whose device and directory come from the mapping. The other components of the new pathname are left the same. There is also, for each logical host, a "default device" (it is an instance variable of the host object). If the directory is not found in the mapping, then the new pathname will have the same directory name as the old one, and its device will be the "default device" for the logical host. The "default device" is also used if a translation exists but specifies nil as the device.
This means that when you invent a new logical host for a certain set of files, you also make up a set of logical directory names, one for each of the directories that the set of files is stored in. Now when you create the mappings at particular sites, you can choose any physical host for the files to reside on, and for each of your logical directory names, you can specify the actual directory name to use on the physical host. This gives you flexibility in setting up your directory names; if you used a logical directory name called fred and you want to move your set of files to a new file server that already has a directory called fred, being used by someone else, you can translate fred to some other name and so avoid getting in the way of the existing directory. Furthermore, you can set up your directories on each host to conform to the local naming conventions of that host.
(fs:add-logical-pathname-host "music" "music-10-a" '(("melody" "ss: |
This creates a new logical host called music. If you try to read the file music:doc;manual text 2, you will be re-directed to the file music-10-a:ps:<music-documentation>manual.text.2 (assuming that the host music-10-a is a TOPS-20 system).
If this message is sent to a physical pathname, it simply returns itself.
An example of how this would be used is in connection with truenames. Given a stream which was obtained by opening a logical pathname,
(funcall stream ':pathname) |
(funcall stream ':truename) |
(funcall (funcall stream ':pathname) ':back-translated-pathname (funcall stream ':truename)) |
If this message is sent to a physical pathname, it simply returns its argument. Thus the above example will work no matter what kind of pathname was opened to create the stream.
A logical pathname looks like "HOST: DIRECTORY; NAME TYPE VERSION". There is no way to specify a device; parsing a logical pathname always returns a pathname whose device component is :unspecific. This is because devices don't have any meaning in logical pathnames.
The equivalence-sign character () can be used for quoting special characters such as spaces and semicolons. The double-arrow character () can be used as a place-holder for unspecified components. Components are not mapped to upper-case. The :newest, :oldest, and :wild values for versions are specified with the strings ">", "<", and "*" respectively.
There isn't any init file naming convention for logical hosts; you can't log into them. The :string-for-host, :string-for-wholine, :string-for-dired, and :string-for-editor messages are all passed on to the translated pathname, but the :string-for-printing is handled by the fs:logical-pathname flavor itself and shows the logical name.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Each host known to the Lisp Machine is represented by a flavor instance known as a host object. The host object records such things as the name(s) of the host, its operating system type, and its network address(es).
Not all hosts support file access. Those that do, appear on the list fs:*pathname-host-list* and can be the host component of pathnames. A host object is also used as an argument when you make a chaosnet connection for any purpose.
The hosts that you can use for making network connections appear in the value of si:host-alist. Most of the hosts you can use for pathnames are among these; but some, such as logical hosts, are not.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
If unknown-ok is non-nil, an unrecognized string is used to construct a new host object. However, that host object will not have a known operating system type or network addresses.
The first argument is allowed to be a host object instead of a string. In this case, that argument is simply returned.
nil is returned if there is no known host with that address.
The first argument is allowed to be a host object instead of a string. In this case, that argument is simply returned.
si:parse-host and fs:get-pathname-host differ in the set of hosts searched.
(full-name host-object (nickname nickname2 ... full-name) system-type machine-type site network list-of-addresses network2 list-of-addresses2 ...) |
The host-object is a flavor instance that represents this host. It may be nil if none has been created yet; si:parse-host creates them when they are referred to.
The nicknames are alternate names which si:parse-host will recognize for this host, but which are not its official name.
The system-type is a symbol which tells what software the host runs. This is used to decide what flavor of host object to construct. Symbols now used include :lispm, :its, :tops-20, :tenex, :vms, :unix, :multics, :minits, :waits, :chaos-gateway, :dos, :rsx, :magicsix, and others. Not all of these are specifically understood in any way by the Lisp machine. If none of these applies to a host you wish to add, use a new symbol.
The machine-type is a symbol which describes tha hardware of the host. Symbols in use include :lispm, :pdp10, :pdp11, :vax, :pe3230. (nil) has also been observed to appear here. Note that these machine types attempt to have wide meanings, lumping together as various brands, models, etc.
The site does not describe anything about the host. Instead it serves to say what the Lisp Machine's site name was when the host was defined. This is so that, when a Lisp Machine system is moved to a different institution which has a disjoint set of hosts, all the old site's hosts can be deleted from the host alist by site reinitialization.
The networks and lists of addresses describe how to reach the host. Usually there will be only one network and only one address in the list. The generality is so that hosts with multiple addresses on multiple networks can be recorded. Networks include :chaos and :arpa. The address is meaningful only to code for a specific network.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
.defmessage host :name Returns the full, official name of the host. .end_defmessage
.defmessage host :name-as-file-computer Returns the name to print in pathnames on this host (assuming it supports files). This is likely to be a short nickname of the host. .end_defmessage
.defmessage host :short-name Returns the shortest known nickname for this host. .end_defmessage
.defmessage host :pathname-host-namep string Returns t if string is recognized as a name for this host for purposes of pathname parsing. .end_defmessage
.defmessage host :system-type Returns the operating system type symbol for this host. See (host-table). .end_defmessage
.defmessage host :network-type Returns the symbol for one network that this host is connected to, or nil if it is not connected to any. :chaos is preferred if it is one of the possible values. .end_defmessage
.defmessage host :network-typep network Returns t if the host is connected to the specified network. .end_defmessage
.defmessage host :open-streams Returns a list of all the open file streams for files on this host. .end_defmessage
.defmessage host :close-all-files Closes all file streams open for files on this host. .end_defmessage
.defmessage host :generic-base-type type-component Returns the type component for a generic pathname assuming it is being made from a pathname whose type component is the one specified. .end_defmessage
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This section briefly discusses how to convert from Maclisp I/O and filename functions to the corresponding but often more general Lisp Machine ones.
The functions load, open, probef, renamef, and deletef are upward compatible. Most of them take optional additional arguments to do additional things, usually connected with error handling. Where Maclisp wants to see a file name in the form of a symbol or a list, the Lisp Machine will accept those or a string or a pathname object. probef returns a pathname or nil rather than a namelist or nil.
load keeps defaults, which it updates from the file name it is given.
The old-I/O functions uread, crunit, etc. do not exist in the Lisp Machine. fasload exists but is a function rather than a special form.
There is a special form, with-open-file, which should replace most calls to open. See (with-open-file-fun).
The functions for manipulating file names themselves are different. The system will accept a namelist as a pathname, but will never create a namelist. mergef is replaced by fs:merge-pathname-defaults. defaultf is replaced by fs:default-pathname or fs:set-default-pathname, depending on whether it is given an argument. namestring is replaced by the :string-for-printing message to a pathname, or the string function. namelist is approximately replaced by fs:parse-pathname. (status udir) and (status homedir) are approximately replaced by fs:user-homedir. The truename function is replaced by the :truename stream operation, which returns a pathname containing the actual name of the file open on that stream. The directory and allfiles functions are replaced by fs:directory-list.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The following examples illustrate some of the rules of parsing and merging. They assume that the default host is an ITS host named AI.
If we parse the string "AI:COMMON;NOMEN 5" (by calling fs:parse-pathname), we get back a pathname that prints as #<ITS-PATHNAME "AI: COMMON; NOMEN 5">. Its host is "AI", its device is "DSK" (because of the rule that when you specify a host and don't specify a device, the standard file-storage device for that host is used), its directory is "COMMON", its name is "NOMEN", its type is nonexistent (:unspecific), and its version is 5. Call this pathname p.
Parsing just the string "foo" returns a pathname that prints as #<ITS-PATHNAME "AI: FOO">. The host is "AI", the name is "FOO", and all the other components are unspecified, i.e. nil.
If we merge this with p (by calling fs:merge-pathname-defaults with this pathname as its first argument and p as its second), the result is a pathname that prints as #<ITS-PATHNAME "AI: COMMON; FOO >">, with host "AI", device "DSK", directory "COMMON", name "FOO", type :unspecific, and version :newest. This is because of the rule that when a name is explicitly specified, the type and version of the defaults are ignored. The version, 5, was ignored, and the version of the result came from the default-version argument to fs:merge-pathname-defaults, which had the value :newest. The type, similarly, came from the default-type argument, which had the value :unspecific.
Parsing "FOO BAR" returns a pathname that prints as #<ITS-PATHNAME "AI: FOO BAR">. It has host "AI", name "FOO", and type "BAR"; the directory is nil and the version is :newest. Merging this with p gives a pathname that prints as #<ITS-PATHNAME "AI: COMMON; FOO BAR">; it has host "AI", device "DSK", directory "COMMON", name "FOO", type "BAR", and version :newest. If we ask for the generic pathname of this new pathname, what we get prints exactly the same, but one of its components is different: its version is :unspecific. This difference does not appear in the printed representation because ITS filenames cannot convey both a meaningful type and a meaningful version number at the same time.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |