diff options
Diffstat (limited to 'support/dktools/dk3dir.ctr')
-rw-r--r-- | support/dktools/dk3dir.ctr | 1397 |
1 files changed, 0 insertions, 1397 deletions
diff --git a/support/dktools/dk3dir.ctr b/support/dktools/dk3dir.ctr deleted file mode 100644 index f50e8c90d8..0000000000 --- a/support/dktools/dk3dir.ctr +++ /dev/null @@ -1,1397 +0,0 @@ -%% options - -copyright owner = Dirk Krause -copyright year = 2011-xxxx -SPDX-License-Identifier: BSD-3-Clause - - - -%% header - -#include "dk3conf.h" -#include "dk3types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** Open a directory. - @param dn Directory name. - @param app Application structure for diagnostics, may be NULL. - @return Pointer to directory structure on success, NULL on error. -*/ -dk3_dir_t * -dk3dir_open_app(dkChar const *dn, dk3_app_t *app); - -/** Open directory structure to expand a file name. - @param fn File name. - @param app Application structure for diagnostics, may be NULL. - @return Pointer to directory structure on success, NULL on errror. -*/ -dk3_dir_t * -dk3dir_fne_open_app(dkChar const *fn, dk3_app_t *app); - -/** Close directory. - @param dp Directory to close. -*/ -void -dk3dir_close(dk3_dir_t *dp); - -/** Get number of subdirectories. - @param d Directory structure. - @return Number of subdirectories. -*/ -dk3_um_t -dk3dir_get_number_of_directories(dk3_dir_t const *d); - -/** Get number of files. - @param d Directory structure. - @return Number of non-directory entries in directory. -*/ -dk3_um_t -dk3dir_get_number_of_files(dk3_dir_t const *d); - -/** Attempt to retrieve information about the next sub-directory. - @param d Directory structure. - @return 1 on success, 0 on error. -*/ -int -dk3dir_get_next_directory(dk3_dir_t *d); - -/** Attempt to retrieve information about the next non-sub-directory entry. - @param d Directory structure. - @return 1 on success, 0 on error. -*/ -int -dk3dir_get_next_file(dk3_dir_t *d); - -/** Retrieve short file name of entry found. - May be used after a successful call to dk3dir_get_next_directory() or - dk3dir_get_next_file() only. - @param d Directory structure. - @return Pointer to file name on success, NULL on error. -*/ -dkChar const * -dk3dir_get_shortname(dk3_dir_t const *d); - -/** Retrieve full file name of entry found. - May be used after a successful call to dk3dir_get_next_directory() or - dk3dir_get_next_file() only. - @param d Directory structure. - @return Pointer to file name on success, NULL on error. -*/ -dkChar const * -dk3dir_get_fullname(dk3_dir_t const *d); - -/** Retrieve file status information. - May be used after a successful call to dk3dir_get_next_directory() or - dk3dir_get_next_file() only. - @param d Directory structure. - @return Pointer to file name on success, NULL on error. -*/ -dk3_stat_t const * -dk3dir_get_stat(dk3_dir_t *d); - -/** Reset directory for new traversal. - @param d Directory structure. -*/ -void -dk3dir_reset(dk3_dir_t *d); - -/** Retrieve directory name. - @param dir Directory structure. - @return Directory path name. -*/ -dkChar const * -dk3dir_get_directory_name(dk3_dir_t const *dir); - -/** Remove directory recursively, including all contents. - @param dn Directory name. - @param app Application structure for diagnostics, may be NULL. - @return 1 on success, 0 on error. -*/ -int -dk3dir_remove_app(dkChar const *dn, dk3_app_t *app); - -#ifdef __cplusplus -} -#endif - - - -%% module - -#include "dk3all.h" -#include "dk3unused.h" - - - -$!trace-include - - - -/* Error flags used in ec: - 1 Failed to allocate memory for name to save. - 2 Failed to save name to storage. - 4 Directory name too long. - 8 stat() failed for full name. - 16 Failed to list directory contents. -*/ - -/** Keywords and texts used in this module. -*/ -static dkChar const * const kw[] = { -/* 0 */ dkT("."), -/* 1 */ dkT(".."), -#if DK3_ON_WINDOWS || DK3_HAVE_BACKSLASH -/* 2 */ dkT("\\"), -/* 3 */ dkT("\\*"), -#else -/* 2 */ dkT("/"), -/* 3 */ dkT("/*"), -#endif -/* 4 */ dkT("*"), -NULL -}; - - - -/** Compare two directory entries by name. - @param l Left name. - @param r Right name. - @param cr Comparison criteria (ignored). - @return Comparison result. -*/ -static -int -dk3dir_compare_by_name(void const *l, void const *r, int DK3_ARG_UNUSED(cr) ) -{ - int back = 0; - - DK3_UNUSED_ARG(cr) - if(l) { - if(r) { -#if DK3_ON_WINDOWS || DK3_HAVE_FNCASEINS - back = dk3str_casecmp((dkChar const *)l,(dkChar const *)r); -#else - back = dk3str_cmp((dkChar const *)l,(dkChar const *)r); -#endif - } else { back = 1; } - } else { - if(r) { back = -1; } - } - return back; -} - - - -/** Release all directory entries in a storage. - @param s Storage to clean up. - @param i Iterator for \a s. -*/ -static -void -dk3dir_release_entries(dk3_sto_t *s, dk3_sto_it_t *i) -{ - dkChar *p = NULL; /* Current name to release. */ - $? "+ dk3dir_release_entries" - if(s) { - if(i) { - dk3sto_it_reset(i); - while((p = (dkChar *)dk3sto_it_next(i)) != NULL) { - $? ". release entry %!ds", p - dk3_delete(p); - } - dk3sto_it_close(i); - } - dk3sto_close(s); - } $? "- dk3dir_release_entries" -} - - - -/** Close directory. - @param dp Directory to close. -*/ -void -dk3dir_close(dk3_dir_t *dp) -{ - $? "+ dk3dir_close" - if(dp) { - dk3dir_release_entries(dp->sdi, dp->idi); - dk3dir_release_entries(dp->sfi, dp->ifi); - dp->sdi = NULL; dp->sfi = NULL; dp->idi = NULL; dp->ifi = NULL; - dk3_release(dp->dirname); - dk3_release(dp->fullname); - dp->app = NULL; - dp->ndir = dp->nfi = DK3_UM_0; - dk3_delete(dp); - } $? "- dk3dir_close" -} - - - -/** Create new dir structure. - @param dn Directory name. - @param app Application structure for diagnostics, may be NULL. - @return Pointer to new structure on success, NULL on error. -*/ -static -dk3_dir_t * -dk3dir_new(dkChar const *dn, dk3_app_t *app) -{ - dk3_dir_t *back = NULL; - int ok = 0; /* Flag: Success. */ - $? "+ dk3dir_new \"%!ds\"", TR_STR(dn) - back = dk3_new_app(dk3_dir_t,1,app); - if(back) { - back->sdi = NULL; back->sfi = NULL; back->idi = NULL; back->ifi = NULL; - back->dirname = NULL; back->fullname = NULL; back->app = app; - back->ndir = back->nfi = DK3_UM_0; - back->sdi = dk3sto_open_app(app); - if(back->sdi) { - back->idi = dk3sto_it_open(back->sdi); - if(back->idi) { - back->sfi = dk3sto_open_app(app); - if(back->sfi) { - back->ifi = dk3sto_it_open(back->sfi); - if(back->ifi) { - dk3sto_set_comp(back->sdi,dk3dir_compare_by_name,0); - dk3sto_set_comp(back->sfi,dk3dir_compare_by_name,0); - back->dirname = dk3str_dup_app(dn, NULL); - if(back->dirname) { - back->fullname = dk3_new_app(dkChar,DK3_MAX_PATH,app); - if(back->fullname) { - ok = 1; - } - } - } - } - } - } - if(!ok) { - dk3dir_close(back); back = NULL; - } - } $? "- dk3dir_new %!8s", TR_8PTR(back) - return back; -} - - - -dkChar const * -dk3dir_get_directory_name(dk3_dir_t const *dir) -{ - dkChar const *back = NULL; - $? "+ dk3dir_get_directory_name" - if(dir) { - back = dir->dirname; - } $? "- dk3dir_get_directory_name \"%!ds\"", TR_STR(back) - return back; -} - - - -void -dk3dir_reset(dk3_dir_t *d) -{ - $? "+ dk3dir_reset" - if(d) { - dk3sto_it_reset(d->idi); - dk3sto_it_reset(d->ifi); - d->shortname = NULL; - } $? "- dk3dir_reset" -} - - - -dk3_um_t -dk3dir_get_number_of_directories(dk3_dir_t const *d) -{ - dk3_um_t back = DK3_UM_0; - if(d) { - back = d->ndir; - } $? "= dk3dir_get_number_of_directories %lu", (unsigned long)back - return back; -} - - - -dk3_um_t -dk3dir_get_number_of_files(dk3_dir_t const *d) -{ - dk3_um_t back = DK3_UM_0; - if(d) { - back = d->nfi; - } $? "= dk3dir_get_number_of_files %lu", (unsigned long)back - return back; -} - - - -dkChar const * -dk3dir_get_fullname(dk3_dir_t const *d) -{ - dkChar const *back = NULL; - $? "+ dk3dir_get_fullname" - if(d) { - back = (dkChar const *)(d->fullname); - } $? "- dk3dir_get_fullname \"%!ds\"", TR_STR(back) - return back; -} - - - -dk3_stat_t const * -dk3dir_get_stat(dk3_dir_t *d) -{ - dk3_stat_t *back = NULL; - $? "+ dk3dir_get_stat" - if(d) { - back = &(d->stb); - } $? "- dk3dir_get_stat %!8s", TR_8PTR(back) - return back; -} - - - -dkChar const * -dk3dir_get_shortname(dk3_dir_t const *d) -{ - dkChar const *back = NULL; - $? "+ dk3dir_get_shortname" - if(d) { - back = (dkChar const *)(d->shortname); - } $? "- dk3dir_get_shortname \"%!ds\"", TR_STR(back) - return back; -} - - - -/** Get next entry. - @param d Directory structure. - @param s Iterator for the storage. - @param isdir Flag: Current entry is a directory. - @return 1 on success, 0 on error. -*/ -static -int -dk3dir_get_next_entry(dk3_dir_t *d, dk3_sto_it_t *s, int isdir) -{ - int back = 0; - int cc = 1; /* Flag: Can continue. */ - size_t sz = 0; /* Directory name length. */ - $? "+ dk3dir_get_next_entry dir=%d", isdir - do { - cc = 0; - d->shortname = (dkChar *)dk3sto_it_next(s); - if(d->shortname) { $? ". shortname = \"%!ds\"", d->shortname - cc = 1; - if(d->dirname) { - if(dk3str_len(d->dirname)) { - dk3str_cpy_not_overlapped(d->fullname, d->dirname); - sz = dk3str_len(d->dirname); - if(sz > 0) { - if((d->dirname)[sz - 1] != DK3_CHAR_SEP) { - dk3str_cat(d->fullname, kw[2]); - } - } else { - dk3str_cat(d->fullname, kw[2]); - } - dk3str_cat(d->fullname, d->shortname); - } else { - dk3str_cpy_not_overlapped(d->fullname, d->shortname); - } - } else { - dk3str_cpy_not_overlapped(d->fullname, d->shortname); - } - if(dk3sf_stat_app(&(d->stb), d->fullname, (dk3_app_t *)(d->app))) { - switch(((d->stb).ft) & (~(DK3_FT_SYMLINK))) { - case DK3_FT_DIRECTORY: { - if(isdir) { - back = 1; cc = 0; - } - } break; - default: { - if(!isdir) { - back = 1; cc = 0; - } - } break; - } - } - } $? ". cc = %d shortname=\"%!ds\"", cc, TR_STR(d->shortname) - } while(cc); $? "- dk3dir_get_next_entry %d", back - return back; -} - - - -int -dk3dir_get_next_directory(dk3_dir_t *d) -{ - int back = 0; - $? "+ dk3dir_get_next_directory" - if(d) { - back = dk3dir_get_next_entry(d, d->idi, 1); - } $? "- dk3dir_get_next_directory %d", back - return back; -} - - - -int -dk3dir_get_next_file(dk3_dir_t *d) -{ - int back = 0; - $? "+ dk3dir_get_next_file" - if(d) { - back = dk3dir_get_next_entry(d, d->ifi, 0); - } $? "- dk3dir_get_next_file %d", back - return back; -} - - - -/** Add a found item to a storage. - @param s Storage to add item to. - @param n Item name. - @param c Pointer to variable to increase to. - @param ec Pointer to error code variable. - @param app Application structure for diagnostics. -*/ -static -void -dk3dir_add(dk3_sto_t *s, dkChar const *n, dk3_um_t *c, int *ec, dk3_app_t *app) -{ - dkChar *newname = NULL; /* New copy of name. */ - dk3_um_t mu = DK3_UM_0; /* Number of entries. */ - $? "+ dk3dir_add \"%!ds\"", TR_STR(n) - newname = dk3str_dup_app(n,(((*ec) & 1) ? NULL : app)); - if(newname) { - if(dk3sto_add(s, newname)) { - mu = *c; - mu++; - *c = mu; - } else { - dk3_delete(newname); - *ec |= 2; $? "! failed to store name" - } - } else { - *ec |= 1; $? "! failed to allocate name" - } $? "- dk3dir_add" -} - - - -#if DK3_ON_WINDOWS -/* +++ Windows +++ */ -#if DK3_CHAR_SIZE > 1 -/* +++ Windows > 8 bit +++ */ - - -#if VERSION_BEFORE_2012_04_13 - -dk3_dir_t * -dk3dir_open_app(dkChar const *dn, dk3_app_t *app) -{ - dk3_dir_t *back = NULL; - int ec = 0; /* Error code. */ - dkChar buffer[DK3_MAX_PATH]; /* Buffer for entry names. */ - intptr_t ffres; /* Result of findfirst(). */ - dkChar *namecopy = NULL; /* New copy of name. */ - struct _wfinddata64_t ffdata; /* Find data. */ - if(dn) { - if((dk3str_len(kw[3]) + dk3str_len(dn)) < DK3_SIZEOF(buffer,dkChar)) { - dk3str_cpy_not_overlapped(buffer, dn); - dk3str_cat(buffer, kw[3]); - back = dk3dir_new(dn, app); - if(back) { - ffres = _wfindfirst64(buffer, &ffdata); - if(ffres != -1) { - do { - if(dk3str_cmp(ffdata.name, kw[0])) { - if(dk3str_cmp(ffdata.name, kw[1])) { - if((ffdata.attrib) & _A_SUBDIR) { - dk3dir_add(back->sdi, ffdata.name, &(back->ndir), &ec, app); - } else { - dk3dir_add(back->sfi, ffdata.name, &(back->nfi), &ec, app); - } - } - } - } while(_wfindnext64(ffres, &ffdata) == 0); - _findclose(ffres); - } else { - ec |= 16; - if(app) { - /* ERROR: Failed to open directory! */ - dk3app_log_i3(app, DK3_LL_ERROR, 63, 64, dn); - } - } - } - if(ec) { - if(3 & ec) { - if(app) { - dk3app_log_i1(app, DK3_LL_ERROR, 9); - } - } - dk3dir_close(back); back = NULL; - } - } else { - if(app) { - /* ERROR: Directory name too long! */ - dk3app_log_i3(app, DK3_LL_ERROR, 59, 60, dn); - } - } - } - return back; -} - - -dk3_dir_t * -dk3dir_fne_open_app(dkChar const *fn, dk3_app_t *app) -{ - dk3_dir_t *back = NULL; - int ec = 0; /* Error code. */ - dkChar mybuffer[DK3_MAX_PATH]; /* Buffer for entry names. */ - dkChar myb2[2]; /* Search pattern. */ - dkChar *ptr = NULL; /* Last separator. */ - dkChar *namecopy = NULL; /* New copy of entry name. */ - intptr_t ffres; /* Result from findfirst(). */ - struct _wfinddata64_t ffdata; /* Find data. */ - $? "+ dk3dir_fne_open_app \"%ls\"", fn - if(fn) { - if(dk3str_len(fn) < DK3_MAX_PATH) { - dk3str_cpy_not_overlapped(mybuffer, fn); - ptr = dk3str_rchr(mybuffer, DK3_CHAR_SEP); - if(ptr) { - *ptr = DK3_CHAR_0; - back = dk3dir_new(mybuffer, app); - *ptr = DK3_CHAR_SEP; - } else { - myb2[0] = DK3_CHAR_0; - back = dk3dir_new(myb2, app); - } - if(back) { $? ". mybuffer = \"%ls\"", mybuffer - ffres = _wfindfirst64(mybuffer, &ffdata); - if(ffres != -1) { - do { $? ". entry \"%ls\"", ffdata.name - if(dk3str_cmp(ffdata.name, kw[0])) { $? ". comparison ok" - if(dk3str_cmp(ffdata.name, kw[1])) { $? ". comparison ok" - if((ffdata.attrib) & _A_SUBDIR) { $? ". sub directory" - dk3dir_add(back->sdi, ffdata.name, &(back->ndir), &ec, app); - } else { $? ". regular file" - dk3dir_add(back->sfi, ffdata.name, &(back->nfi), &ec, app); - } - } - } - } while(_wfindnext64(ffres, &ffdata) == 0); - _findclose(ffres); - } else { - ec |= 16; - if(app) { - /* ERROR: Failed to open directory! */ - dk3app_log_i3(app, DK3_LL_ERROR, 215, 216, mybuffer); - } - } - } - if(ec) { - if(3 & ec) { - if(app) { - dk3app_log_i1(app, DK3_LL_ERROR, 9); - } - } - dk3dir_close(back); back = NULL; - } - } else { - /* ERROR: Pattern too long! */ - dk3app_log_i3(app, DK3_LL_ERROR, 65, 66, fn); - } - } $? "- dk3dir_fne_open_app %!8s", TR_8PTR(back) - return back; -} - - -#else - - -static -dk3_dir_t * -dk3dir_my_open_app(dkChar const *dn, int usefne, dk3_app_t *app) -{ - WIN32_FIND_DATAW wfd; /* Details for file. */ - dkChar b1[DK3_MAX_PATH]; /* Directory base. */ - dkChar b2[DK3_MAX_PATH]; /* Pattern. */ - dkChar *p1; /* Separator. */ - dk3_dir_t *back = NULL; - HANDLE hSearch; /* File search handle. */ - size_t sz; /* String length. */ - int ok; /* Flag: No error yet. */ - int ec; /* Error code. */ - int isDir; /* Flag: Entry is dir. */ - $? "+ dk3dir_my_open_app \"%!ds\"", dn - ec = 0; - if(dn) { - ok = 0; - if(usefne) { - if(dk3str_len(dn) < DK3_SIZEOF(b1,dkChar)) { - ok = 1; $? ". ok" - dk3str_cpy_not_overlapped(b1, dn); - dk3str_cpy_not_overlapped(b2, dn); - p1 = dk3str_rchr(b1, DK3_CHAR_SEP); - if(p1) { - *p1 = dkT('\0'); - } else { - b1[0] = dkT('\0'); - } - } else { $? "! name too long" - /* ERROR: Name too long! */ - if(app) { - dk3app_log_i3(app, DK3_LL_ERROR, 65, 66, dn); - } - } - } else { - sz = dk3str_len(dn) + dk3str_len(kw[3]); - if(sz < DK3_SIZEOF(b1,dkChar)) { - ok = 1; $? ". ok" - dk3str_cpy_not_overlapped(b1, dn); - dk3str_cpy_not_overlapped(b2, dn); - sz = dk3str_len(b2); - if(sz > 1) { - dk3str_cat(b2, kw[(DK3_CHAR_SEP == b2[sz - 1]) ? 4 : 3]); - } else { - dk3str_cat(b2, kw[3]); - } - } else { $? "! name too long" - /* Name too long! */ - if(app) { - dk3app_log_i3(app, DK3_LL_ERROR, 59, 60, dn); - } - } - } - if(ok) { $? ". b1=\"%!ds\" b2=\"%!ds\"", b1, b2 - back = dk3dir_new(b1, app); - if(back) { $? ". alloc ok" - hSearch = FindFirstFileW(b2, &wfd); - if(INVALID_HANDLE_VALUE != hSearch) { $? ". FindFirstFile" - do { - isDir = 0; $? ". name=\"%ls\"", wfd.cFileName - if(dk3str_cmp(wfd.cFileName, kw[0])) { - if(dk3str_cmp(wfd.cFileName, kw[1])) { $? ". name ok" - if((wfd.dwFileAttributes) & FILE_ATTRIBUTE_DIRECTORY) { - isDir = 1; -#if 0 - if((wfd.dwFileAttributes) & FILE_ATTRIBUTE_REPARSE_POINT) { - switch(wfd.dwReserved0) { - case IO_REPARSE_TAG_MOUNT_POINT: { - isDir = 0; - } break; - } - } -#endif - } - if(isDir) { $? ". dir" - dk3dir_add(back->sdi, wfd.cFileName, &(back->ndir), &ec, app); - } else { $? ". no dir" - dk3dir_add(back->sfi, wfd.cFileName, &(back->nfi), &ec, app); - } - } - } - } while(FindNextFileW(hSearch, &wfd)); - FindClose(hSearch); - } else { $? "! FindFirstFileW" - /* ERROR: Failed to search for pattern! */ - ec |= 16; - if(app) { - if(usefne) { - dk3app_log_i3(app, DK3_LL_ERROR, 215, 216, dn); - } else { - dk3app_log_i3(app, DK3_LL_ERROR, 63, 64, dn); - } - } - } - if(ec) { - if(3 & ec) { - if(app) { - dk3app_log_i1(app, DK3_LL_ERROR, 9); - } - } - dk3dir_close(back); back = NULL; - } - } else { $? "! alloc" - } - } - } else { $? "! no dn" - } $? "- dk3dir_my_open_app %!8s", TR_8PTR(back) - return back; -} - - - -dk3_dir_t * -dk3dir_open_app(dkChar const *dn, dk3_app_t *app) -{ - dk3_dir_t *back; - $? "+ dk3dir_open_app \"%!ds\"", dn - back = dk3dir_my_open_app(dn, 0, app); - $? "- dk3dir_open_app %!8s", TR_8PTR(back) - return back; -} - - -dk3_dir_t * -dk3dir_fne_open_app(dkChar const *fn, dk3_app_t *app) -{ - dk3_dir_t *back; - $? "+ dk3dir_fne_open_app \"%!ds\"", fn - back = dk3dir_my_open_app(fn, 1, app); - $? "- dk3dir_fne_open_app %!8s", TR_8PTR(back) - return back; -} - - -#endif - - -/* --- Windows > 8 bit --- */ -#else -/* +++ Windows, 8 bit +++ */ - - - -#if VERSION_BEFORE_2012_04_13 - -dk3_dir_t * -dk3dir_open_app(dkChar const *dn, dk3_app_t *app) -{ - dk3_dir_t *back = NULL; - int ec = 0; /* Error code. */ - dkChar buffer[DK3_MAX_PATH]; /* Buffer for entry names. */ - intptr_t ffres; /* Result from findfirst(). */ - dkChar *namecopy = NULL; /* New copy of entry name. */ - struct __finddata64_t ffdata; /* Find data. */ - if(dn) { - if((dk3str_len(kw[3]) + dk3str_len(dn)) < DK3_SIZEOF(buffer,dkChar)) { - dk3str_cpy_not_overlapped(buffer, dn); - dk3str_cat(buffer, kw[3]); - back = dk3dir_new(dn, app); - if(back) { - ffres = _findfirst64(buffer, &ffdata); - if(ffres != -1) { - do { - if(dk3str_cmp(ffdata.name, kw[0])) { - if(dk3str_cmp(ffdata.name, kw[1])) { - if((ffdata.attrib) & _A_SUBDIR) { - dk3dir_add(back->sdi, ffdata.name, &(back->ndir), &ec, app); - } else { - dk3dir_add(back->sfi, ffdata.name, &(back->nfi), &ec, app); - } - } - } - } while(_findnext64(ffres, &ffdata) == 0); - _findclose(ffres); - } else { - ec |= 16; /* Findfirst failed */ - if(app) { - /* ERROR: Findfirst failed! */ - dk3app_log_i3(app, DK3_LL_ERROR, 63, 64, dn); - } - } - } - if(ec) { - if(3 & ec) { - if(app) { - dk3app_log_i1(app, DK3_LL_ERROR, 9); - } - } - dk3dir_close(back); back = NULL; - } - } else { - if(app) { - /* ERROR: Directory name too long! */ - dk3app_log_i3(app, DK3_LL_ERROR, 59, 60, dn); - } - } - } - return back; -} - - - -dk3_dir_t * -dk3dir_fne_open_app(dkChar const *fn, dk3_app_t *app) -{ - dk3_dir_t *back = NULL; - int ec = 0; /* Error code. */ - dkChar mybuffer[DK3_MAX_PATH]; /* Buffer for entry name. */ - dkChar myb2[2]; /* Buffer for pattern. */ - dkChar *ptr = NULL; /* Last separator. */ - dkChar *namecopy = NULL; /* New copy of entry name. */ - intptr_t ffres; /* Result from findfirst(). */ - struct __finddata64_t ffdata; /* Find data. */ - $? "+ dk3dir_fne_open_app \"%!ds\"", fn - if(fn) { - if(dk3str_len(fn) < DK3_MAX_PATH) { - dk3str_cpy_not_overlapped(mybuffer, fn); - ptr = dk3str_rchr(mybuffer, DK3_CHAR_SEP); - if(ptr) { - *ptr = DK3_CHAR_0; - back = dk3dir_new(mybuffer, app); - *ptr = DK3_CHAR_SEP; - } else { - myb2[0] = DK3_CHAR_0; - back = dk3dir_new(myb2, app); - } - if(back) { - ffres = _findfirst64(mybuffer, &ffdata); - if(ffres != -1) { - do { - if(dk3str_cmp(ffdata.name, kw[0])) { - if(dk3str_cmp(ffdata.name, kw[1])) { - if((ffdata.attrib) & _A_SUBDIR) { - dk3dir_add(back->sdi, ffdata.name, &(back->ndir), &ec, app); - } else { - dk3dir_add(back->sfi, ffdata.name, &(back->nfi), &ec, app); - } - } - } - } while(_findnext64(ffres, &ffdata) == 0); - _findclose(ffres); - } else { - ec |= 16; - if(app) { - /* ERROR: Failed to open directory! */ - dk3app_log_i3(app, DK3_LL_ERROR, 215, 216, mybuffer); - } - } - } - if(ec) { - if(3 & ec) { - if(app) { - dk3app_log_i1(app, DK3_LL_ERROR, 9); - } - } - dk3dir_close(back); back = NULL; - } - } else { - if(app) { - /* ERROR: Pattern too long! */ - dk3app_log_i3(app, DK3_LL_ERROR, 65, 66, fn); - } - } - } $? "- dk3dir_fne_open_app %!8s", TR_8PTR(back) - return back; -} - - -#else - - - -static -dk3_dir_t * -dk3dir_my_open_app(dkChar const *dn, int usefne, dk3_app_t *app) -{ - WIN32_FIND_DATAA wfd; /* Details for file. */ - dkChar b1[DK3_MAX_PATH]; /* Directory base. */ - dkChar b2[DK3_MAX_PATH]; /* Pattern. */ - dkChar *p1; /* Separator. */ - dk3_dir_t *back = NULL; - HANDLE hSearch; /* File search handle. */ - size_t sz; /* String length. */ - int ok; /* Flag: No error yet. */ - int ec; /* Error code. */ - int isDir; /* Flag: Entry is dir. */ - $? "+ dk3dir_my_open_app \"%!ds\"", dn - ec = 0; - if(dn) { - ok = 0; - if(usefne) { - if(dk3str_len(dn) < DK3_SIZEOF(b1,dkChar)) { - ok = 1; $? ". ok" - dk3str_cpy_not_overlapped(b1, dn); - dk3str_cpy_not_overlapped(b2, dn); - p1 = dk3str_rchr(b1, DK3_CHAR_SEP); - if(p1) { - *p1 = dkT('\0'); - } else { - b1[0] = dkT('\0'); - } - } else { $? "! name too long" - /* ERROR: Name too long! */ - if(app) { - dk3app_log_i3(app, DK3_LL_ERROR, 65, 66, dn); - } - } - } else { - sz = dk3str_len(dn) + dk3str_len(kw[3]); - if(sz < DK3_SIZEOF(b1,dkChar)) { - ok = 1; $? ". ok" - dk3str_cpy_not_overlapped(b1, dn); - dk3str_cpy_not_overlapped(b2, dn); - sz = dk3str_len(b2); - if(sz > 1) { - dk3str_cat(b2, kw[(DK3_CHAR_SEP == b2[sz - 1]) ? 4 : 3]); - } else { - dk3str_cat(b2, kw[3]); - } - } else { $? "! name too long" - /* ERROR: Name too long! */ - if(app) { - dk3app_log_i3(app, DK3_LL_ERROR, 59, 60, dn); - } - } - } - if(ok) { $? ". b1=\"%!ds\" b2=\"%!ds\"", b1, b2 - back = dk3dir_new(b1, app); - if(back) { $? ". alloc ok" - hSearch = FindFirstFileA(b2, &wfd); - if(INVALID_HANDLE_VALUE != hSearch) { $? ". FIndFirstFile" - do { - isDir = 0; $? ". name=\"%!8s\"", wfd.cFileName - if(dk3str_cmp(wfd.cFileName, kw[0])) { - if(dk3str_cmp(wfd.cFileName, kw[1])) { $? ". name ok" - if((wfd.dwFileAttributes) & FILE_ATTRIBUTE_DIRECTORY) { - isDir = 1; -#if 0 - if((wfd.dwFileAttributes) & FILE_ATTRIBUTE_REPARSE_POINT) { - switch(wfd.dwReserved0) { - case IO_REPARSE_TAG_MOUNT_POINT: { - isDir = 0; - } break; - } - } -#endif - } - if(isDir) { $? ". dir" - dk3dir_add(back->sdi, wfd.cFileName, &(back->ndir), &ec, app); - } else { $? ". no dir" - dk3dir_add(back->sfi, wfd.cFileName, &(back->nfi), &ec, app); - } - } - } - } while(FindNextFileA(hSearch, &wfd)); - FindClose(hSearch); - } else { $? "! FindFirstFileW" - /* ERROR: Failed to search for pattern! */ - ec |= 16; - if(app) { - if(usefne) { - dk3app_log_i3(app, DK3_LL_ERROR, 215, 216, dn); - } else { - dk3app_log_i3(app, DK3_LL_ERROR, 63, 64, dn); - } - } - } - if(ec) { - if(3 & ec) { - if(app) { - dk3app_log_i1(app, DK3_LL_ERROR, 9); - } - } - dk3dir_close(back); back = NULL; - } - } else { $? "! alloc" - } - } - } else { $? "! no dn" - } $? "- dk3dir_my_open_app %!8s", TR_8PTR(back) - return back; -} - - - -dk3_dir_t * -dk3dir_open_app(dkChar const *dn, dk3_app_t *app) -{ - dk3_dir_t *back; - $? "+ dk3dir_open_app \"%!ds\"", dn - back = dk3dir_my_open_app(dn, 0, app); - $? "- dk3dir_open_app %!8s", TR_8PTR(back) - return back; -} - - -dk3_dir_t * -dk3dir_fne_open_app(dkChar const *fn, dk3_app_t *app) -{ - dk3_dir_t *back; - $? "+ dk3dir_fne_open_app \"%!ds\"", fn - back = dk3dir_my_open_app(fn, 1, app); - $? "- dk3dir_fne_open_app %!8s", TR_8PTR(back) - return back; -} - - - -#endif - -/* --- Windows, 8 bit --- */ -#endif -/* --- Windows --- */ -#else -/* +++ non-Windows +++ */ -#if DK3_CHAR_SIZE > 1 -/* +++ non-Windows > 8 bit +++ */ -#error "16/32-bit file names only available on Windows!" -/* --- non-Windows > 8 bit --- */ -#else -/* +++ non-Windows, 8 bit +++ */ - - - -/** Function names used in error messages. -*/ -static dkChar const * const dk3dir_function_names[] = { -$!string-table macro=dkT -# -# 0 -# -opendir: -$!end -}; - - - -#if DK3_HAVE_OPENDIR && DK3_HAVE_READDIR && DK3_HAVE_CLOSEDIR - - - -dk3_dir_t * -dk3dir_open_app(dkChar const *dn, dk3_app_t *app) -{ - dk3_dir_t *back = NULL; - int ec = 0; /* Error code. */ - struct dirent *de = NULL; /* Directory entry from readdir(). */ - DIR *d = NULL; /* Directory structure from opendir(). */ - size_t sz = 0; /* Length of entire file name. */ - size_t dns = 0; /* Directory name length. */ - size_t kw2l = 0; /* Length of separator string. */ - dk3_stat_t stb; /* Buffer for stat() result. */ - $? "+ dk3dir_open_app" - if(dn) { - back = dk3dir_new(dn, app); - if(back) { - d = opendir(dn); - if(d) { - dns = dk3str_len(dn); kw2l = dk3str_len(kw[2]); - while((de = readdir(d)) != NULL) { - if(dk3str_cmp(de->d_name, kw[0])) { - if(dk3str_cmp(de->d_name, kw[1])) { - sz = dns + kw2l + dk3str_len(de->d_name); - if(sz < DK3_MAX_PATH) { - dk3str_cpy_not_overlapped(back->fullname, dn); - dk3str_cat(back->fullname, kw[2]); - dk3str_cat(back->fullname, de->d_name); - if(dk3sf_stat_app(&stb, back->fullname, NULL)) { - switch((stb.ft) & (~(DK3_FT_SYMLINK))) { - case DK3_FT_DIRECTORY: { - dk3dir_add(back->sdi,de->d_name,&(back->ndir),&ec,app); - } break; - default: { - dk3dir_add(back->sfi,de->d_name,&(back->nfi),&ec,app); - } break; - } - } else { - if(!(ec & 8)) { - if(app) { - /* Stat failed! */ - dk3app_log_i3(app,DK3_LL_ERROR,61,62,back->fullname); - } - } ec |= 8; - } - } else { - if(!(ec & 4)) { - if(app) { - /* Directory name too long! */ - dk3app_log_i3(app, DK3_LL_ERROR, 59, 60, dn); - } - } ec |= 4; - } - } - } - } - closedir(d); - } else { - ec |= 16; - if(app) { - /* Failed to open directory! */ - dk3app_log_i3(app, DK3_LL_ERROR, 63, 64, dn); - dk3sf_report_errno(app, errno, dk3dir_function_names[0]); - } - } - if(ec) { - if(3 & ec) { - if(app) { - dk3app_log_i1(app, DK3_LL_ERROR, 9); - } - } - dk3dir_close(back); back = NULL; - } - } - } $? "- dk3dir_open_app %!8s", TR_8PTR(back) - return back; -} - - - -dk3_dir_t * -dk3dir_fne_open_app(dkChar const *fn, dk3_app_t *app) -{ - dk3_dir_t *back = NULL; - int ec = 0; /* Error code. */ - dk3_stat_t stb; /* Stat buffer. */ - dkChar mybuffer[DK3_MAX_PATH]; /* Buffer for entire file name. */ - dkChar myb2[2]; /* Pattern buffer. */ - dkChar *ptr; /* Last separator in pattern. */ - $? "+ dk3dir_fne_open_app \"%!ds\"", fn - if(fn) { - if(dk3str_len(fn) < DK3_MAX_PATH) { - dk3str_cpy_not_overlapped(mybuffer, fn); - if(dk3sf_stat_app(&stb, fn, app)) { - ptr = dk3str_rchr(mybuffer, DK3_CHAR_SEP); - if(ptr) { - *(ptr++) = DK3_CHAR_0; - back = dk3dir_new(mybuffer, app); - } else { - myb2[0] = DK3_CHAR_0; - back = dk3dir_new(myb2, app); - ptr = mybuffer; - } - if(back) { - switch((stb.ft) & (~(DK3_FT_SYMLINK))) { - case DK3_FT_DIRECTORY: { - dk3dir_add(back->sdi, ptr, &(back->ndir), &ec, app); - } break; - default: { - dk3dir_add(back->sfi, ptr, &(back->nfi), &ec, app); - } break; - } - if(ec) { - if(3 & ec) { - if(app) { - dk3app_log_i1(app, DK3_LL_ERROR, 9); - } - } - dk3dir_close(back); back = NULL; - } - } - } - } else { - if(app) { - /* Name too long! */ - dk3app_log_i3(app, DK3_LL_ERROR, 65, 66, fn); - } - } - } $? "- dk3dir_fne_open_app %!8s", TR_8PTR(back) - return back; -} - - - -#else -#error "No opendir()/readdir()/closedir() function set!" -#endif - -/* --- non-Windows, 8 bit --- */ -#endif -/* --- non-Windows --- */ -#endif - - -/** Directory chain cell. -*/ -struct _dk3_dir_cell_t_ { - struct _dk3_dir_cell_t_ *parent; /**< Parent cell. */ - dk3_dir_t *dir; /**< Directory structure. */ -}; -/** Directory chain cell. -*/ -typedef struct _dk3_dir_cell_t_ DK3_DIR_CELL; - - - -/** Destroy chain cell, release memory. - @param c Cell to destroy. -*/ -static -void -dk3dir_cell_delete(DK3_DIR_CELL *c) -{ - if(c) { - if(c->dir) { - dk3dir_close(c->dir); - } - c->dir = NULL; - c->parent = NULL; - dk3_delete(c); - } -} - - - -/** Create directory cell, allocate memory. - @param n Directory name. - @param p Parent cell in chain. - @param app Application structure for diagnostics. - @return Pointer to new cell on success, NULL on error. -*/ -static -DK3_DIR_CELL * -dk3dir_cell_new(dkChar const *n, DK3_DIR_CELL *p, dk3_app_t *app) -{ - DK3_DIR_CELL *back = NULL; - back = dk3_new_app(DK3_DIR_CELL,1,app); - if(back) { - back->parent = p; - back->dir = dk3dir_open_app(n, app); - if(!(back->dir)) { - dk3dir_cell_delete(back); back = NULL; - } - } - return back; -} - - - -#if DK3_ON_WINDOWS -/** Remove a directory reparse point. - @param dn Directory to remove. - @param app Application structure for diagnostics, may be NULL. - @return 1 on success, 0 on error. -*/ -static -int -dk3dir_remove_reparse_point(dkChar const *dn, dk3_app_t *app) -{ - int back = 0; - if(dk3sf_remove_dir_app(dn, app)) { - back = 1; - } else { - if(dk3sf_remove_file_app(dn, app)) { - back = 1; - } - } - return back; -} -#endif - - - -int -dk3dir_remove_app(dkChar const *dn, dk3_app_t *app) -{ - int back = 0; - dk3_stat_t stb; /* Stat buffer. */ - dkChar const *en = NULL; /* Entry name. */ - dkChar const *xdn; /* Current dir to delete. */ - dk3_stat_t const *es = NULL; /* Entry stat buffer. */ - DK3_DIR_CELL *ccell = NULL; /* Current cell. */ - DK3_DIR_CELL *ncell = NULL; /* New cell or next cell. */ -#if VERSION_BEFORE_20150821 - int ft; /* File type. */ -#endif - - if(dn) { - if(dk3sf_stat_app(&stb, dn, app)) { - if((stb.ft) & DK3_FT_SYMLINK) { /* symbolic link */ - /* Removing symbolic link only, not target! */ - back = dk3sf_remove_file_app(dn, app); - } else { - if(stb.ft == DK3_FT_DIRECTORY) { - -#if DK3_ON_WINDOWS - if(0x00 == stb.cReparse) { -#endif - ccell = dk3dir_cell_new(dn, NULL, app); - if(ccell) { - back = 1; - while(ccell) { - if(dk3dir_get_next_directory(ccell->dir)) { - en = dk3dir_get_fullname(ccell->dir); - if(en) { - es = dk3dir_get_stat(ccell->dir); - if(es) { - if((es->ft) & DK3_FT_SYMLINK) { - if(!dk3sf_remove_file_app(en, app)) { - back = 0; - } - } else { -#if DK3_ON_WINDOWS - if(0x00 == es->cReparse) { -#endif - ncell = dk3dir_cell_new(en, ccell, app); - if(ncell) { - ccell = ncell; - } else { - back = 0; - } -#if DK3_ON_WINDOWS - } else { - if(!dk3dir_remove_reparse_point(en, app)) { - back = 0; - } - } -#endif - } - } else { - back = 0; - /* BUG: Internal error. */ - } - } else { - back = 0; - /* BUG: Internal error. */ - } - } else { - while(dk3dir_get_next_file(ccell->dir)) { -#if VERSION_BEFORE_20150821 - ft = DK3_FT_REGULAR; -#endif - en = dk3dir_get_fullname(ccell->dir); -#if VERSION_BEFORE_20150821 - es = dk3dir_get_stat(ccell->dir); - if(es) { ft = es->ft; } -#endif - if(en) { - if(!dk3sf_remove_file_app(en, app)) { - back = 0; - } - } else { - back = 0; - /* BUG: Internal error. */ - } - } - ncell = ccell->parent; - if(ccell->dir) { - xdn = dk3dir_get_directory_name(ccell->dir); - if(xdn) { - if(!dk3sf_remove_dir_app(xdn, app)) { - back = 0; - } - } - } - dk3dir_cell_delete(ccell); - ccell = ncell; - } - } - } -#if DK3_ON_WINDOWS - } else { - if(!dk3dir_remove_reparse_point(dn, app)) { - back = 0; - } - } -#endif - } else { - /* ERROR: Not a directory! */ - dk3app_log_i3(app, DK3_LL_ERROR, 202, 203, dn); - } - } - } - } - return back; -} - - - -/* vim: set ai sw=2 : */ - |