1.\" 2.\" Copyright (c) 2025 Rick Macklem 3.\" 4.\" SPDX-License-Identifier: BSD-2-Clause 5.\" 6.Dd July 3, 2025 7.Dt NAMED_ATTRIBUTE 7 8.Os 9.Sh NAME 10.Nm named_attribute 11.Nd Solaris-like extended attribute system interface 12.Sh DESCRIPTION 13Description of the system interface for named attributes 14(the NFS Version 4 terminology). 15.Ss Introduction 16This document describes an alternate system interface for extended 17attributes as compared to 18.Xr extattr 2 . 19It is based on the interface provided by Solaris and NFS Version 4. 20.Pp 21This interface associates a directory, known as a named attribute directory, 22to a file system object. 23This directory is read in the same manner as a normal directory via the 24.Xr getdents 2 25or 26.Xr getdirentries 2 27system calls. 28The 29.Pa .\& 30and 31.Pa ..\& 32entries refer to the directory itself and to the associated file object, 33respectively. 34The other entries in this directory 35are the names of the extended attributes for the associated file object 36and are referred to as named attributes. 37These named attributes are regular files used to store the attribute's 38value. 39.Pp 40A named attribute directory does not live in the file system's name space. 41It is accessed via an 42.Xr open 2 43or 44.Xr openat 2 45system call done on a file to query the named attributes for the file, 46with the 47.Dv O_NAMEDATTR 48flag specified and a 49.Fa path 50argument of 51.Pa .\& . 52This file descriptor can be used as the 53.Fa fd 54argument for a variety of system calls, such as: 55.Xr fchdir 2 , 56.Xr unlinkat 2 57and 58.Xr renameat 2 . 59.Xr renameat 2 60is only permitted to rename a named attribute within the same named 61attribute directory. 62.Pp 63When a file descriptor for a file object in the file system's namespace 64is used as the 65.Fa fd 66argument of an 67.Xr openat 2 68along with the 69.Fa flag 70.Dv O_NAMEDATTR 71and a 72.Fa path 73argument that is the name of a named attribute (not 74.Pa .\& 75or 76.Pa ..\& 77), a file descriptor for the named attribute is returned. 78If the 79.Fa flag 80.Dv O_CREAT 81is specified, the named attribute will be created if it does not exist. 82The 83.Fa path 84argument must be a single component name, with no embedded 85.Dq / 86in it. 87I/O on these named attribute file descriptors may be performed by 88standard I/O system calls 89such as: 90.Xr read 2 , 91.Xr write 2 , 92.Xr lseek 2 93and 94.Xr ftruncate 2 . 95.Pp 96The 97.Dv _PC_NAMEDATTR_ENABLED 98.Fa name 99argument to 100.Xr pathconf 2 101will return 1 if the file system supports named attributes. 102The 103.Dv _PC_HAS_NAMEDATTR 104.Fa name 105argument to 106.Xr pathconf 2 107will return 1 if there are one or more named attributes for the file. 108If an application does a 109.Xr openat 2 110of 111.Dq .\& 112to open a named attribute directory when no named attribute directory exists, 113an empty named attribute directory will be created. 114Testing 115.Dv _PC_HAS_NAMEDATTR 116can be done to avoid creating these named attribute directories unnecessarily. 117.Pp 118The named attribute interface is a different mechanism/system call interface for 119manipulating extended attributes compared with 120.Xr extattr 2 . 121Although the named attribute machanism might require different internal 122implementation 123of extended attributes within a file system, both ZFS and NFSv4 provide 124both mechanisms, which can be used interchangeably to manipulate 125extended attributes, but with a couple of limitations. 126.Bl -bullet 127.It 128The 129.Xr extattr 2 130interface requires that an extended attribute's value be set or acquired 131via a single system call using a single buffer. 132This limits the size of the attribute's value. 133.It 134The named attribute interface does not support system namespace 135extended attributes and, 136as such, system namespace extended attributes must be manipulated via 137.Xr extattr 2 . 138.El 139.Pp 140The named attribute mechanism/system call interface provides certain 141advantages over 142.Xr extattr 2 . 143Since the attribute's value is updated via 144.Xr read 2 145and 146.Xr write 2 147system calls, the attribute's data may be as large as any regular file 148and may be partially updated. 149(Note that this interface does not provide the atomicity guarantee that 150.Xr extattr 2 151does.) 152The permission to access a named attribute directory is determined from 153the access control information for the associated file object. 154However, access control information can be set on each individual attribute 155in a manner similar to a regular file. 156This provides 157.Dq per attribute 158granular control over attribute permissions via 159.Xr fchown 2 . 160.Pp 161At this time, the only local file system which supports this interface 162is ZFS and only if the 163.Dv xattr 164property is set to 165.Dq dir . 166(Note that, even when 167.Dq zfs get xattr <file-system> 168shows 169.Dq on 170the command 171.Dq zfs set xattr=dir <file-system> 172must be done, followed by a remount to make the setting take effect.) 173A NFSv4 mount will also support this interface, but only if the NFSv4 174server file system supports named attributes (the openattr operation). 175The 176.Fx 177NFSv4 server supports named attributes only 178for ZFS exported file systems where the 179.Dq xattr 180property is set to 181.Dq dir 182for the file system. 183.Sh EXAMPLES 184.Bd -literal 185#include <stdio.h> 186#include <dirent.h> 187#include <fcntl.h> 188#include <unistd.h> 189 190\&... 191 192/* For a file called "myfile". Failure checks removed for brevity. */ 193int file_fd, nameddir_fd, namedattr_fd; 194ssize_t siz; 195char buf[DIRBLKSIZ], *cp; 196struct dirent *dp; 197long named_enabled, has_named_attrs; 198 199\&... 200/* Check to see if named attributes are supported. */ 201named_enabled = pathconf("myfile", _PC_NAMEDATTR_ENABLED); 202if (named_enabled <= 0) 203 err(1, "Named attributes not enabled"); 204/* Test to see if named attribute(s) exist for the file. */ 205has_named_attrs = pathconf("myfile", _PC_HAS_NAMEDATTR); 206if (has_named_attrs == 1) 207 printf("myfile has named attribute(s)\\n"); 208else 209 printf("myfile does not have any named attributes\\n"); 210/* Open a named attribute directory. */ 211file_fd = open("myfile", O_RDONLY, 0); 212nameddir_fd = openat(file_fd, ".", O_NAMEDATTR, 0); 213\&... 214/* and read it, assuming it all fits in DIRBLKSIZ for simplicity. */ 215siz = getdents(fd, buf, sizeof(buf)); 216cp = buf; 217while (cp < &buf[siz]) { 218 dp = (struct dirent *)cp; 219 printf("name=%s\\n", dp->d_name); 220 cp += dp->d_reclen; 221} 222\&... 223/* Open/create a named attribute called "foo". */ 224namedattr_fd = openat(file_fd, "foo", O_CREAT | O_RDWR | 225 O_TRUNC | O_NAMEDATTR, 0600); 226\&... 227/* Write foo's attribute value. */ 228write(namedattr_fd, "xxxyyy", 6); 229\&... 230/* Read foo's attribute value. */ 231lseek(namedattr_fd, 0, SEEK_SET); 232siz = read(namedattr_fd, buf, sizeof(buf)); 233\&... 234/* And close "foo". */ 235close(namedattr_fd); 236\&... 237/* Rename "foo" to "oldfoo". */ 238renameat(nameddir_fd, "foo", nameddir_fd, "oldfoo"); 239/* and delete "oldfoo". */ 240unlinkat(nameddir_fd, "oldfoo", AT_RESOLVE_BENEATH); 241.Ed 242.Pp 243The 244.Xr runat 1 245command may be used to perform shell commands on named attributes. 246For example: 247.Bd -literal 248$ runat myfile cp /etc/hosts attrhosts # creates attrhosts 249$ runat myfile cat attrhosts # displays contents of attrhosts 250$ runat myfile ls -l # lists the attributes for myfile 251.Ed 252.Pp 253If using the 254.Xr bash 1 255shell, the command 256.Dq cd -@ foo 257enters the named attribute directory for the file object 258.Dq foo . 259.Sh SEE ALSO 260.Xr bash 1 , 261.Xr runat 1 , 262.Xr chdir 2 , 263.Xr extattr 2 , 264.Xr lseek 2 , 265.Xr open 2 , 266.Xr pathconf 2 , 267.Xr read 2 , 268.Xr rename 2 , 269.Xr truncate 2 , 270.Xr unlinkat 2 , 271.Xr write 2 , 272.Xr zfsprops 7 273.Sh HISTORY 274This interface first appeared in 275.Fx 15.0 . 276