2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
5 Desc: Examine a directory.
8 #include <exec/memory.h>
9 #include <proto/exec.h>
10 #include <dos/exall.h>
12 #include "dos_intern.h"
13 #include <aros/asmcall.h>
14 #include <aros/debug.h>
16 /*****************************************************************************
19 #include <proto/dos.h>
24 AROS_LHA(BPTR
, lock
, D1
),
25 AROS_LHA(struct ExAllData
*, buffer
, D2
),
26 AROS_LHA(LONG
, size
, D3
),
27 AROS_LHA(LONG
, data
, D4
),
28 AROS_LHA(struct ExAllControl
*, control
, D5
),
31 struct DosLibrary
*, DOSBase
, 72, Dos
)
34 Examine an entire directory.
37 lock - lock on the directory to be examined
38 buffer - buffer for the data that is returned (must be aligned)
39 which is filled with (partial) ExAllData structures
41 size - size of 'buffer' in bytes
42 data - type of the data to be returned
43 control - a control structure allocated by AllocDosObject()
46 An indicator of whether ExAll() is finished. If FALSE is returned,
47 either ExAll() has completed, in which case IoErr() is
48 ERROR_NO_MORE_ENTRIES, or an error occurred. If a non-zero value is
49 returned, ExAll() must be called again until it returns FALSE.
52 The following information is essential information in the ExAllData
59 ED_SIZE - size in bytes
60 ED_PROTECTION - protection bits
61 ED_DATE - date information (3 longwords)
62 ED_COMMENT - file comment (NULL if no comment exists)
63 ED_OWNER - owner user and group id
65 This is an incremental list, meaning that if you specify ED_OWNER
66 you will get ALL attributes!
68 Filesystems that support ExAll() must support at least up to
69 ED_COMMENT. If a filesystem doesn't support a particular type,
70 ERROR_BAD_NUMBER must be returned.
72 ed_Next: pointer to the next entry in the buffer. The last entry
73 has a NULL value for ed_Next.
75 The control structure have the following fields:
77 eac_Entries: the number of entries in the buffer after a call to
78 ExAll(). Make sure that your code handles the case when
79 eac_Entries is 0 and ExAll() returns TRUE.
81 eac_LastKey: must be initialized to 0 before calling ExAll() for the
84 eac_MatchString: if NULL then information on all files will be returned.
85 If non-NULL it's interpreted as a pointer to a string
86 used for pattern matching which files to return
87 information on. This string must have been parsed by
90 eac_MatchFunc: pointer to a hook that will be called to decide if an
91 entry should be included in the buffer. If NULL, no
92 matching function will be called. The hook is called as
95 BOOL = MatchFunc(hook, data, typeptr)
102 Examine(), ExNext(), MatchPatternNoCase(), ParsePatternNoCase(),
103 AllocDosObject(), ExAllEnd()
107 *****************************************************************************/
111 /* Get pointer to filehandle */
112 struct FileLock
*fl
= BADDR(lock
);
116 /* If fib != NULL it means we've already been called and found out that
117 we needed to emulate ExAll, thus don't waste time sending messages to the
119 if (((struct InternalExAllControl
*)control
)->fib
!= NULL
)
121 err
= ERROR_ACTION_NOT_KNOWN
;
125 status
= dopacket5(DOSBase
, &err
, fl
->fl_Task
, ACTION_EXAMINE_ALL
, (SIPTR
)lock
, (IPTR
)buffer
, (IPTR
)size
, (IPTR
)data
, (IPTR
)control
);
126 if (status
!= DOSFALSE
)
132 err
== ERROR_NOT_IMPLEMENTED
||
133 err
== ERROR_ACTION_NOT_KNOWN
136 /* Try to emulate it */
137 STRPTR end
= (STRPTR
)buffer
+ size
;
140 struct ExAllData
*last
= buffer
, *curr
= buffer
;
142 struct InternalExAllControl
*icontrol
= (struct InternalExAllControl
*)control
;
144 static const ULONG sizes
[]=
147 offsetof(struct ExAllData
,ed_Type
),
148 offsetof(struct ExAllData
,ed_Size
),
149 offsetof(struct ExAllData
,ed_Prot
),
150 offsetof(struct ExAllData
,ed_Days
),
151 offsetof(struct ExAllData
,ed_Comment
),
152 offsetof(struct ExAllData
,ed_OwnerUID
),
153 sizeof(struct ExAllData
)
156 /* Reset the 'fake' error */
159 /* Allocate the FIB structure, if not allocated yet. It will be deallocated
160 by DeleteDosObject(). */
163 icontrol
->fib
= AllocDosObject(DOS_FIB
, NULL
);
171 /* No entries found as of now yet. */
172 control
->eac_Entries
= 0;
174 /* If LastKey == 0 it means this is the first time we're getting called,
175 in which case we need to initialize the FIB structure and a few other things.
176 A "nice" side effect of this, is that if one wants to restart the scanning,
177 he/she just has to set LastKey to 0. */
178 if (control
->eac_LastKey
== 0)
180 if (!Examine(lock
, icontrol
->fib
))
185 if (icontrol
->fib
->fib_DirEntryType
<= 0)
187 err
= ERROR_OBJECT_WRONG_TYPE
;
192 /* Macro used when the data doesn't fit in the provided buffer.
193 In case not even one element fit in the buffer, return a buffer
194 overflow error, so that the user knows he/she has to increase the
196 #define ReturnOverflow() \
199 err = ERROR_BUFFER_OVERFLOW; \
201 icontrol->fib->fib_DiskKey = control->eac_LastKey; \
205 /* Copy a string pointer by _source into the buffer provided
206 to the ExAll function. This macro gracefully handles buffer
208 #define CopyStringSafe(_source) \
210 STRPTR source = _source; \
216 if (!(*next++ = *source++)) \
223 /* We don't have that many fields to fill in... */
224 err
= ERROR_BAD_NUMBER
;
229 ExNext(lock
, icontrol
->fib
);
230 /* Record the latest DiskKey into LastKey so that we can roll back to it
231 in case of a buffer overflow and when getting called again. */
232 control
->eac_LastKey
= icontrol
->fib
->fib_DiskKey
235 /* Try to match the filename, if required. */
236 if (control
->eac_MatchString
&&
237 !MatchPatternNoCase(control
->eac_MatchString
,
238 icontrol
->fib
->fib_FileName
))
241 next
= (STRPTR
)curr
+ sizes
[data
];
243 /* Oops, the buffer is full. */
247 /* Switch over the requested fields and fill them as appropriate. */
251 curr
->ed_OwnerUID
= icontrol
->fib
->fib_OwnerUID
;
252 curr
->ed_OwnerGID
= icontrol
->fib
->fib_OwnerGID
;
256 curr
->ed_Comment
= next
;
257 CopyStringSafe(icontrol
->fib
->fib_Comment
);
261 curr
->ed_Days
= icontrol
->fib
->fib_Date
.ds_Days
;
262 curr
->ed_Mins
= icontrol
->fib
->fib_Date
.ds_Minute
;
263 curr
->ed_Ticks
= icontrol
->fib
->fib_Date
.ds_Tick
;
267 curr
->ed_Prot
= icontrol
->fib
->fib_Protection
;
271 curr
->ed_Size
= icontrol
->fib
->fib_Size
;
275 curr
->ed_Type
= icontrol
->fib
->fib_DirEntryType
;
279 curr
->ed_Name
= next
;
280 CopyStringSafe(icontrol
->fib
->fib_FileName
);
284 curr
->ed_Next
= (struct ExAllData
*)(((IPTR
)next
+ AROS_PTRALIGN
- 1) & ~(AROS_PTRALIGN
- 1));
287 /* Do some more matching... */
288 if (control
->eac_MatchFunc
&& !CALLHOOKPKT(control
->eac_MatchFunc
, curr
, &data
))
291 /* Finally go to the next entry in the buffer. */
293 curr
= curr
->ed_Next
;
294 control
->eac_Entries
++;
299 /* This is the last one, after it there's nothing. */
300 last
->ed_Next
= NULL
;
303 /* Set error code and return */
305 return (err
== 0) ? DOSTRUE
: DOSFALSE
;