error_t FAT::traverse(Path path, dirvector& ents, const Dirent* const start) const { // start with given entry (defaults to root) uint32_t cluster = start ? start->block() : 0; Dirent found(this, INVALID_ENTITY); while (!path.empty()) { auto S = this->cl_to_sector(cluster); ents.clear(); // mui importante // sync read entire directory auto err = int_ls(S, ents); if (UNLIKELY(err)) return err; // the name we are looking for const std::string name = path.front(); path.pop_front(); // check for matches in dirents for (auto& e : ents) if (UNLIKELY(e.name() == name)) { // go to this directory, unless its the last name FS_PRINT("traverse_sync: Found match for %s", name.c_str()); // enter the matching directory FS_PRINT("\t\t cluster: %lu\n", e.block()); // only follow if the name is a directory if (e.type() == DIR) { found = e; break; } else { // not dir = error, for now return { error_t::E_NOTDIR, "Cannot list non-directory" }; } } // for (ents) // validate result if (found.type() == INVALID_ENTITY) { FS_PRINT("traverse_sync: NO MATCH for %s\n", name.c_str()); return { error_t::E_NOENT, name }; } // set next cluster cluster = found.block(); } auto S = this->cl_to_sector(cluster); // read result directory entries into ents ents.clear(); // mui importante! return int_ls(S, ents); }
List FAT::ls(const Dirent& ent) const { auto ents = std::make_shared<dirvector> (); // verify ent is a directory if (!ent.is_valid() || !ent.is_dir()) return { { error_t::E_NOTDIR, ent.name() }, ents }; // convert cluster to sector auto S = this->cl_to_sector(ent.block()); // read result directory entries into ents auto err = int_ls(S, *ents); return { err, ents }; }
void FAT::ls(const Dirent& ent, on_ls_func on_ls) const { auto dirents = std::make_shared<dirvector> (); // verify ent is a directory if (!ent.is_valid() || !ent.is_dir()) { on_ls( { error_t::E_NOTDIR, ent.name() }, dirents ); return; } // convert cluster to sector uint32_t S = this->cl_to_sector(ent.block()); // read result directory entries into ents int_ls(S, dirents, on_ls); }
void FAT::traverse(std::shared_ptr<Path> path, cluster_func callback) { // parse this path into a stack of memes typedef std::function<void(uint32_t)> next_func_t; // asynch stack traversal auto next = std::make_shared<next_func_t> (); auto weak_next = std::weak_ptr<next_func_t>(next); *next = [this, path, weak_next, callback] (uint32_t cluster) { if (path->empty()) { // attempt to read directory uint32_t S = this->cl_to_sector(cluster); // result allocated on heap auto dirents = std::make_shared<std::vector<Dirent>> (); int_ls(S, dirents, [callback] (error_t error, dirvec_t ents) { callback(error, ents); }); return; } // retrieve next name std::string name = path->front(); path->pop_front(); uint32_t S = this->cl_to_sector(cluster); debug("Current target: %s on cluster %u (sector %u)\n", name.c_str(), cluster, S); // result allocated on heap auto dirents = std::make_shared<std::vector<Dirent>> (); auto next = weak_next.lock(); // list directory contents int_ls(S, dirents, [name, dirents, next, callback] (error_t err, dirvec_t ents) { if (unlikely(err)) { debug("Could not find: %s\n", name.c_str()); callback(err, dirents); return; } // look for name in directory for (auto& e : *ents) { if (unlikely(e.name() == name)) { // go to this directory, unless its the last name debug("Found match for %s", name.c_str()); // enter the matching directory debug("\t\t cluster: %llu\n", e.block); // only follow directories if (e.type() == DIR) (*next)(e.block); else callback({ error_t::E_NOTDIR, e.name() }, dirents); return; } } // for (ents) debug("NO MATCH for %s\n", name.c_str()); callback({ error_t::E_NOENT, name }, dirents); }); }; // start by reading root directory (*next)(0); }