%% options copyright owner = Dirk Krause copyright year = 2015-xxxx SPDX-License-Identifier: BSD-3-Clause %% header /** @file Directory traversal using dkChar file names. CRT on Windows: Optional. */ #ifndef DK4CONF_H_INCLUDED #if DK4_BUILDING_DKTOOLS4 #include "dk4conf.h" #else #include #endif #endif #ifndef DK4TYPES_H_INCLUDED #if DK4_BUILDING_DKTOOLS4 #include "dk4types.h" #else #include #endif #endif #ifndef DK4ERROR_H_INCLUDED #if DK4_BUILDING_DKTOOLS4 #include "dk4error.h" #else #include #endif #endif #if DK4_CHAR_SIZE > 1 #ifndef DK4DIRWC_H_INCLUDED #if DK4_BUILDING_DKTOOLS4 #include "dk4dirwc.h" #else #include #endif #endif #else #ifndef DK4DIR08_H_INCLUDED #if DK4_BUILDING_DKTOOLS4 #include "dk4dir08.h" #else #include #endif #endif #endif #if DK4_CHAR_SIZE > 1 /** Directory listing. */ typedef dk4_dir_wc_t dk4_dir_t; #else /** Directory listing. */ typedef dk4_dir_c8_t dk4_dir_t; #endif #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_close() to destroy the directory structure. Error codes: - DK4_E_INVALID_ARGUMENTS
if path is NULL, - DK4_E_NOT_SUPPORTED
if no function to traverse directories was found during build process, - DK4_E_MEMORY_ALLOCATION_FAILED
if a memory allocation failed, - DK4_E_MATH_OVERFLOW
if a mathematical overflow occured in a size calculation, - DK4_E_BUFFER_TOO_SMALL
if one of the involved directory or file names is too long for an internal buffer, - DK4_E_OPENDIR_FAILED
with errno value in iDetails1 if the attempt to open the directory failed, - DK4_E_FINDFIRSTFILE_FAILED
with GetLastError() value in lDetails1 if the FindFirstFile() function failed on Windows, - DK4_E_SYSTEM
if the stat() or lstat() function failed for one of the directory items. */ dk4_dir_t * dk4dir_open(const dkChar *path, int om, dk4_er_t *erp); /** Destroy directory structure. @param dptr Structure to destroy. */ void dk4dir_close(dk4_dir_t *dptr); /** Reset directory traversal. @param dptr Directory structure. */ void dk4dir_reset(dk4_dir_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 dkChar * dk4dir_get_path(dk4_dir_t const *dptr); /** Retrieve next directory name. @param dptr Directory structure. @return Pointer to short name on success, NULL if there are no more directories. */ const dkChar * dk4dir_next_dir(dk4_dir_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 dkChar * dk4dir_next_file(dk4_dir_t *dptr); /** Skip files (remove information about files, release memory). @param dptr Directory structure. */ void dk4dir_skip_files(dk4_dir_t *dptr); /** Get maximum entry name length. @param dptr Directory. @return Maximum name length. */ size_t dk4dir_get_max_entry_length(dk4_dir_t const *dptr); /** Create full path name for short file name in existing buffer. @param buffer Result buffer. @param szbuf Size of result buffer (number of dkChar). @param pdir Directory fn was obtained from. @param fn Short file or directory name. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if buffer, pdir or fn is NULL or szbuf is 0, - DK4_E_BUFFER_TOO_SMALL
if the buffer is too small. */ int dk4dir_full_name_buffer( dkChar *buffer, size_t szbuf, dk4_dir_t const *pdir, dkChar const *fn, dk4_er_t *erp ); /** Create full path name for short file name in newly allocated buffer. @param pdir Directory fn was obtained from. @param fn Short file or directory name. @param erp Error report, may be NULL. @return Valid pointer to newly allocated buffer on success, NULL on error. On success use dk4mem_free() to release the memory when done with the name. Error codes: - DK4_E_INVALID_ARGUMENTS
if pdir or fn is NULL, - DK4_E_MATH_OVERFLOW
if the size calculation results in a numeric overflow. - DK4_E_MEMORY_ALLOCATION_FAILED
if the memory allocation failed, - DK4_E_BUFFER_TOO_SMALL
if the buffer is too small. */ dkChar * dk4dir_full_name_new( dk4_dir_t const *pdir, dkChar const *fn, dk4_er_t *erp ); #ifdef __cplusplus } #endif /** Open modes for directories. */ enum { /* Value definitions */ /** Sort file names. */ DK4_DIR_OPEN_SORTED = 1, /** Treat symbolic links pointing to directories as files. */ DK4_DIR_SYMLINK_DIR_AS_FILE = 2, /* Default modes for special purposes */ /** For deltree we do not follow symbolic links, no need for sorting. */ DK4_DIR_OPEN_DELTREE = DK4_DIR_SYMLINK_DIR_AS_FILE }; %% module #include "dk4conf.h" #include "dk4dir.h" #if DK4_CHAR_SIZE > 1 #include "dk4dirwc.h" #else #include "dk4dir08.h" #endif #if DK4_HAVE_ASSERT_H #ifndef ASSERT_H_INCLUDED #include #define ASSERT_H_INCLUDED 1 #endif #endif dk4_dir_t * dk4dir_open(const dkChar *path, int om, dk4_er_t *erp) { #if DK4_USE_ASSERT assert(NULL != path); #endif #if DK4_CHAR_SIZE > 1 return (dk4dir_wc_open(path, om, erp)); #else return (dk4dir_c8_open(path, om, erp)); #endif } void dk4dir_close(dk4_dir_t *dptr) { #if DK4_USE_ASSERT assert(NULL != dptr); #endif #if DK4_CHAR_SIZE > 1 dk4dir_wc_close(dptr); #else dk4dir_c8_close(dptr); #endif } void dk4dir_reset(dk4_dir_t *dptr) { #if DK4_USE_ASSERT assert(NULL != dptr); #endif #if DK4_CHAR_SIZE > 1 dk4dir_wc_reset(dptr); #else dk4dir_c8_reset(dptr); #endif } const dkChar * dk4dir_get_path(dk4_dir_t const *dptr) { #if DK4_USE_ASSERT assert(NULL != dptr); #endif #if DK4_CHAR_SIZE > 1 return (dk4dir_wc_get_path(dptr)); #else return (dk4dir_c8_get_path(dptr)); #endif } const dkChar * dk4dir_next_dir(dk4_dir_t *dptr) { #if DK4_USE_ASSERT assert(NULL != dptr); #endif #if DK4_CHAR_SIZE > 1 return (dk4dir_wc_next_dir(dptr)); #else return (dk4dir_c8_next_dir(dptr)); #endif } const dkChar * dk4dir_next_file(dk4_dir_t *dptr) { #if DK4_USE_ASSERT assert(NULL != dptr); #endif #if DK4_CHAR_SIZE > 1 return (dk4dir_wc_next_file(dptr)); #else return (dk4dir_c8_next_file(dptr)); #endif } void dk4dir_skip_files(dk4_dir_t *dptr) { #if DK4_USE_ASSERT assert(NULL != dptr); #endif #if DK4_CHAR_SIZE > 1 dk4dir_wc_skip_files(dptr); #else dk4dir_c8_skip_files(dptr); #endif } size_t dk4dir_get_max_entry_length(dk4_dir_t const *dptr) { #if DK4_USE_ASSERT assert(NULL != dptr); #endif #if DK4_CHAR_SIZE > 1 return (dk4dir_wc_get_max_entry_length(dptr)); #else return (dk4dir_c8_get_max_entry_length(dptr)); #endif } int dk4dir_full_name_buffer( dkChar *buffer, size_t szbuf, dk4_dir_t const *pdir, dkChar const *fn, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != pdir); assert(NULL != fn); assert(NULL != buffer); assert(0 < szbuf); #endif #if DK4_CHAR_SIZE > 1 return ( dk4dir_wc_full_name_buffer(buffer, szbuf, pdir, fn, erp) ); #else return ( dk4dir_c8_full_name_buffer(buffer, szbuf, pdir, fn, erp) ); #endif } dkChar * dk4dir_full_name_new( dk4_dir_t const *pdir, dkChar const *fn, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != pdir); assert(NULL != fn); #endif #if DK4_CHAR_SIZE > 1 return ( dk4dir_wc_full_name_new(pdir, fn, erp) ); #else return ( dk4dir_c8_full_name_new(pdir, fn, erp) ); #endif }