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 |