└── filesystem.h /filesystem.h: -------------------------------------------------------------------------------- 1 | /* BSD - License 2 | 3 | Copyright (c) 2010, Kevin Hall 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, this 13 | list of conditions and the following disclaimer in the documentation and/or 14 | other materials provided with the distribution. 15 | 16 | * The names of contributors may not be used to endorse or promote products 17 | derived from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 23 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef _FILESYSTEM_H__ 32 | #define _FILESYSTEM_H__ 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #if defined(_WIN32) || defined(_WIN64) 44 | 45 | #define FS_WINDOWS_ 46 | 47 | #define WIN32_LEAN_AND_MEAN 48 | #define NOMCX //no Modem Configuration Extensions 49 | #define NOIME //no Input Method Manager 50 | #define NOGDI //no GDI defines and routines 51 | #define NOUSER //no USER defines and routines 52 | #define NOHELP //no Help engine interface. 53 | //#define NOSERVICE ??? 54 | //#define NOSYSPARAMSINFO ??? 55 | //#define NOWINABLE ??? 56 | #include 57 | #include 58 | #include 59 | #include 60 | 61 | extern "C" { 62 | 63 | struct TMN_REPARSE_DATA_BUFFER 64 | { 65 | DWORD ReparseTag; 66 | WORD ReparseDataLength; 67 | WORD Reserved; 68 | 69 | // IO_REPARSE_TAG_MOUNT_POINT specifics follow 70 | WORD SubstituteNameOffset; 71 | WORD SubstituteNameLength; 72 | WORD PrintNameOffset; 73 | WORD PrintNameLength; 74 | WCHAR PathBuffer[1]; 75 | }; 76 | 77 | } //extern "C" 78 | 79 | #define TMN_REPARSE_DATA_BUFFER_HEADER_SIZE \ 80 | FIELD_OFFSET(TMN_REPARSE_DATA_BUFFER, SubstituteNameOffset) 81 | 82 | #else 83 | 84 | #define FS_POSIX_ 85 | 86 | #include 87 | #include 88 | #include 89 | #include 90 | #include 91 | #include 92 | #include 93 | 94 | #endif 95 | 96 | namespace filesystem 97 | { 98 | 99 | #if 1 // REGION: Exceptions 100 | class string_conversion_error : public std::runtime_error 101 | { 102 | const char* location_file; 103 | int location_line; 104 | 105 | public: 106 | string_conversion_error(const char* what_, const char* file_, int line_) 107 | : std::runtime_error(what_) 108 | , location_file(file_) 109 | , location_line(line_) 110 | { 111 | } 112 | 113 | virtual ~string_conversion_error() throw() 114 | { 115 | } 116 | 117 | const char* source_file() const 118 | { return location_file;} 119 | 120 | int source_line() const 121 | { return location_line;} 122 | }; 123 | 124 | class filesystem_error : public std::runtime_error 125 | { 126 | const char* location_file; 127 | int location_line; 128 | std::string path_1; 129 | std::string path_2; 130 | public: 131 | filesystem_error(const char* what_, const char* file_, int line_, const std::string& path1_, const std::string& path2_) 132 | : std::runtime_error(what_) 133 | , location_file(file_) 134 | , location_line(line_) 135 | , path_1(path1_) 136 | , path_2(path2_) 137 | { 138 | } 139 | 140 | virtual ~filesystem_error() throw() 141 | { 142 | } 143 | 144 | const char* source_file() const 145 | { return location_file;} 146 | 147 | int source_line() const 148 | { return location_line;} 149 | 150 | const std::string& path1() const 151 | { return path_1; } 152 | 153 | const std::string& path2() const 154 | { return path_2; } 155 | }; 156 | 157 | namespace internal 158 | { 159 | #define GENERARE_STRING_CONVERSION_ERROR(msg) generate_string_conversion_error(msg, __FILE__, __LINE__) 160 | 161 | template 162 | void generate_string_conversion_error(const char* msg, const char* file, T line); 163 | 164 | template <> 165 | void generate_string_conversion_error(const char* msg, const char* file, int line) 166 | { 167 | throw string_conversion_error(msg, file, line); 168 | } 169 | 170 | #define GENERARE_FILESYSTEM_ERROR0() generate_filesystem_error(__FILE__, __LINE__, "", "") 171 | #define GENERARE_FILESYSTEM_ERROR1(path1) generate_filesystem_error(__FILE__, __LINE__, path1, "") 172 | #define GENERARE_FILESYSTEM_ERROR2(path1, path2) generate_filesystem_error(__FILE__, __LINE__, path1, path2) 173 | 174 | template 175 | void generate_filesystem_error(const char* file, T line, const std::string& path1, const std::string& path2); 176 | 177 | template <> 178 | void generate_filesystem_error(const char* file, int line, const std::string& path1, const std::string& path2) 179 | { 180 | #ifdef FS_WINDOWS_ 181 | char* msgBuffer; 182 | FormatMessageA( 183 | FORMAT_MESSAGE_ALLOCATE_BUFFER | 184 | FORMAT_MESSAGE_FROM_SYSTEM | 185 | FORMAT_MESSAGE_IGNORE_INSERTS, 186 | NULL, 187 | GetLastError(), 188 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 189 | (LPSTR)&msgBuffer, 190 | 0, NULL ); 191 | std::string msg(msgBuffer); 192 | LocalFree(msgBuffer); 193 | throw filesystem_error(msg.c_str(), file, line, path1, path2); 194 | #endif //#ifdef FS_WINDOWS_ 195 | #ifdef FS_POSIX_ 196 | throw filesystem_error(strerror(errno), file, line, path1, path2); 197 | #endif //#ifdef FS_POSIX_ 198 | } 199 | } //namespace internal 200 | 201 | #endif // REGION: Exceptions 202 | 203 | #if 1 // REGION: narrow/wide string conversion 204 | namespace internal 205 | { 206 | #ifdef FS_WINDOWS_ 207 | template 208 | void to_narrow_string(const std::wstring& in, T& out); 209 | 210 | template<> 211 | void to_narrow_string(const std::wstring& in, std::string& out) 212 | { 213 | if (in.empty()) 214 | { 215 | out.clear(); 216 | return; 217 | } 218 | 219 | int wcharCount = static_cast( 1+ in.size()); // including null terminator 220 | int bufferSize = ::WideCharToMultiByte( 221 | CP_UTF8, 222 | 0, 223 | in.c_str(), 224 | wcharCount, 225 | NULL, 226 | 0, 227 | NULL, NULL 228 | ); 229 | 230 | std::vector buffer(bufferSize); 231 | int result = ::WideCharToMultiByte( 232 | CP_UTF8, 233 | 0, 234 | in.c_str(), 235 | wcharCount, 236 | &buffer[0], 237 | static_cast(buffer.size()), 238 | NULL, NULL 239 | ); 240 | 241 | if (result == 0) 242 | { 243 | GENERARE_STRING_CONVERSION_ERROR("Could not convert wide string to narrow string"); 244 | } 245 | out.assign(&buffer[0]); 246 | } 247 | 248 | template 249 | void to_wide_string(const std::string& in, T& out); 250 | 251 | template<> 252 | void to_wide_string(const std::string& in, std::wstring& out) 253 | { 254 | if (in.empty()) 255 | { 256 | out.clear(); 257 | return; 258 | } 259 | 260 | std::vector buffer(in.size()+1, 0); 261 | if (!MultiByteToWideChar(CP_THREAD_ACP, 262 | MB_PRECOMPOSED, 263 | in.c_str(), 264 | static_cast(in.size()), 265 | &buffer[0], 266 | static_cast(in.size()))) 267 | { 268 | GENERARE_STRING_CONVERSION_ERROR("Could not convert narrow string to wide string"); 269 | } 270 | 271 | out = &buffer[0]; 272 | } 273 | 274 | #endif //#ifdef FS_WINDOWS_ 275 | #ifdef FS_POSIX_ 276 | template 277 | void to_narrow_string(const std::wstring& in, T& out); 278 | 279 | template<> 280 | void to_narrow_string(const std::wstring& in, std::string& out) 281 | { 282 | if (in.empty()) 283 | { 284 | out.clear(); 285 | return; 286 | } 287 | 288 | size_t bufferSize = wcstombs(NULL,in.c_str(),0)+1; // including null terminator 289 | if (bufferSize == 0) 290 | { 291 | GENERARE_STRING_CONVERSION_ERROR("Could not convert wide string to narrow string"); 292 | } 293 | 294 | std::vector buffer(bufferSize); 295 | wcstombs(&buffer[0], in.c_str(), buffer.size()); 296 | out.assign(&buffer[0]); 297 | } 298 | 299 | template 300 | void to_wide_string(const std::string& in, T& out); 301 | 302 | template<> 303 | void to_wide_string(const std::string& in, std::wstring& out) 304 | { 305 | if (in.empty()) 306 | { 307 | out.clear(); 308 | return; 309 | } 310 | 311 | size_t bufferSize = mbstowcs(NULL,in.c_str(),0)+1; // including null terminator 312 | if (bufferSize == 0) 313 | { 314 | GENERARE_STRING_CONVERSION_ERROR("Could not convert narrow string to wide string"); 315 | } 316 | 317 | std::vector buffer(bufferSize); 318 | mbstowcs(&buffer[0], in.c_str(), buffer.size()); 319 | out.assign(&buffer[0]); 320 | } 321 | #endif //#ifdef FS_POSIX_ 322 | 323 | template 324 | void to_narrow_string(const std::vector& in, std::vector& out); 325 | 326 | template<> 327 | void to_narrow_string(const std::vector& in, std::vector& out) 328 | { 329 | out.clear(); 330 | 331 | std::vector::const_iterator it = in.begin(); 332 | std::vector::const_iterator itEnd = in.end(); 333 | std::string temp; 334 | 335 | for (; it!=itEnd; ++it) 336 | { 337 | internal::to_narrow_string(*it, temp); 338 | out.push_back(temp); 339 | } 340 | } 341 | 342 | template 343 | void to_wide_string(const std::vector& in, std::vector& out); 344 | 345 | template<> 346 | void to_wide_string(const std::vector& in, std::vector& out) 347 | { 348 | out.clear(); 349 | 350 | std::vector::const_iterator it = in.begin(); 351 | std::vector::const_iterator itEnd = in.end(); 352 | std::wstring temp; 353 | 354 | for (; it!=itEnd; ++it) 355 | { 356 | internal::to_wide_string(*it, temp); 357 | out.push_back(temp); 358 | } 359 | } 360 | } //namespace internal 361 | #endif // REGION: narrow/wide string conversion 362 | 363 | #if 1 // REGION: POSIX Glob 364 | namespace internal 365 | { 366 | #ifdef FS_POSIX_ 367 | //template 368 | //bool glob_match(std::basic_string::const_iterator i_begin, std::basic_string::const_iterator i_end, 369 | // std::basic_string::const_iterator p_begin, std::basic_string::const_iterator p_end) 370 | template 371 | bool glob_match(T i_begin, T i_end, 372 | T p_begin, T p_end) 373 | { 374 | if (i_begin == i_end) 375 | { 376 | return (p_begin == p_end); 377 | } 378 | while ((i_begin != i_end) && (p_begin != p_end)) 379 | { 380 | switch (*p_begin) 381 | { 382 | case '*': 383 | { 384 | return 385 | glob_match(i_begin+1, i_end, p_begin, p_end) 386 | || 387 | glob_match(i_begin, i_end, p_begin+1, p_end) // needed since '*' can be non-consuming 388 | || 389 | glob_match(i_begin+1, i_end, p_begin+1, p_end); 390 | } 391 | case '\\': 392 | { 393 | ++p_begin; 394 | if (p_begin == p_end) 395 | { 396 | return false; 397 | } 398 | // fall through 399 | } 400 | default: 401 | { 402 | if (*p_begin != *i_begin) 403 | { 404 | return false; 405 | } 406 | // fall through 407 | } 408 | case '?': 409 | { 410 | ++i_begin; 411 | ++p_begin; 412 | break; 413 | } 414 | } 415 | } 416 | return (i_begin == i_end); 417 | } 418 | 419 | template 420 | bool glob_match(const std::basic_string& in, const std::basic_string& pattern) 421 | { 422 | return glob_match(in.begin(), in.end(), pattern.begin(), pattern.end()); 423 | } 424 | #endif //#ifdef FS_POSIX_ 425 | } //namespace internal 426 | #endif // REGION: POSIX Glob 427 | 428 | #if 1 // REGION: Win32 Utility Functions 429 | namespace internal 430 | { 431 | #ifdef FS_WINDOWS_ 432 | template 433 | void to_win32_path(T& path_str); 434 | 435 | template<> 436 | void to_win32_path(std::string& path_str) 437 | { 438 | std::string::iterator it = path_str.begin(); 439 | std::string::iterator itEnd = path_str.end(); 440 | for (; it!=itEnd; ++it) 441 | { 442 | if (*it == '/') 443 | { 444 | *it = '\\'; 445 | } 446 | } 447 | } 448 | 449 | template<> 450 | void to_win32_path(std::wstring& path_str) 451 | { 452 | std::wstring::iterator it = path_str.begin(); 453 | std::wstring::iterator itEnd = path_str.end(); 454 | for (; it!=itEnd; ++it) 455 | { 456 | if (*it == '/') 457 | { 458 | *it = '\\'; 459 | } 460 | } 461 | } 462 | 463 | template 464 | void remove_extended_fs_indicator(T& path_str); 465 | 466 | template<> 467 | void remove_extended_fs_indicator(std::string& path_str) 468 | { 469 | std::string extended_fs_indicator("\\\\?\\"); 470 | if (path_str.find(extended_fs_indicator) == 0) 471 | { 472 | path_str.erase(0, extended_fs_indicator.size()); 473 | } 474 | } 475 | 476 | template<> 477 | void remove_extended_fs_indicator(std::wstring& path_str) 478 | { 479 | std::wstring extended_fs_indicator(L"\\\\?\\"); 480 | if (path_str.find(extended_fs_indicator) == 0) 481 | { 482 | path_str.erase(0, extended_fs_indicator.size()); 483 | } 484 | } 485 | 486 | template 487 | void prepend_extended_fs_indicator(T& path_str); 488 | 489 | template<> 490 | void prepend_extended_fs_indicator(std::wstring& path_str) 491 | { 492 | // Prevent expansion if path contains "$" (indicating environment variable replacement) 493 | if (path_str.find('$') != std::wstring::npos) 494 | { 495 | std::string npath; 496 | to_narrow_string(path_str, npath); 497 | throw filesystem_error("Path strings with environment variable indicators ('$') cannot be used in this context.", __FILE__, __LINE__, npath, ""); 498 | } 499 | 500 | // Don't bother if a path is less than (MAX_PATH-12) characters. 501 | // MAX_PATH - 12 is needed when creating directories (due to the mandatory 8.3 minimum filename requirements). 502 | // Source: http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath 503 | if (path_str.size() < (MAX_PATH - 12)) 504 | { 505 | return; // if the path is empty, we'll return here... 506 | } 507 | 508 | // Prevent expansion if path contains "." or ".." elements. 509 | // The extended indicator "\\?\" prevents expansion of "." and ".." path elements. 510 | // Source: http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath 511 | // 512 | // We don't have to worry about the path being exactly ".." or "." since these path 513 | // strings are too short and the function will return inside the previous if block. 514 | // We need to test for the following: 515 | // * occurrances of "\..\" 516 | // * occurrances of "\.\" 517 | // * occurrances of "..\" at the beginning of the path string 518 | // * occurrances of ".\" at the beginning of the path string 519 | // * occurrances of "\.." at the end of the path string 520 | // * occurrances of "\." at the end of the path string 521 | if ((path_str.find(L"\\..\\") != std::wstring::npos) || 522 | (path_str.find(L"\\.\\") != std::wstring::npos) || 523 | (path_str.find(L"..\\") == 0) || 524 | (path_str.find(L".\\") == 0) || 525 | (path_str.find(L"\\..", path_str.size()-3) != std::wstring::npos) || 526 | (path_str.find(L"\\.", path_str.size()-2) != std::wstring::npos)) 527 | { 528 | std::string npath; 529 | to_narrow_string(path_str, npath); 530 | throw filesystem_error("Path is too long to contain \".\" or \"..\". Windows cannot properly expand the path string.", __FILE__, __LINE__, npath, ""); 531 | } 532 | 533 | std::wstring extended_fs_indicator(L"\\\\?\\"); 534 | std::wstring extended_unc_indicator(L"\\\\?\\UNC"); 535 | if (path_str.find(extended_fs_indicator) != 0) // will also match the UNC extended filesystem indicator 536 | { 537 | if (path_str.find(L"\\\\") == 0) // "\\" found at the beginning of the string -- indicative of a UNC path 538 | { 539 | // "\\server\share" should become "\\?\UNC\server\share". 540 | // Source: http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath 541 | path_str.swap(extended_unc_indicator.append(path_str.begin()+1, path_str.end())); 542 | } 543 | else 544 | { 545 | path_str.swap(extended_fs_indicator.append(path_str)); 546 | } 547 | } 548 | } 549 | 550 | template 551 | T cur_drive_path(const T& in); 552 | 553 | template<> 554 | std::wstring cur_drive_path(const std::wstring& in) 555 | { 556 | std::wstring cpath; 557 | int drive, curdrive; 558 | 559 | // Save current drive. 560 | curdrive = _getdrive(); 561 | 562 | if ((in[0] >= 'A') && (in[0] <= 'Z')) 563 | { 564 | drive = 1 + (in[0] - 'A'); 565 | } 566 | else if ((in[0] >= 'a') && (in[0] <= 'z')) 567 | { 568 | drive = 1 + (in[0] - 'a'); 569 | } 570 | else 571 | { 572 | std::string nin; 573 | to_narrow_string(in, nin); 574 | GENERARE_FILESYSTEM_ERROR1(nin); 575 | } 576 | 577 | if(!_chdrive(drive)) 578 | { 579 | wchar_t* buffer = _wgetdcwd(drive, 0, 0); 580 | 581 | if (buffer == NULL) 582 | { 583 | std::string nin; 584 | to_narrow_string(in, nin); 585 | GENERARE_FILESYSTEM_ERROR1(nin); 586 | } 587 | cpath = buffer; 588 | free(buffer); 589 | } 590 | else 591 | { 592 | std::string nin; 593 | to_narrow_string(in, nin); 594 | GENERARE_FILESYSTEM_ERROR1(nin); 595 | } 596 | 597 | _chdrive( curdrive ); // Restore original drive. 598 | 599 | return cpath; 600 | } 601 | 602 | template<> 603 | std::string cur_drive_path(const std::string& in) 604 | { 605 | std::string result; 606 | std::wstring wresult = cur_drive_path(std::wstring(1, in[0])); 607 | to_narrow_string(wresult, result); 608 | return result; 609 | } 610 | #endif //#ifdef FS_WINDOWS_ 611 | } //namespace internal 612 | #endif // REGION: Win32 Utility Functions 613 | 614 | #if 1 // REGION: compare_path_element 615 | namespace internal 616 | { 617 | #ifdef FS_WINDOWS_ 618 | template 619 | bool compare_path_element(T e1, T e2); 620 | 621 | template<> 622 | bool compare_path_element(std::string e1, std::string e2) 623 | { 624 | std::string::iterator it = e1.begin(); 625 | std::string::iterator itEnd = e1.end(); 626 | for (; it!=itEnd; ++it) 627 | { 628 | if (__isascii(*it) && isupper(*it)) 629 | { 630 | *it = _tolower(*it); 631 | } 632 | } 633 | it = e2.begin(); 634 | itEnd = e2.end(); 635 | for (; it!=itEnd; ++it) 636 | { 637 | if (__isascii(*it) && isupper(*it)) 638 | { 639 | *it = _tolower(*it); 640 | } 641 | } 642 | 643 | return (e1 == e2); 644 | } 645 | 646 | template<> 647 | bool compare_path_element(std::wstring e1, std::wstring e2) 648 | { 649 | std::wstring::iterator it = e1.begin(); 650 | std::wstring::iterator itEnd = e1.end(); 651 | for (; it!=itEnd; ++it) 652 | { 653 | *it = _tolower(*it); 654 | } 655 | it = e2.begin(); 656 | itEnd = e2.end(); 657 | for (; it!=itEnd; ++it) 658 | { 659 | *it = towlower(*it); 660 | } 661 | 662 | return (e1 == e2); 663 | } 664 | #endif //#ifdef FS_WINDOWS_ 665 | #ifdef FS_POSIX_ 666 | template 667 | bool compare_path_element(T e1, T e2) 668 | { 669 | return (e1 == e2); 670 | } 671 | #endif //#ifdef FS_POSIX_ 672 | } //namespace internal 673 | #endif // REGION: compare_path_element 674 | 675 | #if 1 // REGION: current_working_dir 676 | namespace internal 677 | { 678 | #ifdef FS_WINDOWS_ 679 | template 680 | void current_working_dir(T& path); 681 | 682 | template<> 683 | void current_working_dir(std::wstring& path) 684 | { 685 | DWORD bufferSize = GetCurrentDirectoryW(0, 0)+1; 686 | std::vector buffer(bufferSize); 687 | if (0==GetCurrentDirectoryW(bufferSize, &buffer[0])) 688 | { 689 | GENERARE_FILESYSTEM_ERROR0(); 690 | } 691 | path.assign(&buffer[0]); 692 | } 693 | 694 | template<> 695 | void current_working_dir(std::string& path) 696 | { 697 | std::wstring wpath; 698 | current_working_dir(wpath); 699 | to_narrow_string(wpath, path); 700 | } 701 | #endif //#ifdef FS_WINDOWS_ 702 | #ifdef FS_POSIX_ 703 | template 704 | void current_working_dir(T& path); 705 | 706 | template<> 707 | void current_working_dir(std::string& path) 708 | { 709 | char* pbuffer = getcwd(0, 0); 710 | path = pbuffer; 711 | free(pbuffer); 712 | } 713 | 714 | template<> 715 | void current_working_dir(std::wstring& path) 716 | { 717 | std::string npath; 718 | current_working_dir(npath); 719 | to_wide_string(npath, path); 720 | } 721 | #endif //#ifdef FS_POSIX_ 722 | } //namespace internal 723 | #endif // REGION: current_working_dir 724 | 725 | #if 1 // REGION: full_pathname 726 | namespace internal 727 | { 728 | #ifdef FS_WINDOWS_ 729 | template 730 | T full_pathname(const T& in); 731 | 732 | template<> 733 | std::wstring full_pathname(const std::wstring& in) 734 | { 735 | std::wstring extended_in = in; 736 | prepend_extended_fs_indicator(extended_in); 737 | DWORD bufferSize = GetFullPathNameW(extended_in.c_str(), 0, 0, NULL); 738 | std::vector buffer(bufferSize); 739 | if (0==GetFullPathNameW(extended_in.c_str(), bufferSize, &buffer[0], NULL)) 740 | { 741 | std::string nin; 742 | to_narrow_string(in, nin); 743 | GENERARE_FILESYSTEM_ERROR1(nin); 744 | } 745 | return std::wstring(&buffer[0]); 746 | } 747 | 748 | template<> 749 | std::string full_pathname(const std::string& in) 750 | { 751 | std::wstring win; 752 | to_wide_string(in, win); 753 | std::wstring wresult = full_pathname(win); 754 | std::string result; 755 | to_narrow_string(wresult, result); 756 | return result; 757 | } 758 | #endif //#ifdef FS_WINDOWS_ 759 | #ifdef FS_POSIX_ 760 | template 761 | T full_pathname(const T& in); 762 | 763 | template<> 764 | std::string full_pathname(const std::string& in) 765 | { 766 | char* buffer = realpath(in.c_str(), 0); 767 | std::string result(buffer); 768 | free(buffer); 769 | return result; 770 | } 771 | 772 | template<> 773 | std::wstring full_pathname(const std::wstring& in) 774 | { 775 | std::string nin; 776 | to_narrow_string(in, nin); 777 | std::string nresult = full_pathname(nin); 778 | std::wstring result; 779 | to_wide_string(nresult, result); 780 | return result; 781 | } 782 | #endif //#ifdef FS_POSIX_ 783 | } //namespace internal 784 | #endif // REGION: full_pathname 785 | 786 | #if 1 // REGION: is_directory_empty 787 | namespace internal 788 | { 789 | #ifdef FS_WINDOWS_ 790 | template 791 | bool is_directory_empty(T dir); 792 | 793 | template<> 794 | bool is_directory_empty(std::wstring dir) 795 | { 796 | bool result = true; // we'll assume the directory is empty 797 | 798 | to_win32_path(dir); 799 | prepend_extended_fs_indicator(dir); 800 | dir.append(L"\\*"); 801 | 802 | WIN32_FIND_DATAW FindFileData; 803 | HANDLE hFind; 804 | 805 | hFind = FindFirstFileW(dir.c_str(), &FindFileData); 806 | if (hFind == INVALID_HANDLE_VALUE) 807 | { 808 | throw; // failed to access directory (directory doesn't exist?) 809 | } 810 | BOOL foundEntry = TRUE; 811 | do 812 | { 813 | if ((wcscmp(FindFileData.cFileName, L".") != 0) && 814 | (wcscmp(FindFileData.cFileName, L"..") != 0)) 815 | { 816 | result = false; 817 | break; 818 | } 819 | foundEntry = FindNextFileW(hFind, &FindFileData); 820 | } 821 | while (foundEntry); 822 | 823 | FindClose(hFind); 824 | return result; 825 | } 826 | 827 | template<> 828 | bool is_directory_empty(std::string dir) 829 | { 830 | std::wstring wdir; 831 | to_wide_string(dir, wdir); 832 | return is_directory_empty(wdir); 833 | } 834 | #endif //#ifdef FS_WINDOWS_ 835 | #ifdef FS_POSIX_ 836 | template 837 | bool is_directory_empty(T dir); 838 | 839 | template<> 840 | bool is_directory_empty(std::string directory) 841 | { 842 | DIR* dir; 843 | struct dirent* ent; 844 | struct stat st; 845 | bool result = true; 846 | 847 | dir = opendir(directory.c_str()); 848 | if (dir == NULL) 849 | { 850 | GENERARE_FILESYSTEM_ERROR1(directory); 851 | } 852 | while (result && ((ent = readdir(dir)) != NULL)) { 853 | std::string file_name = ent->d_name; 854 | std::string full_file_name = directory + "/" + file_name; 855 | 856 | if ((file_name == ".") || (file_name == "..")) 857 | continue; 858 | 859 | if (stat(full_file_name.c_str(), &st) == -1) 860 | continue; 861 | 862 | result = false; 863 | } 864 | closedir(dir); 865 | return result; 866 | } 867 | 868 | template<> 869 | bool is_directory_empty(std::wstring dir) 870 | { 871 | std::string ndir; 872 | to_narrow_string(dir, ndir); 873 | return is_directory_empty(ndir); 874 | } 875 | #endif //#ifdef FS_POSIX_ 876 | } //namespace internal 877 | #endif // REGION: is_directory_empty 878 | 879 | #if 1 // REGION: is_file, is_directory 880 | namespace internal 881 | { 882 | #ifdef FS_WINDOWS_ 883 | template 884 | bool is_file(const T&); 885 | 886 | template<> 887 | bool is_file(const std::wstring& path) 888 | { 889 | std::wstring ext_path = path; 890 | to_win32_path(ext_path); 891 | prepend_extended_fs_indicator(ext_path); 892 | 893 | DWORD result = GetFileAttributesW(ext_path.c_str()); 894 | if ((result == INVALID_FILE_ATTRIBUTES) || 895 | ((result & FILE_ATTRIBUTE_DEVICE) != 0) || 896 | ((result & FILE_ATTRIBUTE_DIRECTORY) != 0) || 897 | ((result & FILE_ATTRIBUTE_OFFLINE) != 0)) // For now, we won't allow access to offline files. 898 | { 899 | DWORD result = GetFileAttributesW(ext_path.c_str()); 900 | if ((result == INVALID_FILE_ATTRIBUTES) || 901 | ((result & FILE_ATTRIBUTE_DEVICE) != 0) || 902 | ((result & FILE_ATTRIBUTE_DIRECTORY) != 0) || 903 | ((result & FILE_ATTRIBUTE_OFFLINE) != 0)) // For now, we won't allow access to offline files. 904 | { 905 | return false; 906 | } 907 | } 908 | return true; 909 | } 910 | 911 | template<> 912 | bool is_file(const std::string& path) 913 | { 914 | std::wstring wpath; 915 | to_wide_string(path, wpath); 916 | return is_file(wpath); 917 | } 918 | 919 | template 920 | bool is_directory(const T&); 921 | 922 | template<> 923 | bool is_directory(const std::wstring& path) 924 | { 925 | std::wstring ext_path = path; 926 | to_win32_path(ext_path); 927 | prepend_extended_fs_indicator(ext_path); 928 | 929 | DWORD result = GetFileAttributesW(ext_path.c_str()); 930 | return ((result != INVALID_FILE_ATTRIBUTES) && 931 | ((result & FILE_ATTRIBUTE_DIRECTORY) != 0)); 932 | } 933 | 934 | template<> 935 | bool is_directory(const std::string& path) 936 | { 937 | std::wstring wpath; 938 | to_wide_string(path, wpath); 939 | return is_directory(wpath); 940 | } 941 | #endif //#ifdef FS_WINDOWS_ 942 | #ifdef FS_POSIX_ 943 | template 944 | bool is_file(const T&); 945 | 946 | template<> 947 | bool is_file(const std::string& path) 948 | { 949 | struct stat info; 950 | if (lstat(path.c_str(), &info) != 0) 951 | { 952 | GENERARE_FILESYSTEM_ERROR1(path); 953 | } 954 | return S_ISREG(info.st_mode); 955 | } 956 | 957 | template<> 958 | bool is_file(const std::wstring& path) 959 | { 960 | std::string npath; 961 | to_narrow_string(path, npath); 962 | return is_file(npath); 963 | } 964 | 965 | template 966 | bool is_directory(const T&); 967 | 968 | template<> 969 | bool is_directory(const std::string& path) 970 | { 971 | struct stat info; 972 | if (lstat(path.c_str(), &info) != 0) 973 | { 974 | GENERARE_FILESYSTEM_ERROR1(path); 975 | } 976 | return S_ISDIR(info.st_mode); 977 | } 978 | 979 | template<> 980 | bool is_directory(const std::wstring& path) 981 | { 982 | std::string npath; 983 | to_narrow_string(path, npath); 984 | return is_directory(npath); 985 | } 986 | #endif //#ifdef FS_POSIX_ 987 | } //namespace internal 988 | #endif // REGION: is_file, is_directory 989 | 990 | #if 1 // REGION: dir_get_subdirs, dir_get_files 991 | namespace internal 992 | { 993 | #ifdef FS_WINDOWS_ 994 | template 995 | void scan_directory(std::basic_string dir, const std::basic_string& pattern, std::vector >& results, bool search_directories); 996 | 997 | template<> 998 | void scan_directory(std::wstring dir, const std::wstring& pattern, std::vector& results, bool search_directories) 999 | { 1000 | results.clear(); 1001 | 1002 | DWORD fileAttrMask = FILE_ATTRIBUTE_DIRECTORY; 1003 | DWORD fileAttrComp = FILE_ATTRIBUTE_DIRECTORY; 1004 | if (!search_directories) 1005 | { 1006 | fileAttrMask = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_OFFLINE; 1007 | fileAttrComp = 0; 1008 | } 1009 | 1010 | to_win32_path(dir); 1011 | prepend_extended_fs_indicator(dir); 1012 | dir.push_back('\\'); 1013 | if (pattern.empty()) 1014 | { 1015 | dir.push_back('*'); 1016 | } 1017 | else 1018 | { 1019 | dir.append(pattern); 1020 | } 1021 | 1022 | WIN32_FIND_DATAW FindFileData; 1023 | HANDLE hFind; 1024 | 1025 | hFind = FindFirstFileW(dir.c_str(), &FindFileData); 1026 | if (hFind == INVALID_HANDLE_VALUE) 1027 | { 1028 | return; 1029 | } 1030 | BOOL foundEntry = TRUE; 1031 | do 1032 | { 1033 | if ((FindFileData.dwFileAttributes & fileAttrMask) == fileAttrComp) 1034 | { 1035 | if ((wcscmp(FindFileData.cFileName, L".") != 0) && 1036 | (wcscmp(FindFileData.cFileName, L"..") != 0)) 1037 | { 1038 | results.push_back(FindFileData.cFileName); 1039 | } 1040 | } 1041 | foundEntry = FindNextFileW(hFind, &FindFileData); 1042 | } 1043 | while (foundEntry); 1044 | 1045 | FindClose(hFind); 1046 | } 1047 | 1048 | template<> 1049 | void scan_directory(std::string dir, const std::string& pattern, std::vector& results, bool search_directories) 1050 | { 1051 | results.clear(); 1052 | 1053 | std::wstring wdir, wpattern; 1054 | std::vector wsubdirs; 1055 | 1056 | internal::to_wide_string(dir, wdir); 1057 | internal::to_wide_string(pattern, wpattern); 1058 | 1059 | scan_directory(wdir, wpattern, wsubdirs, search_directories); 1060 | 1061 | to_narrow_string(wsubdirs, results); 1062 | } 1063 | 1064 | #endif //#ifdef FS_WINDOWS_ 1065 | #ifdef FS_POSIX_ 1066 | template 1067 | void scan_directory(std::basic_string directory, const std::basic_string& pattern, std::vector >& results, bool search_directories); 1068 | 1069 | template<> 1070 | void scan_directory(std::string directory, const std::string& pattern, std::vector& results, bool search_directories) 1071 | { 1072 | DIR *dir; 1073 | struct dirent *ent; 1074 | struct stat st; 1075 | 1076 | const bool no_pattern = pattern.empty(); 1077 | 1078 | dir = opendir(directory.c_str()); 1079 | while ((ent = readdir(dir)) != NULL) { 1080 | std::string file_name = ent->d_name; 1081 | std::string full_file_name = directory + "/" + file_name; 1082 | 1083 | if ((file_name == ".") || (file_name == "..")) 1084 | continue; 1085 | 1086 | if (stat(full_file_name.c_str(), &st) == -1) 1087 | continue; 1088 | 1089 | if (search_directories) 1090 | { 1091 | if (!S_ISDIR(st.st_mode)) // directory 1092 | continue; 1093 | } 1094 | else 1095 | { 1096 | if (!S_ISREG(st.st_mode)) // file 1097 | continue; 1098 | } 1099 | 1100 | if (no_pattern || glob_match(file_name, pattern)) 1101 | { 1102 | results.push_back(file_name); 1103 | } 1104 | } 1105 | closedir(dir); 1106 | } 1107 | 1108 | template<> 1109 | void scan_directory(std::wstring directory, const std::wstring& pattern, std::vector& results, bool search_directories) 1110 | { 1111 | results.clear(); 1112 | 1113 | std::string ndir, npattern; 1114 | std::vector nsubdirs; 1115 | 1116 | internal::to_narrow_string(directory, ndir); 1117 | internal::to_narrow_string(pattern, npattern); 1118 | 1119 | scan_directory(ndir, npattern, nsubdirs, search_directories); 1120 | 1121 | to_wide_string(nsubdirs, results); 1122 | } 1123 | #endif //#ifdef FS_POSIX_ 1124 | 1125 | template 1126 | void dir_get_subdirs(const T& dir, const T& pattern, std::vector& results); 1127 | 1128 | template<> 1129 | void dir_get_subdirs(const std::wstring& dir, const std::wstring& pattern, std::vector& results) 1130 | { 1131 | scan_directory(dir, pattern, results, true); 1132 | } 1133 | 1134 | template<> 1135 | void dir_get_subdirs(const std::string& dir, const std::string& pattern, std::vector& results) 1136 | { 1137 | scan_directory(dir, pattern, results, true); 1138 | } 1139 | 1140 | template 1141 | void dir_get_files(const T& dir, const T& pattern, std::vector& results); 1142 | 1143 | template<> 1144 | void dir_get_files(const std::wstring& dir, const std::wstring& pattern, std::vector& results) 1145 | { 1146 | scan_directory(dir, pattern, results, false); 1147 | } 1148 | 1149 | template<> 1150 | void dir_get_files(const std::string& dir, const std::string& pattern, std::vector& results) 1151 | { 1152 | scan_directory(dir, pattern, results, false); 1153 | } 1154 | } //namespace internal 1155 | #endif // REGION: dir_get_subdirs, dir_get_files 1156 | 1157 | #if 1 // REGION: create_directory, remove_directory 1158 | namespace internal 1159 | { 1160 | #ifdef FS_WINDOWS_ 1161 | template 1162 | void create_directory(const T& dir); 1163 | 1164 | template<> 1165 | void create_directory(const std::wstring& dir) 1166 | { 1167 | std::wstring ext_dir = dir; 1168 | to_win32_path(ext_dir); 1169 | prepend_extended_fs_indicator(ext_dir); 1170 | 1171 | if (0 == CreateDirectoryW(ext_dir.c_str(), NULL)) 1172 | { 1173 | std::string ndir; 1174 | to_narrow_string(dir, ndir); 1175 | GENERARE_FILESYSTEM_ERROR1(ndir); 1176 | } 1177 | } 1178 | 1179 | template<> 1180 | void create_directory(const std::string& dir) 1181 | { 1182 | std::wstring wdir; 1183 | to_wide_string(dir, wdir); 1184 | create_directory(wdir); 1185 | } 1186 | 1187 | template 1188 | void remove_directory(const T& dir); 1189 | 1190 | template<> 1191 | void remove_directory(const std::wstring& dir) 1192 | { 1193 | std::wstring ext_dir = dir; 1194 | to_win32_path(ext_dir); 1195 | prepend_extended_fs_indicator(ext_dir); 1196 | 1197 | if (0 == RemoveDirectoryW(ext_dir.c_str())) 1198 | { 1199 | std::string ndir; 1200 | to_narrow_string(dir, ndir); 1201 | GENERARE_FILESYSTEM_ERROR1(ndir); 1202 | } 1203 | } 1204 | 1205 | template<> 1206 | void remove_directory(const std::string& dir) 1207 | { 1208 | } 1209 | #endif //#ifdef FS_WINDOWS_ 1210 | #ifdef FS_POSIX_ 1211 | template 1212 | void create_directory(const T& dir); 1213 | 1214 | template<> 1215 | void create_directory(const std::string& dir) 1216 | { 1217 | if (mkdir(dir.c_str(), S_IRWXU | S_IRWXO | S_IRWXG) != 0) 1218 | { 1219 | GENERARE_FILESYSTEM_ERROR1(dir); 1220 | } 1221 | } 1222 | 1223 | template<> 1224 | void create_directory(const std::wstring& dir) 1225 | { 1226 | std::string ndir; 1227 | to_narrow_string(dir, ndir); 1228 | create_directory(ndir); 1229 | } 1230 | 1231 | template 1232 | void remove_directory(const T& dir); 1233 | 1234 | template<> 1235 | void remove_directory(const std::string& dir) 1236 | { 1237 | if (rmdir(dir.c_str()) != 0) 1238 | { 1239 | GENERARE_FILESYSTEM_ERROR1(dir); 1240 | } 1241 | } 1242 | 1243 | template<> 1244 | void remove_directory(const std::wstring& dir) 1245 | { 1246 | std::string ndir; 1247 | to_narrow_string(dir, ndir); 1248 | remove_directory(ndir); 1249 | } 1250 | #endif //#ifdef FS_POSIX_ 1251 | } //namespace internal 1252 | #endif // REGION: create_directory, remove_directory 1253 | 1254 | #if 1 // REGION: remove_file 1255 | namespace internal 1256 | { 1257 | #ifdef FS_WINDOWS_ 1258 | template 1259 | void remove_file(const T&); 1260 | 1261 | template<> 1262 | void remove_file(const std::wstring& path) 1263 | { 1264 | std::wstring ext_path = path; 1265 | to_win32_path(ext_path); 1266 | prepend_extended_fs_indicator(ext_path); 1267 | 1268 | if (0 == DeleteFileW(ext_path.c_str())) 1269 | { 1270 | std::string npath; 1271 | to_narrow_string(path, npath); 1272 | GENERARE_FILESYSTEM_ERROR1(npath); 1273 | } 1274 | } 1275 | 1276 | template<> 1277 | void remove_file(const std::string& path) 1278 | { 1279 | std::wstring wpath; 1280 | to_wide_string(path, wpath); 1281 | remove_file(wpath); 1282 | } 1283 | #endif //#ifdef FS_WINDOWS_ 1284 | #ifdef FS_POSIX_ 1285 | template 1286 | bool remove_file(const T& path); 1287 | 1288 | template<> 1289 | bool remove_file(const std::string& path) 1290 | { 1291 | if (unlink(path.c_str()) != 0) 1292 | { 1293 | GENERARE_FILESYSTEM_ERROR1(path); 1294 | } 1295 | return true; 1296 | } 1297 | 1298 | template<> 1299 | bool remove_file(const std::wstring& path) 1300 | { 1301 | std::string npath; 1302 | to_narrow_string(path, npath); 1303 | return remove_file(npath); 1304 | } 1305 | #endif //#ifdef FS_POSIX_ 1306 | } //namespace internal 1307 | #endif // REGION: remove_file 1308 | 1309 | #if 1 // REGION: move 1310 | namespace internal 1311 | { 1312 | #ifdef FS_WINDOWS_ 1313 | template 1314 | void move(const T& oldpath, const T& newpath); 1315 | 1316 | template<> 1317 | void move(const std::wstring& oldpath, const std::wstring& newpath) 1318 | { 1319 | std::wstring ext_oldpath = oldpath; 1320 | to_win32_path(ext_oldpath); 1321 | prepend_extended_fs_indicator(ext_oldpath); 1322 | 1323 | std::wstring ext_newpath = newpath; 1324 | to_win32_path(ext_newpath); 1325 | prepend_extended_fs_indicator(ext_newpath); 1326 | 1327 | if (0 == MoveFileW(ext_oldpath.c_str(), ext_newpath.c_str())) 1328 | { 1329 | std::string noldpath; 1330 | to_narrow_string(oldpath, noldpath); 1331 | std::string nnewpath; 1332 | to_narrow_string(newpath, nnewpath); 1333 | GENERARE_FILESYSTEM_ERROR2(noldpath, nnewpath); 1334 | } 1335 | } 1336 | 1337 | template<> 1338 | void move(const std::string& oldpath, const std::string& newpath) 1339 | { 1340 | std::wstring woldpath, wnewpath; 1341 | to_wide_string(oldpath, woldpath); 1342 | to_wide_string(newpath, wnewpath); 1343 | move(woldpath, wnewpath); 1344 | } 1345 | #endif //#ifdef FS_WINDOWS_ 1346 | #ifdef FS_POSIX_ 1347 | template 1348 | void move(const T& oldpath, const T& newpath); 1349 | 1350 | template<> 1351 | void move(const std::string& oldpath, const std::string& newpath) 1352 | { 1353 | if (rename(oldpath.c_str(), newpath.c_str()) != 0) 1354 | { 1355 | GENERARE_FILESYSTEM_ERROR2(oldpath, newpath); 1356 | } 1357 | } 1358 | 1359 | template<> 1360 | void move(const std::wstring& oldpath, const std::wstring& newpath) 1361 | { 1362 | std::string noldpath, nnewpath; 1363 | to_narrow_string(oldpath, noldpath); 1364 | to_narrow_string(newpath, nnewpath); 1365 | move(noldpath, nnewpath); 1366 | } 1367 | #endif //#ifdef FS_POSIX_ 1368 | } //namespace internal 1369 | #endif // REGION: move 1370 | 1371 | #if 1 // REGION: create_hard_link 1372 | namespace internal 1373 | { 1374 | #ifdef FS_WINDOWS_ 1375 | template 1376 | void create_hard_link(const T& link, const T& source); 1377 | 1378 | template<> 1379 | void create_hard_link(const std::wstring& link, const std::wstring& source) 1380 | { 1381 | std::wstring ext_link = link; 1382 | to_win32_path(ext_link); 1383 | prepend_extended_fs_indicator(ext_link); 1384 | 1385 | std::wstring ext_source = source; 1386 | to_win32_path(ext_source); 1387 | prepend_extended_fs_indicator(ext_source); 1388 | 1389 | if (0 == CreateHardLinkW(ext_link.c_str(), ext_source.c_str(), NULL)) 1390 | { 1391 | std::string nlink; 1392 | to_narrow_string(link, nlink); 1393 | std::string nsource; 1394 | to_narrow_string(source, nsource); 1395 | GENERARE_FILESYSTEM_ERROR2(nlink, nsource); 1396 | } 1397 | } 1398 | 1399 | template<> 1400 | void create_hard_link(const std::string& link, const std::string& source) 1401 | { 1402 | std::wstring wlink, wsource; 1403 | to_wide_string(link, wlink); 1404 | to_wide_string(source, wsource); 1405 | create_hard_link(wlink, wsource); 1406 | } 1407 | #endif //#ifdef FS_WINDOWS_ 1408 | #ifdef FS_POSIX_ 1409 | template 1410 | void create_hard_link(const T& oldpath, const T& newpath); 1411 | 1412 | template<> 1413 | void create_hard_link(const std::string& oldpath, const std::string& newpath) 1414 | { 1415 | if (link(oldpath.c_str(), newpath.c_str()) != 0) 1416 | { 1417 | GENERARE_FILESYSTEM_ERROR2(oldpath, newpath); 1418 | } 1419 | } 1420 | 1421 | template<> 1422 | void create_hard_link(const std::wstring& oldpath, const std::wstring& newpath) 1423 | { 1424 | std::string noldpath, nnewpath; 1425 | to_narrow_string(oldpath, noldpath); 1426 | to_narrow_string(newpath, nnewpath); 1427 | create_hard_link(noldpath, nnewpath); 1428 | } 1429 | #endif //#ifdef FS_POSIX_ 1430 | } //namespace internal 1431 | #endif // REGION: create_hard_link 1432 | 1433 | #if 1 // REGION: exists 1434 | namespace internal 1435 | { 1436 | template 1437 | bool exists(const T& path) 1438 | { 1439 | return is_directory(path) || is_file(path); 1440 | } 1441 | } //namespace internal 1442 | #endif // REGION: exists 1443 | 1444 | #if 1 // REGION: Win32 Junction Points 1445 | #ifdef FS_WINDOWS_ 1446 | namespace internal 1447 | { 1448 | template 1449 | bool create_junction_point(T link, T source); 1450 | 1451 | template<> 1452 | bool create_junction_point(std::wstring link, std::wstring source) 1453 | { 1454 | if (link.empty() || source.empty()) 1455 | { 1456 | return false; 1457 | } 1458 | 1459 | to_win32_path(link); 1460 | prepend_extended_fs_indicator(link); 1461 | 1462 | remove_extended_fs_indicator(source); 1463 | to_win32_path(source); 1464 | std::wstring(L"\\??\\").append(source).swap(source); 1465 | 1466 | char raw_reparse_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE] = { 0 }; 1467 | TMN_REPARSE_DATA_BUFFER& reparse_buffer = *reinterpret_cast(raw_reparse_buffer); 1468 | 1469 | const WORD nDestMountPointBytes = static_cast(source.size()) * 2; 1470 | 1471 | reparse_buffer.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; 1472 | reparse_buffer.ReparseDataLength = nDestMountPointBytes + 12; 1473 | reparse_buffer.Reserved = 0; 1474 | reparse_buffer.SubstituteNameOffset = 0; 1475 | reparse_buffer.SubstituteNameLength = nDestMountPointBytes; 1476 | reparse_buffer.PrintNameOffset = nDestMountPointBytes + 2; 1477 | reparse_buffer.PrintNameLength = 0; 1478 | lstrcpyW(reparse_buffer.PathBuffer, source.c_str()); 1479 | 1480 | HANDLE dirHandle = 1481 | CreateFile( link.c_str(), 1482 | GENERIC_READ | GENERIC_WRITE, 1483 | 0, 1484 | 0, 1485 | OPEN_EXISTING, 1486 | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 1487 | 0); 1488 | if (dirHandle == INVALID_HANDLE_VALUE) 1489 | { 1490 | return false; 1491 | } 1492 | 1493 | DWORD dummy; 1494 | return (0 != 1495 | DeviceIoControl(dirHandle, 1496 | FSCTL_SET_REPARSE_POINT, 1497 | (LPVOID)&reparse_buffer, 1498 | reparse_buffer.ReparseDataLength + TMN_REPARSE_DATA_BUFFER_HEADER_SIZE, 1499 | NULL, 1500 | 0, 1501 | &dummy, 1502 | 0)); 1503 | } 1504 | 1505 | template<> 1506 | bool create_junction_point(std::string link, std::string source) 1507 | { 1508 | std::wstring wlink, wsource; 1509 | to_wide_string(link, wlink); 1510 | to_wide_string(source, wsource); 1511 | return create_junction_point(wlink, wsource); 1512 | } 1513 | 1514 | template 1515 | bool is_junction_point(const T&); 1516 | 1517 | template<> 1518 | bool is_junction_point(const std::wstring& path) 1519 | { 1520 | std::wstring ext_path = path; 1521 | to_win32_path(ext_path); 1522 | prepend_extended_fs_indicator(ext_path); 1523 | 1524 | DWORD result = GetFileAttributesW(ext_path.c_str()); 1525 | return ((result != INVALID_FILE_ATTRIBUTES) && 1526 | ((result & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)) == (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT))); 1527 | } 1528 | 1529 | template<> 1530 | bool is_junction_point(const std::string& path) 1531 | { 1532 | std::wstring wpath; 1533 | to_wide_string(path, wpath); 1534 | return is_junction_point(wpath); 1535 | } 1536 | } 1537 | #endif //#ifdef FS_WINDOWS_ 1538 | #endif // REGION: Win32 Junction Points 1539 | 1540 | #if 1 // REGION: class basic_path 1541 | 1542 | struct Initializer 1543 | { 1544 | enum Enum 1545 | { 1546 | CurrentWorkingDirectory, 1547 | }; 1548 | }; 1549 | 1550 | template 1551 | class basic_path 1552 | { 1553 | public: 1554 | typedef T char_t; 1555 | typedef std::basic_string string_t; 1556 | typedef std::vector vecstr_t; 1557 | 1558 | private: 1559 | vecstr_t path_elems; 1560 | mutable string_t path_string; 1561 | mutable bool path_string_valid; 1562 | bool relative; 1563 | bool drive_specified; 1564 | bool unc_path; 1565 | 1566 | void initialize(string_t path_) 1567 | { 1568 | #ifdef FS_WINDOWS_ 1569 | internal::remove_extended_fs_indicator(path_); 1570 | #endif //#ifdef FS_WINDOWS_ 1571 | 1572 | if (path_.empty()) 1573 | { 1574 | throw filesystem_error("Path cannot be initialized to empty value", __FILE__, __LINE__, "", ""); 1575 | } 1576 | 1577 | typename string_t::iterator it = path_.begin(); 1578 | typename string_t::iterator itEnd = path_.end(); 1579 | for (; it!=itEnd; ++it) 1580 | { 1581 | if (*it == '\\') 1582 | { 1583 | *it = '/'; 1584 | } 1585 | } 1586 | 1587 | if (path_.find(string_t(2, '/').c_str(), 1) != string_t::npos) // find "//" 1588 | { 1589 | throw filesystem_error("Path encountered unexpected neighboring directory separators: '//'", __FILE__, __LINE__, "", ""); 1590 | } 1591 | if ((path_.find(string_t(3, '.').c_str()) == 0) && 1592 | (path_.find_first_not_of('.') == string_t::npos)) // find repeats of elipses more than 2 in length 1593 | { 1594 | throw filesystem_error("Invalid path specified", __FILE__, __LINE__, "", ""); 1595 | } 1596 | 1597 | size_t searchIndex = 0; 1598 | size_t nextDelimiter = 0; 1599 | 1600 | // Detect non-relative and/or drive-specified paths 1601 | if (path_[0] == '/') 1602 | { 1603 | relative = false; 1604 | if (path_.length() == 1) 1605 | { 1606 | // our path is "/". We can short-cut and return. 1607 | path_elems.push_back(path_); 1608 | return; 1609 | } 1610 | if (path_[1] == '/') 1611 | { 1612 | // we have a UNC path 1613 | unc_path = true; 1614 | nextDelimiter = path_.find('/', 2); 1615 | if (nextDelimiter == string_t::npos) 1616 | { 1617 | // we only have the root path. We can short-cut and return. 1618 | path_elems.push_back(path_); 1619 | return; 1620 | } 1621 | path_elems.push_back(path_.substr(0, nextDelimiter)); 1622 | searchIndex = nextDelimiter + 1; 1623 | } 1624 | else 1625 | { 1626 | // we have a non-UNC root path. Just set the first element to "/" 1627 | path_elems.push_back(string_t(1, '/')); 1628 | searchIndex = 1; 1629 | } 1630 | } 1631 | else 1632 | { 1633 | if ((path_.length() >= 2) && 1634 | (path_[1] == ':') && 1635 | ( 1636 | ((path_[0] >= 'A') && (path_[0] <= 'Z')) || 1637 | ((path_[0] >= 'a') && (path_[0] <= 'z')) 1638 | ) 1639 | ) 1640 | { 1641 | // we have a drive specification. 1642 | drive_specified = true; 1643 | 1644 | if ((path_.length() >= 3) && 1645 | (path_[2] == '/')) 1646 | { 1647 | relative = false; 1648 | path_elems.push_back(path_.substr(0, 3)); 1649 | searchIndex = 3; 1650 | } 1651 | else 1652 | { 1653 | path_elems.push_back(path_.substr(0, 2)); 1654 | searchIndex = 2; 1655 | } 1656 | } 1657 | } 1658 | 1659 | // Now parse the remainding part of the path string. 1660 | if (searchIndex != string_t::npos) 1661 | { 1662 | for (;;) 1663 | { 1664 | nextDelimiter = path_.find('/', searchIndex); 1665 | if (nextDelimiter == string_t::npos) 1666 | { 1667 | string_t lastElem = path_.substr(searchIndex); 1668 | if (!lastElem.empty()) 1669 | { 1670 | path_elems.push_back(lastElem); 1671 | } 1672 | break; 1673 | } 1674 | path_elems.push_back(path_.substr(searchIndex, nextDelimiter-searchIndex)); 1675 | searchIndex = nextDelimiter+1; 1676 | } 1677 | } 1678 | 1679 | // Path cleanup & final validity checks 1680 | 1681 | // Validate environment variable members. Ex: "$(PATH)" 1682 | { 1683 | typename vecstr_t::iterator it = path_elems.begin(); 1684 | typename vecstr_t::iterator endIt = path_elems.end(); 1685 | for (; it!=endIt; ++it) 1686 | { 1687 | size_t dollarSignLocation = it->find('$'); 1688 | if (dollarSignLocation != string_t::npos) 1689 | { 1690 | if ((dollarSignLocation != 0) || // '(' is not where we expect it. 1691 | (it->length() < 4) || // element is too short. It can't hold "$(A)". 1692 | (it->find('$', 1) != string_t::npos) || // There's too many dollar signs. 1693 | (it->find('(') != 1) || // '(' is not where we expect it. 1694 | (it->find('(', 2) != string_t::npos) || // There's too many open parentheses. 1695 | (it->find(')') != it->length()-1)) // ')' is not where we expect it. 1696 | { 1697 | throw filesystem_error("Path element contains '$', but has invalid environment variable format", __FILE__, __LINE__, "", ""); 1698 | } 1699 | // Everything is OK if we reach here. 1700 | } 1701 | else if ((it->find('(') != string_t::npos) || 1702 | (it->find('(') != string_t::npos)) 1703 | { 1704 | throw filesystem_error("Path element contains parentheses, but has invalid environment variable format", __FILE__, __LINE__, "", ""); 1705 | } 1706 | } 1707 | } 1708 | 1709 | // Remove "." 1710 | path_elems.erase(std::remove(path_elems.begin(), path_elems.end(), string_t(1, '.')), path_elems.end()); 1711 | if (path_elems.size() == 0) 1712 | { 1713 | path_elems.push_back(string_t(1, '.')); // The path was something like "." or "././." indicating the current path. We need to keep this. 1714 | } 1715 | 1716 | // Remove "..". 1717 | remove_double_elipses(); 1718 | } 1719 | 1720 | void remove_double_elipses() 1721 | { 1722 | // This section is O(n^2) and could likely be optimized further. But it works for now and is clear. 1723 | string_t doubleElipses(2, '.'); // ".." 1724 | 1725 | bool isDone = false; 1726 | while (!isDone) 1727 | { 1728 | typename vecstr_t::iterator endIt = path_elems.end(); 1729 | typename vecstr_t::iterator startIt = path_elems.begin(); 1730 | if (drive_specified || unc_path || (!relative)) 1731 | { 1732 | ++startIt; 1733 | } 1734 | typename vecstr_t::iterator prevIt = startIt; 1735 | typename vecstr_t::iterator it = startIt; 1736 | if (it != endIt) 1737 | { 1738 | ++it; 1739 | isDone = true; 1740 | while (it != endIt) 1741 | { 1742 | if ((*it == doubleElipses) && 1743 | (*prevIt != doubleElipses) && 1744 | ((*prevIt)[0] != '$')) 1745 | { 1746 | path_elems.erase(prevIt, it+1); 1747 | isDone = false; 1748 | break; 1749 | } 1750 | prevIt = it; 1751 | ++it; 1752 | } 1753 | } 1754 | } 1755 | } 1756 | 1757 | const string_t& get_path_string() const 1758 | { 1759 | if (!path_string_valid) 1760 | { 1761 | size_t elementCount = path_elems.size(); 1762 | size_t element = 1; 1763 | 1764 | path_string = path_elems[0]; 1765 | 1766 | if ((elementCount > 1) && (!unc_path)) 1767 | { 1768 | if (!relative) // ex: "c:/" or "/" 1769 | { 1770 | path_string.append(path_elems[1]); 1771 | element = 2; 1772 | } 1773 | } 1774 | 1775 | for (; element& results) 1804 | { 1805 | std::vector dir_results; 1806 | directory_get_files(pattern, dir_results); 1807 | 1808 | results.insert(results.end(), dir_results.begin(), dir_results.end()); 1809 | 1810 | directory_get_subdirs(dir_results); 1811 | 1812 | std::vector::iterator it = dir_results.begin(); 1813 | std::vector::iterator itEnd = dir_results.end(); 1814 | for (; it!=itEnd; ++it) 1815 | { 1816 | it->directory_scan_subdirs_for_files_helper(pattern, results); 1817 | } 1818 | } 1819 | 1820 | public: 1821 | basic_path(const string_t& path_) 1822 | : path_string_valid(false) 1823 | , relative(true) 1824 | , drive_specified(false) 1825 | , unc_path(false) 1826 | { 1827 | initialize(path_); 1828 | } 1829 | 1830 | basic_path(const char_t* path_) 1831 | : path_string_valid(false) 1832 | , relative(true) 1833 | , drive_specified(false) 1834 | , unc_path(false) 1835 | { 1836 | initialize(string_t(path_)); 1837 | } 1838 | 1839 | basic_path(Initializer::Enum initializer) 1840 | : path_string_valid(false) 1841 | , relative(true) 1842 | , drive_specified(false) 1843 | , unc_path(false) 1844 | { 1845 | switch (initializer) 1846 | { 1847 | case Initializer::CurrentWorkingDirectory: 1848 | { 1849 | string_t path; 1850 | internal::current_working_dir(path); 1851 | initialize(path); 1852 | break; 1853 | } 1854 | default: 1855 | { 1856 | throw filesystem_error("Invalid path initializer specified", __FILE__, __LINE__, "", ""); 1857 | } 1858 | } 1859 | } 1860 | 1861 | basic_path& operator=(const string_t& path_string) 1862 | { 1863 | basic_path newPath(path_string); 1864 | swap(newPath); 1865 | return *this; 1866 | } 1867 | 1868 | basic_path& operator=(Initializer::Enum initializer) 1869 | { 1870 | basic_path newPath(initializer); 1871 | swap(newPath); 1872 | return *this; 1873 | } 1874 | 1875 | void swap(basic_path& other) 1876 | { 1877 | path_elems.swap(other.path_elems); 1878 | path_string.swap(other.path_string); 1879 | 1880 | std::swap(path_string_valid, other.path_string_valid); 1881 | std::swap(relative, other.relative); 1882 | std::swap(drive_specified, other.drive_specified); 1883 | std::swap(unc_path, other.unc_path); 1884 | } 1885 | 1886 | basic_path operator/(const string_t& other) 1887 | { 1888 | string_t temp = to_portable_string(); 1889 | temp.append(string_t(1,'/')).append(other); 1890 | return basic_path(temp); 1891 | } 1892 | 1893 | basic_path operator/(const basic_path& other) 1894 | { 1895 | return operator/(other.to_portable_string()); 1896 | } 1897 | 1898 | basic_path& operator/=(const string_t& other) 1899 | { 1900 | basic_path newPath = operator/(other); 1901 | swap(newPath); 1902 | return *this; 1903 | } 1904 | 1905 | basic_path& operator/=(const basic_path& other) 1906 | { 1907 | basic_path newPath = operator/(other); 1908 | swap(newPath); 1909 | return *this; 1910 | } 1911 | 1912 | basic_path& append(const string_t& other) 1913 | { 1914 | return (*this)/= other; 1915 | } 1916 | 1917 | basic_path& append(const basic_path& other) 1918 | { 1919 | return (*this)/= other; 1920 | } 1921 | 1922 | bool is_relative() const 1923 | { 1924 | return relative; 1925 | } 1926 | 1927 | bool is_drive_specified() const 1928 | { 1929 | return drive_specified; 1930 | } 1931 | 1932 | bool is_unc_path() const 1933 | { 1934 | return unc_path; 1935 | } 1936 | 1937 | bool exists() const 1938 | { 1939 | return internal::exists(get_path_string()); 1940 | } 1941 | 1942 | bool is_file() const 1943 | { 1944 | return internal::is_file(get_path_string()); 1945 | } 1946 | 1947 | bool is_directory() const 1948 | { 1949 | return internal::is_directory(get_path_string()); 1950 | } 1951 | 1952 | bool is_directory_empty() const 1953 | { 1954 | return internal::is_directory_empty(get_path_string()); 1955 | } 1956 | 1957 | const string_t to_portable_string() const 1958 | { 1959 | return get_path_string(); 1960 | } 1961 | 1962 | string_t to_win32_string() const 1963 | { 1964 | string_t win23_str = get_path_string(); 1965 | typename string_t::iterator it = win23_str.begin(); 1966 | typename string_t::iterator itEnd = win23_str.end(); 1967 | for (; it!=itEnd; ++it) 1968 | { 1969 | if (*it == '/') 1970 | { 1971 | *it = '\\'; 1972 | } 1973 | } 1974 | return win23_str; 1975 | } 1976 | 1977 | basic_path full_path() const 1978 | { 1979 | string_t temp_path_string; 1980 | 1981 | #ifdef FS_WINDOWS_ 1982 | if (drive_specified & relative) 1983 | { 1984 | temp_path_string = internal::cur_drive_path(path_elems[0]); 1985 | size_t elements = path_elems.size(); 1986 | if (elements > 0) 1987 | { 1988 | size_t lastIndex = temp_path_string.length() - 1; 1989 | if ((temp_path_string[lastIndex] != '/') && 1990 | (temp_path_string[lastIndex] != '\\')) 1991 | { 1992 | temp_path_string.push_back('/'); 1993 | } 1994 | 1995 | temp_path_string.append(path_elems[1]); 1996 | for (size_t elem=2; elem& varmap) const 2067 | { 2068 | typename std::map::const_iterator it; 2069 | 2070 | size_t elemCount = path_elems.size(); 2071 | size_t elem = 0; 2072 | string_t newPathString; 2073 | string_t varId; 2074 | 2075 | if (!relative) 2076 | { 2077 | newPathString = path_elems[0]; 2078 | } 2079 | else 2080 | { 2081 | if (get_variable_id(path_elems[0], varId) && 2082 | ((it = varmap.find(varId)) != varmap.end())) 2083 | { 2084 | newPathString = it->second; 2085 | char_t lastChar = *(newPathString.end()-1); 2086 | if ((lastChar != '/') && (lastChar != '\\')) 2087 | { 2088 | newPathString.push_back('/'); 2089 | } 2090 | } 2091 | else 2092 | { 2093 | newPathString = path_elems[0]; 2094 | newPathString.push_back('/'); 2095 | } 2096 | } 2097 | 2098 | for (elem=1; elemsecond); 2104 | char_t lastChar = *(newPathString.end()-1); 2105 | if ((lastChar != '/') && (lastChar != '\\')) 2106 | { 2107 | newPathString.push_back('/'); 2108 | } 2109 | } 2110 | else 2111 | { 2112 | newPathString.append(path_elems[elem]); 2113 | newPathString.push_back('/'); 2114 | } 2115 | } 2116 | 2117 | return basic_path(newPathString); 2118 | } 2119 | 2120 | bool operator==(const basic_path& other) const 2121 | { 2122 | size_t elems = path_elems.size(); 2123 | if (elems != other.path_elems.size()) 2124 | { 2125 | return false; 2126 | } 2127 | for (size_t elem=0; elem& results) 2160 | { 2161 | if (!this->is_directory()) 2162 | { 2163 | throw filesystem_error("Specified path is not a directory.", __FILE__, __LINE__, "", ""); 2164 | } 2165 | internal::dir_get_files(to_portable_string(), string_t(), results); 2166 | } 2167 | 2168 | void directory_get_files(const string_t& pattern, std::vector& results) 2169 | { 2170 | if (!this->is_directory()) 2171 | { 2172 | throw filesystem_error("Specified path is not a directory.", __FILE__, __LINE__, "", ""); 2173 | } 2174 | internal::dir_get_files(to_portable_string(), pattern, results); 2175 | } 2176 | 2177 | void directory_get_files(const string_t& pattern, std::vector& results) 2178 | { 2179 | basic_path fullpath = full_path(); 2180 | std::vector str_results; 2181 | 2182 | fullpath.directory_get_files(pattern, str_results); 2183 | results.clear(); 2184 | 2185 | std::vector::iterator it = str_results.begin(); 2186 | std::vector::iterator itEnd = str_results.end(); 2187 | for (; it!=itEnd; ++it) 2188 | { 2189 | results.push_back(fullpath / *it); 2190 | } 2191 | } 2192 | 2193 | void directory_get_files(std::vector& results) 2194 | { 2195 | directory_get_files(string_t(), results); 2196 | } 2197 | 2198 | void directory_get_subdirs(std::vector& results) 2199 | { 2200 | if (!this->is_directory()) 2201 | { 2202 | throw filesystem_error("Specified path is not a directory.", __FILE__, __LINE__, "", ""); 2203 | } 2204 | internal::dir_get_subdirs(to_portable_string(), string_t(), results); 2205 | } 2206 | 2207 | void directory_get_subdirs(const string_t& pattern, std::vector& results) 2208 | { 2209 | if (!this->is_directory()) 2210 | { 2211 | throw filesystem_error("Specified path is not a directory.", __FILE__, __LINE__, "", ""); 2212 | } 2213 | internal::dir_get_subdirs(to_portable_string(), pattern, results); 2214 | } 2215 | 2216 | void directory_get_subdirs(const string_t& pattern, std::vector& results) 2217 | { 2218 | basic_path fullpath = full_path(); 2219 | std::vector str_results; 2220 | 2221 | fullpath.directory_get_subdirs(pattern, str_results); 2222 | results.clear(); 2223 | 2224 | std::vector::iterator it = str_results.begin(); 2225 | std::vector::iterator itEnd = str_results.end(); 2226 | for (; it!=itEnd; ++it) 2227 | { 2228 | results.push_back(fullpath / *it); 2229 | } 2230 | } 2231 | 2232 | void directory_get_subdirs(std::vector& results) 2233 | { 2234 | directory_get_subdirs(string_t(), results); 2235 | } 2236 | 2237 | void directory_scan_subdirs_for_files(const string_t& pattern, std::vector& results) 2238 | { 2239 | results.clear(); 2240 | directory_scan_subdirs_for_files_helper(pattern, results); 2241 | } 2242 | 2243 | void directory_scan_subdirs_for_files(std::vector& results) 2244 | { 2245 | results.clear(); 2246 | directory_scan_subdirs_for_files_helper(string_t(), results); 2247 | } 2248 | 2249 | #ifdef FS_WINDOWS_ 2250 | bool is_junction_point() const 2251 | { 2252 | return internal::is_junction_point(get_path_string()); 2253 | } 2254 | #endif //#ifdef FS_WINDOWS_ 2255 | }; 2256 | #endif // REGION: class basic_path 2257 | 2258 | #if 1 // REGION: free filesystem functions 2259 | 2260 | template 2261 | void create_directory(const basic_path& dir) 2262 | { 2263 | internal::create_directory(dir.to_portable_string()); 2264 | } 2265 | 2266 | template 2267 | void remove_directory(const basic_path& dir) 2268 | { 2269 | internal::remove_directory(dir.to_portable_string()); 2270 | } 2271 | 2272 | template 2273 | void remove_file(const basic_path& dir) 2274 | { 2275 | internal::remove_file(dir.to_portable_string()); 2276 | } 2277 | 2278 | template 2279 | void move(const basic_path& oldpath, const basic_path& newpath) 2280 | { 2281 | internal::move(oldpath.to_portable_string(), newpath.to_portable_string()); 2282 | } 2283 | 2284 | template 2285 | void create_hard_link(const basic_path& link, const basic_path& source) 2286 | { 2287 | internal::create_hard_link(link.to_portable_string(), source.to_portable_string()); 2288 | } 2289 | 2290 | template 2291 | std::fstream open_fstream(const basic_path& filename, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) 2292 | { 2293 | return std::fstream(filename.to_portable_string().c_str(), mode); 2294 | } 2295 | 2296 | template 2297 | std::fstream open_fstream(const basic_path& filename, std::ios_base::openmode mode, int protection) 2298 | { 2299 | return std::fstream(filename.to_portable_string().c_str(), mode, protection); 2300 | } 2301 | 2302 | template 2303 | std::wfstream open_wfstream(const basic_path& filename, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) 2304 | { 2305 | return std::wfstream(filename.to_portable_string().c_str(), mode); 2306 | } 2307 | 2308 | template 2309 | std::wfstream open_wfstream(const basic_path& filename, std::ios_base::openmode mode, int protection) 2310 | { 2311 | return std::wfstream(filename.to_portable_string().c_str(), mode, protection); 2312 | } 2313 | 2314 | template 2315 | std::ifstream open_ifstream(const basic_path& filename, std::ios_base::openmode mode = std::ios_base::in) 2316 | { 2317 | return std::ifstream(filename.to_portable_string().c_str(), mode); 2318 | } 2319 | 2320 | template 2321 | std::ifstream open_ifstream(const basic_path& filename, std::ios_base::openmode mode, int protection) 2322 | { 2323 | return std::ifstream(filename.to_portable_string().c_str(), mode, protection); 2324 | } 2325 | 2326 | template 2327 | std::wifstream open_wifstream(const basic_path& filename, std::ios_base::openmode mode = std::ios_base::in) 2328 | { 2329 | return std::wifstream(filename.to_portable_string().c_str(), mode); 2330 | } 2331 | 2332 | template 2333 | std::wifstream open_wifstream(const basic_path& filename, std::ios_base::openmode mode, int protection) 2334 | { 2335 | return std::wifstream(filename.to_portable_string().c_str(), mode, protection); 2336 | } 2337 | 2338 | template 2339 | std::ofstream open_ofstream(const basic_path& filename, std::ios_base::openmode mode = std::ios_base::out) 2340 | { 2341 | return std::ofstream(filename.to_portable_string().c_str(), mode); 2342 | } 2343 | 2344 | template 2345 | std::ofstream open_ofstream(const basic_path& filename, std::ios_base::openmode mode, int protection) 2346 | { 2347 | return std::ofstream(filename.to_portable_string().c_str(), mode, protection); 2348 | } 2349 | 2350 | template 2351 | std::wofstream open_wofstream(const basic_path& filename, std::ios_base::openmode mode = std::ios_base::out) 2352 | { 2353 | return std::wofstream(filename.to_portable_string().c_str(), mode); 2354 | } 2355 | 2356 | template 2357 | std::wofstream open_wofstream(const basic_path& filename, std::ios_base::openmode mode, int protection) 2358 | { 2359 | return std::wofstream(filename.to_portable_string().c_str(), mode, protection); 2360 | } 2361 | 2362 | #ifdef FS_WINDOWS_ 2363 | 2364 | template 2365 | void create_junction_point(const basic_path& link, const basic_path& source) 2366 | { 2367 | if (source.is_directory()) 2368 | { 2369 | if (!link.exists()) 2370 | { 2371 | create_directory(link); 2372 | } 2373 | if (link.is_directory()) 2374 | { 2375 | if (link.is_junction_point() || link.is_directory_empty()) 2376 | { 2377 | if (!internal::create_junction_point(link.to_portable_string(), source.full_path().to_portable_string())) 2378 | { 2379 | throw filesystem_error("Failed to create junction point", __FILE__, __LINE__, "", ""); 2380 | } 2381 | return; 2382 | } 2383 | else 2384 | { 2385 | throw filesystem_error("Directory exists, but is not empty", __FILE__, __LINE__, "", ""); 2386 | } 2387 | } 2388 | else 2389 | { 2390 | if (link.is_file()) 2391 | { 2392 | throw filesystem_error("Link is a file", __FILE__, __LINE__, "", ""); 2393 | } 2394 | throw filesystem_error("Link is not a directory", __FILE__, __LINE__, "", ""); 2395 | } 2396 | } 2397 | throw filesystem_error("Source is not a directory", __FILE__, __LINE__, "", ""); 2398 | } 2399 | #endif //#ifdef FS_WINDOWS_ 2400 | 2401 | #endif // REGION: free filesystem functions 2402 | 2403 | typedef basic_path path; 2404 | typedef basic_path wpath; 2405 | 2406 | } //namespace filesystem 2407 | 2408 | #endif //#ifndef _FILESYSTEM_H__ 2409 | --------------------------------------------------------------------------------