NAMED_ATTRIBUTE(7)                    FreeBSD Miscellaneous Information Manual

NAME

     named_attribute - Solaris-like extended attribute system interface

DESCRIPTION

     Description of the system interface for named attributes (the NFS Version
     4 terminology).

Introduction

     This document describes an alternate system interface for extended
     attributes as compared to extattr(2).  It is based on the interface
     provided by Solaris and NFS Version 4.

     This interface associates a directory, known as a named attribute
     directory, to a file system object.  This directory is read in the same
     manner as a normal directory via the getdents(2) or getdirentries(2)
     system calls.  The . and .. entries refer to the directory itself and to
     the associated file object, respectively.  The other entries in this
     directory are the names of the extended attributes for the associated
     file object and are referred to as named attributes.  These named
     attributes are regular files used to store the attribute's value.

     A named attribute directory does not live in the file system's name
     space.  It is accessed via an open(2) or openat(2) system call done on a
     file to query the named attributes for the file, with the O_NAMEDATTR
     flag specified and a path argument of ..  This file descriptor can be
     used as the fd argument for a variety of system calls, such as:
     fchdir(2), unlinkat(2) and renameat(2).  renameat(2) is only permitted to
     rename a named attribute within the same named attribute directory.

     When a file descriptor for a file object in the file system's namespace
     is used as the fd argument of an openat(2) along with the flag
     O_NAMEDATTR and a path argument that is the name of a named attribute
     (not . or .. ), a file descriptor for the named attribute is returned.
     If the flag O_CREAT is specified, the named attribute will be created if
     it does not exist.  The path argument must be a single component name,
     with no embedded "/" in it.  I/O on these named attribute file
     descriptors may be performed by standard I/O system calls such as:
     read(2), write(2), lseek(2) and ftruncate(2).

     The _PC_NAMEDATTR_ENABLED name argument to pathconf(2) will return 1 if
     the file system supports named attributes.  The _PC_HAS_NAMEDATTR name
     argument to pathconf(2) will return 1 if there are one or more named
     attributes for the file.  If an application does a openat(2) of "." to
     open a named attribute directory when no named attribute directory
     exists, an empty named attribute directory will be created.  Testing
     _PC_HAS_NAMEDATTR can be done to avoid creating these named attribute
     directories unnecessarily.

     The named attribute interface is a different mechanism/system call
     interface for manipulating extended attributes compared with extattr(2).
     Although the named attribute machanism might require different internal
     implementation of extended attributes within a file system, both ZFS and
     NFSv4 provide both mechanisms, which can be used interchangeably to
     manipulate extended attributes, but with a few limitations.

     o   The extattr(2) interface requires that an extended attribute's value
         be set or acquired via a single system call using a single buffer.
         This limits the size of the attribute's value.

     o   The named attribute interface does not support system namespace
         extended attributes and, as such, system namespace extended
         attributes must be manipulated via extattr(2).

     o   For ZFS, if an extended attribute with a value that is a small length
         in bytes is created when the ZFS xattr property is set to "sa", that
         extended attribute is only visible via extattr(2) and not as a named
         attribute.  Archiving/de-archiving the file via tar(1) after setting
         the xattr property to "dir" will make the attribute(s) visible as
         both named attributes and via extattr(2).

     o   For ZFS, it is also possible to create two attributes with the same
         name by creating one when the ZFS xattr property is set to "sa" and
         then creating another one with the same name after the ZFS property
         xattr has been changed to "dir".  The one created when the ZFS xattr
         property is set to "sa" may be removed via rmextattr(8).

     o   To avoid these issues for ZFS, it is strongly recommended that the
         ZFS property xattr be set to "dir" as soon as the file system is
         created, if named attributes are to be used on the file system.

     The named attribute mechanism/system call interface provides certain
     advantages over extattr(2).  Since the attribute's value is updated via
     read(2) and write(2) system calls, the attribute's data may be as large
     as any regular file and may be partially updated.  (Note that this
     interface does not provide the atomicity guarantee that extattr(2) does.)
     The permission to access a named attribute directory is determined from
     the access control information for the associated file object.  However,
     access control information can be set on each individual attribute in a
     manner similar to a regular file.  This provides "per attribute" granular
     control over attribute permissions via fchown(2).

     At this time, the only local file system which supports this interface is
     ZFS and only if the xattr property is set to "dir".  (Note that, even
     when "zfs get xattr <file-system>" shows "on" the command "zfs set
     xattr=dir <file-system>" must be done, followed by a remount to make the
     setting take effect.)  A NFSv4 mount will also support this interface,
     but only if the NFSv4 server file system supports named attributes (the
     openattr operation).  The FreeBSD NFSv4 server supports named attributes
     only for ZFS exported file systems where the "xattr" property is set to
     "dir" for the file system.

EXAMPLES

     #include <stdio.h>
     #include <dirent.h>
     #include <fcntl.h>
     #include <unistd.h>

     ...

     /* For a file called "myfile". Failure checks removed for brevity. */
     int file_fd, nameddir_fd, namedattr_fd;
     ssize_t siz;
     char buf[DIRBLKSIZ], *cp;
     struct dirent *dp;
     long named_enabled, has_named_attrs;

     ...
     /* Check to see if named attributes are supported. */
     named_enabled = pathconf("myfile", _PC_NAMEDATTR_ENABLED);
     if (named_enabled <= 0)
             err(1, "Named attributes not enabled");
     /* Test to see if named attribute(s) exist for the file. */
     has_named_attrs = pathconf("myfile", _PC_HAS_NAMEDATTR);
     if (has_named_attrs == 1)
             printf("myfile has named attribute(s)\n");
     else
             printf("myfile does not have any named attributes\n");
     /* Open a named attribute directory. */
     file_fd = open("myfile", O_RDONLY, 0);
     nameddir_fd = openat(file_fd, ".", O_NAMEDATTR, 0);
     ...
     /* and read it, assuming it all fits in DIRBLKSIZ for simplicity. */
     siz = getdents(fd, buf, sizeof(buf));
     cp = buf;
     while (cp < &buf[siz]) {
             dp = (struct dirent *)cp;
             printf("name=%s\n", dp->d_name);
             cp += dp->d_reclen;
     }
     ...
     /* Open/create a named attribute called "foo". */
     namedattr_fd = openat(file_fd, "foo", O_CREAT | O_RDWR |
         O_TRUNC | O_NAMEDATTR, 0600);
     ...
     /* Write foo's attribute value. */
     write(namedattr_fd, "xxxyyy", 6);
     ...
     /* Read foo's attribute value. */
     lseek(namedattr_fd, 0, SEEK_SET);
     siz = read(namedattr_fd, buf, sizeof(buf));
     ...
     /* And close "foo". */
     close(namedattr_fd);
     ...
     /* Rename "foo" to "oldfoo". */
     renameat(nameddir_fd, "foo", nameddir_fd, "oldfoo");
     /* and delete "oldfoo". */
     unlinkat(nameddir_fd, "oldfoo", AT_RESOLVE_BENEATH);

     The runat(1) command may be used to perform shell commands on named
     attributes.  For example:

     $ runat myfile cp /etc/hosts attrhosts  # creates attrhosts
     $ runat myfile cat attrhosts            # displays contents of attrhosts
     $ runat myfile ls -l                    # lists the attributes for myfile

     If using the bash(1) shell, the command "cd -@ foo" enters the named
     attribute directory for the file object "foo".

SEE ALSO

     bash(1), runat(1), tar(1), chdir(2), extattr(2), lseek(2), open(2),
     pathconf(2), read(2), rename(2), truncate(2), unlinkat(2), write(2),
     zfsprops(7), rmextattr(8)

HISTORY

     This interface first appeared in FreeBSD 15.0.

FreeBSD 15.1-STABLE-HBSD        August 5, 2025              NAMED_ATTRIBUTE(7)