xref: /xnu-12377.61.12/bsd/man/man2/getdirentriesattr.2 (revision 4d495c6e23c53686cf65f45067f79024cf5dcee8)
1q.\" Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
2.\"
3.\" The contents of this file constitute Original Code as defined in and
4.\" are subject to the Apple Public Source License Version 1.1 (the
5.\" "License").  You may not use this file except in compliance with the
6.\" License.  Please obtain a copy of the License at
7.\" http://www.apple.com/publicsource and read it before using this file.
8.\"
9.\" This Original Code and all software distributed under the License are
10.\" distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
11.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
12.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
13.\" FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
14.\" License for the specific language governing rights and limitations
15.\" under the License.
16.\"
17.\"     @(#)getdirentriesattr.2
18.
19.Dd December 15, 2003
20.Dt GETDIRENTRIESATTR 2
21.Os Darwin
22.Sh NAME
23.Nm getdirentriesattr(NOW DEPRECATED)
24.Nd get file system attributes for multiple directory entries
25.Sh SYNOPSIS
26.Fd #include <sys/attr.h>
27.Fd #include <unistd.h>
28.Pp
29.Fd #if __LP64__
30.Ft int
31.Fn getdirentriesattr "int fd" "struct attrlist * attrList" "void * attrBuf" "size_t attrBufSize" "unsigned int * count" "unsigned int * basep" "unsigned int * newState" "unsigned int options"
32.Fd #else
33.Ft int
34.Fn getdirentriesattr "int fd" "struct attrlist * attrList" "void * attrBuf" "size_t attrBufSize" "unsigned long * count" "unsigned long * basep" "unsigned long * newState" "unsigned long options"
35.Fd #endif
36.
37.
38.Sh DESCRIPTION
39The
40.Fn getdirentriesattr
41function reads directory entries and returns their attributes (that is, metadata).
42You can think of it as a combination of
43.Xr getdirentries 2
44and
45.Xr getattrlist 2 .
46.Fn getdirentriesattr
47iterates over the items in a directory like
48.Xr getdirentries 2 ,
49and returns information about each directory entry like
50.Xr getattrlist 2 .
51Note: when
52.Fn getdirentriesattr
53returns information about a symbolic link, the information returned is about the link itself, not the target of the link.
54.Pp
55The function reads directory entries from the directory referenced by the
56file descriptor
57.Fa fd .
58Attributes of those directory entries are placed into the buffer specified by
59.Fa attrBuf
60and
61.Fa attrBufSize .
62The
63.Fa attrList
64parameter determines what attributes are returned for each entry.
65The
66.Fa count
67parameter contains the number of directory entries requested and returned.
68The
69.Fa basep
70parameter returns the directory offset in a manner similar to
71.Xr getdirentries 2 .
72The
73.Fa newState
74parameter allows you to check whether the directory has been modified while
75you were reading it.
76The
77.Fa options
78parameter lets you control specific aspects of the function's behaviour.
79.Pp
80.
81The
82.Fn getdirentriesattr
83function is only supported by certain volume format implementations.
84For maximum compatibility, client programs should use high-level APIs
85(such as the Carbon File Manager) to access file system attributes.
86These high-level APIs include logic to emulate file system attributes
87on volumes that don't support
88.Fn getdirentriesattr .
89.Pp
90.
91.\" fd parameter
92.
93The
94.Fa fd
95parameter must be a file descriptor that references a directory that you have opened for reading.
96.Pp
97.
98.\" attrList parameter
99.
100The
101.Fa attrList
102parameter is a pointer to an
103.Vt attrlist
104structure.
105You are responsible for filling out all fields of this structure before calling the function.
106See the discussion of the
107.Xr getattrlist 2
108function for a detailed description of this structure.
109To get an attribute you must set the corresponding bit in the appropriate
110.Vt attrgroup_t
111field of the
112.Vt attrlist
113structure.
114You must not request volume attributes.
115.Pp
116.
117.\" attrBuf and attrBufSize parameters
118.
119The
120.Fa attrBuf
121and
122.Fa attrBufSize
123parameters specify a buffer into which the function places attribute values.
124The attributes for any given directory entry are grouped together and
125packed in exactly the same way as they are returned from
126.Xr getattrlist 2 .
127These groups are then placed into the buffer, one after another.
128As each group starts with a leading
129.Vt u_int32_t
130that contains the
131overall length of the group, you can step from one group to the next
132by simply adding this length to your pointer.
133The sample code (below) shows how to do this.
134The initial contents of this buffer are ignored.
135.Pp
136.
137.\" count parameter
138.
139The
140.Fa count
141parameter points to an
142.Vt unsigned long
143or
144.Vt unsigned int
145variable.
146You should initialise this variable to be the number of directory entries for which
147you wish to get attributes.
148On return, this variable contains the number of directory entries whose attributes
149have been placed into the attribute buffer.
150This may be smaller than the number that you requested.
151.Pp
152.
153.\" basep parameter
154The
155.Fa basep
156parameter returns the offset of the last directory entry read, in a
157manner identical to
158.Xr getdirentries 2 .
159You can use this value to reset a directory iteration to a known position
160using
161.Xr lseek 2 .
162However, since the variable is too small to hold an
163.Vt off_t ,
164you should use
165.Xr lseek 2
166to get the directory's current position instead of using this parameter.
167The initial value of the variable is ignored.
168.Pp
169.
170.\" newState parameter
171.
172The
173.Fa newState
174parameter returns a value that changes if the directory has been modified.
175If you're iterating through the directory by making repeated calls to
176.Fn getdirentriesattr ,
177you can compare subsequent values of
178.Fa newState
179to determine whether the directory has been modified (and thus restart
180your iteration at the beginning).
181The initial value of the variable is ignored.
182.Pp
183.
184.\" options parameter
185.
186The
187.Fa options
188parameter is a bit set that controls the behaviour of
189.Fn getdirentriesattr .
190The following option bits are defined.
191.
192.Bl -tag -width FSOPT_NOINMEMUPDATE
193.
194.It FSOPT_NOINMEMUPDATE
195This tells
196.Fn getdirentriesattr
197to return the directory entries from disk rather than taking the extra step of looking
198at data structures in-memory which may contain changes that haven't been flushed to disk.
199.Pp
200This option allowed for specific performance optimizations for specific clients on older systems.
201We currently recommend that clients not set this option and that file system
202implementations ignore it.
203.
204.El
205.Pp
206It is typical to ask for a combination of common, file, and directory
207attributes and then use the value of the
208.Dv ATTR_CMN_OBJTYPE
209attribute to parse the resulting attribute buffer.
210.Sh NOTES
211As of Mac OS X 10.10,
212.Fn getdirentriesattr
213is deprecated. It is replaced by
214.Nm getattrlistbulk(2).
215Continued use of
216.Fn getdirentriesattr
217is strongly discouraged as comprehensive results are not guaranteed.
218.Sh RETURN VALUES
219Upon successful completion a value of 0 or 1 is returned.
220The value 0 indicates that the routine completed successfully.
221The value 1 indicates that the routine completed successfully and has
222returned the last entry in the directory.
223On error, a value of -1 is returned and
224.Va errno
225is set to indicate the error.
226.
227.Sh COMPATIBILITY
228Not all volumes support
229.Fn getdirentriesattr .
230You can test whether a volume supports
231.Fn getdirentriesattr
232by using
233.Xr getattrlist 2
234to get the volume capabilities attribute
235.Dv ATTR_VOL_CAPABILITIES ,
236and then testing the
237.Dv VOL_CAP_INT_READDIRATTR
238flag.
239.Pp
240.
241The
242.Fn getdirentriesattr
243function has been undocumented for more than two years.
244In that time a number of volume format implementations have been created without
245a proper specification for the behaviour of this routine.
246You may encounter volume format implementations with slightly different
247behaviour than what is described here.
248Your program is expected to be tolerant of this variant behaviour.
249.Pp
250.
251If you're implementing a volume format that supports
252.Fn getdirentriesattr ,
253you should be careful to support the behaviour specified by this document.
254.
255.Pp
256If the directory contains a mount point, then
257.Dq DIR_MNTSTATUS_MNTPOINT
258will be set in the
259.Dv ATTR_DIR_MOUNTSTATUS
260for that entry; all other attributes for that entry, however,
261will be for the underlying file system (as opposed to the mounted
262file system).
263.Xr getattrlist 2
264should be used to get the attributes for the mount point.
265.Pp
266A directory which is a firmlink will have the
267.Dq SF_FIRMLINK
268flag set in its
269ATTR_CMN_FLAGS attribute entry.
270However the attributes returned by
271.Fn getdirentriesattr
272will be those from the firmlink, not the firmlink's target.
273To get the attributes of the firmlink's target, call
274.Xr getattrlist 2
275on the firmlink.
276.Sh ERRORS
277.Fn getdirentriesattr
278will fail if:
279.Bl -tag -width Er
280.
281.It Bq Er ENOTSUP
282The volume does not support
283.Fn getdirentriesattr .
284.
285.It Bq Er EBADF
286.Fa fd
287is not a valid file descriptor for a directory open for reading.
288.
289.It Bq Er EFAULT
290.Fa attrList
291or
292.Em attrBuf
293points to an invalid address.
294.
295.It Bq Er EINVAL
296The
297.Fa bitmapcount
298field of
299.Fa attrList
300is not
301.Dv ATTR_BIT_MAP_COUNT .
302.
303.It Bq Er EINVAL
304You requested an invalid attribute.
305.
306.It Bq Er EINVAL
307You requested volume attributes.
308.
309.It Bq Er EINVAL
310The
311.Fa options
312parameter contains an invalid flag.
313.
314.It Bq Er EIO
315An I/O error occurred while reading from or writing to the file system.
316.El
317.Pp
318.
319.Sh EXAMPLES
320.
321The following code lists the contents of a directory using
322.Fn getdirentriesattr .
323The listing includes the file type and creator for files.
324.
325.Bd -literal
326#include <assert.h>
327#include <stdio.h>
328#include <stddef.h>
329#include <string.h>
330#include <sys/attr.h>
331#include <sys/errno.h>
332#include <unistd.h>
333#include <sys/vnode.h>
334#include <stdbool.h>
335#include <fcntl.h>
336.Pp
337.
338typedef struct attrlist attrlist_t;
339.Pp
340.
341struct FInfoAttrBuf {
342    u_int32_t       length;
343    attrreference_t name;
344    fsobj_type_t    objType;
345    char            finderInfo[32];
346    u_int32_t       dirStatus;
347} __attribute__((aligned(4), packed));
348typedef struct FInfoAttrBuf FInfoAttrBuf;
349.Pp
350.
351enum {
352    kEntriesPerCall = 10
353};
354.Pp
355.
356static int FInfoDemo(const char *dirPath)
357{
358    int             err;
359    int             junk;
360    int             dirFD;
361    attrlist_t      attrList;
362#ifdef __LP64__
363    unsigned int    index;
364    unsigned int    count;
365    unsigned int    junkBaseP;
366    unsigned int    oldState;
367    unsigned int    newState;
368#else
369    unsigned long   index;
370    unsigned long   count;
371    unsigned long   junkBaseP;
372    unsigned long   oldState;
373    unsigned long   newState;
374#endif
375    bool            oldStateValid;
376    bool            done;
377    FInfoAttrBuf *  thisEntry;
378    char            attrBuf[kEntriesPerCall * (sizeof(FInfoAttrBuf) + 64)];
379.Pp
380.
381    // attrBuf is big enough for kEntriesPerCall entries, assuming that
382    // the average name length is less than 64.
383.Pp
384.
385    memset(&attrList, 0, sizeof(attrList));
386    attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
387    attrList.commonattr  =    ATTR_CMN_NAME
388                            | ATTR_CMN_OBJTYPE
389                            | ATTR_CMN_FNDRINFO;
390    attrList.dirattr     = ATTR_DIR_MOUNTSTATUS;
391.Pp
392
393    err = 0;
394    dirFD = open(dirPath, O_RDONLY, 0);
395    if (dirFD < 0) {
396        err = errno;
397    }
398    if (err == 0) {
399        oldStateValid = false;
400        done = false;
401        do {
402            count = kEntriesPerCall;
403.Pp
404            err = getdirentriesattr(
405                dirFD,
406                &attrList,
407                &attrBuf,
408                sizeof(attrBuf),
409                &count,
410                &junkBaseP,
411                &newState,
412                0
413            );
414            if (err < 0) {
415                err = errno;
416            } else {
417                done = err;
418                err = 0;
419            }
420.Pp
421            if (err == 0) {
422                if (oldStateValid) {
423                    if (newState != oldState) {
424                        printf("*** Directory has changed\en");
425                        oldState = newState;
426                    }
427                } else {
428                    oldState = newState;
429                    oldStateValid = true;
430                }
431.Pp
432                thisEntry = (FInfoAttrBuf *) attrBuf;
433.Pp
434                for (index = 0; index < count; index++) {
435                    switch (thisEntry->objType) {
436                        case VREG:
437                            printf(
438                                "'%4.4s' '%4.4s' ",
439                                &thisEntry->finderInfo[0],
440                                &thisEntry->finderInfo[4]
441                            );
442                            break;
443                        case VDIR:
444                            if (thisEntry->dirStatus & DIR_MNTSTATUS_MNTPOINT)
445                                printf("mount-point   ");
446                            else
447                                printf("directory     ");
448                            break;
449                        default:
450                            printf(
451                                "objType = %-2d  ",
452                                thisEntry->objType
453                            );
454                            break;
455                    }
456                    printf(
457                        "%s\en",
458                        ((char *) &thisEntry->name)
459                            + thisEntry->name.attr_dataoffset
460                    );
461.Pp
462                    // Advance to the next entry.
463.Pp
464                    thisEntry = (FInfoAttrBuf*)((char*)thisEntry + thisEntry->length);
465                }
466            }
467        } while ( err == 0 && ! done );
468    }
469.Pp
470    if (dirFD != -1) {
471        junk = close(dirFD);
472        assert(junk == 0);
473    }
474.Pp
475    return err;
476}
477.Ed
478.Pp
479.
480.Sh SEE ALSO
481.
482.Xr getattrlist 2 ,
483.Xr getdirentries 2 ,
484.Xr lseek 2
485.
486.Sh HISTORY
487A
488.Fn getdirentriesattr
489function call appeared in Darwin 1.3.1 (Mac OS X version 10.0).
490.
491