%% options copyright owner = Dirk Krause copyright year = 2015-xxxx license = bsd %% header /** @file Create directory structure. */ #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 DK4APP_H_INCLUDED #include "dk4app.h" #endif #ifdef __cplusplus extern "C" { #endif /** Create directory structure. @param fn File name. @param lc Flag: Last component in fn is directory too. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk4app_mkdir_hierarchy(const dkChar *fn, int lc, dk4_app_t *app); #ifdef __cplusplus } #endif %% module #include "dk4conf.h" #include "dk4types.h" #if DK4_ON_WINDOWS #ifndef WINDOWS_H_INCLUDED #include #define WINDOWS_H_INCLUDED 1 #endif #endif #include "dk4appmkdh.h" #if DK4_HAVE_SYS_STAT_H #ifndef SYS_STAT_H_INCLUDED #include #define SYS_STAT_H_INCLUDED 1 #endif #endif #if DK4_HAVE_SYS_TYPES_H #ifndef SYS_TYPES_H_INCLUDED #include #define SYS_TYPES_H_INCLUDED 1 #endif #endif #if DK4_HAVE_DIRECT_H #ifndef DIRECT_H_INCLUDED #include #define DIRECT_H_INCLUDED 1 #endif #endif #if DK4_HAVE_STDLIB_H #ifndef STDLIB_H_INCLUDED #include #define STDLIB_H_INCLUDED 1 #endif #endif #if DK4_HAVE_UNISTD_H #ifndef UNISTD_H_INCLUDED #include #define UNISTD_H_INCLUDED 1 #endif #endif #if DK4_HAVE_STRING_H #ifndef STRING_H_INCLUDED #include #define STRING_H_INCLUDED 1 #endif #endif #if DK4_HAVE_ERRNO_H #ifndef ERRNO_H_INCLUDED #include #define ERRNO_H_INCLUDED 1 #endif #endif #ifndef DK4MEM_H_INCLUDED #include "dk4mem.h" #endif #ifndef DK4CONST_H_INCLUDED #include "dk4const.h" #endif #ifndef DK4MPL_H_INCLUDED #include "dk4mpl.h" #endif #ifndef DK4STR_H_INCLUDED #include "dk4strd.h" #endif #ifndef DK4STRDA_H_INCLUDED #include "dk4strda.h" #endif #ifndef DK4MAODD_H_INCLUDED #include "dk4maodd.h" #endif #ifndef DK4MAODH_H_INCLUDED #include "dk4maodh.h" #endif #ifndef DK4STAT_H_INCLUDED #include "dk4stat.h" #endif #ifndef DK4PATH_H_INCLUDED #include "dk4pathd.h" #endif #if DK4_CHAR_SIZE > 1 #ifndef DK4MKDHW_H_INCLUDED #include "dk4mkdhw.h" #endif #else #ifndef DK4MKDH8_H_INCLUDED #include "dk4mkdh8.h" #endif #endif $!trace-include static void dk4app_mkdir_hierarchy_report(dk4_app_t *app, const dkChar *fnb, dk4_er_t *erp) { #if DK4_ON_WINDOWS dkChar eb1[8 * sizeof(DWORD)]; dkChar eb2[8 * sizeof(DWORD)]; int res; #endif switch (erp->ec) { case DK4_E_NON_DIR: { dk4app_log_base3(app, DK4_LL_ERROR, 43, 44, fnb); } break; #if DK4_ON_WINDOWS case DK4_E_CREATE_DIR_FAILED: { if (ERROR_ALREADY_EXISTS == (erp->dt).lDetails1) { dk4app_log_base3(app, DK4_LL_ERROR, 43, 44, fnb); goto finished; } if (ERROR_PATH_NOT_FOUND == (erp->dt).lDetails1) { dk4app_log_base3(app, DK4_LL_ERROR, 46, 51, fnb); goto finished; } if (ERROR_ACCESS_DENIED == (erp->dt).lDetails1) { dk4app_log_base3(app, DK4_LL_ERROR, 46, 55, fnb); goto finished; } if (ERROR_BAD_NET_NAME == (erp->dt).lDetails1) { dk4app_log_base3(app, DK4_LL_ERROR, 46, 74, fnb); goto finished; } if (ERROR_BAD_NETPATH == (erp->dt).lDetails1) { dk4app_log_base3(app, DK4_LL_ERROR, 46, 75, fnb); goto finished; } res = dk4ma_write_decimal_unsigned( eb1, DK4_SIZEOF(eb1,dkChar), (dk4_um_t)((erp->dt).lDetails1), 0, NULL ); if (0 != res) { res = dk4ma_write_hex_unsigned( eb2, DK4_SIZEOF(eb2,dkChar), (dk4_um_t)((erp->dt).lDetails1), 0, NULL ); } if (0 != res) { dk4app_log_base7( app, DK4_LL_ERROR, 46, 69, 70, 71, fnb, eb1, eb2); } else { dk4app_log_base3(app, DK4_LL_ERROR, 46, 40, fnb); } } break; #endif case DK4_E_MKDIR_FAILED: { switch ((erp->dt).iDetails1) { #ifdef EEXIST case EEXIST : { /* Path already exists */ dk4app_log_base3(app, DK4_LL_ERROR, 46, 49, fnb); } break; #endif #ifdef ENOENT case ENOENT : { /* Path not found */ dk4app_log_base3(app, DK4_LL_ERROR, 46, 51, fnb); } break; #endif #ifdef EACCES case EACCES : { /* Permissions problem */ dk4app_log_base3(app, DK4_LL_ERROR, 46, 55, fnb); } break; #endif #ifdef EIO case EIO : { /* I/O error occured */ dk4app_log_base3(app, DK4_LL_ERROR, 46, 59, fnb); } break; #endif #ifdef EMLINK case EMLINK : { dk4app_log_base3(app, DK4_LL_ERROR, 46, 63, fnb); } break; #endif #ifdef ENAMETOOLONG case ENAMETOOLONG : { /* Name too long */ dk4app_log_base3(app, DK4_LL_ERROR, 46, 65, fnb); } break; #endif #ifdef ENOMEM case ENOMEM : { /* Insufficient kernel memory */ dk4app_log_base3(app, DK4_LL_ERROR, 46, 62, fnb); } break; #endif #ifdef ENOSPC case ENOSPC : { /* Not enough space (space/quota) */ dk4app_log_base3(app, DK4_LL_ERROR, 46, 60, fnb); } break; #endif #ifdef EPERM case EPERM : { /* FS does not support dir creation */ dk4app_log_base3(app, DK4_LL_ERROR, 46, 58, fnb); } break; #endif #ifdef EROFS case EROFS : { /* Read-only file system */ dk4app_log_base3(app, DK4_LL_ERROR, 46, 56, fnb); } break; #endif #ifdef ENOTDIR case ENOTDIR : { /* One component is not a dir */ dk4app_log_base3(app, DK4_LL_ERROR, 46, 150, fnb); } break; #endif default: { dk4app_log_with_errno( app, DK4_LL_ERROR, 46, 79, 80, 46, 77, fnb, errno ); } break; } } break; case DK4_E_NOT_FOUND : { dk4app_log_base3(app, DK4_LL_ERROR, 46, 73, fnb); } break; case DK4_E_INVALID_ARGUMENTS : { dk4app_log_base3(app, DK4_LL_ERROR, 46, 47, fnb); } break; default: { dk4app_log_base3(app, DK4_LL_ERROR, 46, 72, fnb); } break; } #if DK4_ON_WINDOWS finished: ; #endif } static int dk4app_mkdir_hierarchy_on_copy(dkChar *fn, int lc, dk4_app_t *app) { dk4_er_t er; dkChar *pc = NULL; int back = 0; /* Correct path name */ dk4path_correct_sep(fn); dk4error_init(&er); #if DK4_CHAR_SIZE > 1 pc = dk4mkdir_hierarchy_wc_first_sep(fn, &back, lc, &er); #else pc = dk4mkdir_hierarchy_c8_first_sep(fn, &back, lc, &er); #endif if ((NULL != pc) || (0 != back)) { if (NULL != pc) { back = 1; while (NULL != pc) { *pc = dkT('\0'); if (0 < dk4str_len(fn)) { dk4error_init(&er); #if DK4_CHAR_SIZE > 1 if (0 == dk4mkdir_hierarchy_wc_one(fn, 0, &er)) #else if (0 == dk4mkdir_hierarchy_c8_one(fn, 0, &er)) #endif { back = 0; dk4app_mkdir_hierarchy_report(app, fn, &er); } } #if DK4_HAVE_BACKSLASH_AS_SEP *pc = dkT('\\'); pc = dk4str_chr(&(pc[1]), dkT('\\')); #else *pc = dkT('/'); pc = dk4str_chr(&(pc[1]), dkT('/')); #endif } if (0 != lc) { dk4error_init(&er); #if DK4_CHAR_SIZE > 1 if (0 == dk4mkdir_hierarchy_wc_one(fn, 0, &er)) #else if (0 == dk4mkdir_hierarchy_c8_one(fn, 0, &er)) #endif { back = 0; dk4app_mkdir_hierarchy_report(app, fn, &er); } } } } else { dk4app_mkdir_hierarchy_report(app, fn, &er); } return back; } static int dk4app_mkdir_hierarchy_local(const dkChar *fn, int lc, dk4_app_t *app) { dkChar mycp[DK4_MAX_PATH]; int back = 0; if (dk4str_cpy_s(mycp, DK4_SIZEOF(mycp,dkChar), fn, NULL)) { back = dk4app_mkdir_hierarchy_on_copy(mycp, lc, app); } else { /* ERROR: Bug */ } return back; } int dk4app_mkdir_hierarchy(const dkChar *fn, int lc, dk4_app_t *app) { dkChar *mycp; size_t sz; int back = 0; $? "+ dk4app_mkdir_hierarchy PTR=%d", TR_IPTR(fn) if (NULL != fn) { #if DK4_ON_WINDOWS || (1 == DK4_CHAR_SIZE) sz = dk4str_len(fn); if (DK4_MAX_PATH > sz) { back = dk4app_mkdir_hierarchy_local(fn, lc, app); } else { mycp = dk4str_dup_app(fn, app); if (NULL != mycp) { back = dk4app_mkdir_hierarchy_on_copy(mycp, lc, app); dk4mem_free(mycp); } } #else /* ERROR: Not supported */ #error "Wide characters are supported on the Windows platform only!" #endif } else { $? "! fn" } $? "- dk4app_mkdir_hierarchy %d", back return back; }