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 UNIXSTL_INCL_UNIXSTL_FILESYSTEM_HPP_DIRECTORY_FUNCTIONS
00048 #define UNIXSTL_INCL_UNIXSTL_FILESYSTEM_HPP_DIRECTORY_FUNCTIONS
00049
00050 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00051 # define UNIXSTL_VER_UNIXSTL_FILESYSTEM_HPP_DIRECTORY_FUNCTIONS_MAJOR 3
00052 # define UNIXSTL_VER_UNIXSTL_FILESYSTEM_HPP_DIRECTORY_FUNCTIONS_MINOR 0
00053 # define UNIXSTL_VER_UNIXSTL_FILESYSTEM_HPP_DIRECTORY_FUNCTIONS_REVISION 5
00054 # define UNIXSTL_VER_UNIXSTL_FILESYSTEM_HPP_DIRECTORY_FUNCTIONS_EDIT 41
00055 #endif
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 #ifndef UNIXSTL_INCL_UNIXSTL_H_UNIXSTL
00072 # include <unixstl/unixstl.h>
00073 #endif
00074 #ifndef UNIXSTL_INCL_UNIXSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS
00075 # include <unixstl/filesystem/filesystem_traits.hpp>
00076 #endif
00077 #ifndef UNIXSTL_INCL_UNIXSTL_FILESYSTEM_HPP_FILE_PATH_BUFFER
00078 # include <unixstl/filesystem/file_path_buffer.hpp>
00079 #endif
00080
00081
00082
00083
00084
00085 #ifndef _UNIXSTL_NO_NAMESPACE
00086 # if defined(_STLSOFT_NO_NAMESPACE) || \
00087 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00088
00089 namespace unixstl
00090 {
00091 # else
00092
00093
00094 namespace stlsoft
00095 {
00096
00097 namespace unixstl_project
00098 {
00099
00100 # endif
00101 #endif
00102
00103
00104
00105
00106
00107 template <ss_typename_param_k C>
00108 inline C *find_last_path_name_separator_(C const* s)
00109 {
00110 typedef filesystem_traits<C> traits_t;
00111
00112 ss_typename_type_k traits_t::char_type const *slash = traits_t::str_rchr(s, '/');
00113 #ifdef _WIN32
00114 ss_typename_type_k traits_t::char_type const *bslash = traits_t::str_rchr(s, '\\');
00115
00116 if(NULL == slash)
00117 {
00118 slash = bslash;
00119 }
00120 else if(NULL != bslash)
00121 {
00122 if(slash < bslash)
00123 {
00124 slash = bslash;
00125 }
00126 }
00127 #endif
00128
00129 return const_cast<C*>(slash);
00130 }
00131
00132 template <ss_typename_param_k C>
00133 inline us_bool_t create_directory_recurse_impl(C const* dir, unsigned short mode)
00134 {
00135 typedef C char_type;
00136 typedef filesystem_traits<C> traits_t;
00137 typedef basic_file_path_buffer<char_type> file_path_buffer_t;
00138
00139 us_bool_t bRet;
00140
00141 if( NULL == dir ||
00142 '\0' == *dir)
00143 {
00144 traits_t::set_last_error(ENOTDIR);
00145
00146 bRet = false;
00147 }
00148 else
00149 {
00150 if(traits_t::file_exists(dir))
00151 {
00152 if(traits_t::is_directory(dir))
00153 {
00154 traits_t::set_last_error(EISDIR);
00155
00156 bRet = true;
00157 }
00158 else
00159 {
00160 traits_t::set_last_error(EEXIST);
00161
00162 bRet = false;
00163 }
00164 }
00165 else
00166 {
00167 file_path_buffer_t sz;
00168 file_path_buffer_t szParent;
00169
00170
00171
00172
00173
00174
00175 if( 0 == sz.size() ||
00176 0 == szParent.size())
00177 {
00178 bRet = false;
00179 }
00180 else
00181 {
00182 traits_t::str_copy(&sz[0], dir);
00183 traits_t::remove_dir_end(&sz[0]);
00184
00185 if( traits_t::create_directory(sz.c_str(), mode) ||
00186 EEXIST == traits_t::get_last_error())
00187 {
00188 traits_t::set_last_error(0);
00189
00190 bRet = true;
00191 }
00192 else
00193 {
00194
00195 traits_t::str_copy(&szParent[0], sz.c_str());
00196
00197 char_type *pszSlash = find_last_path_name_separator_(szParent.c_str());
00198 if(pszSlash == NULL)
00199 {
00200 traits_t::set_last_error(ENOTDIR);
00201
00202 bRet = false;
00203 }
00204 else
00205 {
00206 *pszSlash = '\0';
00207
00208
00209
00210 if( ( szParent[1] == ':' &&
00211 (traits_t::set_last_error(EACCES), traits_t::str_len(szParent.c_str()) < 4)) ||
00212 !create_directory_recurse(szParent.c_str(), mode))
00213 {
00214 bRet = false;
00215 }
00216 else
00217 {
00218 bRet = traits_t::create_directory(sz.c_str(), mode) || EEXIST == traits_t::get_last_error();
00219 }
00220 }
00221 }
00222 }
00223 }
00224 }
00225
00226 return bRet;
00227 }
00228
00229 template< ss_typename_param_k C
00230 , ss_typename_param_k FD
00231 >
00232 inline us_int_t remove_directory_recurse_impl(C const* dir, us_int_t (*pfn)(void* param, C const* subDir, FD const* st, struct dirent const* de, int err), void* param)
00233 {
00234 typedef C char_type;
00235 typedef filesystem_traits<C> traits_t;
00236 typedef basic_file_path_buffer<char_type> file_path_buffer_t;
00237 us_int_t dwRet;
00238
00239 if(NULL != pfn)
00240 {
00241 (void)(*pfn)(param, dir, NULL, NULL, ~0);
00242 }
00243
00244 if( NULL == dir ||
00245 '\0' == *dir)
00246 {
00247 dwRet = ENOTDIR;
00248
00249 if(NULL != pfn)
00250 {
00251 (void)(*pfn)(param, dir, NULL, NULL, dwRet);
00252 }
00253 }
00254 else
00255 {
00256 if(!traits_t::file_exists(dir))
00257 {
00258
00259
00260
00261 dwRet = ENOENT;
00262
00263 if(NULL != pfn)
00264 {
00265 (void)(*pfn)(param, dir, NULL, NULL, dwRet);
00266 }
00267 }
00268 else
00269 {
00270 if(traits_t::is_file(dir))
00271 {
00272
00273 dwRet = EEXIST;
00274
00275 if(NULL != pfn)
00276 {
00277 (void)(*pfn)(param, dir, NULL, NULL, dwRet);
00278 }
00279 }
00280 else
00281 {
00282
00283 if(traits_t::remove_directory(dir))
00284 {
00285 dwRet = 0;
00286
00287 if(NULL != pfn)
00288 {
00289 (void)(*pfn)(param, dir, NULL, NULL, dwRet);
00290 }
00291 }
00292 else
00293 {
00294 const int removeError = traits_t::get_last_error();
00295
00296 if(ENOTEMPTY != removeError)
00297 {
00298 dwRet = removeError;
00299
00300 if(NULL != pfn)
00301 {
00302 (void)(*pfn)(param, dir, NULL, NULL, dwRet);
00303 }
00304 }
00305 else
00306 {
00307
00308
00309 file_path_buffer_t sz;
00310 DIR *hSrch;
00311 us_size_t n;
00312
00313 traits_t::str_copy(&sz[0], dir);
00314 traits_t::ensure_dir_end(&sz[0]);
00315 n = traits_t::str_len(sz.c_str());
00316
00317 hSrch = traits_t::open_dir(sz.c_str());
00318 if(NULL == hSrch)
00319 {
00320 dwRet = traits_t::get_last_error();
00321 }
00322 else
00323 {
00324 dwRet = 0;
00325
00326 for(struct dirent const* de; 0 == dwRet && NULL != (de = traits_t::read_dir(hSrch)); )
00327 {
00328 if(!traits_t::is_dots(de->d_name))
00329 {
00330 ss_typename_type_k traits_t::stat_data_type st;
00331
00332 traits_t::str_copy(&sz[0] + n, de->d_name);
00333 if(!traits_t::stat(sz.c_str(), &st))
00334 {
00335 dwRet = traits_t::get_last_error();
00336
00337 if(NULL != pfn)
00338 {
00339 (void)(*pfn)(param, dir, NULL, de, dwRet);
00340 }
00341 }
00342 else
00343 {
00344 if(traits_t::is_file(&st))
00345 {
00346
00347
00348
00349 if( NULL == pfn ||
00350 !(*pfn)(param, dir, &st, de, 0))
00351 {
00352 dwRet = ENOTEMPTY;
00353
00354 if(NULL != pfn)
00355 {
00356 (void)(*pfn)(param, dir, &st, de, dwRet);
00357 }
00358
00359 break;
00360 }
00361 else
00362 {
00363 if(!traits_t::delete_file(sz.c_str()))
00364 {
00365 dwRet = traits_t::get_last_error();
00366
00367 if(NULL != pfn)
00368 {
00369 (void)(*pfn)(param, dir, &st, de, dwRet);
00370 }
00371
00372 break;
00373 }
00374 }
00375 }
00376 else
00377 {
00378
00379
00380 if( NULL != pfn &&
00381 !(*pfn)(param, dir, &st, de, 0))
00382 {
00383 dwRet = ENOTEMPTY;
00384
00385 if(NULL != pfn)
00386 {
00387 (void)(*pfn)(param, dir, &st, de, dwRet);
00388 }
00389
00390 break;
00391 }
00392 else
00393 {
00394 dwRet = remove_directory_recurse_impl(sz.c_str(), pfn, param);
00395 }
00396 }
00397 }
00398 }
00399 }
00400
00401 traits_t::close_dir(hSrch);
00402
00403 if(0 == dwRet)
00404 {
00405 if(traits_t::remove_directory(dir))
00406 {
00407 if(NULL != pfn)
00408 {
00409 (void)(*pfn)(param, dir, NULL, NULL, 0);
00410 }
00411 }
00412 else
00413 {
00414 dwRet = traits_t::get_last_error();
00415 }
00416 }
00417 }
00418 }
00419 }
00420 }
00421 }
00422 }
00423
00424 return dwRet;
00425 }
00426
00427
00428
00429
00430
00439 inline us_bool_t create_directory_recurse(us_char_a_t const* dir, unsigned short mode = 0755)
00440 {
00441 return create_directory_recurse_impl(dir, mode);
00442 }
00443
00444 #if 0
00445
00453 inline us_bool_t create_directory_recurse(us_char_w_t const* dir, unsigned short mode = 0755)
00454 {
00455 return create_directory_recurse_impl(dir, mode);
00456 }
00457 #endif
00458
00467 template <ss_typename_param_k S>
00468 inline us_bool_t create_directory_recurse(S const& dir, unsigned short mode = 0755)
00469 {
00470 return create_directory_recurse(stlsoft_ns_qual(c_str_ptr)(dir), mode);
00471 }
00472
00521 inline us_bool_t remove_directory_recurse(
00522 us_char_a_t const* dir
00523 , us_int_t (*pfn)(void* param, us_char_a_t const* subDir, struct stat const* st, struct dirent const* de, int err)
00524 , void* param
00525 )
00526 {
00527 typedef filesystem_traits<us_char_a_t> traits_t;
00528
00529 us_int_t dwRet = remove_directory_recurse_impl<us_char_a_t, struct stat>(dir, pfn, param);
00530
00531 traits_t::set_last_error(dwRet);
00532
00533 return 0 == dwRet;
00534 }
00535
00540 inline us_bool_t remove_directory_recurse(us_char_a_t const* dir)
00541 {
00542 return remove_directory_recurse(dir, NULL, NULL);
00543 }
00544
00545 #if 0
00546
00550 inline us_bool_t remove_directory_recurse( us_char_w_t const* dir
00551 , us_int_t (*pfn)(void* param, us_char_w_t const* subDir, struct stat const* st, struct dirent const* de, int err)
00552 , void* param)
00553 {
00554 typedef filesystem_traits<us_char_w_t> traits_t;
00555
00556 us_int_t dwRet = remove_directory_recurse_impl<us_char_w_t, struct stat>(dir, pfn, param);
00557
00558 traits_t::set_last_error(dwRet);
00559
00560 return 0 == dwRet;
00561 }
00562
00567 inline us_bool_t remove_directory_recurse(us_char_w_t const* dir)
00568 {
00569 return remove_directory_recurse(dir, NULL, NULL);
00570 }
00571 #endif
00572
00577 template <ss_typename_param_k S>
00578 inline us_bool_t remove_directory_recurse(S const& dir)
00579 {
00580 typedef filesystem_traits<us_char_a_t> traits_t;
00581
00582 us_int_t dwRet = remove_directory_recurse(stlsoft_ns_qual(c_str_ptr)(dir), NULL, NULL);
00583
00584 traits_t::set_last_error(dwRet);
00585
00586 return 0 == dwRet;
00587 }
00588
00589
00590
00591
00592
00593 #ifdef STLSOFT_UNITTEST
00594 # include "./unittest/directory_functions_unittest_.h"
00595 #endif
00596
00597
00598
00599 #ifndef _UNIXSTL_NO_NAMESPACE
00600 # if defined(_STLSOFT_NO_NAMESPACE) || \
00601 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00602 }
00603 # else
00604 }
00605 }
00606 # endif
00607 #endif
00608
00609
00610
00611 #endif
00612
00613