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