Get Extended Attributes of File in C

  1. Use getxattr and listxattr Functions to Get Extended Attributes of File
  2. Use the setxattr Function to Set Extended Attributes on File

This article will explain several methods of how to get extended attributes of a file in C.

Use getxattr and listxattr Functions to Get Extended Attributes of File

Some UNIX-based systems provide extended attributes for the files, representing name-value pairs of metadata that can be associated with the file. Extended attributes require the underlying file system support, but the common filesystem types have this feature. Extended attributes have the specific format of type - namespace.name, where namespace is utilized to group functionally similar ones, while the name part identifies an individual extended attribute. A namespace can have the following values: user, trusted, system and security, which distinguish several permission types as a convention (described in detail on the page). In this case, we implement an example program that takes multiple filenames as command-line arguments and consequently retrieves all extended attributes for each file. Notice that the program processes the multiple file arguments with the getopt function.

The getxattr function takes four arguments to retrieve an extended attribute value. The first argument specifies a path in the filesystem to indicate the file for which EAs should be retrieved, and the second argument specifies an attribute name. The last two arguments are the pointer to the location where the value will be stored by getxattr and the available buffer size on this address. Note that the size of the attribute value can be retrieved by passing the value 0 as a size argument and the return value of the call is the number of bytes for the needed buffer. Although, when the second call is invoked to retrieve the value, it might be changed and have a different size; thus, it’s better to check for the error codes to guarantee faultless execution.

On the other hand, the listxattr function retrieves the list of extended attribute names for the given file path. It takes three arguments, the first of which is the file path. The next two arguments represent the buffer where the retrieved list will be stored and its size specified in bytes. Note that this buffer is caller-allocated, and the caller is responsible for allocating sufficient memory. Also, similar to the getxattr, one can pass the value 0 as the third argument to this function, and returned value will be the buffer size needed to store the full list.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/xattr.h>

#define XATTR_SIZE 10000

#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
                               } while (0)


static void usageError(char *progName)
{
    fprintf(stderr, "Usage: %s [-x] file...\n", progName);
    exit(EXIT_FAILURE);
}

int main(int argc, char *argv[]) {
    char list[XATTR_SIZE], value[XATTR_SIZE];
    ssize_t listLen, valueLen;
    int ns, j, k, opt;
    bool hexDisplay;

    hexDisplay = 0;
    while ((opt = getopt(argc, argv, "x")) != -1) {
        switch (opt) {
            case 'x': hexDisplay = 1; break;
            case '?': usageError(argv[0]);
        }
    }

    if (optind >= argc)
        usageError(argv[0]);

    for (j = optind; j < argc; j++) {
        listLen = listxattr(argv[j], list, XATTR_SIZE);
        if (listLen == -1)
            errExit("listxattr");

        printf("%s:\n", argv[j]);

        for (ns = 0; ns < listLen; ns += strlen(&list[ns]) + 1) {
            printf("        name=%s; ", &list[ns]);

            valueLen = getxattr(argv[j], &list[ns], value, XATTR_SIZE);
            if (valueLen == -1) {
                printf("couldn't get value");
            } else if (!hexDisplay) {
                printf("value=%.*s", (int) valueLen, value);
            } else {
                printf("value=");
                for (k = 0; k < valueLen; k++)
                    printf("%02x ", (unsigned char) value[k]);
            }

            printf("\n");
        }

        printf("\n");
    }

    exit(EXIT_SUCCESS);
}

Use the setxattr Function to Set Extended Attributes on File

Alternatively, we can set arbitrary attributes to the files using the setxattr function, which takes the file’s pathname, name-value pair as separate arguments, the size of the value, an integer that specifies the predefined values for different set operations. If the last argument is zero, which is the default value, the extended attribute is created if it does not exist; otherwise, the value is replaced. The XATTR_CREATE macro can be specified to indicate only create option, which will fail if the attribute exists, and XATTR_REPLACE to perform replacement which fails if the attribute does not exist.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/xattr.h>


#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
                               } while (0)


static void usageError(char *progName)
{
    fprintf(stderr, "Usage: %s file\n", progName);
    exit(EXIT_FAILURE);
}

int main(int argc, char *argv[]) {
    char *value;

    if (argc < 2 || strcmp(argv[1], "--help") == 0)
        usageError(argv[0]);

    value = "x attribute value";
    if (setxattr(argv[1], "user.x", value, strlen(value), 0) == -1)
        errExit("setxattr");

    value = "y attribute value";
    if (setxattr(argv[1], "user.y", value, strlen(value), 0) == -1)
        errExit("setxattr");

    exit(EXIT_SUCCESS);
}
Contribute
DelftStack is a collective effort contributed by software geeks like you. If you like the article and would like to contribute to DelftStack by writing paid articles, you can check the write for us page.

Related Article - C File

  • Read a File in C