---
name: "setattrlist"
section: "2"
platform: "macos"
package: "xnu"
version: "12377.121.6"
release: "macOS 26.5"
platforms: ["macos"]
url: "https://new.carta.tech/setattrlist"
---

# setattrlist(2)

set file system attributes

## NAME

**setattrlist**, **fsetattrlist**, **setattrlistat** – set file system attributes

## SYNOPSIS

**#include \<sys/attr.h\>**

**#include \<unistd.h\>**

*int*\

**setattrlist**(*const char \* path*, *struct attrlist \* attrList*, *void \* attrBuf*, *size\_t attrBufSize*, *unsigned long options*);

*int*\

**fsetattrlist**(*int fd*, *struct attrlist \* attrList*, *void \* attrBuf*, *size\_t attrBufSize*, *unsigned long options*);

*int*\

**setattrlistat**(*int dir\_fd*, *const char \* path*, *struct attrlist \* attrList*, *void \* attrBuf*, *size\_t attrBufSize*, *uint32\_t options*);

## DESCRIPTION

The **setattrlist**() and **fsetattrlist**() functions set attributes (that is, metadata) of file system objects. They are the logical opposite of [getattrlist(2)](/getattrlist/2.md). The  **setattrlist**() function sets attributes about the file system object specified by  *path* from the values in the buffer specified by  *attrBuf* and *attrBufSize*; the **fsetattrlist**() function does the same for the *fd* file descriptor. The  *attrList* parameter determines what attributes are set.  The  *options* parameter lets you control specific aspects of the function's behaviour.

The **setattrlistat**() system call is equivalent to **setattrlist**() except in the case where *path* specifies a relative path. In this case the attributes are set for the file system object named by path relative to the directory associated with the file descriptor *fd* instead of the current working directory. If **setattrlistat**() is passed the special value AT\_FDCWD in the *fd* parameter, the current working directory is used and the behavior is identical to a call to **setattrlist**().

The  functions are only supported by certain volume format implementations.  For maximum compatibility, client programs should use high-level APIs  (such as the Carbon File Manager) to access file system attributes. These high-level APIs include logic to emulate file system attributes  on volumes that don't support  **setattrlist**() and **fsetattrlist**().

The *path* parameter for **setattrlist**() must reference a valid file system object. All directories listed in the path name leading to the object  must be searchable. The *fd* parameter for **fsetattrlist**() must be a valid file descriptor for the calling process. The list of potentially settable attributes via  **setattrlist**() is different than the list of attributes that are accessible via  **getattrlist**() In particular, only the following attributes are modifiable via  **setattrlist**() and not all of them may be supported on all filesystems.

-

  ATTR\_CMN\_SCRIPT

-

  ATTR\_CMN\_CRTIME

-

  ATTR\_CMN\_MODTIME

-

  ATTR\_CMN\_CHGTIME

-

  ATTR\_CMN\_ACCTIME

-

  ATTR\_CMN\_BKUPTIME

-

  ATTR\_CMN\_FNDRINFO

-

  ATTR\_CMN\_OWNERID

-

  ATTR\_CMN\_GRPID

-

  ATTR\_CMN\_ACCESSMASK

-

  ATTR\_CMN\_FLAGS

-

  ATTR\_CMN\_EXTENDED\_SECURITY

-

  ATTR\_CMN\_GRPUUID

-

  ATTR\_CMN\_ADDEDTIME

-

  ATTR\_VOL\_NAME

-

  ATTR\_VOL\_INFO

-

  ATTR\_FILE\_DEVTYPE

You must own the file system object in order to set any of the  following attributes:

-

  ATTR\_CMN\_GRPID

-

  ATTR\_CMN\_ACCESSMASK

-

  ATTR\_CMN\_FLAGS

-

  ATTR\_CMN\_CRTIME

-

  ATTR\_CMN\_MODTIME

-

  ATTR\_CMN\_ACCTIME

-

  ATTR\_CMN\_ADDEDTIME

  ATTR\_CMN\_CHGTIME  *cannot*, *be*, *set*, *programmatically.*, *Any*, *attempt*, *to*, *set*, *change*, *time*, *is*, *ignored.*

If ATTR\_CMN\_MODTIME is set to a time before ATTR\_CMN\_CRTIME, the value of ATTR\_CMN\_CRTIME is set to the same value as ATTR\_CMN\_MODTIME.

You must be root (that is, your process's effective UID must be 0) in order to change the  ATTR\_CMN\_OWNERID attribute Setting other attributes requires that you have write access to the object.

The *attrList* parameter is a pointer to an  *attrlist* structure.  You are responsible for filling out all fields of this structure before calling the function.  See the discussion of the   [getattrlist(2)](/getattrlist/2.md) function for a detailed description of this structure.  To set an attribute you must set the corresponding bit in the appropriate  *attrgroup\_t* field of the  *attrlist* structure.

The *attrBuf* and  *attrBufSize* parameters specify a buffer that contains the attribute values to set.  Attributes are packed in exactly the same way as they are returned from  [getattrlist(2)](/getattrlist/2.md) except that, when setting attributes, the buffer does not include the leading  *u\_int32\_t* length value.

The *options* parameter is a bit set that controls the behaviour of **setattrlist**(). The following option bits are defined.

- FSOPT\_NOFOLLOW

  If this bit is set,  **setattrlist**() will not follow a symlink if it occurs as  the last component of *path*.

- FSOPT\_NOFOLLOW\_ANY

  If this bit is set, **setattrlist**() will not follow a symlink if it occurs as the last component of *path*. In addition, if a symbolic link is encountered before the final component, an error is returned

- FSOPT\_RESOLVE\_BENEATH

  If this bit is set, path resolution must not escape the directory associated with the file descriptor.

- FSOPT\_UNIQUE

  If this bit is set, the path lookup will fail if the target file has multiple hard links.

## RETURN VALUES

Upon successful completion a value of 0 is returned. Otherwise, a value of -1 is returned and *errno* is set to indicate the error.

## COMPATIBILITY

Not all volumes support  **setattrlist**(). However, if a volume supports  [getattrlist(2)](/getattrlist/2.md), it must also support  **setattrlist**(). See the documentation for  [getattrlist(2)](/getattrlist/2.md) for details on how to tell whether a volume supports it.

The  **setattrlist**() function has been undocumented for more than two years.  In that time a number of volume format implementations have been created without  a proper specification for the behaviour of this routine.  You may encounter volume format implementations with slightly different  behaviour than what is described here.  Your program is expected to be tolerant of this variant behaviour.

If you're implementing a volume format that supports  **setattrlist**(), you should be careful to support the behaviour specified by this document.

## ERRORS

**setattrlist**() and **fsetattrlist**() will fail if:

- \[ENOTSUP\]

  The call is not supported by the volume.

- \[ENOTDIR\]

  A component of the path for **setattrlist**() prefix is not a directory.

- \[ENAMETOOLONG\]

  A component of a path name for **setattrlist**() exceeded  NAME\_MAX characters, or an entire path name exceeded  PATH\_MAX characters.

- \[ENOENT\]

  The file system object for **setattrlist**() does not exist.

- \[EBADF\]

  The file descriptor argument for **fsetattrlist**() is not a valid file descriptor.

- \[EROFS\]

  The volume is read-only.

- \[EACCES\]

  Search permission is denied for a component of the path prefix for **setattrlist**().

- \[ELOOP\]

  Too many symbolic links were encountered in translating the pathname for **setattrlist**().

- \[ELOOP\]

  FSOPT\_NOFOLLOW\_ANY was passed and a symbolic link was encountered in translating the pathname for **setattrlist**().

- \[EFAULT\]

  *path*, *attrList* or *attrBuf* points to an invalid address.

- \[EINVAL\]

  The  *bitmapcount* field of  *attrList* is not  ATTR\_BIT\_MAP\_COUNT.

- \[EINVAL\]

  You try to set an invalid attribute.

- \[EINVAL\]

  You try to set an attribute that is read-only.

- \[EINVAL\]

  You try to set volume attributes and directory or file attributes at the same time.

- \[EINVAL\]

  You try to set volume attributes but  *path* does not reference the root of the volume.

- \[EPERM\]

  You try to set an attribute that can only be set by the owner.

- \[EACCES\]

  You try to set an attribute that's only settable if you have write permission,  and you do not have write permission.

- \[EINVAL\]

  The buffer size you specified in  *attrBufSize* is too small to hold all the attributes that you are trying to set.

- \[EIO\]

  An I/O error occurred while reading from or writing to the file system.

In addition to the errors returned by the **setattrlist**(), the **setattrlistat**() function may fail if:

- \[EBADF\]

  The *path* argument does not specify an absolute path and the *fd* argument is neither AT\_FDCWD nor a valid file descriptor open for searching.

- \[ENOTDIR\]

  The *path* argument is not an absolute path and *fd* is neither AT\_FDCWD nor a file descriptor associated with a directory.

- \[ENOTCAPABLE\]

  if FSOPT\_RESOLVE\_BENEATH was passed and *path* does not reside in the directory hierarchy beneath the starting directory.

- \[ENOTCAPABLE\]

  if FSOPT\_UNIQUE was passed and *path* has multiple hard links.

## CAVEATS

If you try to set any volume attributes, you must set  ATTR\_VOL\_INFO in the  *volattr* field, even though it consumes no data from the attribute buffer.

For more caveats, see also the compatibility notes above.

## EXAMPLES

The following code shows how to set the file type and creator of  a file by getting the  ATTR\_CMN\_FNDRINFO attribute using  [getattrlist(2)](/getattrlist/2.md), modifying the appropriate fields of the 32-byte Finder information structure,  and then setting the attribute back using  **setattrlist**(). This assumes that the target volume supports the required attributes

```
#include <assert.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <sys/attr.h>
#include <sys/errno.h>
#include <unistd.h>
#include <sys/vnode.h>
typedef struct attrlist attrlist_t;
struct FInfoAttrBuf {
    u_int32_t       length;
    fsobj_type_t    objType;
    char            finderInfo[32];
};
typedef struct FInfoAttrBuf FInfoAttrBuf;
static int FInfoDemo(
    const char *path,
    const char *type,
    const char *creator
)
{
    int             err;
    attrlist_t      attrList;
    FInfoAttrBuf    attrBuf;
    assert( strlen(type)    == 4 );
    assert( strlen(creator) == 4 );
    memset(&attrList, 0, sizeof(attrList));
    attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
    attrList.commonattr  = ATTR_CMN_OBJTYPE | ATTR_CMN_FNDRINFO;
    err = getattrlist(path, &attrList, &attrBuf, sizeof(attrBuf), 0);
    if (err != 0) {
        err = errno;
    }
    if ( (err == 0) && (attrBuf.objType != VREG) ) {
        fprintf(stderr, "Not a standard file.\n");
        err = EINVAL;
    } else {
        memcpy( &attrBuf.finderInfo[0], type,    4 );
        memcpy( &attrBuf.finderInfo[4], creator, 4 );
        attrList.commonattr = ATTR_CMN_FNDRINFO;
        err = setattrlist(
            path,
            &attrList,
            attrBuf.finderInfo,
            sizeof(attrBuf.finderInfo),
            0
        );
    }
    return err;
}
```

## SEE ALSO

[chflags(2)](/chflags/2.md), [chmod(2)](/chmod/2.md), [chown(2)](/chown/2.md), [getattrlist(2)](/getattrlist/2.md), getdirentriesattr(2), [searchfs(2)](/searchfs/2.md), [utimes(2)](/utimes/2.md)

## HISTORY

A **setattrlist**() function call appeared in Darwin 1.3.1 (Mac OS X version 10.0). The setatrlistat function call first appeared in macOS version 10.13.
