diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/dk4dir08.ctr |
Initial commit
Diffstat (limited to 'support/dktools/dk4dir08.ctr')
-rw-r--r-- | support/dktools/dk4dir08.ctr | 588 |
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; +} + + |