static bool remote_build_list(SyncConnection& sc, std::vector<copyinfo>* file_list, const std::string& rpath, const std::string& lpath) { std::vector<copyinfo> dirlist; std::vector<copyinfo> linklist; // Add an entry for the current directory to ensure it gets created before pulling its contents. copyinfo ci(android::base::Dirname(lpath), android::base::Dirname(rpath), android::base::Basename(lpath), S_IFDIR); file_list->push_back(ci); // Put the files/dirs in rpath on the lists. auto callback = [&](unsigned mode, uint64_t size, uint64_t time, const char* name) { if (IsDotOrDotDot(name)) { return; } copyinfo ci(lpath, rpath, name, mode); if (S_ISDIR(mode)) { dirlist.push_back(ci); } else if (S_ISLNK(mode)) { linklist.push_back(ci); } else { if (!should_pull_file(ci.mode)) { sc.Warning(“skipping special file ‘%s’ (mode = 0o%o)”, ci.rpath.c_str(), ci.mode); ci.skip = true; } ci.time = time; ci.size = size; file_list->push_back(ci); } }; if (!sync_ls(sc, rpath, callback)) { return false; } // Check each symlink we found to see whether it’s a file or directory. for (copyinfo& link_ci : linklist) { struct stat st; if (!sync_stat_fallback(sc, link_ci.rpath, &st)) { sc.Warning(“stat failed for path %s: %s”, link_ci.rpath.c_str(), strerror(errno)); continue; } if (S_ISDIR(st.st_mode)) { dirlist.emplace_back(std::move(link_ci)); } else { file_list->emplace_back(std::move(link_ci)); } } // Recurse into each directory we found. while (!dirlist.empty()) { copyinfo current = dirlist.back(); dirlist.pop_back(); if (!remote_build_list(sc, file_list, current.rpath, current.lpath)) { return false; } } return true; }