| GETATTRLISTBULK(2) | System Calls Manual | GETATTRLISTBULK(2) | 
getattrlistbulk —
    get file system attributes for multiple directory
    entries
#include
    <sys/attr.h>
  
  #include <unistd.h>
  
  int
  
  getattrlistbulk(int
    dirfd, struct attrlist *
    attrList, void *
    attrBuf, size_t
    attrBufSize, uint64_t
    options);
The
    getattrlistbulk()
    function iterates over the items in a directory and returns information
    about each directory entry like
    getattrlist(2). Note: when
    getattrlistbulk() returns information about a
    symbolic link, the information returned is about the link itself, not the
    target of the link. The order of the directory entries (and their associated
    metadata) vended by getattrlistbulk() is not
    specified. Some file systems may return entries in lexicographic sort order
    and others may not.
The function reads directory entries from the directory referenced by the file descriptor dirfd. The attrList parameter determines what attributes are returned for each entry. Attributes of those directory entries are placed into the buffer specified by attrBuf and attrBufSize. The options parameter allows you to modify the behaviour of the call.
The dirfd parameter must be a file descriptor that references a directory that you have opened for reading.
The attrList parameter is a
    pointer to an attrlist structure. All fields of this
    structure must be filled before calling the function. See the discussion of
    the getattrlist(2) function for a
    detailed description of this structure. To get an attribute, the
    corresponding bit in the appropriate attrgroup_t field
    of the attrlist structure must be set. Volume
    attributes cannot be requested but all other supported getattrlist
    attributes can be used. For this function,
    ATTR_CMN_NAME and
    ATTR_CMN_RETURNED_ATTRS are required and the absence
    of these attributes in the attrList parameter results in an error. Note that
    not all attributes supported by
    getattrlist()
    may be vended back by this call, which is why the aforementioned flag must
    be supplied. In particular ATTR_CMN_FULLPATH may not
    be valid on all directory entries whose information is requested by this
    call.
The attrBuf and
    attrBufSize parameters specify a buffer into which the
    function places attribute values. The attributes for any given directory
    entry are grouped together and packed in exactly the same way as they are
    returned from getattrlist(2) and
    are subject to exactly the same alignment specifications and restrictions.
    These groups are then placed into the buffer, one after another.
    getattrlist(2) should be consulted
    on details of the attributes that can be requested for and returned. The
    name of the entry itself is provided by the
    ATTR_CMN_NAME attribute. Each group starts with a
    leading uint32_t , which will always be 8-byte aligned
    that contains the overall length of the group. You can step from one group
    to the next by simply adding this length to your pointer. The sample code
    (below) shows how to do this. The initial contents of this buffer are
    ignored.
The options parameter
    is a bit set that controls the behaviour of
    getattrlistbulk().
    The following option bits are defined.
ATTR_CMN_RETURNED_ATTRS attribute. Default values
      will be returned for invalid attributes and should be ignored.
    Please see the discussion of this flag in getattrlist(2)
If ATTR_CMN_ERROR has been requested and
    an error specific to a directory entry occurs, an error will be reported.
    The ATTR_CMN_ERROR attribute is a uint32_t which, if
    non-zero, specifies the error code that was encountered during the
    processing of that directory entry. The
    ATTR_CMN_ERROR attribute will be after
    ATTR_CMN_RETURNED_ATTRS attribute in the returned
    buffer.
It is typical to ask for a combination of common, file, and
    directory attributes and then use the value of the
    ATTR_CMN_OBJTYPE attribute to parse the resulting
    attribute buffer.
A directory which is a mount point for a file system, will have a value of “DIR_MNTSTATUS_MNTPOINT” set for its ATTR_DIR_MOUNTSTATUS attribute entry. However the attributes for the mount point will be those from the (underlying) file system. To get the attributes of the mounted root directory, call getattrlist(2) on the mount point.
A directory which is a firmlink will have
    the “SF_FIRMLINK” flag set in its ATTR_CMN_FLAGS attribute
    entry. However, the attributes returned by
    getattrlistbulk()
    will be those from the firmlink, not the firmlink's target. To get the
    attribute of the firmlink's target, call
    getattrlist(2) on the
  firmlink.
Upon successful completion the numbers of entries successfully
    read is returned. A value of 0 indicates there are no more entries. Once 0
    is returned, no further entries are returned even if new entries are added
    to the directory. Directory iteration should be restarted either by
    repostioning the offset to 0 by lseek() or by
    closing the file descriptor and opening the directory again. On error, a
    value of -1 is returned and errno is set to indicate
    the error.
When iterating all entries in a directory,
    getattrlistbulk() is called repeatedly until a 0 is
    returned. In such a case if readdir() and
    getattrlistbulk() calls on the same fd are mixed,
    the behavior is undefined.
getattrlistbulk() will fail if:
EBADF]ENOTDIR]EACCES]EFAULT]ERANGE]EINVAL]ATTR_BIT_MAP_COUNT.EINVAL]EINVAL]EINVAL]ATTR_CMN_NAME
      or ATTR_CMN_RETURNED_ATTRS was not requested in
      the attrList parameter.EIO]The following code lists the contents of a directory using
    getattrlistbulk(). The listing includes the file
    type.
#include <sys/syscall.h>
#include <sys/attr.h>
#include <sys/errno.h>
#include <sys/vnode.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <assert.h>
#include <stddef.h>
#include <string.h>
#include <stdbool.h>
typedef struct val_attrs {
    uint32_t          length;
    attribute_set_t   returned;
    uint32_t          error;
    attrreference_t   name_info;
    char              *name;
    fsobj_type_t      obj_type;
} val_attrs_t;
void demo(const char *dirpath)
{
    int error;
    int dirfd;
    struct attrlist attrList;
    char *entry_start;
    char attrBuf[256];
    memset(&attrList, 0, sizeof(attrList));
    attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
    attrList.commonattr  = ATTR_CMN_RETURNED_ATTRS |
                           ATTR_CMN_NAME |
                           ATTR_CMN_ERROR |
                           ATTR_CMN_OBJTYPE;
    error = 0;
    dirfd = open(dirpath, O_RDONLY, 0);
    if (dirfd < 0) {
        error = errno;
        printf("Could not open directory %s", dirpath);
        perror("Error was ");
    } else {
        for (;;) {
            int retcount;
            retcount = getattrlistbulk(dirfd, &attrList, &attrBuf[0],
                               sizeof(attrBuf), 0);
            printf("\ngetattrlistbulk returned %d", retcount);
            if (retcount == -1) {
                error = errno;
                perror("Error returned : ");
                printf("\n");
                break;
            } else if (retcount == 0) {
                /* No more entries in directory */
                error = 0;
                break;
            } else {
                int    index;
                uint32_t total_length;
                char   *field;
                entry_start = &attrBuf[0];
                total_length = 0;
                printf(" -> entries returned");
                for (index = 0; index < retcount; index++) {
                    val_attrs_t    attrs = {0};
                    printf("\n Entry %d", index);
                    printf("  --  ");
                    field = entry_start;
                    attrs.length = *(uint32_t *)field;
                    printf(" Length %d ", attrs.length);
                    total_length += attrs.length;
                    printf(" Total Length %d ", total_length);
                    field += sizeof(uint32_t);
                    printf("  --  ");
                    /* set starting point for next entry */
                    entry_start += attrs.length;
                    attrs.returned = *(attribute_set_t *)field;
                    field += sizeof(attribute_set_t);
                    if (attrs.returned.commonattr & ATTR_CMN_ERROR) {
                        attrs.error = *(uint32_t *)field;
                        field += sizeof(uint32_t);
                    }
                    if (attrs.returned.commonattr & ATTR_CMN_NAME) {
                        attrs.name =  field;
                        attrs.name_info = *(attrreference_t *)field;
                        field += sizeof(attrreference_t);
                        printf("  %s ", (attrs.name +
                            attrs.name_info.attr_dataoffset));
                    }
                    /* Check for error for this entry */
                    if (attrs.error) {
                        /*
                         * Print error and move on to next
                         * entry
                         */
                        printf("Error in reading attributes for directory                                entry %d", attrs.error);
                        continue;
                    }
                    printf("  --  ");
                    if (attrs.returned.commonattr & ATTR_CMN_OBJTYPE) {
                        attrs.obj_type = *(fsobj_type_t *)field;
                        field += sizeof(fsobj_type_t);
                        switch (attrs.obj_type) {
                            case VREG:
                                printf("file  ");
                                break;
                            case VDIR:
                                printf("directory    ");
                                break;
                            default:
                                printf("obj_type = %-2d  ", attrs.obj_type);
                                break;
                        }
                    }
                    printf("  --  ");
                }
            }
        }
        (void)close(dirfd);
    }
}
A getattrlistbulk() function call appeared
    in OS X version 10.10
| November 15, 2013 | Darwin |