00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00047 #ifndef WINSTL_INCL_WINSTL_FILESYSTEM_HPP_DIRECTORY_FUNCTIONS
00048 #define WINSTL_INCL_WINSTL_FILESYSTEM_HPP_DIRECTORY_FUNCTIONS
00049
00050 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00051 # define WINSTL_VER_WINSTL_FILESYSTEM_HPP_DIRECTORY_FUNCTIONS_MAJOR 5
00052 # define WINSTL_VER_WINSTL_FILESYSTEM_HPP_DIRECTORY_FUNCTIONS_MINOR 0
00053 # define WINSTL_VER_WINSTL_FILESYSTEM_HPP_DIRECTORY_FUNCTIONS_REVISION 3
00054 # define WINSTL_VER_WINSTL_FILESYSTEM_HPP_DIRECTORY_FUNCTIONS_EDIT 47
00055 #endif
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 #ifndef WINSTL_INCL_WINSTL_H_WINSTL
00072 # include <winstl/winstl.h>
00073 #endif
00074 #ifndef WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS
00075 # include <winstl/filesystem/filesystem_traits.hpp>
00076 #endif
00077 #ifndef WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FILE_PATH_BUFFER
00078 # include <winstl/filesystem/file_path_buffer.hpp>
00079 #endif
00080 #ifdef _ATL_MIN_CRT
00081 # ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_SELECTOR
00082 # include <stlsoft/memory/allocator_selector.hpp>
00083 # endif
00084 #endif
00085
00086
00087
00088
00089
00090 #ifndef _WINSTL_NO_NAMESPACE
00091 # if defined(_STLSOFT_NO_NAMESPACE) || \
00092 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00093
00094 namespace winstl
00095 {
00096 # else
00097
00098
00099 namespace stlsoft
00100 {
00101
00102 namespace winstl_project
00103 {
00104
00105 # endif
00106 #endif
00107
00108
00109
00110
00111
00112 template <ss_typename_param_k C>
00113 inline C* find_last_path_name_separator_(C const* s)
00114 {
00115 typedef filesystem_traits<C> traits_t;
00116
00117 ss_typename_type_k traits_t::char_type const* slash = traits_t::str_rchr(s, '/');
00118 ss_typename_type_k traits_t::char_type const* bslash = traits_t::str_rchr(s, '\\');
00119
00120 if(NULL == slash)
00121 {
00122 slash = bslash;
00123 }
00124 else if(NULL != bslash)
00125 {
00126 if(slash < bslash)
00127 {
00128 slash = bslash;
00129 }
00130 }
00131
00132 return const_cast<C*>(slash);
00133 }
00134
00135 template <ss_typename_param_k C>
00136 inline ws_bool_t create_directory_recurse_impl(C const* dir, LPSECURITY_ATTRIBUTES lpsa)
00137 {
00138 typedef C char_type;
00139 typedef filesystem_traits<C> traits_t;
00140 #ifdef _ATL_MIN_CRT
00141 typedef ss_typename_type_k stlsoft_ns_qual(allocator_selector)<C>::allocator_type allocator_t;
00142 typedef basic_file_path_buffer< char_type
00143 , allocator_t
00144 > file_path_buffer_t;
00145 #else
00146 typedef basic_file_path_buffer<char_type> file_path_buffer_t;
00147 #endif
00148
00149 ws_bool_t bRet;
00150
00151 if( NULL == dir ||
00152 '\0' == *dir)
00153 {
00154 traits_t::set_last_error(ERROR_DIRECTORY);
00155
00156 bRet = false;
00157 }
00158 else
00159 {
00160 if(traits_t::file_exists(dir))
00161 {
00162 if(traits_t::is_directory(dir))
00163 {
00164 traits_t::set_last_error(ERROR_ALREADY_EXISTS);
00165
00166 bRet = true;
00167 }
00168 else
00169 {
00170 traits_t::set_last_error(ERROR_FILE_EXISTS);
00171
00172 bRet = false;
00173 }
00174 }
00175 else
00176 {
00177 file_path_buffer_t sz;
00178 file_path_buffer_t szParent;
00179
00180
00181
00182
00183
00184
00185 if( 0 == sz.size() ||
00186 0 == szParent.size())
00187 {
00188 bRet = false;
00189 }
00190 else
00191 {
00192 ws_size_t dirLen = traits_t::str_len(dir);
00193 traits_t::char_copy(&sz[0], dir, dirLen);
00194 sz[dirLen] = '\0';
00195 traits_t::remove_dir_end(&sz[0]);
00196
00197 if( traits_t::create_directory(sz.c_str(), lpsa) ||
00198 ERROR_ALREADY_EXISTS == traits_t::get_last_error())
00199 {
00200 traits_t::set_last_error(ERROR_SUCCESS);
00201
00202 bRet = true;
00203 }
00204 else
00205 {
00206
00207 ws_size_t szLen = traits_t::str_len(dir);
00208 traits_t::char_copy(&szParent[0], sz.c_str(), szLen);
00209 szParent[szLen] = '\0';
00210
00211 char_type* pszSlash = find_last_path_name_separator_<C>(szParent.c_str());
00212 if(pszSlash == NULL)
00213 {
00214 traits_t::set_last_error(ERROR_DIRECTORY);
00215
00216 bRet = false;
00217 }
00218 else
00219 {
00220 *pszSlash = '\0';
00221
00222
00223
00224 if( ( szParent[1] == ':' &&
00225 (traits_t::set_last_error(ERROR_CANNOT_MAKE), traits_t::str_len(szParent.c_str()) < 4)) ||
00226 !create_directory_recurse(szParent.c_str(), lpsa))
00227 {
00228 bRet = false;
00229 }
00230 else
00231 {
00232 bRet = traits_t::create_directory(sz.c_str(), lpsa) || ERROR_ALREADY_EXISTS == traits_t::get_last_error();
00233 }
00234 }
00235 }
00236 }
00237 }
00238 }
00239
00240 return bRet;
00241 }
00242
00243 template< ss_typename_param_k C
00244 , ss_typename_param_k FD
00245 >
00246 inline ws_dword_t remove_directory_recurse_impl(C const* dir, ws_int_t (*pfn)(void* param, C const* subDir, FD const* st, DWORD err), void* param)
00247 {
00248 typedef C char_type;
00249 typedef filesystem_traits<C> traits_t;
00250 #ifdef _ATL_MIN_CRT
00251 typedef ss_typename_type_k stlsoft_ns_qual(allocator_selector)<C>::allocator_type allocator_t;
00252 typedef basic_file_path_buffer< char_type
00253 , allocator_t
00254 > file_path_buffer_t;
00255 #else
00256 typedef basic_file_path_buffer<char_type> file_path_buffer_t;
00257 #endif
00258
00259 ws_dword_t dwRet = static_cast<ws_dword_t>(E_FAIL);
00260
00261 if(NULL != pfn)
00262 {
00263
00264 (void)(*pfn)(param, dir, NULL, ~static_cast<ws_dword_t>(0));
00265 }
00266
00267 if( NULL == dir ||
00268 '\0' == *dir)
00269 {
00270 dwRet = ERROR_DIRECTORY;
00271
00272 if(NULL != pfn)
00273 {
00274
00275 (void)(*pfn)(param, dir, NULL, dwRet);
00276 }
00277 }
00278 else
00279 {
00280 if(!traits_t::file_exists(dir))
00281 {
00282
00283
00284
00285 dwRet = ERROR_PATH_NOT_FOUND;
00286
00287 if(NULL != pfn)
00288 {
00289
00290 (void)(*pfn)(param, dir, NULL, dwRet);
00291 }
00292 }
00293 else
00294 {
00295 if(traits_t::is_file(dir))
00296 {
00297
00298 dwRet = ERROR_FILE_EXISTS;
00299
00300 if(NULL != pfn)
00301 {
00302
00303 (void)(*pfn)(param, dir, NULL, dwRet);
00304 }
00305 }
00306 else
00307 {
00308
00309 if(traits_t::remove_directory(dir))
00310 {
00311 dwRet = ERROR_SUCCESS;
00312
00313 if(NULL != pfn)
00314 {
00315
00316 (void)(*pfn)(param, dir, NULL, dwRet);
00317 }
00318 }
00319 else
00320 {
00321 const DWORD removeError = traits_t::get_last_error();
00322
00323 if( ERROR_DIR_NOT_EMPTY != removeError &&
00324 ERROR_SHARING_VIOLATION != removeError)
00325 {
00326 dwRet = removeError;
00327
00328 if(NULL != pfn)
00329 {
00330
00331 (void)(*pfn)(param, dir, NULL, dwRet);
00332 }
00333 }
00334 else
00335 {
00336
00337
00338 ss_typename_type_k traits_t::stat_data_type st;
00339 file_path_buffer_t sz;
00340 HANDLE hSrch;
00341 ws_size_t n;
00342 ws_size_t dirLen = traits_t::str_len(dir);
00343 ws_size_t allLen = traits_t::str_len(traits_t::pattern_all());
00344
00345 traits_t::char_copy(&sz[0], dir, dirLen);
00346 sz[dirLen] = '\0';
00347 traits_t::ensure_dir_end(&sz[0]);
00348 n = traits_t::str_len(sz.c_str());
00349 WINSTL_ASSERT(n + traits_t::str_len(traits_t::pattern_all()) < traits_t::maxPathLength);
00350 traits_t::char_copy(&sz[n], traits_t::pattern_all(), allLen);
00351 sz[n + allLen] = '\0';
00352
00353 hSrch = traits_t::find_first_file(sz.c_str(), &st);
00354 if(INVALID_HANDLE_VALUE == hSrch)
00355 {
00356 dwRet = traits_t::get_last_error();
00357 }
00358 else
00359 {
00360 dwRet = ERROR_SUCCESS;
00361
00362 do
00363 {
00364 if(!traits_t::is_dots(st.cFileName))
00365 {
00366 ws_size_t filenameLen = traits_t::str_len(st.cFileName);
00367 traits_t::char_copy(&sz[n], st.cFileName, filenameLen);
00368 sz[n + filenameLen] = '\0';
00369
00370 if(traits_t::is_file(sz.c_str()))
00371 {
00372
00373
00374
00375 ws_int_t r = 0;
00376
00377 if( NULL == pfn ||
00378 0 == (r = (*pfn)(param, dir, &st, ERROR_SUCCESS)))
00379 {
00380 dwRet = ERROR_DIR_NOT_EMPTY;
00381
00382 if(NULL != pfn)
00383 {
00384
00385 (void)(*pfn)(param, dir, &st, dwRet);
00386 }
00387
00388 break;
00389 }
00390 else
00391 {
00392 if(r > 0)
00393 {
00394 if(!traits_t::delete_file(sz.c_str()))
00395 {
00396 dwRet = traits_t::get_last_error();
00397
00398 if(NULL != pfn)
00399 {
00400
00401 (void)(*pfn)(param, dir, &st, dwRet);
00402 }
00403
00404 break;
00405 }
00406 }
00407 }
00408 }
00409 else
00410 {
00411 ws_int_t r = 1;
00412
00413
00414
00415 if( NULL != pfn &&
00416 0 == (r = (*pfn)(param, dir, &st, ERROR_SUCCESS)))
00417 {
00418 dwRet = ERROR_DIR_NOT_EMPTY;
00419
00420 if(NULL != pfn)
00421 {
00422
00423 (void)(*pfn)(param, dir, &st, dwRet);
00424 }
00425
00426 break;
00427 }
00428 else
00429 {
00430 if(r > 0)
00431 {
00432 dwRet = remove_directory_recurse_impl(sz.c_str(), pfn, param);
00433 }
00434 }
00435 }
00436 }
00437
00438 } while(traits_t::find_next_file(hSrch, &st));
00439
00440 traits_t::find_file_close(hSrch);
00441
00442 if(ERROR_SUCCESS == dwRet)
00443 {
00444 if(traits_t::remove_directory(dir))
00445 {
00446 if(NULL != pfn)
00447 {
00448
00449 (void)(*pfn)(param, dir, NULL, ERROR_SUCCESS);
00450 }
00451 }
00452 else
00453 {
00454 dwRet = traits_t::get_last_error();
00455 }
00456 }
00457 }
00458 }
00459 }
00460 }
00461 }
00462 }
00463
00464 return dwRet;
00465 }
00466
00467
00468
00469
00470
00479 inline ws_bool_t create_directory_recurse(ws_char_a_t const* dir, LPSECURITY_ATTRIBUTES lpsa = NULL)
00480 {
00481 return create_directory_recurse_impl(dir, lpsa);
00482 }
00483
00492 inline ws_bool_t create_directory_recurse(ws_char_w_t const* dir, LPSECURITY_ATTRIBUTES lpsa = NULL)
00493 {
00494 return create_directory_recurse_impl(dir, lpsa);
00495 }
00496
00505 template <ss_typename_param_k S>
00506 inline ws_bool_t create_directory_recurse(S const& dir, LPSECURITY_ATTRIBUTES lpsa = NULL)
00507 {
00508 return create_directory_recurse(stlsoft_ns_qual(c_str_ptr)(dir), lpsa);
00509 }
00510
00557 inline ws_bool_t remove_directory_recurse( ws_char_a_t const* dir
00558 , ws_int_t (*pfn)(void* param, ws_char_a_t const* subDir, WIN32_FIND_DATAA const* st, DWORD err)
00559 , void* param)
00560 {
00561 typedef filesystem_traits<ws_char_a_t> traits_t;
00562
00563 ws_dword_t dwRet = remove_directory_recurse_impl<ws_char_a_t, WIN32_FIND_DATAA>(dir, pfn, param);
00564
00565 traits_t::set_last_error(dwRet);
00566
00567 return ERROR_SUCCESS == dwRet;
00568 }
00569
00574 inline ws_bool_t remove_directory_recurse(ws_char_a_t const* dir)
00575 {
00576 return remove_directory_recurse(dir, NULL, NULL);
00577 }
00578
00583 inline ws_bool_t remove_directory_recurse(
00584 ws_char_w_t const* dir
00585 , ws_int_t (*pfn)(void* param, ws_char_w_t const* subDir, WIN32_FIND_DATAW const* st, DWORD err)
00586 , void* param
00587 )
00588 {
00589 typedef filesystem_traits<ws_char_w_t> traits_t;
00590
00591 ws_dword_t dwRet = remove_directory_recurse_impl<ws_char_w_t, WIN32_FIND_DATAW>(dir, pfn, param);
00592
00593 traits_t::set_last_error(dwRet);
00594
00595 return ERROR_SUCCESS == dwRet;
00596 }
00597
00602 inline ws_bool_t remove_directory_recurse(ws_char_w_t const* dir)
00603 {
00604 return remove_directory_recurse(dir, NULL, NULL);
00605 }
00606
00607 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00608
00613 template <ss_typename_param_k S>
00614 inline ws_bool_t remove_directory_recurse(S const& dir)
00615 {
00616 typedef filesystem_traits<ws_char_w_t> traits_t;
00617
00618 ws_dword_t dwRet = remove_directory_recurse(stlsoft_ns_qual(c_str_ptr)(dir), NULL, NULL);
00619
00620 traits_t::set_last_error(dwRet);
00621
00622 return ERROR_SUCCESS == dwRet;
00623 }
00624
00625 #endif
00626
00627
00628
00629
00630
00631 #ifdef STLSOFT_UNITTEST
00632 # include "./unittest/directory_functions_unittest_.h"
00633 #endif
00634
00635
00636
00637 #ifndef _WINSTL_NO_NAMESPACE
00638 # if defined(_STLSOFT_NO_NAMESPACE) || \
00639 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00640 }
00641 # else
00642 }
00643 }
00644 # endif
00645 #endif
00646
00647
00648
00649 #endif
00650
00651