Buffer FAT::read(const Dirent& ent, uint64_t pos, uint64_t n) const { // bounds check the read position and length auto stapos = std::min(ent.size(), pos); auto endpos = std::min(ent.size(), pos + n); // new length n = endpos - stapos; // cluster -> sector + position auto sector = stapos / this->sector_size; auto nsect = roundup(endpos, sector_size) / sector_size - sector; // read @nsect sectors ahead buffer_t data = device.read_sync(this->cl_to_sector(ent.block()) + sector, nsect); // where to start copying from the device result auto internal_ofs = stapos % device.block_size(); // when the offset is non-zero we aren't on a sector boundary if (internal_ofs != 0) { data = construct_buffer(data->begin() + internal_ofs, data->begin() + internal_ofs + n); } else { // when not offset all we have to do is resize the buffer down from // a sector size multiple to its given length data->resize(n); } return Buffer(no_error, std::move(data)); }
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::read(const Dirent& ent, uint64_t pos, uint64_t n, on_read_func callback) const { // when n=0 roundup() will return an invalid value if (n == 0) { callback({ error_t::E_IO, "Zero read length" }, nullptr); return; } // bounds check the read position and length uint32_t stapos = std::min(ent.size(), pos); uint32_t endpos = std::min(ent.size(), pos + n); // new length n = endpos - stapos; // calculate start and length in sectors uint32_t sector = stapos / this->sector_size; uint32_t nsect = roundup(endpos, sector_size) / sector_size - sector; uint32_t internal_ofs = stapos % device.block_size(); // cluster -> sector + position device.read( this->cl_to_sector(ent.block()) + sector, nsect, hw::Block_device::on_read_func::make_packed( [n, callback, internal_ofs] (buffer_t data) { if (!data) { // general I/O error occurred callback({ error_t::E_IO, "Unable to read file" }, nullptr); return; } // when the offset is non-zero we aren't on a sector boundary if (internal_ofs != 0) { // so, we need to create new buffer with offset data data = construct_buffer(data->begin() + internal_ofs, data->begin() + internal_ofs + n); } else { // when not offset all we have to do is resize the buffer down from // a sector size multiple to its given length data->resize(n); } callback(no_error, data); }) ); }