FSATTR(7) Standards, Environments, and Macros FSATTR(7)
NAME
fsattr - extended file attributes
DESCRIPTION
Attributes are logically supported as files within the file system.
The file system is therefore augmented with an orthogonal name space
of file attributes. Any file (including attribute files) can have an
arbitrarily deep attribute tree associated with it. Attribute values
are accessed by file descriptors obtained through a special attribute
interface. This logical view of "attributes as files" allows the
leveraging of existing file system interface functionality to support
the construction, deletion, and manipulation of attributes.
The special files "." and ".." retain their accustomed semantics
within the attribute hierarchy. The "." attribute file refers to the
current directory and the ".." attribute file refers to the parent
directory. The unnamed directory at the head of each attribute tree
is considered the "child" of the file it is associated with and the
".." file refers to the associated file. For any non-directory file
with attributes, the ".." entry in the unnamed directory refers to a
file that is not a directory.
Conceptually, the attribute model is fully general. Extended
attributes can be any type of file (doors, links, directories, and so
forth) and can even have their own attributes (fully recursive). As
a result, the attributes associated with a file could be an
arbitrarily deep directory hierarchy where each attribute could have
an equally complex attribute tree associated with it. Not all
implementations are able to, or want to, support the full model.
Implementation are therefore permitted to reject operations that are
not supported. For example, the implementation for the UFS file
system allows only regular files as attributes (for example, no sub-
directories) and rejects attempts to place attributes on attributes.
The following list details the operations that are rejected in the
current implementation:
link Any attempt to create links between
attribute and non-attribute space is
rejected to prevent security-related or
otherwise sensitive attributes from being
exposed, and therefore manipulable, as
regular files.
rename Any attempt to rename between attribute and
non-attribute space is rejected to prevent
an already linked file from being renamed
and thereby circumventing the
link restriction above.
mkdir,
symlink,
mknod Any attempt to create a "non-regular" file
in attribute space is rejected to reduce the
functionality, and therefore exposure and
risk, of the initial implementation.
The entire available name space has been allocated to "general use"
to bring the implementation in line with the NFSv4 draft standard
[NFSv4]. That standard defines "named attributes" (equivalent to
Solaris Extended Attributes) with no naming restrictions. All Sun
applications making use of opaque extended attributes will use the
prefix "SUNW".
Shell-level API The command interface for extended attributes is the set of
applications provided by Solaris for the manipulation of attributes
from the command line. This interface consists of a set of existing
utilities that have been extended to be "attribute-aware", plus the
runat utility designed to "expose" the extended attribute space so
that extended attributes can be manipulated as regular files.
The
-@ option enable utilities to manipulate extended attributes. As
a rule, this option enables the utility to enter into attribute space
when the utility is performing a recursive traversal of file system
space. This is a fully recursive concept. If the underlying file
system supports recursive attributes and directory structures, the
-@ option opens these spaces to the file tree-walking algorithms.
The following utilities accommodate extended attributes (see the
individual manual pages for details):
cp By default,
cp ignores attributes and copies only file data.
This is intended to maintain the semantics implied by
cp currently, where attributes (such as owner and mode) are not
copied unless the
-p option is specified. With the
-@ (or
-p)
option,
cp attempts to copy all attributes along with the
file data.
cpio The
-@ option informs
cpio to archive attributes, but by
default
cpio ignores extended attributes. See
Extended Archive Formats below for a description of the new archive
records.
du File sizes computed include the space allocated for any
extended attributes present.
find By default,
find ignores attributes. The
-xattr expression
provides support for searches involving attribute space. It
returns true if extended attributes are present on the
current file.
fsck The
fsck utility manages extended attribute data on the disk.
A file system with extended attributes can be mounted on
versions of Solaris that are not attribute-aware (versions
prior to Solaris 9), but the attributes will not be
accessible and
fsck will strip them from the files and place
them in
lost+found. Once the attributes have been stripped
the file system is completely stable on Solaris versions that
are not attribute-aware, but would now be considered
corrupted on attribute-aware versions of Solaris. The
attribute-aware
fsck utility should be run to stabilize the
file system before using it in an attribute-aware
environment.
fsdb This
fsdb utility is able to find the inode for the "hidden"
extended attribute directory.
ls The
ls -@ command displays an "@" following the mode
information when extended attributes are present. More
precisely, the output line for a given file contains an "@"
character following the mode characters if the
pathconf(2) variable
XATTR_EXISTS is set to true. See the
pathconf() section below. The
-@ option uses the same general output
format as the
-l option.
mv When a file is moved, all attributes are carried along with
the file rename. When a file is moved across a file system
boundary, the copy command invoked is similar to the
cp -p variant described above and extended attributes are "moved".
If the extended file attributes cannot be replicated, the
move operation fails and the source file is not removed.
pax The
-@ option informs
pax to archive attributes, but by
default
pax ignores extended attributes. The
pax(1) utility
is a generic replacement for both
tar(1) and
cpio(1) and is
able to produce either output format in its archive. See
Extended Archive Formats below for a description of the new
archive records.
tar In the default case,
tar does not attempt to place attributes
in the archive. If the
-@ option is specified, however,
tar traverses into the attribute space of all files being placed
in the archive and attempts to add the attributes to the
archive. A new record type has been introduced for extended
attribute entries in
tar archive files (the same is true for
pax and
cpio archives) similar to the way ACLs records were
defined. See
Extended Archive Formats below for a description
of the new archive records.
There is a class of utilities (
chmod,
chown,
chgrp) that one might
expect to be modified in a manner similar to those listed above. For
example, one might expect that performing
chmod on a file would not
only affect the file itself but would also affect at least the
extended attribute directory if not any existing extended attribute
files. This is not the case. The model chosen for extended
attributes implies that the attribute directory and the attributes
themselves are all file objects in their own right, and can therefore
have independent file status attributes associated with them (a
given implementation cannot support this, for example, for intrinsic
attributes). The relationship is left undefined and a fine-grained
control mechanism (
runat(1)) is provided to allow manipulation of
extended attribute status attributes as necessary.
The
runat utility has the following syntax:
runat
filename [
command]
The
runat utility executes the supplied command in the context of the
"attribute space" associated with the indicated file. If no command
argument is supplied, a shell is invoked. See
runat(1) for details.
Application-level API The primary interface required to access extended attributes at the
programmatic level is the
openat(2) function. Once a file descriptor
has been obtained for an attribute file by an
openat() call, all
normal file system semantics apply. There is no attempt to place
special semantics on
read(2),
write(2),
ftruncate(3C), or other
functions when applied to attribute file descriptors relative to
"normal" file descriptors.
The set of existing attributes can be browsed by calling
openat() with "." as the file name and the
O_XATTR flag set, resulting in a
file descriptor for the attribute directory. The list of attributes
is obtained by calls to
getdents(2) on the returned file descriptor.
If the target file did not previously have any attributes associated
with it, an empty top-level attribute directory is created for the
file and subsequent
getdents() calls will return only "." and "..".
While the owner of the parent file owns the extended attribute
directory, it is not charged against its quota if the directory is
empty. Attribute files themselves, however, are charged against the
user quota as any other regular file.
Additional system calls have been provided as convenience functions.
These include the
fchownat(2),
fstatat(2),
futimesat(2),
renameat(2),
unlinkat(2). These new functions, along with
openat(), provide a
mechanism to access files relative to an arbitrary point in the file
system, rather than only the current working directory. This
mechanism is particularly useful in situations when a file descriptor
is available with no path. The
openat() function, in particular, can
be used in many contexts where
chdir() or
fchdir() is currently
required. See
chdir(2).
Open a file relative to a file descriptor
int openat (int
fd, const char *
path, int
oflag [, mode_t
mode])
The
openat(2) function behaves exactly as
open(2) except when given a
relative path. Where
open() resolves a relative path from the
current working directory,
openat() resolves the path based on the
vnode indicated by the supplied file descriptor. When
oflag is
O_XATTR,
openat() interprets the
path argument as an extended
attribute reference. The following code fragment uses
openat() to
examine the attributes of some already opened file:
dfd = openat(fd, ".", O_RDONLY|O_XATTR);
(void)getdents(dfd, buf, nbytes);
If
openat() is passed the special value
AT_FDCWD as its first (
fd)
argument, its behavior is identical to
open() and the relative path
arguments are interpreted relative to the current working directory.
If the
O_XATTR flag is provided to
openat() or to
open(), the
supplied path is interpreted as a reference to an extended attribute
on the current working directory.
Unlink a file relative to a directory file descriptor
int unlinkat (int
dirfd, const char *path
flag, int flag
flag)
The
unlinkat(2) function deletes an entry from a directory. The
path argument indicates the name of the entry to remove. If
path an
absolute path, the
dirfd argument is ignored. If it is a relative
path, it is interpreted relative to the directory indicated by the
dirfd argument. If
dirfd does not refer to a valid directory, the
function returns
ENOTDIR. If the special value
AT_FDCWD is specified
for
dirfd, a relative path argument is resolved relative to the
current working directory. If the
flag argument is 0, all other
semantics of this function are equivalent to
unlink(2). If
flag is
set to
AT_REMOVEDIR, all other semantics of this function are
equivalent to
rmdir(2).
Rename a file relative to directories
int renameat (int
fromfd, const char *
old, int
tofd, const char *
new)
The
renameat(2) function renames an entry in a directory, possibly
moving the entry into a different directory. The
old argument
indicates the name of the entry to rename. If this argument is a
relative path, it is interpreted relative to the directory indicated
by the
fd argument. If it is an absolute path, the
fromfd argument is
ignored. The
new argument indicates the new name for the entry. If
this argument is a relative path, it is interpreted relative to the
directory indicated by the
tofd argument. If it is an absolute path,
the
tofd argument is ignored.
In the relative path cases, if the directory file descriptor
arguments do not refer to a valid directory, the function returns
ENOTDIR. All other semantics of this function are equivalent to
rename(2).
If a special value
AT_FDCWD is specified for either the
fromfd or
tofd arguments, their associated path arguments (
old and
new) are
interpreted relative to the current working directory if they are not
specified as absolute paths. Any attempt to use
renameat() to move a
file that is not an extended attribute into an extended attribute
directory (so that it becomes an extended attribute) will fail. The
same is true for an attempt to move a file that is an extended
attribute into a directory that is not an extended attribute
directory.
Obtain information about a file
int fstatat (int
fd, const char *
path, struct stat*
buf, int
flag)
The
fstatat(2) function obtains information about a file. If the
path argument is relative, it is resolved relative to the
fd argument
file descriptor, otherwise the
fd argument is ignored. If the
fd argument is a special value
AT_FDCWD the path is resolved relative to
the current working directory. If the
path argument is a null
pointer, the function returns information about the file referenced
by the
fd argument. In all other relative path cases, if the
fd argument does not refer to a valid directory, the function returns
ENOTDIR. If
AT_SYMLINK_NOFOLLOW is set in the
flag argument, the
function will not automatically traverse a symbolic link at the
position of the path. If
_AT_TRIGGER is set in the
flag argument and
the vnode is a trigger mount point, the mount is performed and the
function returns the attributes of the root of the mounted
filesystem. The
fstatat() function is a multipurpose function that
can be used in place of
stat(),
lstat(), or
fstat(). See
stat(2) The function call
stat(path, buf) is identical to
fstatat(AT_FDCWD,
path, buf, 0).
The function call
lstat(path, buf) is identical to
fstatat(AT_FDCWD,
path, buf,
AT_SYMLINK_NOFOLLOW) The function call
fstat(fildes, buf) is identical to
fstatat(fildes,
NULL,
buf,
0).
Set owner and group ID
int fchownat (int
fd, const char *
path, uid_t
owner, gid_t
group, \
int
flag)
The
fchownat(2) function sets the owner ID and group ID for a file.
If the
path argument is relative, it is resolved relative to the
fd argument file descriptor, otherwise the
fd argument is ignored. If
the
fd argument is a special value
AT_FDCWD the path is resolved
relative to the current working directory. If the path argument is a
null pointer, the function sets the owner and group ID of the file
referenced by the
fd argument. In all other relative path cases, if
the
fd argument does not refer to a valid directory, the function
returns
ENOTDIR. If the
flag argument is set to
AT_SYMLINK_NOFOLLOW,
the function will not automatically traverse a symbolic link at the
position of the path. The
fchownat() function is a multi-purpose
function that can be used in place of
chown(),
lchown(), or
fchown().
See
chown(2).
The function call
chown(path, owner, group) is equivalent to
fchownat(AT_FDCWD,
path, owner, group, 0).
The function call
lchown(path, owner, group) is equivalent to
fchownat(AT_FDCWD,
path, owner, group, AT_SYMLINK_NOFOLLOW).
Set file access and modification times
int futimesat (int
fd, const char *
path, const struct timeval \
times[2])
The
futimesat(2) function sets the access and modification times for
a file. If the
path argument is relative, it is resolved relative to
the
fd argument file descriptor; otherwise the
fd argument is
ignored. If the
fd argument is the special value
AT_FDCWD, the path
is resolved relative to the current working directory. If the
path argument is a null pointer, the function sets the access and
modification times of the file referenced by the
fd argument. In all
other relative path cases, if the
fd argument does not refer to a
valid directory, the function returns
ENOTDIR. The
futimesat() function can be used in place of
utimes(2).
The function call
utimes(path, times) is equivalent to
futimesat(AT_FDCWD,
path, times).
New pathconf() functionality long int pathconf(const char *
path, int
name)
Two variables have been added to
pathconf(2) to provide enhanced
support for extended attribute manipulation. The
XATTR_ENABLED variable allows an application to determine if attribute support is
currently enabled for the file in question. The
XATTR_EXISTS variable
allows an application to determine whether there are any extended
attributes associated with the supplied path.
Open/Create an attribute file int attropen (const char *
path, const char *
attrpath, int
oflag \
[, mode_t
mode])
The
attropen(3C) function returns a file descriptor for the named
attribute,
attrpath, of the file indicated by
path. The
oflag and
mode arguments are identical to the
open(2) arguments and are applied
to the open operation on the attribute file (for example, using the
O_CREAT flag creates a new attribute). Once opened, all normal file
system operations can be used on the attribute file descriptor. The
attropen() function is a convenience function and is equivalent to
the following sequence of operations:
fd = open (path, O_RDONLY);
attrfd = openat(fd, attrpath, oflag|O_XATTR, mode);
close(fd);
The set of existing attributes can be browsed by calling
attropen() with "." as the attribute name. The list of attributes is obtained
by calling
getdents(2) (or
fdopendir(3C) followed by
readdir(3C), see
below) on the returned file descriptor.
Convert an open file descriptor for a directory into a directory
descriptor DIR * fdopendir (const int
fd)
The
fdopendir(3C) function promotes a file descriptor for a directory
to a directory pointer suitable for use with the
readdir(3C) function. The originating file descriptor should not be used again
following the call to
fdopendir(). The directory pointer should be
closed with a call to
closedir(3C). If the provided file descriptor
does not reference a directory, the function returns
ENOTDIR. This
function is useful in circumstances where the only available handle
on a directory is a file descriptor. See
attropen(3C) and
openat(2).
Using the API
The following examples demonstrate how the API might be used to
perform basic operations on extended attributes:
Example 1: List extended attributes on a file.
attrdirfd = attropen("test", ".", O_RDONLY);
dirp = fdopendir(attrdirfd);
while (dp = readdir(dirp)) {
...
Example 2: Open an extended attribute.
attrfd = attropen("test", dp->d_name, O_RDONLY);
or
attrfd = openat(attrdirfd, dp->d_name, O_RDONLY);
Example 3: Read from an extended attribute.
while (read(attrfd, buf, 512) > 0) {
...
Example 4: Create an extended attribute.
newfd = attropen("test", "attr", O_CREAT|O_RDWR);
or
newfd = openat(attrdirfd, "attr", O_CREAT|O_RDWR);
Example 5: Write to an extended attribute.
count = write(newfd, buf, length);
Example 6: Delete an extended attribute.
error = unlinkat(attrdirfd, "attr");
Applications intending to access the interfaces defined here as well
as the POSIX and X/Open specification-conforming interfaces should
define the macro
_ATFILE_SOURCE to be 1 and set whichever feature
test macros are appropriate to obtain the desired environment. See
standards(7).
Extended Archive Formats
As noted above in the description of command utilities modified to
provide support for extended attributes, the archive formats for
tar(1) and
cpio(1) have been extended to provide support for
archiving extended attributes. This section describes the specifics
of the archive format extensions.
Extended tar format
The
tar archive is made up of a series of 512 byte blocks. Each
archived file is represented by a header block and zero or more data
blocks containing the file contents. The header block is structured
as shown in the following table.
Field Name Length (in Octets) Description
Name 100 File name string
Mode 8 12 file mode bits
Uid 8 User ID of file owner
Gid 8 Group ID of file owner
Size 12 Size of file
Mtime 12 File modification time
Chksum 8 File contents checksum
Typeflag 1 File type flag
Linkname 100 Link target name if file linked
Magic 6 "ustar"
Version 2 "00"
Uname 32 User name of file owner
Gname 32 Group name of file owner
Devmajor 8 Major device ID if special file
Devminor 8 Minor device ID if special file
Prefix 155 Path prefix string for file
The extended attribute project extends the above header format by
defining a new header type (for the
Typeflag field). The type 'E' is
defined to be used for all extended attribute files. Attribute files
are stored in the
tar archive as a sequence of two
<header ,data> pairs. The first file contains the data necessary to locate and name
the extended attribute in the file system. The second file contains
the actual attribute file data. Both files use an 'E' type header.
The prefix and name fields in extended attribute headers are ignored,
though they should be set to meaningful values for the benefit of
archivers that do not process these headers. Solaris archivers set
the prefix field to "
/dev/null" to prevent archivers that do not
understand the type 'E' header from trying to restore extended
attribute files in inappropriate places.
Extended cpio format
The
cpio archive format is octet-oriented rather than block-oriented.
Each file entry in the archive includes a header that describes the
file, followed by the file name, followed by the contents of the
file. These data are arranged as described in the following table.
Field Name Length (in Octets) Description
c_magic 6 70707
c_dev 6 First half of unique file ID
c_ino 6 Second half of unique file ID
c_mode 6 File mode bits
c_uid 6 User ID of file owner
c_gid 6 Group ID of file owner
c_nlink 6 Number of links referencing file
c_rdev 6 Information for special files
c_mtime 11 Modification time of file
c_namesize 6 Length of file pathname
c_filesize 11 Length of file content
c_name c_namesize File pathname
c_filedata c_filesize File content
The basic archive file structure is not changed for extended
attributes. The file type bits stored in the
c_mode field for an
attribute file are set to
0xB000. As with the
tar archive format,
extended attributes are stored in
cpio archives as two consecutive
file entries. The first file describes the location/name for the
extended attribute. The second file contains the actual attribute
file content. The
c_name field in extended attribute headers is
ignored, though it should be set to a meaningful value for the
benefit of archivers that do not process these headers. Solaris
archivers start the pathname with "
/dev/null/"to prevent archivers
that do not understand the type 'E' header from trying to restore
extended attribute files in inappropriate places.
Attribute identification data format
Both the
tar and
cpio archive formats can contain the special files
described above, always paired with the extended attribute data
record, for identifying the precise location of the extended
attribute. These special data files are necessary because there is
no simple naming mechanism for extended attribute files. Extended
attributes are not visible in the file system name space. The
extended attribute name space must be "tunneled into" using the
openat() function. The attribute identification data must support not
only the flat naming structure for extended attributes, but also the
possibility of future extensions allowing for attribute directory
hierarchies and recursive attributes. The data file is therefore
composed of a sequence of records. It begins with a fixed length
header describing the content. The following table describes the
format of this data file.
Field Name Length (in Octets) Description
h_version 7 Name file version
h_size 10 Length of data file
h_component_len 10 Total length of all path segments
h_link_comp_len 10 Total length of all link segments
path h_component_len Complex path
link_path h_link_comp_len Complex link path
As demonstrated above, the header is followed by a record describing
the "path" to the attribute file. This path is composed of two or
more path segments separated by a null character. Each segment
describes a path rooted at the hidden extended attribute directory of
the leaf file of the previous segment, making it possible to name
attributes on attributes. The first segment is always the path to
the parent file that roots the entire sequence in the normal name
space. The following table describes the format of each segment.
Field Name Length (in Octets) Description
---------------------------------------------------------------------
h_namesz 7 Length of segment path
h_typeflag 1 Actual file type of attribute file
h_names h_namesz Parent path + segment path
If the attribute file is linked to another file, the path record is
followed by a second record describing the location of the
referencing file. The structure of this record is identical to the
record described above.
SEE ALSO
cp(1),
cpio(1),
du(1),
find(1),
ls(1),
mv(1),
pax(1),
runat(1),
tar(1),
chown(2),
link(2),
open(2),
pathconf(2),
rename(2),
stat(2),
unlink(2),
utimes(2),
attropen(3C),
standards(7),
fsck(8) October 10, 2007 FSATTR(7)