1 /* 2 * 3 * Copyright (c) 1998-2002 4 * John Maddock 5 * 6 * Use, modification and distribution are subject to the 7 * Boost Software License, Version 1.0. (See accompanying file 8 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 * 10 */ 11 12 /* 13 * LOCATION: see http://www.boost.org for most recent version. 14 * FILE: fileiter.cpp 15 * VERSION: see <boost/version.hpp> 16 * DESCRIPTION: Implements file io primitives + directory searching for class boost::RegEx. 17 */ 18 19 20 #define BOOST_REGEX_SOURCE 21 22 #include <boost/config.hpp> 23 #include <climits> 24 #include <stdexcept> 25 #include <string> 26 #include <boost/throw_exception.hpp> 27 #include <boost/regex/v4/fileiter.hpp> 28 #include <boost/regex/v4/regex_workaround.hpp> 29 #include <boost/regex/pattern_except.hpp> 30 31 #include <cstdio> 32 #if defined(BOOST_NO_STDC_NAMESPACE) 33 namespace std{ 34 using ::sprintf; 35 using ::fseek; 36 using ::fread; 37 using ::ftell; 38 using ::fopen; 39 using ::fclose; 40 using ::FILE; 41 using ::strcpy; 42 using ::strcpy; 43 using ::strcat; 44 using ::strcmp; 45 using ::strlen; 46 } 47 #endif 48 49 50 #ifndef BOOST_REGEX_NO_FILEITER 51 52 #if defined(__CYGWIN__) || defined(__CYGWIN32__) 53 #include <sys/cygwin.h> 54 #endif 55 56 #ifdef BOOST_MSVC 57 # pragma warning(disable: 4800) 58 #endif 59 60 namespace boost{ 61 namespace BOOST_REGEX_DETAIL_NS{ 62 // start with the operating system specific stuff: 63 64 #if (defined(__BORLANDC__) || defined(BOOST_REGEX_FI_WIN32_DIR) || defined(BOOST_MSVC)) && !defined(BOOST_RE_NO_WIN32) 65 66 // platform is DOS or Windows 67 // directories are separated with '\\' 68 // and names are insensitive of case 69 70 BOOST_REGEX_DECL const char* _fi_sep = "\\"; 71 const char* _fi_sep_alt = "/"; 72 #define BOOST_REGEX_FI_TRANSLATE(c) std::tolower(c) 73 74 #else 75 76 // platform is not DOS or Windows 77 // directories are separated with '/' 78 // and names are sensitive of case 79 80 BOOST_REGEX_DECL const char* _fi_sep = "/"; 81 const char* _fi_sep_alt = _fi_sep; 82 #define BOOST_REGEX_FI_TRANSLATE(c) c 83 84 #endif 85 86 #ifdef BOOST_REGEX_FI_WIN32_MAP 87 88 void mapfile::open(const char* file) 89 { 90 #if defined(BOOST_NO_ANSI_APIS) 91 int filename_size = strlen(file); 92 LPWSTR wide_file = (LPWSTR)_alloca( (filename_size + 1) * sizeof(WCHAR) ); 93 if(::MultiByteToWideChar(CP_ACP, 0, file, filename_size, wide_file, filename_size + 1) == 0) 94 hfile = INVALID_HANDLE_VALUE; 95 else 96 hfile = CreateFileW(wide_file, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); 97 #elif defined(__CYGWIN__)||defined(__CYGWIN32__) 98 char win32file[ MAX_PATH ]; 99 cygwin_conv_to_win32_path( file, win32file ); 100 hfile = CreateFileA(win32file, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); 101 #else 102 hfile = CreateFileA(file, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); 103 #endif 104 if(hfile != INVALID_HANDLE_VALUE) 105 { 106 hmap = CreateFileMapping(hfile, 0, PAGE_READONLY, 0, 0, 0); 107 if((hmap == INVALID_HANDLE_VALUE) || (hmap == NULL)) 108 { 109 CloseHandle(hfile); 110 hmap = 0; 111 hfile = 0; 112 std::runtime_error err("Unable to create file mapping."); 113 boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err); 114 } 115 _first = static_cast<const char*>(MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0)); 116 if(_first == 0) 117 { 118 CloseHandle(hmap); 119 CloseHandle(hfile); 120 hmap = 0; 121 hfile = 0; 122 std::runtime_error err("Unable to create file mapping."); 123 } 124 _last = _first + GetFileSize(hfile, 0); 125 } 126 else 127 { 128 hfile = 0; 129 #ifndef BOOST_NO_EXCEPTIONS 130 throw std::runtime_error("Unable to open file."); 131 #else 132 BOOST_REGEX_NOEH_ASSERT(hfile != INVALID_HANDLE_VALUE); 133 #endif 134 } 135 } 136 137 void mapfile::close() 138 { 139 if(hfile != INVALID_HANDLE_VALUE) 140 { 141 UnmapViewOfFile((void*)_first); 142 CloseHandle(hmap); 143 CloseHandle(hfile); 144 hmap = hfile = 0; 145 _first = _last = 0; 146 } 147 } 148 149 #elif !defined(BOOST_RE_NO_STL) 150 151 mapfile_iterator& mapfile_iterator::operator = (const mapfile_iterator& i) 152 { 153 if(file && node) 154 file->unlock(node); 155 file = i.file; 156 node = i.node; 157 offset = i.offset; 158 if(file) 159 file->lock(node); 160 return *this; 161 } 162 163 mapfile_iterator& mapfile_iterator::operator++ () 164 { 165 if((++offset == mapfile::buf_size) && file) 166 { 167 ++node; 168 offset = 0; 169 file->lock(node); 170 file->unlock(node-1); 171 } 172 return *this; 173 } 174 175 mapfile_iterator mapfile_iterator::operator++ (int) 176 { 177 mapfile_iterator temp(*this); 178 if((++offset == mapfile::buf_size) && file) 179 { 180 ++node; 181 offset = 0; 182 file->lock(node); 183 file->unlock(node-1); 184 } 185 return temp; 186 } 187 188 mapfile_iterator& mapfile_iterator::operator-- () 189 { 190 if((offset == 0) && file) 191 { 192 --node; 193 offset = mapfile::buf_size - 1; 194 file->lock(node); 195 file->unlock(node + 1); 196 } 197 else 198 --offset; 199 return *this; 200 } 201 202 mapfile_iterator mapfile_iterator::operator-- (int) 203 { 204 mapfile_iterator temp(*this); 205 if((offset == 0) && file) 206 { 207 --node; 208 offset = mapfile::buf_size - 1; 209 file->lock(node); 210 file->unlock(node + 1); 211 } 212 else 213 --offset; 214 return temp; 215 } 216 217 mapfile_iterator operator + (const mapfile_iterator& i, long off) 218 { 219 mapfile_iterator temp(i); 220 temp += off; 221 return temp; 222 } 223 224 mapfile_iterator operator - (const mapfile_iterator& i, long off) 225 { 226 mapfile_iterator temp(i); 227 temp -= off; 228 return temp; 229 } 230 231 mapfile::iterator mapfile::begin()const 232 { 233 return mapfile_iterator(this, 0); 234 } 235 236 mapfile::iterator mapfile::end()const 237 { 238 return mapfile_iterator(this, _size); 239 } 240 241 void mapfile::lock(pointer* node)const 242 { 243 BOOST_ASSERT(node >= _first); 244 BOOST_ASSERT(node <= _last); 245 if(node < _last) 246 { 247 if(*node == 0) 248 { 249 if(condemed.empty()) 250 { 251 *node = new char[sizeof(int) + buf_size]; 252 *(reinterpret_cast<int*>(*node)) = 1; 253 } 254 else 255 { 256 pointer* p = condemed.front(); 257 condemed.pop_front(); 258 *node = *p; 259 *p = 0; 260 *(reinterpret_cast<int*>(*node)) = 1; 261 } 262 263 std::size_t read_size = 0; 264 int read_pos = std::fseek(hfile, (node - _first) * buf_size, SEEK_SET); 265 266 if(0 == read_pos && node == _last - 1) 267 read_size = std::fread(*node + sizeof(int), _size % buf_size, 1, hfile); 268 else 269 read_size = std::fread(*node + sizeof(int), buf_size, 1, hfile); 270 if((read_size == 0) || (std::ferror(hfile))) 271 { 272 #ifndef BOOST_NO_EXCEPTIONS 273 unlock(node); 274 throw std::runtime_error("Unable to read file."); 275 #else 276 BOOST_REGEX_NOEH_ASSERT((0 == std::ferror(hfile)) && (read_size != 0)); 277 #endif 278 } 279 } 280 else 281 { 282 if(*reinterpret_cast<int*>(*node) == 0) 283 { 284 *reinterpret_cast<int*>(*node) = 1; 285 condemed.remove(node); 286 } 287 else 288 ++(*reinterpret_cast<int*>(*node)); 289 } 290 } 291 } 292 293 void mapfile::unlock(pointer* node)const 294 { 295 BOOST_ASSERT(node >= _first); 296 BOOST_ASSERT(node <= _last); 297 if(node < _last) 298 { 299 if(--(*reinterpret_cast<int*>(*node)) == 0) 300 { 301 condemed.push_back(node); 302 } 303 } 304 } 305 306 long int get_file_length(std::FILE* hfile) 307 { 308 long int result; 309 std::fseek(hfile, 0, SEEK_END); 310 result = std::ftell(hfile); 311 std::fseek(hfile, 0, SEEK_SET); 312 return result; 313 } 314 315 316 void mapfile::open(const char* file) 317 { 318 hfile = std::fopen(file, "rb"); 319 #ifndef BOOST_NO_EXCEPTIONS 320 try{ 321 #endif 322 if(hfile != 0) 323 { 324 _size = get_file_length(hfile); 325 long cnodes = (_size + buf_size - 1) / buf_size; 326 327 // check that number of nodes is not too high: 328 if(cnodes > (long)((INT_MAX) / sizeof(pointer*))) 329 { 330 std::fclose(hfile); 331 hfile = 0; 332 _size = 0; 333 return; 334 } 335 336 _first = new pointer[(int)cnodes]; 337 _last = _first + cnodes; 338 std::memset(_first, 0, cnodes*sizeof(pointer)); 339 } 340 else 341 { 342 std::runtime_error err("Unable to open file."); 343 } 344 #ifndef BOOST_NO_EXCEPTIONS 345 }catch(...) 346 { close(); throw; } 347 #endif 348 } 349 350 void mapfile::close() 351 { 352 if(hfile != 0) 353 { 354 pointer* p = _first; 355 while(p != _last) 356 { 357 if(*p) 358 delete[] *p; 359 ++p; 360 } 361 delete[] _first; 362 _size = 0; 363 _first = _last = 0; 364 std::fclose(hfile); 365 hfile = 0; 366 condemed.erase(condemed.begin(), condemed.end()); 367 } 368 } 369 370 371 #endif 372 373 inline _fi_find_handle find_first_file(const char* wild, _fi_find_data& data) 374 { 375 #ifdef BOOST_NO_ANSI_APIS 376 std::size_t wild_size = std::strlen(wild); 377 LPWSTR wide_wild = (LPWSTR)_alloca( (wild_size + 1) * sizeof(WCHAR) ); 378 if (::MultiByteToWideChar(CP_ACP, 0, wild, wild_size, wide_wild, wild_size + 1) == 0) 379 return _fi_invalid_handle; 380 381 return FindFirstFileW(wide_wild, &data); 382 #else 383 return FindFirstFileA(wild, &data); 384 #endif 385 } 386 387 inline bool find_next_file(_fi_find_handle hf, _fi_find_data& data) 388 { 389 #ifdef BOOST_NO_ANSI_APIS 390 return FindNextFileW(hf, &data); 391 #else 392 return FindNextFileA(hf, &data); 393 #endif 394 } 395 396 inline void copy_find_file_result_with_overflow_check(const _fi_find_data& data, char* path, size_t max_size) 397 { 398 #ifdef BOOST_NO_ANSI_APIS 399 if (::WideCharToMultiByte(CP_ACP, 0, data.cFileName, -1, path, max_size, NULL, NULL) == 0) 400 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(1); 401 #else 402 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(path, max_size, data.cFileName)); 403 #endif 404 } 405 406 inline bool is_not_current_or_parent_path_string(const _fi_find_data& data) 407 { 408 #ifdef BOOST_NO_ANSI_APIS 409 return (std::wcscmp(data.cFileName, L".") && std::wcscmp(data.cFileName, L"..")); 410 #else 411 return (std::strcmp(data.cFileName, ".") && std::strcmp(data.cFileName, "..")); 412 #endif 413 } 414 415 416 file_iterator::file_iterator() 417 { 418 _root = _path = 0; 419 ref = 0; 420 #ifndef BOOST_NO_EXCEPTIONS 421 try{ 422 #endif 423 _root = new char[MAX_PATH]; 424 BOOST_REGEX_NOEH_ASSERT(_root) 425 _path = new char[MAX_PATH]; 426 BOOST_REGEX_NOEH_ASSERT(_path) 427 ptr = _path; 428 *_path = 0; 429 *_root = 0; 430 ref = new file_iterator_ref(); 431 BOOST_REGEX_NOEH_ASSERT(ref) 432 ref->hf = _fi_invalid_handle; 433 ref->count = 1; 434 #ifndef BOOST_NO_EXCEPTIONS 435 } 436 catch(...) 437 { 438 delete[] _root; 439 delete[] _path; 440 delete ref; 441 throw; 442 } 443 #endif 444 } 445 446 file_iterator::file_iterator(const char* wild) 447 { 448 _root = _path = 0; 449 ref = 0; 450 #ifndef BOOST_NO_EXCEPTIONS 451 try{ 452 #endif 453 _root = new char[MAX_PATH]; 454 BOOST_REGEX_NOEH_ASSERT(_root) 455 _path = new char[MAX_PATH]; 456 BOOST_REGEX_NOEH_ASSERT(_path) 457 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_root, MAX_PATH, wild)); 458 ptr = _root; 459 while(*ptr)++ptr; 460 while((ptr > _root) && (*ptr != *_fi_sep) && (*ptr != *_fi_sep_alt))--ptr; 461 if((ptr == _root) && ( (*ptr== *_fi_sep) || (*ptr==*_fi_sep_alt) ) ) 462 { 463 _root[1]='\0'; 464 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, _root)); 465 } 466 else 467 { 468 *ptr = 0; 469 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, _root)); 470 if(*_path == 0) 471 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, ".")); 472 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcat_s(_path, MAX_PATH, _fi_sep)); 473 } 474 ptr = _path + std::strlen(_path); 475 476 ref = new file_iterator_ref(); 477 BOOST_REGEX_NOEH_ASSERT(ref) 478 ref->hf = find_first_file(wild, ref->_data); 479 ref->count = 1; 480 481 if(ref->hf == _fi_invalid_handle) 482 { 483 *_path = 0; 484 ptr = _path; 485 } 486 else 487 { 488 copy_find_file_result_with_overflow_check(ref->_data, ptr, (MAX_PATH - (ptr - _path))); 489 if(ref->_data.dwFileAttributes & _fi_dir) 490 next(); 491 } 492 #ifndef BOOST_NO_EXCEPTIONS 493 } 494 catch(...) 495 { 496 delete[] _root; 497 delete[] _path; 498 delete ref; 499 throw; 500 } 501 #endif 502 } 503 504 file_iterator::file_iterator(const file_iterator& other) 505 { 506 _root = _path = 0; 507 ref = 0; 508 #ifndef BOOST_NO_EXCEPTIONS 509 try{ 510 #endif 511 _root = new char[MAX_PATH]; 512 BOOST_REGEX_NOEH_ASSERT(_root) 513 _path = new char[MAX_PATH]; 514 BOOST_REGEX_NOEH_ASSERT(_path) 515 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_root, MAX_PATH, other._root)); 516 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, other._path)); 517 ptr = _path + (other.ptr - other._path); 518 ref = other.ref; 519 #ifndef BOOST_NO_EXCEPTIONS 520 } 521 catch(...) 522 { 523 delete[] _root; 524 delete[] _path; 525 throw; 526 } 527 #endif 528 ++(ref->count); 529 } 530 531 file_iterator& file_iterator::operator=(const file_iterator& other) 532 { 533 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_root, MAX_PATH, other._root)); 534 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, other._path)); 535 ptr = _path + (other.ptr - other._path); 536 if(--(ref->count) == 0) 537 { 538 if(ref->hf != _fi_invalid_handle) 539 FindClose(ref->hf); 540 delete ref; 541 } 542 ref = other.ref; 543 ++(ref->count); 544 return *this; 545 } 546 547 548 file_iterator::~file_iterator() 549 { 550 delete[] _root; 551 delete[] _path; 552 if(--(ref->count) == 0) 553 { 554 if(ref->hf != _fi_invalid_handle) 555 FindClose(ref->hf); 556 delete ref; 557 } 558 } 559 560 file_iterator file_iterator::operator++(int) 561 { 562 file_iterator temp(*this); 563 next(); 564 return temp; 565 } 566 567 568 void file_iterator::next() 569 { 570 if(ref->hf != _fi_invalid_handle) 571 { 572 bool cont = true; 573 while(cont) 574 { 575 cont = find_next_file(ref->hf, ref->_data); 576 if(cont && ((ref->_data.dwFileAttributes & _fi_dir) == 0)) 577 break; 578 } 579 if(!cont) 580 { 581 // end of sequence 582 FindClose(ref->hf); 583 ref->hf = _fi_invalid_handle; 584 *_path = 0; 585 ptr = _path; 586 } 587 else 588 copy_find_file_result_with_overflow_check(ref->_data, ptr, MAX_PATH - (ptr - _path)); 589 } 590 } 591 592 593 594 directory_iterator::directory_iterator() 595 { 596 _root = _path = 0; 597 ref = 0; 598 #ifndef BOOST_NO_EXCEPTIONS 599 try{ 600 #endif 601 _root = new char[MAX_PATH]; 602 BOOST_REGEX_NOEH_ASSERT(_root) 603 _path = new char[MAX_PATH]; 604 BOOST_REGEX_NOEH_ASSERT(_path) 605 ptr = _path; 606 *_path = 0; 607 *_root = 0; 608 ref = new file_iterator_ref(); 609 BOOST_REGEX_NOEH_ASSERT(ref) 610 ref->hf = _fi_invalid_handle; 611 ref->count = 1; 612 #ifndef BOOST_NO_EXCEPTIONS 613 } 614 catch(...) 615 { 616 delete[] _root; 617 delete[] _path; 618 delete ref; 619 throw; 620 } 621 #endif 622 } 623 624 directory_iterator::directory_iterator(const char* wild) 625 { 626 _root = _path = 0; 627 ref = 0; 628 #ifndef BOOST_NO_EXCEPTIONS 629 try{ 630 #endif 631 _root = new char[MAX_PATH]; 632 BOOST_REGEX_NOEH_ASSERT(_root) 633 _path = new char[MAX_PATH]; 634 BOOST_REGEX_NOEH_ASSERT(_path) 635 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_root, MAX_PATH, wild)); 636 ptr = _root; 637 while(*ptr)++ptr; 638 while((ptr > _root) && (*ptr != *_fi_sep) && (*ptr != *_fi_sep_alt))--ptr; 639 640 if((ptr == _root) && ( (*ptr== *_fi_sep) || (*ptr==*_fi_sep_alt) ) ) 641 { 642 _root[1]='\0'; 643 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, _root)); 644 } 645 else 646 { 647 *ptr = 0; 648 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, _root)); 649 if(*_path == 0) 650 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, ".")); 651 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcat_s(_path, MAX_PATH, _fi_sep)); 652 } 653 ptr = _path + std::strlen(_path); 654 655 ref = new file_iterator_ref(); 656 BOOST_REGEX_NOEH_ASSERT(ref) 657 ref->count = 1; 658 ref->hf = find_first_file(wild, ref->_data); 659 if(ref->hf == _fi_invalid_handle) 660 { 661 *_path = 0; 662 ptr = _path; 663 } 664 else 665 { 666 copy_find_file_result_with_overflow_check(ref->_data, ptr, MAX_PATH - (ptr - _path)); 667 if(((ref->_data.dwFileAttributes & _fi_dir) == 0) || (std::strcmp(ptr, ".") == 0) || (std::strcmp(ptr, "..") == 0)) 668 next(); 669 } 670 #ifndef BOOST_NO_EXCEPTIONS 671 } 672 catch(...) 673 { 674 delete[] _root; 675 delete[] _path; 676 delete ref; 677 throw; 678 } 679 #endif 680 } 681 682 directory_iterator::~directory_iterator() 683 { 684 delete[] _root; 685 delete[] _path; 686 if(--(ref->count) == 0) 687 { 688 if(ref->hf != _fi_invalid_handle) 689 FindClose(ref->hf); 690 delete ref; 691 } 692 } 693 694 directory_iterator::directory_iterator(const directory_iterator& other) 695 { 696 _root = _path = 0; 697 ref = 0; 698 #ifndef BOOST_NO_EXCEPTIONS 699 try{ 700 #endif 701 _root = new char[MAX_PATH]; 702 BOOST_REGEX_NOEH_ASSERT(_root) 703 _path = new char[MAX_PATH]; 704 BOOST_REGEX_NOEH_ASSERT(_path) 705 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_root, MAX_PATH, other._root)); 706 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, other._path)); 707 ptr = _path + (other.ptr - other._path); 708 ref = other.ref; 709 #ifndef BOOST_NO_EXCEPTIONS 710 } 711 catch(...) 712 { 713 delete[] _root; 714 delete[] _path; 715 throw; 716 } 717 #endif 718 ++(ref->count); 719 } 720 721 directory_iterator& directory_iterator::operator=(const directory_iterator& other) 722 { 723 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_root, MAX_PATH, other._root)); 724 BOOST_REGEX_DETAIL_NS::overflow_error_if_not_zero(BOOST_REGEX_DETAIL_NS::strcpy_s(_path, MAX_PATH, other._path)); 725 ptr = _path + (other.ptr - other._path); 726 if(--(ref->count) == 0) 727 { 728 if(ref->hf != _fi_invalid_handle) 729 FindClose(ref->hf); 730 delete ref; 731 } 732 ref = other.ref; 733 ++(ref->count); 734 return *this; 735 } 736 737 directory_iterator directory_iterator::operator++(int) 738 { 739 directory_iterator temp(*this); 740 next(); 741 return temp; 742 } 743 744 void directory_iterator::next() 745 { 746 if(ref->hf != _fi_invalid_handle) 747 { 748 bool cont = true; 749 while(cont) 750 { 751 cont = find_next_file(ref->hf, ref->_data); 752 if(cont && (ref->_data.dwFileAttributes & _fi_dir)) 753 { 754 if(is_not_current_or_parent_path_string(ref->_data)) 755 break; 756 } 757 } 758 if(!cont) 759 { 760 // end of sequence 761 FindClose(ref->hf); 762 ref->hf = _fi_invalid_handle; 763 *_path = 0; 764 ptr = _path; 765 } 766 else 767 copy_find_file_result_with_overflow_check(ref->_data, ptr, MAX_PATH - (ptr - _path)); 768 } 769 } 770 771 772 #ifdef BOOST_REGEX_FI_POSIX_DIR 773 774 struct _fi_priv_data 775 { 776 char root[MAX_PATH]; 777 char* mask; 778 DIR* d; 779 _fi_priv_data(const char* p); 780 }; 781 782 _fi_priv_data::_fi_priv_data(const char* p) 783 { 784 std::strcpy(root, p); 785 mask = root; 786 while(*mask) ++mask; 787 while((mask > root) && (*mask != *_fi_sep) && (*mask != *_fi_sep_alt)) --mask; 788 if(mask == root && ((*mask== *_fi_sep) || (*mask == *_fi_sep_alt)) ) 789 { 790 root[1] = '\0'; 791 std::strcpy(root+2, p+1); 792 mask = root+2; 793 } 794 else if(mask == root) 795 { 796 root[0] = '.'; 797 root[1] = '\0'; 798 std::strcpy(root+2, p); 799 mask = root+2; 800 } 801 else 802 { 803 *mask = 0; 804 ++mask; 805 } 806 } 807 808 bool iswild(const char* mask, const char* name) 809 { 810 while(*mask && *name) 811 { 812 switch(*mask) 813 { 814 case '?': 815 ++name; 816 ++mask; 817 continue; 818 case '*': 819 ++mask; 820 if(*mask == 0) 821 return true; 822 while(*name) 823 { 824 if(iswild(mask, name)) 825 return true; 826 ++name; 827 } 828 return false; 829 case '.': 830 if(0 == *name) 831 { 832 ++mask; 833 continue; 834 } 835 // fall through: 836 default: 837 if(BOOST_REGEX_FI_TRANSLATE(*mask) != BOOST_REGEX_FI_TRANSLATE(*name)) 838 return false; 839 ++mask; 840 ++name; 841 continue; 842 } 843 } 844 if(*mask != *name) 845 return false; 846 return true; 847 } 848 849 unsigned _fi_attributes(const char* root, const char* name) 850 { 851 char buf[MAX_PATH]; 852 // verify that we can not overflow: 853 if(std::strlen(root) + std::strlen(_fi_sep) + std::strlen(name) >= MAX_PATH) 854 return 0; 855 int r; 856 if( ( (root[0] == *_fi_sep) || (root[0] == *_fi_sep_alt) ) && (root[1] == '\0') ) 857 r = (std::sprintf)(buf, "%s%s", root, name); 858 else 859 r = (std::sprintf)(buf, "%s%s%s", root, _fi_sep, name); 860 if(r < 0) 861 return 0; // sprintf failed 862 DIR* d = opendir(buf); 863 if(d) 864 { 865 closedir(d); 866 return _fi_dir; 867 } 868 return 0; 869 } 870 871 _fi_find_handle _fi_FindFirstFile(const char* lpFileName, _fi_find_data* lpFindFileData) 872 { 873 _fi_find_handle dat = new _fi_priv_data(lpFileName); 874 875 DIR* h = opendir(dat->root); 876 dat->d = h; 877 if(h != 0) 878 { 879 if(_fi_FindNextFile(dat, lpFindFileData)) 880 return dat; 881 closedir(h); 882 } 883 delete dat; 884 return 0; 885 } 886 887 bool _fi_FindNextFile(_fi_find_handle dat, _fi_find_data* lpFindFileData) 888 { 889 dirent* d; 890 do 891 { 892 d = readdir(dat->d); 893 } while(d && !iswild(dat->mask, d->d_name)); 894 895 if(d) 896 { 897 std::strcpy(lpFindFileData->cFileName, d->d_name); 898 lpFindFileData->dwFileAttributes = _fi_attributes(dat->root, d->d_name); 899 return true; 900 } 901 return false; 902 } 903 904 bool _fi_FindClose(_fi_find_handle dat) 905 { 906 closedir(dat->d); 907 delete dat; 908 return true; 909 } 910 911 #endif 912 913 } // namespace BOOST_REGEX_DETAIL_NS 914 } // namspace boost 915 916 #endif // BOOST_REGEX_NO_FILEITER 917 918 919 920 921 922 923 924 925 926 927 928 929