Pfs — C Library Procedures
NAME
Pfs_Open, Pfs_OpenConnection, Pfs_SetHandler, Pfs_PassFile, Pfs_Close − Package for servicing pseudo-file-systems.
SYNOPSIS
#include <pdev.h> Pfs_Token
Pfs_Open(prefix, rootIDPtr, pfsService, clientData)
Pdev_Stream ∗
Pfs_OpenConnection(pfsToken, fileIDPtr, reqBufSize, readBufSize, readBuf, selectBits, pdevService)
int (∗
Pfs_SetHandler(pfsToken, operation, handler))()
int
Pfs_PassFile(pfsToken, streamID)
void
Pfs_Close(pfsToken)
ARGUMENTS
char ∗prefix (in) File name prefix of the pseudo-file-system.
Fs_FileID ∗rootIDPtr (in) The server-defined ID of the root.
Pfs_CallBacks ∗pfsService (in) Set of name service call-back procedures.
ClientData clientData (in) User-defined data passed to service call-backs.
Pfs_Token pfsToken (in) Return value of Pfs_Open.
Fs_FileID ∗fileIDPtr (in) Server’s identifier for file in pseudo-file-system.
int reqBufSize (in) Preferred size for the request buffer.
int readBufSize (in) Size of read buffer. Zero means no read buffering.
char ∗readBuf (in) Optional read buffer, or NULL.
int selectBits (in) FS_READABLE, FS_WRITABLE, FS_EXCEPTION
Pdev_CallBacks ∗pdevService (in) Set of pseudo-device service call-back procedures.
int streamID (in) A regular open file descriptor returned from open.
Pfs_Open
Pfs_Open declares a server process for a pseudo-file-system and installs a set of service procedures for it. The service procedures are called when client processes do file naming operations on the pseudo-file-system, i.e. open, stat, unlink, mkdir, rmdir, rename, and link. As a side effect of opening a file in the pseudo-file-system the server can set up a pseudo-device connection for the open file. Thus the server can completely implement file system access to the pseudo-file-system.
The prefix argument indicates what part of the global file system hierarchy is controlled by the pseudo-file-system server. This prefix can be arbitrarily nested in the hierarchy but there must be a remote link that corresponds to it. (The command ln -r prefix creates a remote link for the prefix.) The existence of the remote link ensures that the kernel’s lookup algorithm will automatically find the pseudo-file-system server. The pseudo-file-system is visible across the network as well.
The rootIDPtr defines the file ID for the root of the pseudo-file-system. This ID will be presented as the prefixID for pathnames that begin at the root (prefix) of the pseudo-file-system. The file ID has the following format. The server can define the file ID to fit its own needs. However, the special type value of -1 is reserved to indicate an invalid file ID. typedef struct {
int type;
int serverID;
int major;
int minor; } Fs_FileID;
The pfsService procedures are described in detail below. The clientData argument is passed to all the naming service procedures. It is ordinarily used to get to the state of the pseudo-file-system.
The return value of Pfs_Open is a token for the pseudo-file-system, which must be used in calls to Pfs_OpenConnection, Pfs_PassFile, Pfs_SetHandler, and Pfs_Close. If a pseudo-file-system couldn’t be opened, then NULL is returned and pfs_ErrorMsg contains a string describing the problem.
The Pfs package uses the facilities of Fs_Dispatch in order to keep track of the streams associated with the pseudo-file-system and ensure that Pfs is notified whenever those streams become readable. In order to use Pfs, you must also use Fs_Dispatch.
Pfs_OpenConnection
Pfs_OpenConnection is used to create open file connections to the pseudo-file-system indicated by pfsToken. Open file connections can only be made during an open call-back. The open file connection is the same as a connection to a pseudo-device with the addition of two new requests to handle fstat, fchmod, and fchown. The details of using the pseudo-device call-backs are given in the Pdev man page.
The fileIDPtr is a server-defined identifier for the open file. The server can set the file ID fields to any values that make sense to it. However, by convention a type of -1 indicates an invalid fileID. This special case may occur when handling the rename and hardLink call-backs. Note that the file IDs for directories in the pseudo-file-system may be presented back to the server as a prefixID that indicates the starting point of the lookup operation. Thus a process can have a current directory inside the pseudo-file-system and name files relative to that directory.
The pdevService parameter is a set of pseudo-device call-backs. The use of these call-backs is described in detail in the Pdev man page.
The reqBufSize parameter indicates the preferred size of the request buffer associated with the pseudo-device connection. This size determines how many requests can be bufferred before the kernel has to wait on the server. A minimum size is enforced by the library, so zero can be passed to get the default size (about 1 Kbyte).
The readBufSize and readBuf parameters indicate the size and location of an optional read buffer. No buffering is indicated by a zero read buffer size. See the library Pdev and device pdev man pages for more details on using a read buffer.
Pfs_PassFile
Pfs_PassFile is used to pass the open file descriptor of a regular file back to a client in response to an open request. If this is done then the pseudo-file-system server sees no further requests concerning this open file; the file is handled in the regular way the by kernel.
Pfs_PassFile exists, but the kernel doesn’t support it, yet.
Pfs_Close
Pfs_Close is used to end pseudo-file-system service. This closes the naming stream to the kernel and frees up any dynamically allocated storage. After this call pfsToken should not be used.
Pfs_PassFile exists, but the kernel doesn’t support it, yet.
NAME SERVICE PROCEDURES
The callbacks are given to Pfs_Open as a record of procedures: typedef struct {
int (∗open)();/∗ PFS_OPEN ∗/
int (∗getAttr)();/∗ PFS_GET_ATTR ∗/
int (∗setAttr)();/∗ PFS_SET_ATTR ∗/
int (∗makeDevice)();/∗ PFS_MAKE_DEVICE ∗/
int (∗makeDir)();/∗ PFS_MAKE_DIR ∗/
int (∗remove)();/∗ PFS_REMOVE ∗/
int (∗removeDir)();/∗ PFS_REMOVE_DIR ∗/
int (∗rename)();/∗ PFS_RENAME ∗/
int (∗hardLink)();/∗ PFS_HARD_LINK ∗/
int (∗symLink)();/∗ PFS_SYM_LINK ∗/ } Pfs_CallBacks;
Any of the elements can be NULL to indicate that the operation should be handled by a default handler that is a no-op procedure that returns a file-not-found error. The service parameter to Pfs_Open itself can also be NULL to indicate default handling for all operations. This is only useful during initial test. The global variable pfs_Trace can be set to a non-zero value to generate printfs to stderr when each service procedure (default or user-supplied) is invoked.
All the name service procedures have a similar calling sequence that includes a relative pathname, a record containing input parameters, and a buffer for pathname redirection. (The rename and hardlink procedures have slighly different calling sequences because they handle two pathnames.) The pathname is relative to a prefix indicated by a prefixID in the input parameters. This ID is either for the root as defined by the rootIDPtr argument to Pfs_Open, or for some directory who’s ID was defined by Pfs_OpenConnection when the directory was entered by a client process.
The service procedures should return 0 to mean success, otherwise they should return a suitable errno value. There are no other return results. Open file connections are created as a side effect using Pfs_OpenConnection.
It is possible that the pathname may leave the pseudo-file-system during any lookup operation. This happens with remote links, symbolic links back to the root, or with enough “..” components to take the pathname out the top of the pseudo-file-system. In this case the pseudo-file-system server should return the remaining, or new, pathname instead of attempting to follow it itself. The return code EREMOTE is used to indicate this situation, and the redirectPtr argument is used to return the new name: typedef struct FsRedirectInfo {
intprefixLength;
char fileName[FS_MAX_PATH_NAME_LENGTH]; } FsRedirectInfo;
If the lookup hits a symbolic link to the root the server should expand the link and return the new absolute pathname in this buffer. A remote link is like a symbolic link, except it indicates a nested prefix and its contents are the prefix itself. Expanding it will result in a new absolute pathname. The length of the prefix that is embedded in the absolute path should be returned in the prefixLength field. With regular symbolic links this field should be zero. If the server hits a “..” component that leaves its root it should place the remaining pathname, including the offending “..” component, into the buffer. The prefix length is again zero in this case.
open
int (∗service->open)(clientData, name, openArgsPtr, redirectPtr)
ClientData clientData;/∗ Passed into Pfs_Open ∗/
char ∗name;/∗ Relative pathname ∗/
Fs_OpenArgs ∗openArgsPtr;/∗ Identifies prefix and caller ∗/
FsRedirectInfo ∗redirectPtr;/∗ Return - new pathname and prefix info if ∗ name leaves the pseudo-file-system ∗/
The open service procedure is invoked in response to an open system call by a client process. The clientData argument is the value passed into Pfs_Open and is generally used to get back to the state kept for the pseudo-file-system. The name is a relative pathname that begins at the prefix indicated by ∗openArgsPtr. The FsOpenArgs structure identifies the root of the pseudo-file-system, the prefix or starting directory of the pathname, and the identity of the calling process: typedef struct {
Fs_FileID prefixID;/∗ File ID from prefix handle ∗/
Fs_FileID rootID;/∗ File ID of root. ∗/
int useFlags;/∗ Flags defined in fs.h ∗/
int permissions;/∗ Permission bits for created files. Already ∗ reflects per-process permission mask ∗/
int type;/∗ Used to contrain open to a specific type ∗/
int clientID;/∗ Host ID of client doing the open ∗/
Fs_UserIDs id;/∗ User and group IDs ∗/ } FsOpenArgs;
The prefixID is either the fileID of the root of the pseudo-file-system, or the fileID of some directory in the pseudo-file-system that has been previously opened. The useFlags is an or’d combination of flags defined in <fs.h> that include FS_READ, FS_WRITE, and FS_EXECUTE. The permissions define the file mode when creating a file. File creation is indicated by the FS_CREATE usage flag.
The type is used to constrain the open to a particular kind of file. Possible values are FS_FILE, which means any type will do, FS_DIRECTORY when changing the current directory, and FS_SYMBOLIC_LINK when reading links.
IMPORTANT: Pfs_OpenConnection and Pfs_PassFile can only be called during the servicing of an open request. If they are called (successfully) by the open call-back it must return 0, never a non-zero error status.
getAttr
int (∗service->getAttr)(clientData, name, openArgsPtr, attrPtr, redirectInfoPtr)
ClientData clientData;/∗ Passed into Pfs_Open ∗/
char ∗name;/∗ Relative pathname ∗/
FsOpenArgs ∗openArgsPtr;/∗ Bundled arguments ∗/
Fs_Attributes ∗attrPtr;/∗ Return - attributes of the file ∗/
FsRedirectInfo ∗redirectInfoPtr; /∗ Used when name leaves our domain ∗/
This call-back is made to get the attributes of a file in the pseudo-file-system given its pathname. The arguments are similar to those of the open call-back. The attrPtr argument is used to return the attributes.
setAttr
int (∗service->setAttr)(clientData, name, openArgsPtr, flags, attrPtr, redirectInfoPtr)
ClientData clientData;/∗ Passed into Pfs_Open ∗/
char ∗name;/∗ Relative pathname ∗/
FsOpenArgs ∗openArgsPtr;/∗ Bundled arguments ∗/
int flags;/∗ Specifies which attrs to set ∗/
Fs_Attributes ∗attrPtr;/∗ New attributes of the file ∗/
FsRedirectInfo ∗redirectInfoPtr; /∗ Used when name leaves our domain ∗/
This call-back is made to set certain attributes of a file in the pseudo-file-system given its pathname. The arguments are similar to those of the open call-back. Additionally, the flags argument indicates which attributes are to be set, and the attrPtr argument specifies their new values. The flags are an or’d combination of FS_SET_TIMES, FS_SET_MODE, FS_SET_OWNER, FS_SET_FILE_TYPE, FS_SET_DEVICE.
makeDevice
int (∗service->makeDevice)(clientData, name, makeDevArgsPtr, redirectInfoPtr)
ClientData clientData;/∗ Passed into Pfs_Open ∗/
char ∗name;/∗ Relative pathname ∗/
FsMakeDeviceArgs ∗makeDevArgsPtr; /∗ Bundled arguments ∗/
FsRedirectInfo ∗redirectInfoPtr; /∗ Used when name leaves our domain ∗/
This call-back is made to create a special device file in the pseudo-file-system. The FsMakeDeviceArgs are similar to the FsOpenArgs with some addition information about the device: typedef struct {
Fs_FileID prefixID;/∗ FileID of the prefix ∗/
Fs_FileID rootID;/∗ FileID of the root ∗/
Fs_Device device;/∗ Device attributes ∗/
int permissions;/∗ Permissions already reflect per-process mask ∗/
Fs_UserIDs id;/∗ Identifies calling process ∗/
int clientID;/∗ Identifies host of calling process ∗/ } FsMakeDeviceArgs;
makeDir
int (∗service->makeDir)(clientData, name, openArgsPtr, redirectInfoPtr)
ClientData clientData;/∗ Passed into Pfs_Open ∗/
char ∗name;/∗ Relative pathname ∗/
FsOpenArgs ∗openArgsPtr;/∗ Bundled arguments ∗/
FsRedirectInfo ∗redirectInfoPtr; /∗ Used when name leaves our domain ∗/
This call-back is made to create a directory. The arguments are similar to those of the open call-back.
remove
int (∗service->remove)(clientData, name, lookupArgsPtr, redirectInfoPtr)
ClientData clientData;/∗ Passed into Pfs_Open ∗/
char ∗name;/∗ Relative pathname ∗/
FsLookupArgs ∗lookupArgsPtr; /∗ Bundled arguments ∗/
FsRedirectInfo ∗redirectInfoPtr; /∗ Used when name leaves our domain ∗/
This call-back is made to remove a file in the pseudo-file-system. FsLookupArgs are a simplified sub-set of FsOpenArgs: typedef struct {
Fs_FileID prefixID;/∗ FileID of the prefix ∗/
Fs_FileID rootID;/∗ FileID of the root ∗/
int useFlags;/∗ not used ∗/
Fs_UserIDs id;/∗ User and group IDs of calling process ∗/
int clientID;/∗ Host ID of calling process ∗/ } FsLookupArgs;
removeDir
int (∗service->removeDir)(clientData, name, lookupArgsPtr, redirectInfoPtr)
ClientData clientData;/∗ Passed into Pfs_Open ∗/
char ∗name;/∗ Relative pathname ∗/
FsLookupArgs ∗lookupArgsPtr; /∗ Bundled arguments ∗/
FsRedirectInfo ∗redirectInfoPtr; /∗ Used when name leaves our domain ∗/
This call-back is made to remove a directory in the pseudo-file-system. The server should check against removing non-empty directories. The arguments are the same as for remove.
rename
int (∗service->rename)(clientData, srcName, dstName, twoNameArgsPtr, redirect2InfoPtr)
ClientData clientData;/∗ Passed into Pfs_Open ∗/
char ∗srcName;/∗ Original name ∗/
char ∗dstName;/∗ New name ∗/
Fs2PathParams ∗twoNameArgsPtr;/∗ Lookup args plus prefixID2 ∗/
Fs2PathRedirectInfo ∗redirect2InfoPtr; /∗ Used when name leaves our domain ∗/
This call-back is made to change the name of a file in the pseudo-file-system. The arguments are bundled into the Fs2PathParams structure: typedef struct Fs2PathParams {
FsLookupArgs lookup;/∗ Regular lookup parameters ∗/
Fs_FileID prefixID2;/∗ Prefix of second pathname ∗/ } Fs2PathParams;
It is possible that the second pathname is not a part of the pseudo-file-system. The Sprite kernel still calls out to the pseudo-file-system in this case because the first pathname might be redirected out of the pseudo-file-system. If the second prefixID does not belong to the pseudo-file-system that is indicated by a type value of -1. If the first pathname remains in the pseudo-file-system but the second prefixID is not in the pseudo-file-system then the error EXDEV should be returned. If either of the pathnames gets redirected, or an error occurs during pathname interpretation, the Fs2PathRedirectInfo structure is used to return more information: typedef struct {
int name1ErrorP;/∗ TRUE if redirection or other error applies ∗ to the first pathname, FALSE if the error ∗ applies to second pathname, or no error ∗/
int prefixLength;/∗ The length of the prefix embedded in ∗ fileName. This is used when a server hits ∗ a remote link and has to return a new file ∗ name plus an indication of a new prefix. ∗/
char fileName[FS_MAX_PATH_NAME_LENGTH]; /∗ The new file name. Returned ∗ from the server when its lookup is about ∗ to leave its domain. ∗/ } Fs2PathRedirectInfo;
hardLink
int (∗service->hardLink)(clientData, srcName, dstName, twoNameArgsPtr, redirect2InfoPtr)
ClientData clientData;/∗ Passed into Pfs_Open ∗/
char ∗srcName;/∗ Original name ∗/
char ∗dstName;/∗ New name ∗/
Fs2PathParams ∗twoNameArgsPtr;/∗ Lookup args plus prefixID2 ∗/
Fs2PathRedirectInfo ∗redirect2InfoPtr; /∗ Used when name leaves our domain ∗/
This call-back is used to create a hard link between two files in the pseudo-file-system. The arguments are the same as those for rename, and the same comments about pathname redirection apply.
symLink
int (∗service->symLink)(clientData, linkName, value, openArgsPtr, redirectInfoPtr)
ClientData clientData;/∗ returned from Pfs_Open ∗/
char ∗linkName;/∗ SymLink file name ∗/
char ∗value;/∗ Symlink value ∗/
FsOpenArgs ∗openArgsPtr;/∗ Open arguments ∗/
FsRedirectInfo ∗redirectInfoPtr;/∗ Used when srcName leaves our domain ∗/
This call-back is used to create a symbolic link in the pseudo-file-system. The arguments are similar to those for open, except there are two pathnames. Pathname redirection is only possible on the linkName. The value pathname is simply used as the value of the link regardless of its location in the system. (This is not currently used. Symbolic links are created instead by opening a file of type FS_SYMBOLIC_LINK and writing the link value into it. This will change, although it currently works in NFS.)
The type field in the open args is used differentiate between a regular symbolic link and a remote link. A remote link is a circular symbolic link with a different file descriptor type than a symbolic link. Remote links are used in native Sprite file systems to indicate a nested prefix that is stored elsewhere. Bumping into a remote link causes a pathname redirection just like hitting a symbolic link back to the root. Additionally, however, the redirection information also includes the length of the prefix that is embedded into the returned pathname.
SEE ALSO
pfs (devices), Pdev, Swap_Buffer
KEYWORDS
pseudo-file-system
Sprite version 1.0 — June 27, 1990