NAME
getattrlistbulk
—
get file system attributes for multiple
directory entries
SYNOPSIS
#include
<sys/attr.h>
#include <unistd.h>
int
getattrlistbulk
(int
dirfd, struct attrlist *
attrList, void *
attrBuf, size_t
attrBufSize, uint64_t
options);
DESCRIPTION
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.
- FSOPT_PACK_INVAL_ATTRS
- If this is bit is set, then all requested attributes, even ones that are
not supported by the object or file file system, will be returned the
attrBuf. The attributes actually returned can be determined by looking at
the attribute_set_t structure returned for the
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.
RETURN VALUES
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.
ERRORS
getattrlistbulk
() will fail if:
- [
EBADF
] - dirfd is not a valid file descriptor for a directory open for reading.
- [
ENOTDIR
] - The File descriptor dirfd is not a directory.
- [
EACCES
] - Search permission is denied on the directory whose descriptor is given as input.
- [
EFAULT
] - attrList or attrBuf points to an invalid address.
- [
ERANGE
] - The buffer was too small.
- [
EINVAL
] - The bitmapcount field of
attrList is not
ATTR_BIT_MAP_COUNT
. - [
EINVAL
] - An invalid attribute was requested.
- [
EINVAL
] - Volume attributes were requested.
- [
EINVAL
] ATTR_CMN_NAME
orATTR_CMN_RETURNED_ATTRS
was not requested in the attrList parameter.- [
EIO
] - An I/O error occurred while reading from or writing to the file system.
EXAMPLES
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); } }
SEE ALSO
HISTORY
A getattrlistbulk
() function call appeared
in OS X version 10.10