xref: /freebsd/share/man/man7/named_attribute.7 (revision 654dea596703eb422055a7d637356fbde36f8540)
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