64
64
namespace {
65
65
std::function<bool (std::string const &)> const passAllFilter =
66
66
[](std::string const &) { return false ; };
67
+
68
+ enum class StatResultType {
69
+ Error, // in case it cannot be determined
70
+ Directory,
71
+ SymLink,
72
+ File,
73
+ Other // potentially file
74
+ };
75
+
76
+ StatResultType statResultType (TRI_stat_t const & stbuf) {
77
+ #ifdef _WIN32
78
+ if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
79
+ return StatResultType::Directory;
80
+ }
81
+ #else
82
+ if (S_ISDIR (stbuf.st_mode )) {
83
+ return StatResultType::Directory;
84
+ }
85
+ #endif
86
+
87
+ #ifndef TRI_HAVE_WIN32_SYMBOLIC_LINK
88
+ if (S_ISLNK (stbuf.st_mode )) {
89
+ return StatResultType::SymLink;
90
+ }
91
+ #endif
92
+
93
+ if ((stbuf.st_mode & S_IFMT) == S_IFREG) {
94
+ return StatResultType::File;
95
+ }
96
+
97
+ return StatResultType::Other;
67
98
}
68
99
100
+ StatResultType statResultType (std::string const & path) {
101
+ TRI_stat_t stbuf;
102
+ int res = TRI_STAT (path.c_str (), &stbuf);
103
+ if (res != 0 ) {
104
+ return StatResultType::Error;
105
+ }
106
+ return statResultType (stbuf);
107
+ }
108
+
109
+ } // namespace
110
+
69
111
namespace arangodb {
70
112
namespace basics {
71
113
namespace FileUtils {
@@ -401,12 +443,15 @@ bool copyRecursive(std::string const& source, std::string const& target,
401
443
bool copyDirectoryRecursive (std::string const & source, std::string const & target,
402
444
std::function<TRI_copy_recursive_e(std::string const &)> const & filter,
403
445
std::string& error) {
404
- char * fn = nullptr ;
405
446
bool rc_bool = true ;
447
+
448
+ // these strings will be recycled over and over
449
+ std::string dst = target + TRI_DIR_SEPARATOR_STR;
450
+ size_t const dstPrefixLength = dst.size ();
451
+ std::string src = source + TRI_DIR_SEPARATOR_STR;
452
+ size_t const srcPrefixLength = src.size ();
453
+
406
454
407
- auto isSubDirectory = [](std::string const & name) -> bool {
408
- return isDirectory (name);
409
- };
410
455
#ifdef TRI_HAVE_WIN32_LIST_FILES
411
456
struct _wfinddata_t oneItem;
412
457
intptr_t handle;
@@ -427,7 +472,7 @@ bool copyDirectoryRecursive(std::string const& source, std::string const& target
427
472
rcs.clear ();
428
473
icu::UnicodeString d ((wchar_t *)oneItem.name , static_cast <int32_t >(wcslen (oneItem.name )));
429
474
d.toUTF8String <std::string>(rcs);
430
- fn = (char *)rcs.c_str ();
475
+ char const * fn = (char *)rcs.c_str ();
431
476
#else
432
477
DIR* filedir = opendir (source.c_str ());
433
478
@@ -445,57 +490,79 @@ bool copyDirectoryRecursive(std::string const& source, std::string const& target
445
490
// to be thread-safe in reality, and newer versions of POSIX may require its
446
491
// thread-safety formally, and in addition obsolete readdir_r() altogether
447
492
while ((oneItem = (readdir (filedir))) != nullptr && rc_bool) {
448
- fn = oneItem->d_name ;
493
+ char const * fn = oneItem->d_name ;
449
494
#endif
450
495
451
496
// Now iterate over the items.
452
497
// check its not the pointer to the upper directory:
453
498
if (!strcmp (fn, " ." ) || !strcmp (fn, " .." )) {
454
499
continue ;
455
500
}
456
- std::string dst = target + TRI_DIR_SEPARATOR_STR + fn;
457
- std::string src = source + TRI_DIR_SEPARATOR_STR + fn;
458
501
459
- switch (filter (src)) {
460
- case TRI_COPY_IGNORE:
461
- break ;
502
+ // add current filename to prefix
503
+ src.resize (srcPrefixLength);
504
+ TRI_ASSERT (src.back () == TRI_DIR_SEPARATOR_CHAR);
505
+ src.append (fn);
506
+
507
+ auto filterResult = filter (src);
508
+
509
+ if (filterResult != TRI_COPY_IGNORE) {
510
+ // prepare dst filename
511
+ dst.resize (dstPrefixLength);
512
+ TRI_ASSERT (dst.back () == TRI_DIR_SEPARATOR_CHAR);
513
+ dst.append (fn);
514
+
515
+ // figure out the type of the directory entry.
516
+ StatResultType type = StatResultType::Error;
517
+ TRI_stat_t stbuf;
518
+ int res = TRI_STAT (src.c_str (), &stbuf);
519
+ if (res == 0 ) {
520
+ type = ::statResultType (stbuf);
521
+ }
462
522
463
- case TRI_COPY_COPY:
464
- // Handle subdirectories:
465
- if (isSubDirectory (src)) {
466
- long systemError;
467
- auto rc = TRI_CreateDirectory (dst.c_str (), systemError, error);
468
- if (rc != TRI_ERROR_NO_ERROR && rc != TRI_ERROR_FILE_EXISTS) {
469
- rc_bool = false ;
470
- break ;
471
- }
472
- if (!copyDirectoryRecursive (src, dst, filter, error)) {
473
- rc_bool = false ;
474
- break ;
475
- }
476
- if (!TRI_CopyAttributes (src, dst, error)) {
477
- rc_bool = false ;
478
- break ;
479
- }
480
- #ifndef _WIN32
481
- } else if (isSymbolicLink (src)) {
482
- if (!TRI_CopySymlink (src, dst, error)) {
483
- rc_bool = false ;
484
- }
523
+ switch (filterResult) {
524
+ case TRI_COPY_IGNORE:
525
+ TRI_ASSERT (false );
526
+ break ;
527
+
528
+ case TRI_COPY_COPY:
529
+ // Handle subdirectories:
530
+ if (type == StatResultType::Directory) {
531
+ long systemError;
532
+ auto rc = TRI_CreateDirectory (dst.c_str (), systemError, error);
533
+ if (rc != TRI_ERROR_NO_ERROR && rc != TRI_ERROR_FILE_EXISTS) {
534
+ rc_bool = false ;
535
+ break ;
536
+ }
537
+ if (!copyDirectoryRecursive (src, dst, filter, error)) {
538
+ rc_bool = false ;
539
+ break ;
540
+ }
541
+ if (!TRI_CopyAttributes (src, dst, error)) {
542
+ rc_bool = false ;
543
+ break ;
544
+ }
545
+ } else if (type == StatResultType::SymLink) {
546
+ if (!TRI_CopySymlink (src, dst, error)) {
547
+ rc_bool = false ;
548
+ }
549
+ } else {
550
+ #ifdef _WIN32
551
+ rc_bool = TRI_CopyFile (src, dst, error);
552
+ #else
553
+ // optimized version that reuses the already retrieved stat data
554
+ rc_bool = TRI_CopyFile (src, dst, error, &stbuf);
485
555
#endif
486
- } else {
487
- if (!TRI_CopyFile (src, dst, error)) {
488
- rc_bool = false ;
489
556
}
490
- }
491
- break ;
557
+ break ;
492
558
493
- case TRI_COPY_LINK:
494
- if (!TRI_CreateHardlink (src, dst, error)) {
495
- rc_bool = false ;
496
- } // if
497
- break ;
498
- } // switch
559
+ case TRI_COPY_LINK:
560
+ if (!TRI_CreateHardlink (src, dst, error)) {
561
+ rc_bool = false ;
562
+ } // if
563
+ break ;
564
+ } // switch
565
+ }
499
566
#ifdef TRI_HAVE_WIN32_LIST_FILES
500
567
} while (_wfindnext (handle, &oneItem) != -1 && rc_bool);
501
568
@@ -578,48 +645,19 @@ std::vector<std::string> listFiles(std::string const& directory) {
578
645
}
579
646
580
647
bool isDirectory (std::string const & path) {
581
- TRI_stat_t stbuf;
582
- int res = TRI_STAT (path.c_str (), &stbuf);
583
-
584
- #ifdef _WIN32
585
- return (res == 0 ) && ((stbuf.st_mode & S_IFMT) == S_IFDIR);
586
- #else
587
- return (res == 0 ) && S_ISDIR (stbuf.st_mode );
588
- #endif
648
+ return ::statResultType (path) == ::StatResultType::Directory;
589
649
}
590
650
591
651
bool isSymbolicLink (std::string const & path) {
592
- #ifdef TRI_HAVE_WIN32_SYMBOLIC_LINK
593
-
594
- // .....................................................................
595
- // TODO: On the NTFS file system, there are the following file links:
596
- // hard links -
597
- // junctions -
598
- // symbolic links -
599
- // .....................................................................
600
- return false ;
601
-
602
- #else
603
-
604
- struct stat stbuf;
605
- int res = TRI_STAT (path.c_str (), &stbuf);
606
-
607
- return (res == 0 ) && S_ISLNK (stbuf.st_mode );
608
-
609
- #endif
652
+ return ::statResultType (path) == ::StatResultType::SymLink;
610
653
}
611
654
612
655
bool isRegularFile (std::string const & path) {
613
- TRI_stat_t stbuf;
614
- int res = TRI_STAT (path.c_str (), &stbuf);
615
- return (res == 0 ) && ((stbuf.st_mode & S_IFMT) == S_IFREG);
656
+ return ::statResultType (path) == ::StatResultType::File;
616
657
}
617
658
618
659
bool exists (std::string const & path) {
619
- TRI_stat_t stbuf;
620
- int res = TRI_STAT (path.c_str (), &stbuf);
621
-
622
- return res == 0 ;
660
+ return ::statResultType (path) != ::StatResultType::Error;
623
661
}
624
662
625
663
off_t size (std::string const & path) {
0 commit comments