Previous section.

Protocols for Interworking: XNFS, Version 3W
Copyright © 1998 The Open Group

Semantic Difference Summary for File Access

Introduction

Many of the entries described in the X/Open System Interfaces and Headers Specification (see reference XSH) and the X/Open Commands and Utilities Specification (see reference XCU) are directly or indirectly concerned with accessing files stored on the system's file system.

When documenting those utilities and functions the assumption was made that files being accessed would reside on the local file system of the system, and that all local file system semantics would be supported. Users or applications using an XCU utility or XSH function could therefore rely on described behaviour and error codes being returned as described in that XPG entry.

When XPG-compliant systems are linked together using XNFS protocols, files on remote systems may be accessible to a process running on a local system, without the process being aware that files are remote. In fact, because XNFS provides transparent access to remote files, it is not possible for a process to distinguish between local and remote files before they are used. Due to the nature of the way XNFS works, there are some semantic differences between operations on local files and equivalent operations on remote files.

This appendix gives a summary of these semantic differences. Together with Open-System Interface Semantics over XNFS and Open System Utilities Semantics over XNFS this appendix specifies differences that can occur when using a given utility or function with a file on a remote file system.

XNFS describes a number of new errors which may occur when CAE applications issue XSH function calls which refer to XNFS file systems. One error, which occurs when a file handle is rejected as invalid by the XNFS server, is represented by a new error code, [ESTALE]. All other errors discussed in this specification are represented by existing XSH error codes; thus the set of possible interpretations for each of these codes is extended when XNFS is being used. It should be noted that the X/Open Commands and Utilities Specification (see reference XCU) explicitly allows implementors to define additional error codes, and does not define which error should be reported when multiple errors occur during a single operation. Notwithstanding this, the XNFS specification defines only one new error code, [ESTALE], and implementors of XNFS are strongly discouraged from introducing additional error codes which are specific to XNFS. See also the description of NFSERR_STALE in stat .

There are not many areas in which semantic differences manifest themselves. The following list summarises differences which are common to many system interface functions or utilities. Specific differences that are not common to several functions or utilities are discussed in the description of that function or utility in Open-System Interface Semantics over XNFS and Open System Utilities Semantics over XNFS respectively.

Special File Access

A process may create, rename, unlink, and get the attributes of a special file that is located on a remote file system. A process may also fattach() a STREAMS file descriptor to a remote file. If a process opens a remote special file, a local device will be used instead of the (possibly desired) remote device. This includes the FIFO special file type, support for which is not mandated in the XNFS specification.

If a process opens a remote special file, the local device that is used will be the local device that corresponds to the major and minor numbers associated with the remote special file. If there is no local device corresponding to this major and minor number pair, the operation will fail. For example, if pax is used to extract files from a tape, pax must be run on the host that owns the tape drive.

A process may be unable to create a remote special file, either because the server doesn't support special files at all ([EOPNOTSUPP]), or because the server doesn't support the requested special file type ([EINVAL]).

See also Special Files for semantic differences that can arise when accessing special files with Version 2 of the NFS protocol.

UID Mapping by Server

Access to a file located on a remote file system can be denied, even in the case that the file permissions do not themselves restrict access. When the server exports a file system, the following attributes can be specified which control access to the file system:

  1. The server will treat requests from a client process with an unknown user ID as having the user ID that is specified in the "AnonMapping=" ExportedFileSystem attribute. (See the discussion of the "AnonMapping=" ExportedFileSystem attribute in ExportedFileSystem .)

  2. The server can deny access by privileged user from specified hosts. Should the server receive a request for file access from a process with an effective user ID of 0 on a denied host, the request will be processed. However, the value specified in the "AnonMapping=" ExportedFileSystem attribute will be used instead of the effective user ID of the process. (See the discussion of the "AnonMapping=" and "Root=" ExportedFileSystem attributes in ExportedFileSystem .)

If such a mapping occurs and thus causes the server to deny access to a file, the error [EACCES] will be returned to the process.

In the case that the server denies access by a privileged user, the semantics of those file access functions that require appropriate privileges may not be available to the calling process, the error [EPERM] will be returned to the process in these cases.

For access to regular files using Version 3 of the NFS protocol, restrictions due to user ID mapping are enforced at the time the file is opened, except when a stale entry in the access cache causes the call to succeed. (See Attribute and Access Caching for a discussion of the access cache.) With Version 2, the client need not enforce the restrictions at the time the file is opened. If the process is able to open the file, the client will generally enforce the restrictions when the process tries to read or write the file. Because of data caching, though, the client need not enforce the restrictions until it has tried to read from or write to the server. (See Delayed Write Errors for a discussion of delayed write errors.)

Reads or writes may also fail if, for example, the permissions on the file are changed after the file was opened, as described in File Accessibility Changed after Open

Operations that require directory updates, such as mkdir(), link(), remove() and mknod(), will reflect access restrictions immediately for both versions of the NFS protocol. Because of privilege restrictions, it may be difficult to perform system administration tasks from an XNFS client. For example, cron jobs may need to be run on the server, even if the relevant files are exported by the server. Other tasks, such as restoring or installing files using pax, may only be possible on the server as well.

Execution of Set-user-ID Programs

Execution semantics of a program having the set-user-ID mode bit are different over NFS (see exec in the X/Open System Interfaces and Headers Specification (see reference XSH)). When an NFS file system is mounted by a client, the "SetUID=" mount attribute determines whether normal set-user-ID execution semantics are in effect. If the attribute is "False", execution of such a program over NFS will still occur. However, the effective user ID will not be reassigned to the owner of the program, and will remain equal to the user ID of the process. (See the discussion of the "SetUID=" MountedFileSystem attribute in MountedFileSystem .)

During execution, such a program may be denied an operation such as open(), read() or write(), because it is not running with the effective user ID with which it was designed to run. In this case an [EACCES] or an [EPERM] error may be generated depending upon the type of operation being performed.

Attribute and Access Caching

There are several semantic differences that occur due to attribute and access caching on the client. These differences occur when information in the client's cache does not match the information that is on the server. Since these caches are updated frequently, there is only a small window of time in which this information can differ. If the attribute and access caches are disabled through the "AttribCaching=" MountedFileSystem attribute, or if the client does not implement these caches, these problems no longer exist. (See the "AttribCaching=", "ACRegMin=" and "ACRegMax=" MountedFileSystem attributes in MountedFileSystem .)

Information in a client's attribute and access caches becomes inaccurate when the attributes of a file on the server are changed. When such changes are made from a client, that client's attribute and access caches are updated immediately in order to maintain a consistent view of the server's file system. However, when a process running on the server or on a client changes the attributes of a file, these results may not be immediately noticeable to other clients.

The attribute cache contains information about files on the server, including:

The access cache contains the results of previous NFSPROC3_ACCESS calls. On a per-file, per-user basis, it records which access modes are known to succeed, known to fail, or indeterminate.

Functions such as stat() may return incorrect information if the client's attribute cache is inaccurate. Other operations that are based on information in the client's attribute or access caches may behave incorrectly if the information in the caches is inaccurate. Examples of this are given below.

Denial of Access

Access to a file on the server may be denied because the attributes in the client caches are more restrictive than the attributes on the server. If a privilege has just been allowed on the server, and the client's caches still record this privilege as being "off", functions such as open() may fail on the client.

If the attributes in the client caches are less restrictive than the attributes on the server, functions such as open() may succeed, but functions like read() or write() may fail.

Operations Using File's Byte Count

File operations that rely on the byte count of a file may function incorrectly if the byte count stored in the attribute cache is inaccurate. For example, a write() to a file that was opened with the O_APPEND flag set may result in the overwriting of data that was appended to that file by a process executing on another XNFS client. Record locking operations (see File and Record Locking ) where l_whence is set to SEEK_END may also fail to behave as intended.

File Times

Programs that use file access and modification times may behave incorrectly. For example, make may fail to rebuild a target because of stale information about the source's modification time.

File Accessibility Changed after Open

A process may be denied further access to an open file if the file is located on a remote file system. There are two reasons for this given below.

File Attributes Changed after Open

The attributes of the file could be changed after the file was opened.

As part of the stateless behaviour of NFS, the server does not maintain information regarding files that are open by processes on client systems. Therefore, each time a client process issues a request to access a file, the request is validated. It is possible that the attributes of a file can change in between requests from a client process, thus denying further access to a file that had been previously accessible. In this case functions such as read() and write(), or derived functions such as fread(), fgets(), etc. may fail with [EACCES].

In the XSI specifications, it is stated that the effect of calling chmod() to change the access permissions of an open file is implementation-dependent. With NFS, the semantics of chmod() are different, in that effects are immediate and can cause further access to an open file to be denied or allowed in a manner different to access to a local file. The two additional cases where access is allowed by NFS are:

  1. Once a file handle has been established, the owner of the file is allowed to access it regardless of the permission settings associated with the file.

  2. Once a file handle has been established and a user has permission to execute a file, then that user is also granted permission to read the data from the file.

File Deleted after Open

The file could be deleted by a process on the server, or on another client.

Another function of the stateless behaviour of NFS is that the server cannot prevent the deletion of a file that is open by a process on a client system and is not open by a process on the server. When this occurs, the next client request which refers to the file will be rejected with the XNFS-specific error [ESTALE], indicating that the file handle no longer refers to a valid file system object. An XNFS client implementation may return a code for [ESTALE] as the reason for the failure of the XSI call, or may translate it into some other error code. In addition to file operations such as remove(), read() and stat(), and operations on directories, such as rmdir(), may fail with [ESTALE]. As described in Error Handling , record locking operations may fail in a manner that is implementation-dependent.

If a file is deleted while a process on the server has the file open, client requests using that file may fail with [ESTALE]. Alternatively, the server may continue granting access to the file as long as one or more processes on the server have the file open.

As discussed in Implicit File Access , it is possible for a function to fail with [ESTALE] even if it does not take a file handle or filename as an argument. For example, if a system's user database resides on a remote file, getpwuid() will pass along errors that it receives accessing the database file.

No Protection for In-Use Executables

If an executable file stored on an XNFS server is being executed on a client system, there is no mechanism that prevents the file from being deleted, truncated, or overwritten (for example, via remove(), fopen(), truncate() or write()). The execution of the program may be terminated if this occurs.

The error [ETXTBSY] is never returned by a function operating on a a remote file over NFS. Nonetheless, it is possible for calls such as truncate() or write() to fail because an executable file is being executed on the server. This XNFS Specification does not specify which error code is returned in this case.

Transparent Rename or Unlink While Open

If a file on the server is open by a process running on a client, and the file is deleted by the same or a different process on that client (for example, using remove() or unlink()), the client will rename the file to a temporary file. Any process that has this file open can continue using it. When the last process on the client to have this file open closes it, the client issues a request to the server to delete the temporary file. If a process on the client attempts to remove the temporary file, the client may remove it, ignore the request, or rename the file to a different temporary file. Should the client fail before removing the temporary file, the temporary file may remain indefinitely. It is common practice to have an entry in the XNFS server's crontab database to regularly delete these lingering temporary files.

The client's request to delete the temporary file may not be processed on the server if the server fails and the "RetrySemantics=" attribute of the mounted file system is Soft. (See the discussion of "RetrySemantics=" in MountedFileSystem .)

This XNFS specificationdoes not specify how a client generates the name for the temporary file described in this section. Nonetheless, it is common practice for the client to pick a name starting with a period (.) in the same directory as the original file. The presence of this file can cause attempts to remove the directory (for example, rmdir() or "rm -rf") to fail.

Data Caching

The following semantic differences may occur due to the buffer cache mechanisms.

Delayed Write Errors

Errors that occur when writing data to the file server will not necessarily be returned through write(). Calls to write() may put data into the client's buffer cache and return without error. The error may occur later when the buffer cache is flushed to the server.

The buffer cache may be flushed in response to a call from the process, for example, sync() or close(), or it may be flushed asynchronously. If the cache is flushed in response to a call from the process, the call will return the error. If the buffer cache is flushed asynchronously, the error will be reflected by a subsequent call to fsync() or close(). Some systems may reflect the error at a subsequent write(), but application writers must not depend on this behavior.

The sync() call may fail silently because sync() only schedules writes. The actual writes may happen after sync() has returned.

Some routines, such as fgetpos(), may cause a write() to occur as a side effect. These writes are also potentially subject to delayed write errors.

Read of Old Data

The information in the buffer cache may be inaccurate and not reflect the latest changes to a file. Therefore, the read() function may not get the latest contents of a file.

Similarly, functions that invoke read(), such as fscanf() or fgets(), need not return the latest contents of a file, even when the referenced I/O stream is unbuffered.

Atomicity of Transfer

When a file is being read or written by several processes on different systems, the operations of the caches on the server and clients will affect the atomicity of data reading and writing. No assumption can be made that common submultiples for all the cache sizes or alignments will exist. Consequently, it is impossible to guarantee that any arbitrary multi-byte read or write will be atomic.

File Time Updates

If a client is able to satisfy a read or write request without contacting the server, the client need not update one or more of the corresponding file times (st_mtime, st_ctime, and st_atime). This applies to explicit reads and writes and to implicit reads and writes, such as those from mapped files and the exec family of functions.

For write requests, programs can force st_mtime and st_ctime to be updated by forcing the writes to the server, for example with fsync(). There is no corresponding mechanism for forcing st_atime to be updated. In particular, the functions fstat() and stat() cannot be used to force the update of file times for either reads or writes.

Directory Caching

There are two semantic differences concerning the client's directory caching mechanism. These differences occur when the information in the directory cache does not reflect the server's directories. As with attribute caching, the information in this cache is refreshed frequently from the server. However, there is a window of time in which the information in this cache can be inaccurate. If this caching mechanism is disabled through the "AttribCaching=False" MountedFileSystem attribute, these semantic differences no longer exist. (See the discussions of the "AttribCaching=", "ACDirMin=" and "ACDirMax" MountedFileSystem attributes in MountedFileSystem .)

The following semantic differences can be noted:

  1. It is possible that a client may still record an entry of a file that has just been deleted on the server. Attempts on the client to create a new file with the same name, for example, using creat() or link(), may fail, typically with [EEXIST]. Attempts to remove an otherwise empty directory may fail, typically with [EEXIST] or

  2. The result of a process that modifies the contents of a directory may not be immediately noticeable to other clients. For example, calls to open() or stat() may fail, even if the file exists on the server. Functions such as tmpnam() may return a filename that is already in use on the server.

Time Skew

A process cannot rely on the access times of a remote file to be correct. The access times associated with a remote file will relate to the system clock on the server system rather than to that of the client system which last updated the remote file. A comparison of these access times with the local system clock or the access times of a local file may not be of value. The reasons for this are:

  1. The system clocks on the server and client may not be synchronised.

  2. The client and server systems may each have a different notion of system date and time; for instance, they may be in different time zones.

  3. The attribute cache may be holding inaccurate information concerning the times of a file.

As a result, programs whose behavior depends on file times may behave differently or incorrectly in an XNFS environment. For example, if a file has been modified recently, the ls command may display the file's date and time using the format for a modification time in the future. The make command may mistakenly conclude that a particular target is (or is not) out of date with respect to its sources. The pax command may function incorrectly with the -u option.

This XNFS specification does not specify whether the routines utime() and utimes() use the client time or server time when a null time pointer is used, that is, when setting the file times to the current time.

Server or Network-Induced Delays

When a client makes a request to the server, the client expects a response within a certain time limit. (See the discussion of the "NFSTimeOut=" MountedFileSystem attribute in MountedFileSystem .) Should a response not occur within this time limit, the client may react in two ways, depending upon values of certain mount attributes:

  1. The client may reissue the request repeatedly until either the server responds, or the maximum number of retries is reached. Should this maximum number of retries be reached, the client has detected a server failure and returns an error to the process. (See the discussions of the "RetrySemantics=" and "NFSRetransmissions=" MountedFileSystem attributes in MountedFileSystem .)

  2. The client may reissue the request repeatedly until the the server reponds. (See the discussions of the "RetrySemantics=" and "NFSRetransmissions=" MountedFileSystem attributes in MountedFileSystem .)

    This behaviour may cause a function which is waiting for the server's response to not return to the calling process for an arbitrary duration of time. The effect on the process is that it will sleep until the server responds.

    When a process issues a stat() of a remote NFS mounted object, or of a directory containing a remote NFS mounted object, a server request is generated. This may cause a delay if the server does not respond.

Interruption of Function Calls

A signal may be posted to a process that is making a request that involves an NFS file. For example, a user may wish to interrupt a request that is taking a long time to complete. If the file system was mounted with the "Intr=" attribute set to "True" (see MountedFileSystem ), the pending NFS operation will be cancelled and the signal will be processed. Otherwise the NFS operation will be retried as described in Server or Network-Induced Delays , and the signal will not be processed until the NFS operation succeeds or the retry limit is reached. This behavior applies to any operation that must contact the server, even functions that are not documented as potentially failing with [EINTR] (for example, stat(), readlink()).

File and Record Locking

File and record locking allows all or part of a file to be locked by calling fcntl() (using F_SETLK or F_SETLKW) or lockf(). There are several semantic differences regarding file and record locking over XNFS.

Availability of Locking

For file and record locking to be available, the client and server must support the NLM protocol, typically by running the XNFS lock server. This XNFS specification does not specify any mechanism whereby a client can determine whether a server provides locking services, nor does it define the effects of issuing locking calls when the server does not provide these services.

F_GETLK l_pid

The structure flock that is returned from an F_GETLK command contains the process ID (l_pid) of the process that is holding the lock. When this is a process that is accessing a file on a remote machine, this process ID is provided as a unique identifier for the process holding the lock, but it is not necessarily the same as the process ID of that process. This XNFS specification does not specify a mechanism for identifying which machine the process is running on.

Signals

If a process receives a signal while attempting to acquire or release a remote lock, the call may return with the error [EINTR], even for non-blocking locks (fcntl() with F_SETLK or lockf() with F_TLOCK). If this happens, the process cannot determine whether its request succeeded. If the process exits, the client operating system will release the lock if necessary. If the process catches the signal and resumes processing, the process should either resubmit the lock request, or it should explicitly unlock the region it had tried to lock.

Memory-Mapped Files

Under some circumstances it is possible for cooperating processes to inadvertently defeat file and record locking by mapping all or part of the file into memory with mmap(). For this reason, mmap() may fail if all or part of the file is locked, and attempts to acquire a lock may fail if all or part of the file is mapped into memory. Applications can reduce the chances of running into these restrictions by always locking the entire file, or by locking regions that correspond to whole pages on the client.

Error Handling

Suppose a process tries to acquire a lock. Due to limitations in Version 3 of the NLM protocol, the client is unable to distinguish unrecoverable errors from the case where another process already has a conflicting lock. Examples of unrecoverable errors include:

This XNFS specification does not define the behavior of the client under these circumstances.

Network Heterogeneity

There are several differences that occur because XNFS can connect heterogeneous environments.

Local Execution of a Remote Program

It is possible that a binary file residing on the server may be incompatible for execution on a client. For example, it may have been compiled for a different type of machine, or a different X/Open-compliant operating system. An attempt to execute such a program, for example, via popen() or system(), or from the shell, will usually fail.

A program residing on the server which is compatible for execution with a client may be incompatible in other ways. For example, it may include references to local resources which are not accessible on all systems, or have been compiled for a different version of the operating system which uses a slightly different binary interface. In this case the failure mode cannot be predicted.

This XNFS specification does not specify any mechanism for determining the compatibility of a binary program with a particular system, nor the ways in which incompatibilities may manifest themselves.

Use of Remote Input Files with Varying Formats

Several utilities, for example tabs, as well as several functions, for example getpwuid(), process files that are in a predefined format. Since there is no standard defining the format for some of these input files, different implementations may use different formats for the same input file. Incompatibilities may arise when a utility or function is used with a remote input file having a different format than expected.

Architectural Dependencies

Some utilities may use input files that have a format which is dependent upon the underlying architecture of the system. For example, a utility which uses a binary file may not operate correctly with a binary file from a foreign architecture. Any utility which operates on binary object files and executable files such as ar and cc will not operate correctly with a binary file from a foreign system.

Some algorithms, for example the computation of a file's checksum using sum, may be dependent upon the architecture of the machine. Therefore, computing the checksum of two identical files residing on two different machines having different architectures may yield two different values.

Output Displayed in Conventions of Local System

Utilities which report information about files and/or file systems will behave consistently when viewed from a single system. However, the results of some of these utilities that are executed on different systems may differ. For instance, the execution of df on two different systems may compute the free space of the same mounted file system differently. The output from the nm or od utilities on two different systems may be formatted differently when run on the same object file. In many cases, though, the utility provides a mechanism for generating output in a portable fashion, such as the -P option to df and nm, or the -t option to od.

Filesize Differences

A system need not support native 64-bit file sizes to support the NFS Version 3 protocol. This lets 32-bit clients interoperate with 64-bit servers and vice-versa, with certain restrictions.

If a program is running on a 64-bit client, calls to routines such as write() or truncate() will fail if the program tries to create a file that is larger than that which the server supports. Record locking operations (see File and Record Locking ) will fail if the program tries to lock a region of the file that the server cannot support. The failure status in these cases is typically [EFBIG].

If a program is running on a 32-bit client, routines such as stat() may return an incorrect size for a file. If a file is too big for the client to handle, the client may handle requests for the file in one of two ways:

Characters in File Names

A server may have an implementation-specific set of characters that it does not allow in file names. If a program on the client uses one of these characters in a file name, for example in a creat() or mkdir() call, it may get back the error [EACCES]. Functions that expect the name of an existing file, for example, stat(), may fail with [EACCES] or [ENOENT]. Note that the contents of a symbolic link for the symlink() function are not subject to any character restrictions.

Some server implementations do not preserve character case when creating an object in a file system. That is, they may map all the characters in the name to either lower or upper case. Also, even if they preserve case when creating an object, some server implementations may ignore case distinctions for lookup operations. For example, an attempt to create the file "Makefile" may instead create the file "MAKEFILE". Even if the server creates the file using the name "Makefile", attempts to reference "makefile" or "MakeFILE" may all reference the first file "Makefile".

Server Access Control

The server may use an access model other than the traditional UNIX mode bits, for example, Access Control Lists. In this case the mode bits reported by the client need not accurately represent the permissions on a file. This inaccuracy can cause several problems, as discussed below. Some systems implement an additional protocol to avoid these problems. The details of that protocol are not covered by this XNFS specification and may vary from vendor to vendor.

If the client and server are connected using Version 2 of the NFS protocol, the client relies on the mode bits to determine whether a given process has access to a given file. If the mode bits are sufficiently inaccurate, the client may deny access to a process even though the request would succeed on the server. That is, calls to open() or fopen() may fail on the client when they would succeed on the server. Conversely, the client may grant access based on the mode bits, only to have the request denied by the server. That is, the open() call may succeed, but calls to read() or write() may fail, or there may be delayed write errors as described in Delayed Write Errors .

If the client incorrectly grants a process access to a file and can satisfy read requests from its cache, the process may successfully read or execute the file, bypassing the restrictions on the server. It is also possible for an unauthorized process to read a directory in this manner. A similar security breach is possible for writes to a file: if the client incorrectly grants access to an unauthorized process while a second, authorized, process is writing to the file, the first process may successfully update the file on the server. Unauthorized directory updates such as mkdir(), rmdir(), rename() and remove() should always fail.

If the client is using Version 3 of the NFS protocol, the mode bit information may still be incorrect. Nonetheless, the client's access decisions should be consistent with the server's, after allowing for caching issues as described in Attribute and Access Caching . (With NFS Version 3, the client can ask the server whether a particular access request should be granted.) This greatly reduces the probability that a process will incorrectly granted or denied an operation by the client.

Server Support for File Times

Not all server implementations let the client set the times for a file (st_atime, st_mtime). Those that do need not support a fine enough clock granularity to fully support interfaces like utime() or utimes(). For example, they may support a resolution in milliseconds or in minutes. This means that attempts to set a file's times, for example with touch() or utimes(), need not change the file times at all, or the file times may change to values different than those requested.

Special Files

The encoding of major and minor device numbers is not specified by Version 2 of the NFS protocol, so different implementations may use different encodings. This means that the major and minor device numbers of a special file may have different values, depending on where the file is referenced from. Functions such as open() may behave in an unintended manner under these circumstances.

Bounds checking on the server can cause mknod() to fail, particularly if the client and server are communicating using Version 2 of the NFS protocol and they disagree on the encoding of the major and minor device numbers.

User and Group ID Database Consistency

It is necessary to maintain a consistent user ID to username mapping across the collection of XNFS servers and clients. The group ID to group name mapping should be consistent as well. If these databases are not consistently maintained, programs such as ls may report different owning users or groups depending on where the program is run. Also, access restriction mechanisms need not function as intended. Access which should be denied may be allowed, and conversely access which should be allowed may be denied.

In some cases the server may limit the user or group ID values to a subset of the values that are possible on the client. In this case, of course, it is impossible to have consistent user and group ID mappings. Routines such as chown() will fail with [EINVAL] when an unsupported user or group ID is used.

Access to Read-Only File Systems

Operations which attempt to write to or modify a remote read-only file system will fail and may return the error [EROFS]. This will occur if the file system was exported with the ExportedFileSystem "Mode=" attribute set to "ReadOnly", or if the the file system was mounted with the MountedFileSystem "Mode=" attribute set to "ReadOnly". (See the discussions of the "Mode=" attribute in both ExportedFileSystem and MountedFileSystem .) For access using Version 3 of the NFS protocol, the failure will occur when the file is opened for writing, unless a stale entry in the client access cache (see Attribute and Access Caching ) causes the call to succeed. With Version 2, the call open(), fopen(), etc. will fail if the client has mounted the file system read-only, but the call may succeed if the client has mounted the file system read-write and the server has exported it read-only. If the process is able to open the file for writing, attempts to write to a regular file (for example, write(), writev()) will generally fail, though data caching can delay these failures, as described in Delayed Write Errors .

Directory operations on a read-only file system, for example, rmdir(), unlink(), creat(), mknod(), will fail immediately for both versions of the NFS protocol.

Writes to special files are not subject to read-only restrictions, as they do not require updates to the file system on the server.

An attempt to obtain an exclusive record lock on a file in a read-only file system may fail. As described in Error Handling , the request may fail in an implementation-dependent manner.

Group Ownership of Created Files

When the "GrpID=" attribute of the MountedFileSystem object is set to True, the group owner of a newly created file is always set to the group owner of the directory containing that file. This may differ from the semantics applied to a locally created file where the group owner may be set to the effective group ID of the calling process. This semantic difference affects functions such as open() and creat(), as well as operations such as I/O redirection from the shell.

Consistency of Limits

The limit on the maximum number of simultaneous supplementary group IDs per process is allowed to vary between systems and XNFS does not impose any restrictions on the number of group IDs which are used to determine accessibility to a remote file. However, the server may impose a lower maximum number than the client and may reject requests from the client which contain more than the maximum number of supplementary groups allowed by the server.

A similar problem exists with other limits, such as the maximum number of characters in a filename, or the maximum number of hard links to a file. These limits may vary between different file systems, and Version 2 of the NFS protocol does not provide a mechanism for this information to be made available to a client. The limits provided from a call to pathconf() need not accurately reflect the limit imposed by the server's file system. This may cause file access requests to be rejected by the server or for files to be inaccessible from the client.

Symbolic Links

If the server does not support symbolic links, an attempt to create one with symlink() will fail with [EOPNOTSUPP]. Also, calls to readlink() may fail with [EOPNOTSUPP] instead of [EINVAL].

The server treats the contents of a symbolic link as an opaque object, and the XNFS specification does not define a format for symbolic links. This means that a readlink() call may return a string that does not look like a path name. It also means that the client may be unable to resolve the symbolic link, causing routines that involve path names (open(), remove(), mkdir(), stat(), etc.) to fail if the link is part of the given path.

A client resolves a symbolic link using its own namespace, not the server's namespace. For example, a client will interpret a link to "/bin/sh" as referring to the client's /bin/sh, even if the link was created on the server. Similarly, a link to "../new_dir/some_file" may take the client to a local file or a completely different server if it appears in the top directory of a mounted file system (see MountedFileSystem for an explanation of mounted file systems).

Interrupted Root File System Service

A client's root file system may be accessed using the NFS protocol. Diskless clients usually operate in this manner, and an individual process may change its root file system to a remote file system using the chroot() call. If service for the root file system is interrupted, service for other file systems may be interrupted as well. For example, if the server for a diskless client's root file system crashes, the client may be unable to access any file systems, even file systems that are served by a different server, until the crashed server resumes operation.

Implicit File Access

Several functions in the X/Open System Interfaces and Headers Specification (see reference XSH) access files even though they do not take a stream handle, file descriptor or path name as an argument. For example, getpwnam() and getgrnam() use the system's user and group databases, respectively. If the databases are implemented as remote files, either through individual mounts or because the client is diskless, the operations performed by these functions are subject to the semantic differences described in this appendix.

Other functions may access files other than those specified in the argument list. For example, ttyname() and getcwd() may use calls to stat() to find a desired file or directory. It is possible that some of these calls to stat() will inadvertently refer to remote files or directories. Calls to system() may result in references to remote files, depending on the contents of environment variables such as PATH and ENV. These references to remote files are subject to the semantic differences described in this appendix.

Multiple Hosts

Software that was written for a local file system environment may make uniqueness assumptions, for example, it may assume that process identifiers are unique. These assumptions need not be true in an XNFS environment.

Process Identifiers

A common approach for generating a unique filename, particularly in shell scripts, is to append the process's process identifier to an application-dependent prefix. This approach can fail if two processes, each with the same identifier on a different host, attempt to create a unique file in a shared directory. The X/Open System Interfaces and Headers Specification (see reference XSH) provides several functions, for example, mkstemp(), that can avoid this uniqueness problem. Shell scripts must rely on ad-hoc mechanisms for generating unique files, such as including the host name in the file name.

Unique Daemons

Some system facilities, such as the crontab facility or printer spoolers, may assume the existence of a single daemon that is started during system initialization. If the files that the daemon uses are shared using the NFS protocol, the daemon may behave in an unintended manner. For example, if the crontab database is accessible from more than one system, the same command may be executed concurrently on different hosts, even if this was not the user's intent.
Why not acquire a nicely bound hard copy?
Click here to return to the publication details or order a copy of this publication.

Contents Next section Index