1.\" 2.\" Copyright (c) 2025 Rick Macklem 3.\" 4.\" SPDX-License-Identifier: BSD-2-Clause 5.\" 6.Dd August 5, 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 few 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.It 139For ZFS, if an extended attribute with a value 140that is a small length in bytes is created when the ZFS 141.Dv xattr 142property is set to 143.Dq sa , 144that extended attribute is only visible via 145.Xr extattr 2 146and not as a named attribute. 147Archiving/de-archiving the file via 148.Xr tar 1 149after setting the 150.Dv xattr 151property to 152.Dq dir 153will make the attribute(s) visible as both named attributes 154and via 155.Xr extattr 2 . 156.It 157For ZFS, it is also possible to create two attributes with the same 158name by creating one when the ZFS 159.Dv xattr 160property is set to 161.Dq sa 162and then creating another one with the same name after the ZFS 163property 164.Dv xattr 165has been changed to 166.Dq dir . 167The one created when the ZFS 168.Dv xattr 169property is set to 170.Dq sa 171may be removed via 172.Xr rmextattr 8 . 173.It 174To avoid these issues for ZFS, it is strongly recommended that the ZFS 175property 176.Dv xattr 177be set to 178.Dq dir 179as soon as the file system is created, if named attributes 180are to be used on the file system. 181.El 182.Pp 183The named attribute mechanism/system call interface provides certain 184advantages over 185.Xr extattr 2 . 186Since the attribute's value is updated via 187.Xr read 2 188and 189.Xr write 2 190system calls, the attribute's data may be as large as any regular file 191and may be partially updated. 192(Note that this interface does not provide the atomicity guarantee that 193.Xr extattr 2 194does.) 195The permission to access a named attribute directory is determined from 196the access control information for the associated file object. 197However, access control information can be set on each individual attribute 198in a manner similar to a regular file. 199This provides 200.Dq per attribute 201granular control over attribute permissions via 202.Xr fchown 2 . 203.Pp 204At this time, the only local file system which supports this interface 205is ZFS and only if the 206.Dv xattr 207property is set to 208.Dq dir . 209(Note that, even when 210.Dq zfs get xattr <file-system> 211shows 212.Dq on 213the command 214.Dq zfs set xattr=dir <file-system> 215must be done, followed by a remount to make the setting take effect.) 216A NFSv4 mount will also support this interface, but only if the NFSv4 217server file system supports named attributes (the openattr operation). 218The 219.Fx 220NFSv4 server supports named attributes only 221for ZFS exported file systems where the 222.Dq xattr 223property is set to 224.Dq dir 225for the file system. 226.Sh EXAMPLES 227.Bd -literal 228#include <stdio.h> 229#include <dirent.h> 230#include <fcntl.h> 231#include <unistd.h> 232 233\&... 234 235/* For a file called "myfile". Failure checks removed for brevity. */ 236int file_fd, nameddir_fd, namedattr_fd; 237ssize_t siz; 238char buf[DIRBLKSIZ], *cp; 239struct dirent *dp; 240long named_enabled, has_named_attrs; 241 242\&... 243/* Check to see if named attributes are supported. */ 244named_enabled = pathconf("myfile", _PC_NAMEDATTR_ENABLED); 245if (named_enabled <= 0) 246 err(1, "Named attributes not enabled"); 247/* Test to see if named attribute(s) exist for the file. */ 248has_named_attrs = pathconf("myfile", _PC_HAS_NAMEDATTR); 249if (has_named_attrs == 1) 250 printf("myfile has named attribute(s)\\n"); 251else 252 printf("myfile does not have any named attributes\\n"); 253/* Open a named attribute directory. */ 254file_fd = open("myfile", O_RDONLY, 0); 255nameddir_fd = openat(file_fd, ".", O_NAMEDATTR, 0); 256\&... 257/* and read it, assuming it all fits in DIRBLKSIZ for simplicity. */ 258siz = getdents(fd, buf, sizeof(buf)); 259cp = buf; 260while (cp < &buf[siz]) { 261 dp = (struct dirent *)cp; 262 printf("name=%s\\n", dp->d_name); 263 cp += dp->d_reclen; 264} 265\&... 266/* Open/create a named attribute called "foo". */ 267namedattr_fd = openat(file_fd, "foo", O_CREAT | O_RDWR | 268 O_TRUNC | O_NAMEDATTR, 0600); 269\&... 270/* Write foo's attribute value. */ 271write(namedattr_fd, "xxxyyy", 6); 272\&... 273/* Read foo's attribute value. */ 274lseek(namedattr_fd, 0, SEEK_SET); 275siz = read(namedattr_fd, buf, sizeof(buf)); 276\&... 277/* And close "foo". */ 278close(namedattr_fd); 279\&... 280/* Rename "foo" to "oldfoo". */ 281renameat(nameddir_fd, "foo", nameddir_fd, "oldfoo"); 282/* and delete "oldfoo". */ 283unlinkat(nameddir_fd, "oldfoo", AT_RESOLVE_BENEATH); 284.Ed 285.Pp 286The 287.Xr runat 1 288command may be used to perform shell commands on named attributes. 289For example: 290.Bd -literal 291$ runat myfile cp /etc/hosts attrhosts # creates attrhosts 292$ runat myfile cat attrhosts # displays contents of attrhosts 293$ runat myfile ls -l # lists the attributes for myfile 294.Ed 295.Pp 296If using the 297.Xr bash 1 298shell, the command 299.Dq cd -@ foo 300enters the named attribute directory for the file object 301.Dq foo . 302.Sh SEE ALSO 303.Xr bash 1 , 304.Xr runat 1 , 305.Xr tar 1 , 306.Xr chdir 2 , 307.Xr extattr 2 , 308.Xr lseek 2 , 309.Xr open 2 , 310.Xr pathconf 2 , 311.Xr read 2 , 312.Xr rename 2 , 313.Xr truncate 2 , 314.Xr unlinkat 2 , 315.Xr write 2 , 316.Xr zfsprops 7 , 317.Xr rmextattr 8 318.Sh HISTORY 319This interface first appeared in 320.Fx 15.0 . 321