[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

34. Naming of Files

.setq pathname section-page .setq pathname-chapter chapter-number

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
with DSK being a device name, GEORGE being a directory name, FOO being the first file name and QFASL being the second file name. However, in TOPS-20, a similar file name is expressed as:
 
	PS:<GEORGE>FOO.QFASL
It would be unreasonable for each program that deals with file names to be expected to know about each different file name format that exists; in fact, new formats could get added in the future, and existing programs should retain their abilities to manipulate the names.

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] [ ? ]

34.1 Pathnames

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
An object which represents the file system machine on which the file resides. A host object is an instance of a flavor one of whose components is SI:HOST. The precise flavor varies depending on the type of file system and how the files are to be accessed.

device
Corresponds to the "device" or "file structure" concept in many host file systems.

directory
The name of a group of related files belonging to a single user or project. Corresponds to the "directory" concept in many host file systems.

name
The name of a group of files which can be thought of as conceptually the "same" file.

type
Corresponds to the "filetype" or "extension" concept in many host file systems. This says what kind of file this is.

version
Corresponds to the "version number" concept in many host file systems. This is a number which increments every time the file is modified.

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.
If the string does not specify a host explicitly, the parser will assume some particular host is the one in question, and will use the parser for that host's file system. The optional arguments passed to the parsing function (fs:parse-pathname) tell it which host to assume. Note: the parser won't be confused by strings starting with "DSK:" or "PS:" because it knows that neither of those is a valid host name. (If some file system's syntax allowed file names that start with the name of a valid host followed by a colon, there could be problems.)

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] [ ? ]

34.2 Defaults and Merging

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.

Variable: fs:*defaults-are-per-host*
This is a user customization option intended to be set by a user's LISPM INIT file (see (lispm-init-file)). The default value is nil, which means that each program's set of defaults contains only one default pathname. If you type in just a host name and a colon, the other components of the name will default from the previous host, with appropriate translation to the new host's pathname syntax. If fs:*defaults-are-per-host* is set to t, each program's set of defaults will maintain a separate default pathname for each host. If you type in just a host name and a colon, the last file that was referenced on that host will be used.

Variable: fs:*always-merge-type-and-version*
If this variable is non-nil, then the type and version are defaulted only from the pathname defaults just like the other components.

Variable: fs:*name-specified-default-type*
If fs:*always-merge-type-and-version* is nil, then when a name is specified but not a type, the type defaults from an argument to the merging function. If that argument is not specified, this variable's value is used. The value is initially "LISP".

Variable: fs:*default-pathname-defaults*
This is the default defaults a-list; if the pathname primitives that need a set of defaults are not given one, they use this one. Most programs, however, should have their own defaults rather than using these.

Variable: fs:load-pathname-defaults
This is the defaults a-list for the load and qc-file functions. Other functions may share these defaults if they deem that to be an appropriate user interface.

Variable: fs:last-file-opened
This is the pathname of the last file that was opened. Occasionally this is useful as a default. Since some programs deal with files without notifying the user, you must not expect the user to know what the value of this symbol is. Using this symbol as a default may cause unfortunate surprises, and so such use is discouraged.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

34.3 Generic Pathnames

.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).

Variable: fs:*generic-base-type-alist*
This is an association list of the file types and the type of the generic pathname used for the group of which that file type is a part. Constructing a generic pathname will replace the file type with the association from this list, if there is one (except that ITS hosts, always replace with :UNSPECIFIC). File types not in this list are really part of the name in some sense. The initial list is
 
 (("TEXT" . "TEXT") ("DOC" . "TEXT") ("PRESS" . "TEXT") ("XGP" . "TEXT")
  ("LISP" . :UNSPECIFIC) ("QFASL" . :UNSPECIFIC) (NIL . :UNSPECIFIC))
The association of "LISP" and :UNSPECIFIC is unfortunately made necessary by the problems of ITS mentioned previously. This way makes the generic pathnames of logically mapped LISP files identical no matter whether the logical host is mapped to an ITS host or not.

Some users may need to add to this list.

The system records certain properties on generic pathnames automatically.

:warnings
This property is used to record compilation and other warnings for the file.

:definitions
This property records all the functions and other things defined in the file. The value has one element for each package into which the file has been loaded; the element's car is the package itself and the cdr is a list of definitions made.

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
This property's value is a list of the names of all the systems (defined with defsystem, see (defsystem-fun)) of which this is a source file.

:file-id-package-alist
This property records what version of the file was most recently loaded. In case the file has been loaded into more than one package, as is sometimes necessary, the loaded version is remembered for each package separately. This is how make-system tells whether a file needs to be reloaded. The value is a list with an element for each package that the file has been loaded into; the elements look like
 
(package file-information)
package is the package object itself; file-information is the value returned by the :info operation on a file stream, and is usually a cons whose car is the truename (a pathname) and whose cdr is the file creation date (a universal time number).

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
The value is a string, which is the major mode that should be used to edit the file.

:base
The value is the number to be used as the radix which readfile and qc-file use for reading the file.

:package
The value is the name of the package to be used for reading and editing the file.

:fonts
The value is a list of font names for the fonts to be used in displaying this file.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

34.4 Pathname Functions

These functions are what programs use to parse and default file names that have been typed in or otherwise supplied by the user.

Function: fs:parse-pathname thing &optional host defaults
This turns thing, which can be a pathname, a string, a symbol, or a Maclisp-style name list, into a pathname. Most functions which are advertised to take a pathname argument call fs:parse-pathname on it so that they will accept anything that can be turned into a pathname.

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.

Function: fs:merge-pathname-defaults pathname &optional defaults default-type default-version
Fills in unspecified components of pathname from the defaults, and returns a new pathname. This is the function that most programs should call to process a file name supplied by the user. pathname can be a pathname, a string, a symbol, or a Maclisp namelist. The returned value will always be a pathname. The merging rules are documented on (pathname-merging-rules).

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.

Function: fs:merge-and-set-pathname-defaults pathname &optional defaults default-type default-version
This is the same as fs:merge-pathname-defaults except that after it is done the result is stored back into defaults. This is handy for programs that have "sticky" defaults. (If defaults is a pathname rather than a defaults a-list, then no storing back is done.) The optional arguments default the same way as in fs:merge-pathname-defaults.

.need 1500 This function yields a pathname given its components.

Function: fs:make-pathname &rest options
The options are alternating keywords and values, which specify the components of the pathname. Missing components default to nil, except the host (all pathnames must have a host). The :defaults option specifies what defaults to get the host from if none is specified. The other options allowed are :host, :device, :structured-device, :directory, :structured-directory, :name, :structured-name, :type, and :version.

.need 1500 These functions are used to manipulate defaults a-lists directly.

Function: fs:make-pathname-defaults
Creates a defaults a-list initially containing no defaults. Asking this empty set of defaults for its default pathname before anything has been stored into it will return the file FOO on the user's home directory on the host he logged in to.

Function: fs:copy-pathname-defaults defaults
Creates a defaults a-list initially a copy of defaults.

Function: fs:default-pathname &optional defaults host default-type default-version
This is the primitive function for getting a default pathname out of a defaults a-list. Specifying the optional arguments host, default-type, and default-version to be non-nil forces those fields of the returned pathname to contain those values.

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.

Function: fs:set-default-pathname pathname &optional defaults
This is the primitive function for updating a set of defaults. It stores pathname into defaults. If defaults is not specified, the default defaults are used.

.need 1500 These functions return useful information.

Function: fs:user-homedir &optional host reset-p
Returns the pathname of the logged-in user's home directory on host, which defaults to the host the user logged in to. Home directory is a somewhat system-dependent concept, but from the point of view of the Lisp Machine it is the directory where the user keeps personal files such as init files and mail. This function returns a pathname without any name, type, or version component (those components are all nil). If reset-p is specified non-nil, the machine the user is logged in to is changed to be host.

Function: fs:init-file-pathname program-name &optional host
Returns the pathname of the logged-in user's init file for the program program-name, on the host, which defaults to the host the user logged in to. Programs that load init files containing user customizations call this function to find where to look for the file, so that they need not know the separate init file name conventions of each host operating system. The program-name "LISPM" is used by the login function.

.need 1500 These functions are useful for poking around.

Function: fs:describe-pathname pathname
If pathname is a pathname object, this describes it, showing you its properties (if any) and information about files with that name that have been loaded into the machine. If pathname is a string, this describes all interned pathnames that match that string, ignoring components not specified in the string. One thing this is useful for is finding what directory a file whose name you remember is in. Giving describe (see (describe-fun)) a pathname object will do the same thing as this function will.

Function: fs:pathname-plist pathname
Parses and defaults pathname then returns the list of properties of that pathname.

Variable: fs:*pathname-hash-table*
This is the hash table in which pathname objects are interned. Applying the function maphash-equal to this will extract all the pathnames in the world.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

34.5 Pathname Messages

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.

Method: pathname :host
Method: pathname :device
Method: pathname :directory
Method: pathname :name
Method: pathname :type
Method: pathname :version
These return the components of the pathname. The returned values can be strings, special symbols, or lists of strings in the case of structured components. The type will always be a string or a symbol. The version will always be a number or a symbol.

Method: pathname :new-device dev
Method: pathname :new-directory dir
Method: pathname :new-name name
Method: pathname :new-type type
Method: pathname :new-version version
These return a new pathname which is the same as the pathname they are sent to except that the value of one of the components has been changed. The :new-device, :new-directory and :new-name messages accept a string (or a special symbol) or a list which is a structured name. If the host does not define structured components, and you specify a list, its first element is used.

Method: pathname :new-pathname &rest options
This returns a new pathname which is the same as the pathname it is sent to except that the values of some of the components have been changed. options is a list of alternating keywords and values. The keywords all specify values of pathname components; they are :host, :device, :directory, :name, :type, and :version.

The operations :new-name, etc., are equivalent to :new-pathname specifying only one component to be changed.

Method: pathname :generic-pathname
Returns the generic pathname for the family of files of which this pathname is a member. See (generic-pathname) for documentation on generic pathnames.

Method: pathname :primary-device
Returns the default device name for the pathname's host. This is used in generating the initial default pathname for a host.

.need 1500 Messages to get a path name string out of a pathname object:

Method: pathname :string-for-printing
Returns a string which is the printed representation of the path name. This is the same as what you get if you princ the pathname or take string of it.

Method: pathname :string-for-wholine
Returns a string which may be compressed in order to fit in the wholine.

Method: pathname :string-for-editor
Returns a string which is the path name with its components rearranged so that the name is first. The editor uses this form to name its buffers.

Method: pathname :string-for-dired
Returns a string to be used by the directory editor. The string contains only the name, type, and version.

Method: pathname :string-for-directory
Returns a string which contains only the device and directory of the pathname. It identifies one directory among all directories on the host.

Method: pathname :string-for-host
Returns a string which is the path name the way the host file system likes to see it.

.need 1500 Messages to move around through a hierarchy of directories:

Method: pathname :pathname-as-directory
Assuming that the file described by the pathname is a directory, return another pathname specifying that as a directory. Thus, if sent to a pathname OZ:<RMS>FOO.DIRECTORY, it would return the pathname OZ:<RMS.FOO>. The name, type and version of the returned pathname are :unspecific.

Method: pathname :directory-pathname-as-file
This is the inverse of the preceding operation. It returns a pathname specifying as a file the directory of the original pathname. The name, type and version of the original pathname are ignored.

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:

Method: pathname :get indicator
Method: pathname :getl list-of-indicators
Method: pathname :putprop value indicator
Method: pathname :remprop indicator
Method: pathname :plist
These manipulate the pathname's property list analogously to the functions of the same names (see (get-fun)), which don't (currently) work on instances. Please read the paragraph on (pathname-plist-warning) explaining some care you must take in using property lists of pathnames.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

34.6 Host File Systems Supported

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] [ ? ]

34.6.1 ITS

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".

Variable: fs:*its-uninteresting-types*
The ITS file system does not have separate file types and version numbers; both components are stored in the "FN2". This variable is a list of the file types which are "not important"; files with these types use the FN2 for a version number. Files with other types use the FN2 for the type and do not have a version number. The initial list is
 
("lisp" "text" nil :unspecific)
Some users may need to add to this list.

Method: its-pathname :fn1
Method: its-pathname :fn2
These two messages return a string which is the FN1 or FN2 host-dependent component of the pathname.

Method: pathname :type-and-version
Method: pathname :new-type-and-version new-type new-version
These two operations provide a way of pretending that ITS pathnames can have both a type and a version. It uses the first three characters of the FN2 to store a type and the last three to store a version number.

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] [ ? ]

34.6.2 TOPS-20 (Twenex), Tenex, and VMS.

A pathname on TOPS-20 (better known as Twenex) looks like "HOST:DEVICE:NAME.TYPE.VERSION". The primary device is PS:.

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] [ ? ]

34.6.3 Unix pathnames

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] [ ? ]

34.6.4 Lisp Machine File Systems

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] [ ? ]

34.6.5 Logical Pathnames

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.

Function: fs:add-logical-pathname-host logical-host physical-host translations
This creates a new logical host named logical-host. Its corresponding "physical" host (that is, the host to which it will forward most operations) is physical-host. logical-host and physical-host should both be strings. translations should be a list of translation specifications. Each translation specification should be a list of two strings. The first is the name of a directory on the logical host. The second is a pathname whose device component and directory component are the translation of that directory. A translation for logical directory nil specifies the default device for the logical host; if there is none, the primary device of the physical host is used. Example:
 
(fs:add-logical-pathname-host "music" "music-10-a"
      '(("melody" "ss:")
        ("doc" "ps:")))

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).

Method: fs:logical-pathname :translated-pathname
This converts a logical pathname to a physical pathname. It returns the translated pathname of this instance; a pathname whose :host component is the physical host that corresponds to this instance's logical host.

If this message is sent to a physical pathname, it simply returns itself.

Method: fs:logical-pathname :back-translated-pathname pathname
This converts a physical pathname to a logical pathname. pathname should be a pathname whose host is the physical host corresponding to this instance's logical host. This returns a pathname whose host is the logical host and whose translation is pathname.

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)
returns the logical pathname that was opened.
 
(funcall stream ':truename)
returns the true name of the file that is open, which of course is a pathname on the physical host. To get this in the form of a logical pathname, one would do
 
(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] [ ? ]

34.7 Hosts

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] [ ? ]

34.7.1 Parsing Hostnames

Function: si:parse-host namestring &optional no-error-p unknown-ok
Returns a host object that recognizes the specified name. If the name is not recognized, it is an error, unless no-error-p is non-nil; in that case, nil is returned.

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.

Function: si:get-host-from-address address network
Returns a host object given an address and the name of the network which that address is for. Usually the symbol :chaos is used as the network name.

nil is returned if there is no known host with that address.

Function: fs:get-pathname-host name &optional no-error-p
Returns a host object that can be used in pathnames. If the name is not recognized, it is an error, unless no-error-p is non-nil; in that case, nil is returned.

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.

Variable: fs:*pathname-host-list*
This is a list of all the host objects that support file access.

Variable: si:host-alist
This variable is a list of one element for each known network host. The element looks like this:
 
(full-name host-object (nickname nickname2 ... full-name)
 system-type machine-type site
 network list-of-addresses network2 list-of-addresses2 ...)
The full-name is the host's official name. The :name operation on the host object returns this.

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] [ ? ]

34.7.2 Host Object Messages

.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] [ ? ]

34.8 Maclisp Conversion

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] [ ? ]

34.9 Examples

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] [ ? ]

This document was generated by Brad Parker on June, 13 2006 using texi2html