1%%	options
2
3copyright owner	=	Dirk Krause
4copyright year	=	2015-xxxx
5SPDX-License-Identifier:	BSD-3-Clause
6
7
8
9%%	header
10
11/**	@file
12	Directory traversal using dkChar file names.
13
14	CRT on Windows: Optional.
15*/
16
17
18#ifndef DK4CONF_H_INCLUDED
19#if DK4_BUILDING_DKTOOLS4
20#include "dk4conf.h"
21#else
22#include <dktools-4/dk4conf.h>
23#endif
24#endif
25
26#ifndef DK4TYPES_H_INCLUDED
27#if DK4_BUILDING_DKTOOLS4
28#include <libdk4base/dk4types.h>
29#else
30#include <dktools-4/dk4types.h>
31#endif
32#endif
33
34#ifndef DK4ERROR_H_INCLUDED
35#if DK4_BUILDING_DKTOOLS4
36#include <libdk4base/dk4error.h>
37#else
38#include <dktools-4/dk4error.h>
39#endif
40#endif
41
42#if DK4_CHAR_SIZE > 1
43#ifndef DK4DIRWC_H_INCLUDED
44#if DK4_BUILDING_DKTOOLS4
45#include <libdk4c/dk4dirwc.h>
46#else
47#include <dktools-4/dk4dirwc.h>
48#endif
49#endif
50#else
51#ifndef DK4DIR08_H_INCLUDED
52#if DK4_BUILDING_DKTOOLS4
53#include <libdk4c/dk4dir08.h>
54#else
55#include <dktools-4/dk4dir08.h>
56#endif
57#endif
58#endif
59
60#if DK4_CHAR_SIZE > 1
61/**	Directory listing.
62*/
63typedef	dk4_dir_wc_t	dk4_dir_t;
64#else
65/**	Directory listing.
66*/
67typedef	dk4_dir_c8_t	dk4_dir_t;
68#endif
69
70#ifdef __cplusplus
71extern "C" {
72#endif
73
74/**	Open directory, create directory structure.
75	@param	path	Directory path name.
76	@param	om	Opening mode.
77	@param	erp	Error report, may be NULL.
78	@return	Pointer to new directory structure on success, NULL on error.
79	On success use dk4dir_close() to destroy the directory
80	structure.
81
82	Error codes:
83	- DK4_E_INVALID_ARGUMENTS<br>
84	  if path is NULL,
85	- DK4_E_NOT_SUPPORTED<br>
86	  if no function to traverse directories was found during build process,
87	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
88	  if a memory allocation failed,
89	- DK4_E_MATH_OVERFLOW<br>
90	  if a mathematical overflow occured in a size calculation,
91	- DK4_E_BUFFER_TOO_SMALL<br>
92	  if one of the involved directory or file names is too long for an
93	  internal buffer,
94	- DK4_E_OPENDIR_FAILED<br>
95	  with errno value in iDetails1 if the attempt to open the directory
96	  failed,
97	- DK4_E_FINDFIRSTFILE_FAILED<br>
98	  with GetLastError() value in lDetails1 if the FindFirstFile()
99	  function failed on Windows,
100	- DK4_E_SYSTEM<br>
101	  if the stat() or lstat() function failed for one of the directory
102	  items.
103*/
104dk4_dir_t *
105dk4dir_open(const dkChar *path, int om, dk4_er_t *erp);
106
107/**	Destroy directory structure.
108	@param	dptr	Structure to destroy.
109*/
110void
111dk4dir_close(dk4_dir_t *dptr);
112
113/**	Reset directory traversal.
114	@param	dptr	Directory structure.
115*/
116void
117dk4dir_reset(dk4_dir_t *dptr);
118
119/**	Retrieve directory path.
120	@param	dptr	Directory structure.
121	@return	Directory path on success,
122		NULL on error or if no directory was specified for a
123		file name expansion.
124*/
125const dkChar *
126dk4dir_get_path(dk4_dir_t const *dptr);
127
128/**	Retrieve next directory name.
129	@param	dptr	Directory structure.
130	@return	Pointer to short name on success, NULL if there are no
131	more directories.
132*/
133const dkChar *
134dk4dir_next_dir(dk4_dir_t *dptr);
135
136/**	Retrieve next file (non-directory) name.
137	@param	dptr	Directory structure.
138	@return	Pointer to short name on success, NULL if there are no more
139	files.
140*/
141const dkChar *
142dk4dir_next_file(dk4_dir_t *dptr);
143
144/**	Skip files (remove information about files, release memory).
145	@param	dptr	Directory structure.
146*/
147void
148dk4dir_skip_files(dk4_dir_t *dptr);
149
150/**	Get maximum entry name length.
151	@param	dptr	Directory.
152	@return	Maximum name length.
153*/
154size_t
155dk4dir_get_max_entry_length(dk4_dir_t const *dptr);
156
157/**	Create full path name for short file name in existing buffer.
158	@param	buffer	Result buffer.
159	@param	szbuf	Size of result buffer (number of dkChar).
160	@param	pdir	Directory fn was obtained from.
161	@param	fn	Short file or directory name.
162	@param	erp	Error report, may be NULL.
163	@return	1 on success, 0 on error.
164
165	Error codes:
166	- DK4_E_INVALID_ARGUMENTS<br>
167	  if buffer, pdir or fn is NULL or szbuf is 0,
168	- DK4_E_BUFFER_TOO_SMALL<br>
169	  if the buffer is too small.
170*/
171int
172dk4dir_full_name_buffer(
173  dkChar		*buffer,
174  size_t		 szbuf,
175  dk4_dir_t	const	*pdir,
176  dkChar	const	*fn,
177  dk4_er_t		*erp
178);
179
180/**	Create full path name for short file name in newly allocated buffer.
181	@param	pdir	Directory fn was obtained from.
182	@param	fn	Short file or directory name.
183	@param	erp	Error report, may be NULL.
184	@return	Valid pointer to newly allocated buffer on success,
185	NULL on error.
186	On success use dk4mem_free() to release the memory when done with
187	the name.
188
189	Error codes:
190	- DK4_E_INVALID_ARGUMENTS<br>
191	  if pdir or fn is NULL,
192	- DK4_E_MATH_OVERFLOW<br>
193	  if the size calculation results in a numeric overflow.
194	- DK4_E_MEMORY_ALLOCATION_FAILED<br>
195	  if the memory allocation failed,
196	- DK4_E_BUFFER_TOO_SMALL<br>
197	  if the buffer is too small.
198*/
199dkChar *
200dk4dir_full_name_new(
201  dk4_dir_t	const	*pdir,
202  dkChar	const	*fn,
203  dk4_er_t		*erp
204);
205
206#ifdef __cplusplus
207}
208#endif
209
210/**	Open modes for directories.
211*/
212enum {
213
214  /* Value definitions */
215				/**	Sort file names.
216				*/
217  DK4_DIR_OPEN_SORTED		=	1,
218
219				/**	Treat symbolic links pointing to
220					directories as files.
221				*/
222  DK4_DIR_SYMLINK_DIR_AS_FILE	=	2,
223
224  /* Default modes for special purposes */
225
226				/**	For deltree we do not follow
227					symbolic links, no need for sorting.
228				*/
229  DK4_DIR_OPEN_DELTREE		=	DK4_DIR_SYMLINK_DIR_AS_FILE
230};
231
232
233
234%%	module
235
236#include "dk4conf.h"
237#include <libdk4c/dk4dir.h>
238#if DK4_CHAR_SIZE > 1
239#include <libdk4c/dk4dirwc.h>
240#else
241#include <libdk4c/dk4dir08.h>
242#endif
243
244#if	DK4_HAVE_ASSERT_H
245#ifndef	ASSERT_H_INCLUDED
246#include <assert.h>
247#define	ASSERT_H_INCLUDED 1
248#endif
249#endif
250
251
252dk4_dir_t *
253dk4dir_open(const dkChar *path, int om, dk4_er_t *erp)
254{
255#if	DK4_USE_ASSERT
256  assert(NULL != path);
257#endif
258#if DK4_CHAR_SIZE > 1
259  return (dk4dir_wc_open(path, om, erp));
260#else
261  return (dk4dir_c8_open(path, om, erp));
262#endif
263}
264
265
266
267void
268dk4dir_close(dk4_dir_t *dptr)
269{
270#if	DK4_USE_ASSERT
271  assert(NULL != dptr);
272#endif
273#if DK4_CHAR_SIZE > 1
274  dk4dir_wc_close(dptr);
275#else
276  dk4dir_c8_close(dptr);
277#endif
278}
279
280
281
282void
283dk4dir_reset(dk4_dir_t *dptr)
284{
285#if	DK4_USE_ASSERT
286  assert(NULL != dptr);
287#endif
288#if DK4_CHAR_SIZE > 1
289  dk4dir_wc_reset(dptr);
290#else
291  dk4dir_c8_reset(dptr);
292#endif
293}
294
295
296
297const dkChar *
298dk4dir_get_path(dk4_dir_t const *dptr)
299{
300#if	DK4_USE_ASSERT
301  assert(NULL != dptr);
302#endif
303#if DK4_CHAR_SIZE > 1
304  return (dk4dir_wc_get_path(dptr));
305#else
306  return (dk4dir_c8_get_path(dptr));
307#endif
308}
309
310
311
312const dkChar *
313dk4dir_next_dir(dk4_dir_t *dptr)
314{
315#if	DK4_USE_ASSERT
316  assert(NULL != dptr);
317#endif
318#if DK4_CHAR_SIZE > 1
319  return (dk4dir_wc_next_dir(dptr));
320#else
321  return (dk4dir_c8_next_dir(dptr));
322#endif
323}
324
325
326
327const dkChar *
328dk4dir_next_file(dk4_dir_t *dptr)
329{
330#if	DK4_USE_ASSERT
331  assert(NULL != dptr);
332#endif
333#if DK4_CHAR_SIZE > 1
334  return (dk4dir_wc_next_file(dptr));
335#else
336  return (dk4dir_c8_next_file(dptr));
337#endif
338}
339
340
341
342
343void
344dk4dir_skip_files(dk4_dir_t *dptr)
345{
346#if	DK4_USE_ASSERT
347  assert(NULL != dptr);
348#endif
349#if DK4_CHAR_SIZE > 1
350  dk4dir_wc_skip_files(dptr);
351#else
352  dk4dir_c8_skip_files(dptr);
353#endif
354}
355
356
357
358size_t
359dk4dir_get_max_entry_length(dk4_dir_t const *dptr)
360{
361#if	DK4_USE_ASSERT
362  assert(NULL != dptr);
363#endif
364#if DK4_CHAR_SIZE > 1
365  return (dk4dir_wc_get_max_entry_length(dptr));
366#else
367  return (dk4dir_c8_get_max_entry_length(dptr));
368#endif
369}
370
371
372
373int
374dk4dir_full_name_buffer(
375  dkChar		*buffer,
376  size_t		 szbuf,
377  dk4_dir_t	const	*pdir,
378  dkChar	const	*fn,
379  dk4_er_t		*erp
380)
381{
382#if	DK4_USE_ASSERT
383  assert(NULL != pdir);
384  assert(NULL != fn);
385  assert(NULL != buffer);
386  assert(0 < szbuf);
387#endif
388#if	DK4_CHAR_SIZE > 1
389  return (
390    dk4dir_wc_full_name_buffer(buffer, szbuf, pdir, fn, erp)
391  );
392#else
393  return (
394    dk4dir_c8_full_name_buffer(buffer, szbuf, pdir, fn, erp)
395  );
396#endif
397}
398
399
400
401dkChar *
402dk4dir_full_name_new(
403  dk4_dir_t	const	*pdir,
404  dkChar	const	*fn,
405  dk4_er_t		*erp
406)
407{
408#if	DK4_USE_ASSERT
409  assert(NULL != pdir);
410  assert(NULL != fn);
411#endif
412#if	DK4_CHAR_SIZE > 1
413  return (
414    dk4dir_wc_full_name_new(pdir, fn, erp)
415  );
416#else
417  return (
418    dk4dir_c8_full_name_new(pdir, fn, erp)
419  );
420#endif
421}
422
423
424
425