summaryrefslogtreecommitdiff
path: root/support/dktools/dk4dir08.ctr
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/dk4dir08.ctr
Initial commit
Diffstat (limited to 'support/dktools/dk4dir08.ctr')
-rw-r--r--support/dktools/dk4dir08.ctr588
1 files changed, 588 insertions, 0 deletions
diff --git a/support/dktools/dk4dir08.ctr b/support/dktools/dk4dir08.ctr
new file mode 100644
index 0000000000..4759371680
--- /dev/null
+++ b/support/dktools/dk4dir08.ctr
@@ -0,0 +1,588 @@
+%% options
+
+copyright owner = Dirk Krause
+copyright year = 2015-xxxx
+license = bsd
+
+
+
+%% header
+
+/** @file
+ Directory traversal using char file names.
+
+ CRT on Windows: Optional.
+*/
+
+#ifndef DK4CONF_H_INCLUDED
+#include "dk4conf.h"
+#endif
+
+#ifndef DK4TYPES_H_INCLUDED
+#include "dk4types.h"
+#endif
+
+#ifndef DK4ERROR_H_INCLUDED
+#include "dk4error.h"
+#endif
+
+#ifndef DK4STO_H_INCLUDED
+#include "dk4sto.h"
+#endif
+
+
+/** Directory structure.
+*/
+typedef struct {
+ char *path; /**< Directory path. */
+ dk4_sto_t *s_dir; /**< Storage for directories. */
+ dk4_sto_it_t *i_dir; /**< Iterator for directories. */
+ dk4_sto_t *s_file; /**< Storage for non-directories. */
+ dk4_sto_it_t *i_file; /**< Iterator for non-directories. */
+ size_t maxlen; /**< Maximum entry length. */
+} dk4_dir_c8_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Open directory, create directory structure.
+ @param path Directory path name.
+ @param om Opening mode.
+ @param erp Error report, may be NULL.
+ @return Pointer to new directory structure on success, NULL on error.
+ On success use dk4dir_c8_close() to destroy the directory
+ structure.
+
+ Error codes:
+ - DK4_E_INVALID_ARGUMENTS<br>
+ if path is NULL,
+ - DK4_E_NOT_SUPPORTED<br>
+ if no function to traverse directories was found during build process,
+ - DK4_E_MEMORY_ALLOCATION_FAILED<br>
+ if a memory allocation failed,
+ - DK4_E_MATH_OVERFLOW<br>
+ if a mathematical overflow occured in a size calculation,
+ - DK4_E_BUFFER_TOO_SMALL<br>
+ if one of the involved directory or file names is too long for an
+ internal buffer,
+ - DK4_E_OPENDIR_FAILED<br>
+ with errno value in iDetails1 if the attempt to open the directory
+ failed,
+ - DK4_E_FINDFIRSTFILE_FAILED<br>
+ with GetLastError() value in lDetails1 if the FindFirstFile()
+ function failed on Windows,
+ - DK4_E_SYSTEM<br>
+ if the stat() or lstat() function failed for one of the directory
+ items.
+*/
+dk4_dir_c8_t *
+dk4dir_c8_open(const char *path, int om, dk4_er_t *erp);
+
+/** Destroy directory structure.
+ @param dptr Structure to destroy.
+*/
+void
+dk4dir_c8_close(dk4_dir_c8_t *dptr);
+
+/** Reset directory traversal.
+ @param dptr Directory structure.
+*/
+void
+dk4dir_c8_reset(dk4_dir_c8_t *dptr);
+
+/** Retrieve directory path.
+ @param dptr Directory structure.
+ @return Directory path on success,
+ NULL on error or if no directory was specified for a
+ file name expansion.
+*/
+const char *
+dk4dir_c8_get_path(dk4_dir_c8_t *dptr);
+
+/** Retrieve next directory name.
+ @param dptr Directory structure.
+ @return Pointer to short name on success, NULL if there are no
+ more directories.
+*/
+const char *
+dk4dir_c8_next_dir(dk4_dir_c8_t *dptr);
+
+/** Retrieve next file (non-directory) name.
+ @param dptr Directory structure.
+ @return Pointer to short name on success, NULL if there are no more
+ files.
+*/
+const char *
+dk4dir_c8_next_file(dk4_dir_c8_t *dptr);
+
+/** Skip files (remove information about files, release memory).
+ @param dptr Directory structure.
+*/
+void
+dk4dir_c8_skip_files(dk4_dir_c8_t *dptr);
+
+/** Compare two file or directory names.
+ @param l Left name.
+ @param r Right name.
+ @param cr Comparison criteria (ignored).
+ @return 1 if l>r, 0 if l=r, -1 if l<r.
+*/
+int
+dk4dir_c8_compare(const void *l, const void *r, int cr);
+
+/** Get maximum entry name length.
+ @param dptr Directory.
+ @return Maximum name length.
+*/
+size_t
+dk4dir_c8_get_max_entry_length(dk4_dir_c8_t *dptr);
+
+#ifdef __cplusplus
+}
+#endif
+
+%% module
+
+#include "dk4conf.h"
+
+#if DK4_ON_WINDOWS
+#ifndef WINDOWS_H_INCLUDED
+#include <windows.h>
+#define WINDOWS_H_INCLUDED 1
+#endif
+#endif
+
+#include "dk4dir08.h"
+
+#ifndef DK4DIR_H_INCLUDED
+#include "dk4dir.h"
+#endif
+
+#ifndef DK4STR8_H_INCLUDED
+#include "dk4str8.h"
+#endif
+
+#ifndef DK4STAT_H_INCLUDED
+#include "dk4stat.h"
+#endif
+
+#ifndef DK4STAT8_H_INCLUDED
+#include "dk4stat8.h"
+#endif
+
+#ifndef DK4MEM_H_INCLUDED
+#include "dk4mem.h"
+#endif
+
+#ifndef DK4MPL_H_INCLUDED
+#include "dk4mpl.h"
+#endif
+
+#if DK4_HAVE_SYS_TYPES_H
+#ifndef SYS_TYPES_H_INCLUDED
+#include <sys/types.h>
+#define SYS_TYPES_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_DIRENT_H
+#ifndef DIRENT_H_INCLUDED
+#include <dirent.h>
+#define DIRENT_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_ERRNO_H
+#ifndef ERRNO_H_INCLUDED
+#include <errno.h>
+#define ERRNO_H_INCLUDED 1
+#endif
+#endif
+
+
+
+$!trace-include
+
+
+
+int
+dk4dir_c8_compare(const void *l, const void *r, int cr)
+{
+ int back = 0;
+ if (NULL != l) {
+ if (NULL != r) {
+ back = dk4str8_pathcmp((const char *)l, (const char *)r);
+ } else {
+ back = 1;
+ }
+ } else {
+ if (NULL != r) { back = -1; }
+ }
+ return back;
+}
+
+
+
+static
+void
+dk4dir_c8_clean_storage(dk4_sto_t *s, dk4_sto_it_t *i)
+{
+ char *n;
+ if (NULL != s) {
+ if (NULL != i) {
+ dk4sto_it_reset(i);
+ while (NULL != (n = (char *)dk4sto_it_next(i))) {
+ dk4mem_free(n);
+ }
+ dk4sto_it_close(i);
+ }
+ dk4sto_close(s);
+ }
+}
+
+
+
+void
+dk4dir_c8_close(dk4_dir_c8_t *dptr)
+{
+ $? "+ dk4dir_c8_close"
+ if (NULL != dptr) {
+ dk4mem_release(dptr->path);
+ dk4dir_c8_clean_storage(dptr->s_dir, dptr->i_dir);
+ dptr->s_dir = NULL; dptr->i_dir = NULL;
+ dk4dir_c8_clean_storage(dptr->s_file, dptr->i_file);
+ dptr->s_file = NULL; dptr->i_file = NULL;
+ dk4mem_free(dptr);
+ }
+ $? "- dk4dir_c8_close"
+}
+
+
+
+#if DK4_ON_WINDOWS || DK4_HAVE_DIRENT_H
+/** Fixed texts used by the module.
+*/
+static const char * const dk4dir_c8_kw[] = {
+$!string-table
+#
+# 0 Current directory
+#
+.
+#
+# 1 Parent directory
+#
+..
+#
+# 2 Separator for non-Windows systems
+#
+/
+#
+# 3 Separator for Windows systems
+#
+\\
+#
+# 4 Pattern for all files
+#
+*
+$!end
+};
+
+
+
+static
+int
+dk4dir_c8_fill_directory(dk4_dir_c8_t *dptr, int om, dk4_er_t *erp)
+{
+#if DK4_ON_WINDOWS
+ char pab[DK4_MAX_PATH]; /* Pattern buffer */
+ WIN32_FIND_DATAA ffdata; /* Find result */
+ HANDLE ffres; /* Result from FindFirstFile */
+ DWORD attr; /* File attributes */
+ char *nn; /* Copy of name, dyn */
+ size_t slen; /* Entry name length */
+ int isdir; /* Flag: Entry is directory */
+ int back = 0;
+ $? "+ dk4dir_c8_fill_directory"
+ if (dk4str8_cpy_s(pab, sizeof(pab), dptr->path, erp)) {
+ if (dk4str8_cat_s(pab, sizeof(pab), dk4dir_c8_kw[3], erp)) {
+ if (dk4str8_cat_s(pab, sizeof(pab), dk4dir_c8_kw[4], erp)) {
+ ffres = FindFirstFileA(pab, &ffdata);
+ if (INVALID_HANDLE_VALUE != ffres) {
+ back = 1;
+ do {
+ if (0 != dk4str8_cmp(dk4dir_c8_kw[0], ffdata.cFileName)) {
+ if (0 != dk4str8_cmp(dk4dir_c8_kw[1], ffdata.cFileName)) {
+ slen = dk4str8_len(ffdata.cFileName);
+ if (slen > dptr->maxlen) { dptr->maxlen = slen; }
+ nn = dk4str8_dup(ffdata.cFileName, erp);
+ if (NULL != nn) {
+ isdir = 0;
+ attr = ffdata.dwFileAttributes;
+ if (0 != (FILE_ATTRIBUTE_DIRECTORY & attr)) {
+ isdir = 1;
+ if (0 != (FILE_ATTRIBUTE_REPARSE_POINT & attr)) {
+ if (0 != (DK4_DIR_SYMLINK_DIR_AS_FILE & om)) {
+ isdir = 0;
+ }
+ }
+ }
+ if (0 != isdir) {
+ if (0 == dk4sto_add(dptr->s_dir, (void *)nn, erp)) {
+ back = 0;
+ dk4mem_free(nn);
+ }
+ } else {
+ if (0 == dk4sto_add(dptr->s_file, (void *)nn, erp)) {
+ back = 0;
+ dk4mem_free(nn);
+ }
+ }
+ } else {
+ back = 0;
+ }
+ }
+ }
+ } while(FindNextFileA(ffres, &ffdata));
+ FindClose(ffres);
+ } else {
+ /* ERROR: FindFirstFile failed */
+ dk4error_set_ldetails(
+ erp, DK4_E_FINDFIRSTFILE_FAILED,
+ (long)((unsigned long)GetLastError())
+ );
+ }
+ }
+ }
+ }
+ $? "- dk4dir_c8_fill_directory %d", back
+ return back;
+#else
+ char fnb[DK4_MAX_PATH]; /* File name buffer */
+ dk4_stat_t stb; /* Stat buffer */
+ DIR *dir; /* Directory */
+ struct dirent *de; /* Directory entry */
+ char *nn; /* Dynamic copy of file name */
+ size_t slen; /* Entry name length */
+ int isdir = 0; /* Flag: Current item is directory */
+ int back = 0;
+ $? "+ dk4dir_c8_fill_directory"
+ errno = 0;
+ dir = opendir(dptr->path);
+ if (NULL != dir) { $? ". opendir"
+ back = 1;
+ do {
+ de = readdir(dir);
+ if (NULL != de) {
+ if (0 < (slen = dk4str8_len(de->d_name))) {
+ if (slen > dptr->maxlen) { dptr->maxlen = slen; }
+ if (0 != dk4str8_cmp(dk4dir_c8_kw[0], de->d_name)) {
+ if (0 != dk4str8_cmp(dk4dir_c8_kw[1], de->d_name)) {
+ if (dk4str8_cpy_s(fnb, sizeof(fnb), dptr->path, erp)) {
+ if (dk4str8_cat_s(fnb, sizeof(fnb), dk4dir_c8_kw[2], erp)) {
+ if (dk4str8_cat_s(fnb, sizeof(fnb), de->d_name, erp)) {
+ nn = dk4str8_dup(de->d_name, erp);
+ if (NULL != nn) {
+ isdir = 0;
+ if (0 != dk4stat_c8(&stb, fnb, erp)) {
+ isdir = dk4stat_is_directory(&stb, NULL);
+ if (0 != isdir) {
+ if (0 != (DK4_DIR_SYMLINK_DIR_AS_FILE & om)) {
+ if (0 != dk4stat_l_c8(&stb, fnb, NULL)) {
+ if (dk4stat_is_symlink(&stb, NULL)) {
+ isdir = 0;
+ }
+ }
+ }
+ }
+ } else { $? "! stat"
+#if 0
+ /* 2015-04-11 Dangling links are not
+ directories.
+ */
+ back = 0;
+#endif
+ }
+ if (0 != isdir) {
+ if (0 == dk4sto_add(dptr->s_dir, (void *)nn, erp)) {
+ back = 0; $? "! memory"
+ dk4mem_free(nn);
+ }
+ } else {
+ if (0 == dk4sto_add(dptr->s_file, (void *)nn, erp)) {
+ back = 0; $? "! memory"
+ dk4mem_free(nn);
+ }
+ }
+ } else { $? "! memory"
+ back = 0;
+ }
+ } else { $? "! buffer too small"
+ back = 0;
+ }
+ } else { $? "! buffer too small"
+ back = 0;
+ }
+ } else { $? "! buffer too small"
+ back = 0;
+ }
+ }
+ }
+ }
+ }
+ } while(NULL != de);
+ closedir(dir);
+ } else { $? "! opendir"
+ dk4error_set_idetails(erp, DK4_E_OPENDIR_FAILED, errno);
+ } $? "- dk4dir_c8_fill_directory %d", back
+ return back;
+#endif
+}
+#endif
+
+
+
+dk4_dir_c8_t *
+dk4dir_c8_open(const char *path, int om, dk4_er_t *erp)
+{
+ dk4_dir_c8_t *back = NULL;
+ int ok = 0;
+ $? "+ dk4dir_c8_open \"%!8s\"", TR_8STR(path)
+ if (NULL != path) {
+#if DK4_ON_WINDOWS || DK4_HAVE_DIRENT_H
+ back = dk4mem_new(dk4_dir_c8_t, 1, erp);
+ if (NULL != back) {
+ back->path = NULL;
+ back->s_dir = NULL;
+ back->i_dir = NULL;
+ back->s_file = NULL;
+ back->i_file = NULL;
+ back->path = dk4str8_dup(path, erp);
+ back->maxlen = 0;
+ if (NULL != back->path) {
+ back->s_dir = dk4sto_open(erp);
+ if (NULL != back->s_dir) {
+ if (0 != (DK4_DIR_OPEN_SORTED & om)) {
+ dk4sto_set_comp(back->s_dir, dk4dir_c8_compare, 0);
+ }
+ back->i_dir = dk4sto_it_open(back->s_dir, erp);
+ if (NULL != back->i_dir) {
+ back->s_file = dk4sto_open(erp);
+ if (NULL != back->s_file) {
+ if (0 != (DK4_DIR_OPEN_SORTED & om)) {
+ dk4sto_set_comp(back->s_file, dk4dir_c8_compare, 0);
+ }
+ back->i_file = dk4sto_it_open(back->s_file, erp);
+ if (NULL != back->i_file) {
+ ok = dk4dir_c8_fill_directory(back, om, erp);
+ }
+ }
+ }
+ }
+ }
+ if (0 == ok) {
+ dk4dir_c8_close(back);
+ back = NULL;
+ }
+ }
+#else
+ dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
+#endif
+ } else {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ }
+ $? "- dk4dir_c8_open PTR=%d", TR_IPTR(back)
+ return back;
+}
+
+
+
+void
+dk4dir_c8_reset(dk4_dir_c8_t *dptr)
+{
+ $? "+ dk4dir_c8_reset"
+ if (NULL != dptr) {
+ if ((NULL != dptr->s_dir) && (NULL != dptr->i_dir)) {
+ dk4sto_it_reset(dptr->i_dir);
+ }
+ if ((NULL != dptr->s_file) && (NULL != dptr->i_file)) {
+ dk4sto_it_reset(dptr->i_file);
+ }
+ }
+ $? "- dk4dir_c8_reset"
+}
+
+
+
+const char *
+dk4dir_c8_get_path(dk4_dir_c8_t *dptr)
+{
+ const char *back = NULL;
+ $? "+ dk4dir_c8_get_path"
+ if (NULL != dptr) {
+ back = (const char *)(dptr->path);
+ }
+ $? "- dk4dir_c8_get_path \"%!8s\"", TR_8STR(back)
+ return back;
+}
+
+
+
+const char *
+dk4dir_c8_next_dir(dk4_dir_c8_t *dptr)
+{
+ const char *back = NULL;
+ $? "+ dk4dir_c8_next_dir"
+ if (NULL != dptr) {
+ if ((NULL != dptr->s_dir) && (NULL != dptr->i_dir)) {
+ back = (const char *)dk4sto_it_next(dptr->i_dir);
+ }
+ }
+ $? "- dk4dir_c8_next_dir \"%!8s\"", TR_8STR(back)
+ return back;
+}
+
+
+
+const char *
+dk4dir_c8_next_file(dk4_dir_c8_t *dptr)
+{
+ const char *back = NULL;
+ $? "+ dk4dir_c8_next_file"
+ if (NULL != dptr) {
+ if ((NULL != dptr->s_file) && (NULL != dptr->i_file)) {
+ back = (const char *)dk4sto_it_next(dptr->i_file);
+ }
+ }
+ $? "- dk4dir_c8_next_file \"%!8s\"", TR_8STR(back)
+ return back;
+}
+
+
+
+void
+dk4dir_c8_skip_files(dk4_dir_c8_t *dptr)
+{
+ $? "+ dk4dir_c8_skip_files"
+ if (NULL != dptr) {
+ dk4dir_c8_clean_storage(dptr->s_file, dptr->i_file);
+ dptr->s_file = NULL; dptr->i_file = NULL;
+ }
+ $? "- dk4dir_c8_skip_files"
+}
+
+
+
+size_t
+dk4dir_c8_get_max_entry_length(dk4_dir_c8_t *dptr)
+{
+ size_t back = 0;
+ $? "+ dk4dir_c8_get_max_entry_length"
+ if (NULL != dptr) {
+ back = dptr->maxlen;
+ }
+ $? "- dk4dir_c8_get_max_entry_length %lu", (unsigned long)back
+ return back;
+}
+
+