/* Copyright (C) 2015-2020, Dirk Krause SPDX-License-Identifier: BSD-3-Clause */ /* WARNING: This file was generated by the dkct program (see http://dktools.sourceforge.net/ for details). Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: dk4appdeltree.ctr */ /** @file dk4appdeltree.c The dk4appdeltree module. */ #line 10 "dk4appdeltree.ctr" #include "dk4conf.h" #include "dk4types.h" #if DK4_ON_WINDOWS #ifndef WINDOWS_H_INCLUDED #include #define WINDOWS_H_INCLUDED 1 #endif #endif #ifndef DK4APP_H_INCLUDED #include "dk4app.h" #endif #ifndef DK4CONST_H_INCLUDED #include "dk4const.h" #endif #ifndef DK4STATD_H_INCLUDED #include "dk4statd.h" #endif #ifndef DK4STAT_H_INCLUDED #include "dk4stat.h" #endif #ifndef DK4DIR_H_INCLUDED #include "dk4dir.h" #endif #ifndef DK4DIRA_H_INCLUDED #include "dk4dira.h" #endif #ifndef DK4MEM_H_INCLUDED #include "dk4mem.h" #endif #ifndef DK4MEMA_H_INCLUDED #include "dk4mema.h" #endif #ifndef DK4MPL_H_INCLUDED #include "dk4mpl.h" #endif #ifndef DK4STR_H_INCLUDED #include "dk4strd.h" #endif #ifndef DK4MAASZ_H_INCLUDED #include "dk4maasz.h" #endif #if DK4_HAVE_SYS_TYPES_H #ifndef SYS_TYPES_H_INCLUDED #include #define SYS_TYPES_H_INCLUDED 1 #endif #endif #if DK4_HAVE_DIRENT_H #ifndef DIRENT_H_INCLUDED #include #define DIRENT_H_INCLUDED 1 #endif #endif #if DK4_CHAR_SIZE > 1 #if DK4_HAVE_WCHAR_H #ifndef WCHAR_H_INCLUDED #include #define WCHAR_H_INCLUDED 1 #endif #endif #endif #if DK4_HAVE_ASSERT_H #ifndef ASSERT_H_INCLUDED #include #define ASSERT_H_INCLUDED 1 #endif #endif #line 98 "dk4appdeltree.ctr" /** Information about failed removals of files or directories. */ enum { /** No errors yet. */ NE_NO_ERROR = 0, /** Failed to remove one file. */ NE_ONE_FILE_REMOVAL_FAILED , /** Failed to remove multiple files. */ NE_MULTIPLE_FILE_REMOVALS_FAILED , /** Failed to remove one directory. */ NE_ONE_DIRECTORY_REMOVAL_FAILED , /** Failed to remove multiple dirs. */ NE_MULTIPLE_DIRECTORY_REMOVALS_FAILED }; /** One node in tree to delete. */ typedef struct _dk4_del_tree_node_t_ { struct _dk4_del_tree_node_t_ *parent; /**< Parent node. */ dk4_dir_t *dir; /**< Directory contents. */ size_t dplen; /**< Directory path length. */ int ne; /**< Flag: Not empty. */ } dk4_del_tree_node_t; /** Job structure (information passed downwards). */ typedef struct { dkChar *sbptr; /**< Static buffer. */ dkChar *dbptr; /**< Dynamic buffer, may be NULL. */ size_t sbsz; /**< Static buffer size. */ size_t dbsz; /**< Dynamic buffer size. */ int result; /**< Suggested function result. */ } dk4_del_tree_job_t; #if DK4_ON_WINDOWS /* +++ Windows */ #if DK4_CHAR_SIZE > 1 /* +++ Windows, wchar_t */ /* --- Windows, wchar_t */ #else /* +++ Windows, char */ /* --- Windows, char */ #endif static int dk4app_del_tree_process_dir(const dkChar *dirname) { #if DK4_CHAR_SIZE > 1 WIN32_FIND_DATAW ff; #else WIN32_FIND_DATAA ff; #endif DWORD dwFileAttributes; HANDLE ha; int back = 1; #if DK4_CHAR_SIZE > 1 dwFileAttributes = GetFileAttributesW(dirname); #else dwFileAttributes = GetFileAttributesA(dirname); #endif if (INVALID_FILE_ATTRIBUTES == dwFileAttributes) { #if DK4_CHAR_SIZE > 1 ha = FindFirstFileW(dirname, &ff); #else ha = FindFirstFileA(dirname, &ff); #endif if (INVALID_HANDLE_VALUE != ha) { dwFileAttributes = ff.dwFileAttributes; FindClose(ha); } } if (INVALID_FILE_ATTRIBUTES != dwFileAttributes) { if (0 != (FILE_ATTRIBUTE_REPARSE_POINT & dwFileAttributes)) { #if DK4_CHAR_SIZE > 1 ha = FindFirstFileW(dirname, &ff); #else ha = FindFirstFileA(dirname, &ff); #endif if (INVALID_HANDLE_VALUE != ha) { if (0 != (FILE_ATTRIBUTE_REPARSE_POINT & ff.dwFileAttributes)) { if (IO_REPARSE_TAG_MOUNT_POINT == ff.dwReserved0) { back = 0; } if (IO_REPARSE_TAG_SYMLINK == ff.dwReserved0) { back = 0; } } FindClose(ha); } else { back = 0; } } } return back; } /* --- Windows */ #else /* +++ non-Windows */ #if DK4_CHAR_SIZE > 1 /* +++ non-Windows, wchar_t */ /* --- non-Windows, wchar_t */ #else /* +++ non-Windows, char */ /* --- non-Windows, char */ #endif /* --- non-Windows */ #endif #if DK4_HAVE_BACKSLASH_AS_SEP static const dkChar dk4appdeltree_fnsep[] = { dkT("\\") }; #else static const dkChar dk4appdeltree_fnsep[] = { dkT("/") }; #endif static void dk4app_del_tree_node_close(dk4_del_tree_node_t *ptr) { if (NULL != ptr) { ptr->parent = NULL; if (NULL != ptr->dir) { dk4dir_close(ptr->dir); ptr->dir = NULL; } ptr->dplen = 0; ptr->ne = 0; dk4mem_free(ptr); } } static dk4_del_tree_node_t * dk4app_del_tree_node_open( const dkChar *dn, dk4_del_tree_node_t *par, dk4_del_tree_job_t *job, dk4_app_t *app ) { dk4_er_t er; /* Error report */ const dkChar *fn; /* File name to process */ dkChar *nbptr; /* Buffer pointer */ dk4_del_tree_node_t *back = NULL; size_t lgt; /* Length of buffer */ #if VERSION_BEFORE_20150821 || TRACE_DEBUG int dfres; /* Result from file deletion */ #endif #line 277 "dk4appdeltree.ctr" back = dk4mem_new_app(dk4_del_tree_node_t,1,app); if (NULL != back) { #line 279 "dk4appdeltree.ctr" back->parent = par; back->ne = NE_NO_ERROR; back->dplen = dk4str_len(dn); dk4error_init(&er); back->dir = dk4dir_open_app(dn, DK4_DIR_OPEN_DELTREE, app); if (NULL != back->dir) { #line 285 "dk4appdeltree.ctr" dk4error_init(&er); lgt = dk4ma_size_t_add( dk4ma_size_t_add( back->dplen, dk4dir_get_max_entry_length(back->dir), &er ), 2, &er ); if (DK4_E_NONE == er.ec) { #line 294 "dk4appdeltree.ctr" if ((lgt > job->sbsz) && (lgt > job->dbsz)) { #line 296 "dk4appdeltree.ctr" nbptr = dk4mem_new_app(dkChar,lgt,app); if (NULL != nbptr) { #line 298 "dk4appdeltree.ctr" if (job->dbptr) { dk4mem_free(job->dbptr); #line 300 "dk4appdeltree.ctr" } job->dbptr = nbptr; job->dbsz = lgt; #line 302 "dk4appdeltree.ctr" } else { #line 303 "dk4appdeltree.ctr" dk4app_del_tree_node_close(back); back = NULL; job->result = 0; } } if (NULL != back) { if ((NULL != job->dbptr) && (0 < job->dbsz)) { nbptr = job->dbptr; #line 311 "dk4appdeltree.ctr" lgt = job->dbsz; } else { #line 313 "dk4appdeltree.ctr" nbptr = job->sbptr; lgt = job->sbsz; } #line 316 "dk4appdeltree.ctr" do { fn = dk4dir_next_file(back->dir); if (NULL != fn) { #line 319 "dk4appdeltree.ctr" if (dk4str_cpy_s(nbptr,lgt,dk4dir_get_path(back->dir),NULL)) { #line 321 "dk4appdeltree.ctr" if (dk4str_cat_s(nbptr, lgt, dk4appdeltree_fnsep, NULL)) { #line 323 "dk4appdeltree.ctr" if (dk4str_cat_s(nbptr, lgt, fn, NULL)) { #line 325 "dk4appdeltree.ctr" #line 326 "dk4appdeltree.ctr" switch (back->ne) { case NE_NO_ERROR : { if (0 == dk4app_del_file(nbptr, app)) { back->ne = NE_ONE_FILE_REMOVAL_FAILED; job->result = 0; #line 332 "dk4appdeltree.ctr" } } break; case NE_ONE_FILE_REMOVAL_FAILED : { if (0 == dk4app_del_file(nbptr, NULL)) { back->ne = NE_MULTIPLE_FILE_REMOVALS_FAILED; /* ERROR: Further file removals failed */ dk4app_log_base3( app,DK4_LL_ERROR,94,95,dk4dir_get_path(back->dir) ); #line 342 "dk4appdeltree.ctr" } } break; default : { #if TRACE_DEBUG dfres = dk4app_del_file(nbptr, NULL); if (0 == dfres) { #line 348 "dk4appdeltree.ctr" } #else dk4app_del_file(nbptr, NULL); #endif } break; } } else { #line 355 "dk4appdeltree.ctr" if (NE_ONE_FILE_REMOVAL_FAILED < back->ne) { back->ne = NE_ONE_FILE_REMOVAL_FAILED; } /* ERROR: Directory name too long */ dk4app_log_base3( app, DK4_LL_ERROR, 98, 99, dk4dir_get_path(back->dir) ); } } else { #line 364 "dk4appdeltree.ctr" if (NE_ONE_FILE_REMOVAL_FAILED < back->ne) { back->ne = NE_ONE_FILE_REMOVAL_FAILED; } /* ERROR: Directory name too long */ dk4app_log_base3( app, DK4_LL_ERROR, 98, 99, dk4dir_get_path(back->dir) ); } } else { #line 373 "dk4appdeltree.ctr" if (NE_ONE_FILE_REMOVAL_FAILED < back->ne) { back->ne = NE_ONE_FILE_REMOVAL_FAILED; } /* ERROR: Directory name too long */ dk4app_log_base3( app, DK4_LL_ERROR, 98, 99, dk4dir_get_path(back->dir) ); } } } while(NULL != fn); dk4dir_skip_files(back->dir); } else { #line 385 "dk4appdeltree.ctr" } } else { #line 387 "dk4appdeltree.ctr" /* ERROR: Math error in size calculation */ dk4app_log_base1(app, DK4_LL_ERROR, 82); dk4app_del_tree_node_close(back); back = NULL; job->result = 0; } } else { #line 394 "dk4appdeltree.ctr" dk4app_del_tree_node_close(back); back = NULL; job->result = 0; /* ERROR: Failed to open directory, already reported */ /* !!!!! TODO: Attempt to remove directory or file */ } } else { #line 401 "dk4appdeltree.ctr" } #line 403 "dk4appdeltree.ctr" return back; } static void dk4app_del_tree_debug_file_or_dir( dk4_app_t *app, const dkChar *fn, size_t ind ) { const dkChar *msg[3]; if ((NULL != app) && (NULL != fn)) { if (0 != dk4app_log_do(app, DK4_LL_DEBUG)) { if ((NULL != app->msg_debug) && (ind < app->sz_msg_debug)) { msg[0] = (app->msg_debug)[ind]; msg[1] = fn; msg[2] = NULL; dk4app_log_msg(app, DK4_LL_DEBUG, msg, 2); } } } } int dk4app_del_tree(const dkChar *fn, dk4_app_t *app) { dkChar sb[DK4_MAX_PATH]; dk4_del_tree_job_t job; /* Buffers */ dk4_del_tree_node_t *cn; /* Current node */ dk4_del_tree_node_t *nn; /* Next node */ dkChar *fnb; /* File name buffer */ const dkChar *dn; /* Directory name */ size_t fnbsz; /* File name buffer size */ int res; /* Operation result */ #if VERSION_BEFORE_20150821 || TRACE_DEBUG int dfres; /* Delete file result */ #endif int back = 0; #line 448 "dk4appdeltree.ctr" #if DK4_USE_ASSERT assert(NULL != fn); #endif job.sbptr = sb; job.sbsz = DK4_SIZEOF(sb,dkChar); job.dbptr = NULL; job.dbsz = 0; job.result = 1; if (NULL != fn) { #line 457 "dk4appdeltree.ctr" cn = dk4app_del_tree_node_open(fn, NULL, &job, app); if (NULL != cn) { #line 459 "dk4appdeltree.ctr" while (NULL != cn) { #line 460 "dk4appdeltree.ctr" if ((NULL != job.dbptr) && (0 < job.dbsz)) { fnb = job.dbptr; fnbsz = job.dbsz; #line 462 "dk4appdeltree.ctr" } else { #line 463 "dk4appdeltree.ctr" fnb = job.sbptr; fnbsz = job.sbsz; } dn = dk4dir_next_dir(cn->dir); if (NULL != dn) { #line 467 "dk4appdeltree.ctr" if (0 != dk4str_cpy_s(fnb, fnbsz, dk4dir_get_path(cn->dir), NULL)) { if (0 != dk4str_cat_s(fnb, fnbsz, dk4appdeltree_fnsep, NULL)) { if (0 != dk4str_cat_s(fnb, fnbsz, dn, NULL)) { #line 470 "dk4appdeltree.ctr" #if DK4_ON_WINDOWS res = dk4app_del_tree_process_dir(fnb); #else res = 1; #endif if (0 != res) { #line 476 "dk4appdeltree.ctr" nn = dk4app_del_tree_node_open(fnb, cn, &job, app); if (NULL != nn) { cn = nn; } else { job.result = 0; } } else { #line 483 "dk4appdeltree.ctr" switch (cn->ne) { case NE_NO_ERROR: case NE_ONE_FILE_REMOVAL_FAILED: case NE_MULTIPLE_FILE_REMOVALS_FAILED: { dk4app_del_tree_debug_file_or_dir(app, fnb, 27); if (0 == dk4app_del_dir(fnb, NULL)) { if (0 == dk4app_del_file(fnb, NULL)) { job.result = 0; cn->ne = NE_ONE_DIRECTORY_REMOVAL_FAILED; dk4app_log_base3(app, DK4_LL_ERROR, 66, 77, fnb); #line 494 "dk4appdeltree.ctr" } } } break; case NE_ONE_DIRECTORY_REMOVAL_FAILED: { dk4app_del_tree_debug_file_or_dir(app, fnb, 27); if (0 == dk4app_del_dir(fnb, NULL)) { if (0 == dk4app_del_file(fnb, NULL)) { job.result = 0; cn->ne = NE_MULTIPLE_DIRECTORY_REMOVALS_FAILED; dk4app_log_base3( app, DK4_LL_ERROR, 96, 97, dk4dir_get_path(cn->dir) ); #line 507 "dk4appdeltree.ctr" } } } break; default: { dk4app_del_tree_debug_file_or_dir(app, fnb, 27); if (0 == dk4app_del_dir(fnb, NULL)) { #if TRACE_DEBUG dfres = dk4app_del_file(fnb, NULL); if (0 == dfres) { #line 516 "dk4appdeltree.ctr" } #else dk4app_del_file(fnb, NULL); #endif } } break; } } } else { #line 525 "dk4appdeltree.ctr" /* ERROR: Directory name too long! */ dk4app_log_base3(app, DK4_LL_ERROR, 98, 99, dn); job.result = 0; } } else { #line 530 "dk4appdeltree.ctr" /* ERROR: Directory name too long! */ dk4app_log_base3(app,DK4_LL_ERROR,98,99,dk4dir_get_path(cn->dir)); job.result = 0; } } else { #line 535 "dk4appdeltree.ctr" /* ERROR: Directory name too long! */ dk4app_log_base3(app,DK4_LL_ERROR,98,99,dk4dir_get_path(cn->dir)); job.result = 0; } } else { #line 540 "dk4appdeltree.ctr" nn = cn->parent; if (NULL != nn) { #line 542 "dk4appdeltree.ctr" switch (nn->ne) { case NE_NO_ERROR: case NE_ONE_FILE_REMOVAL_FAILED: case NE_MULTIPLE_FILE_REMOVALS_FAILED: { if (0 == dk4app_del_dir(dk4dir_get_path(cn->dir), app)) { job.result = 0; nn->ne = NE_ONE_DIRECTORY_REMOVAL_FAILED; } } break; case NE_ONE_DIRECTORY_REMOVAL_FAILED: { dk4app_del_tree_debug_file_or_dir( app, dk4dir_get_path(cn->dir), 25 ); if (0 == dk4app_del_dir(dk4dir_get_path(cn->dir), NULL)) { job.result = 0; nn->ne = NE_MULTIPLE_DIRECTORY_REMOVALS_FAILED; dk4app_log_base3( app, DK4_LL_ERROR, 96, 97, dk4dir_get_path(nn->dir) ); } } break; default: { dk4app_del_tree_debug_file_or_dir( app, dk4dir_get_path(cn->dir), 25 ); (void)dk4app_del_dir(dk4dir_get_path(cn->dir), NULL); } break; } } else { #line 571 "dk4appdeltree.ctr" if (0 == dk4app_del_dir(dk4dir_get_path(cn->dir), app)) { job.result = 0; } } dk4app_del_tree_node_close(cn); cn = nn; } } } else { #line 580 "dk4appdeltree.ctr" } } else { #line 582 "dk4appdeltree.ctr" } if ((NULL != job.dbptr) && (0 < job.dbsz)) { dk4mem_free(job.dbptr); #line 585 "dk4appdeltree.ctr" } back = job.result; #line 588 "dk4appdeltree.ctr" return back; }