ATTR_LIST(3)

πŸ“¦
version 2.6.0 Β· 3 versions
, in alpine 3.22, alpine 3.23, alpine 3.24, arch rolling, centos-stream 10, centos-stream 9, debian bookworm, fedora 43, fedora 44, nixpkgs unstable, opensuse-leap 16.0, ubuntu noble

ATTR_LIST(3) πŸ’…

okay so bestie, this is the attr_list / attr_listf page, and it lives in section 3 of the manual, filed under the XFS Compatibility API. It's giving "let me tell you what attributes even exist on this thing" energy. πŸ¦‹


✨ NAME ✨

attr_list, attr_listf β€” list the names of the user attributes of a filesystem object πŸ‘‘


✨ C SYNOPSIS ✨

#include <attr/attributes.h>

int attr_list (const char βˆ—path, char βˆ—buffer,
               const int buffersize, int flags,
               attrlist_cursor_t βˆ—cursor);

int attr_listf (int fd, char βˆ—buffer,
                const int buffersize, int flags,
                attrlist_cursor_t βˆ—cursor);

🌸 DESCRIPTION 🌸

So attr_list and attr_listf are literally the two besties that let you list out the attributes that already exist on a filesystem object. No cap.

path points to a path name for a filesystem object, and fd refers to the file descriptor associated with a file. The buffer gets filled with a structure describing at least a portion of the attributes associated with the given filesystem object. Like, buffer will be overwritten with an attrlist_t structure containing a list of the attributes associated with that filesystem object, up to a maximum of buffersize bytes. 🫢

And the buffer has to be big enough to hold the appropriate data structures plus at least one maximally sized attribute name β€” but it cannot be more than ATTR_MAX_VALUELEN (currently 64KB) bytes long. So there's a ceiling, bestie. Don't fight it. 😭

The contents of an attrlist_t structure include the following members:

int32_t al_count; /βˆ— number of entries in attrlist βˆ—/
int32_t al_more; /βˆ— T/F: more attrs (do syscall again) βˆ—/
int32_t al_offset[1]; /βˆ— byte offsets of attrs [var-sized] βˆ—/

okay so the al_count field shows the number of attributes represented in this buffer, which is also the number of elements in the al_offset array. Two jobs, one field, iconic. πŸ’…

The al_more field will be non-zero if another attr_list call would result in more attributes β€” like a lil "there's more, come back" note. πŸ™ˆ

The al_offset array contains the byte offset within the buffer of the structure describing each of the attributes, an attrlist_ent_t structure. And the ATTR_ENTRY(buffer, index) macro is your bestie here β€” it helps with decoding the list. It takes a pointer to the buffer and an index into the al_offset array and returns a pointer to the corresponding attrlist_ent_t structure. Slay. ✨

The contents of an attrlist_ent_t structure include the following members:

uint32_t a_valuelen; /βˆ— number bytes in value of attr βˆ—/
char a_name[]; /βˆ— attr name (NULL terminated) βˆ—/

The a_valuelen field shows the size in bytes of the value associated with the attribute whose name is stored in the a_name field. And the name is a NULL terminated string, as one does. πŸŽ€

⚠️ Real talk: the value of the attribute cannot be obtained through this interface. You gotta use the attr_get call to get the value. What attr_list does is tell the calling process how large of a buffer it must have in order to get the attribute's value. It's the scout, not the soldier. 🫑

✨ OPTIONS ✨

The flags argument can contain the following symbols bitwise OR'ed together:

  • ATTR_ROOT β€” List the attributes that are in the root address space, not in the user address space. (limited to use by super-user only β€” so like, know your limits bestie πŸ’€)
  • ATTR_DONTFOLLOW β€” Do not follow symbolic links when resolving a path on an attr_list function call. The default is to follow symbolic links. (The default is literally following, she's nosy like that. πŸ¦‹)

πŸŒ€ The cursor situation πŸŒ€

The cursor argument is a pointer to an opaque data structure that the kernel uses to track the calling process's position in the attribute list. And the only valid operations on a cursor are:

  1. pass it into an attr_list function call, or
  2. zero it out.

It should be zero'ed out before the first attr_list call. Periodt. πŸ’…

Also ngl, multi-threaded applications may keep more than one cursor in order to serve multiple contexts, ie: the attr_list call is "thread-safe". Main character energy for your threads, fr fr. πŸ‘‘


πŸ’€ attr_list will fail if one or more of the following are true:

  • [ENOENT] β€” The named file does not exist. (it's not there, bestie, it never was 😭)
  • [EPERM] β€” The effective user ID does not match the owner of the file and the effective user ID is not super-user.
  • [ENOTDIR] β€” A component of the path prefix is not a directory.
  • [EACCES] β€” Search permission is denied on a component of the path prefix.
  • [EINVAL] β€” A bit was set in the flag argument that is not defined for this system call, or the buffer was too small or too large.
  • [EFAULT] β€” Either Path or buffer points outside the allocated address space of the process, or buffer or bufsize are not 32bit aligned.
  • [ELOOP] β€” A path name lookup involved too many symbolic links. (the links ate and left no crumbs, unfortunately πŸŒ€)
  • [ENAMETOOLONG] β€” The length of path exceeds {MAXPATHLEN}, or a pathname component is longer than {MAXNAMELEN}.
  • [ENOATTR] β€” attribute does not exist for this file.

πŸ’€ attr_listf will fail if:

  • [EINVAL] β€” A bit was set in the flag argument that is not defined for this system call, or fd refers to a socket, not a file, or the buffer was too small or too large.
  • [EFAULT] β€” Either Path or buffer points outside the allocated address space of the process, or buffer or bufsize are not 32bit aligned.
  • [EBADF] β€” Fd does not refer to a valid descriptor.

🩺 DIAGNOSTICS 🩺

Upon successful completion, a value of 0 is returned. Otherwise, a value of -1 is returned and errno is set to indicate the error. Like, if you get the 0 you ate. If you get the -1, check errno, she's trying to tell you something. 😀


πŸ‘€ SEE ALSO πŸ‘€

attr(1), attr_multi(3), attr_remove(3), attr_set(3)


and that's the whole vibe ✨

This page is from Extended Attributes, dated Dec 2005. Yes bestie, a vintage. She's been slaying since 2005 and she's still iconic. πŸŽ€πŸ’–πŸ¦‹

πŸ“¦ where this page comes from