@@ -40,7 +40,7 @@ const std::string AZURE_DATE_HEADER = "x-ms-date";
4040const std::string AZURE_VERSION_HEADER = " x-ms-version" ;
4141const std::string AZURE_BLOB_TYPE_HEADER = " x-ms-blob-type" ;
4242const std::string AZURE_STORAGE_CLASS_HEADER = " x-ms-access-tier" ;
43- const std::string AZURE_VERSION_DATE = " 2020-06-12 " ;
43+ const std::string AZURE_VERSION_DATE = " 2020-10-02 " ;
4444const std::string AZURE_DEVELOPMENT_HOST = " 127.0.0.1:10000" ;
4545const std::string AZURE_HOST = " .blob.core.windows.net" ;
4646
@@ -531,9 +531,12 @@ Azure_client::Azure_client(const Http_client *client,
531531 storage_account, access_key, development_storage, storage_class));
532532}
533533
534- bool Azure_client::list_objects_with_prefix (const std::string &container,
535- const std::string &prefix,
536- std::vector<std::string> &objects) {
534+ // Common helper function for listing objects - handles pagination and XML
535+ // parsing
536+ template <typename ProcessBlob>
537+ bool Azure_client::list_objects_common (const std::string &container,
538+ const std::string &prefix,
539+ ProcessBlob &&process_blob) {
537540 bool truncated = true ;
538541 std::string next_marker;
539542
@@ -602,20 +605,67 @@ bool Azure_client::list_objects_with_prefix(const std::string &container,
602605
603606 auto node = blobs_node->first_node (" Blob" );
604607 while (node != nullptr ) {
605- auto name = node->first_node (" Name" );
606- if (name == nullptr ) {
607- msg_ts (
608- " %s: Failed to parse list container result. Cannot find object "
609- " name.\n " ,
610- my_progname);
611- return false ;
608+ if (!process_blob (node)) {
609+ return false ; // Processing failed
612610 }
613- objects.push_back (name->value ());
614611 node = node->next_sibling (" Blob" );
615612 }
616613 }
617614
618615 return true ;
619616}
620617
618+ bool Azure_client::list_objects_with_prefix (const std::string &container,
619+ const std::string &prefix,
620+ std::vector<std::string> &objects) {
621+ return list_objects_common (
622+ container, prefix, [&objects](rapidxml::xml_node<> *node) {
623+ auto name = node->first_node (" Name" );
624+ if (name == nullptr ) {
625+ msg_ts (
626+ " %s: Failed to parse list container result. Cannot find object "
627+ " name.\n " ,
628+ my_progname);
629+ return false ;
630+ }
631+ objects.push_back (name->value ());
632+ return true ;
633+ });
634+ }
635+
636+ bool Azure_client::list_objects_files_and_dirs (const std::string &container,
637+ const std::string &prefix,
638+ std::vector<std::string> &files,
639+ std::vector<std::string> &dirs) {
640+ return list_objects_common (
641+ container, prefix, [&](rapidxml::xml_node<> *node) {
642+ auto name = node->first_node (" Name" );
643+ if (name == nullptr ) {
644+ msg_ts (
645+ " %s: Failed to parse list container result. Cannot find object "
646+ " name.\n " ,
647+ my_progname);
648+ return false ;
649+ }
650+
651+ // HNS returns directories explicitly via the ResourceType property.
652+ bool is_directory = false ;
653+ auto properties_node = node->first_node (" Properties" );
654+ if (properties_node) {
655+ auto type_node = properties_node->first_node (" ResourceType" );
656+ if (type_node && type_node->value () &&
657+ strcmp (type_node->value (), " directory" ) == 0 ) {
658+ is_directory = true ;
659+ }
660+ }
661+
662+ if (is_directory) {
663+ dirs.push_back (name->value ());
664+ } else {
665+ files.push_back (name->value ());
666+ }
667+ return true ;
668+ });
669+ }
670+
621671} // namespace xbcloud
0 commit comments