Esempio n. 1
0
  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));
  }
Esempio n. 2
0
 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 };
 }
Esempio n. 3
0
 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);
 }
Esempio n. 4
0
void Async::disk_transfer(
    Disk          disk,
    const Dirent& ent,
    on_write_func write_func,
    on_after_func callback,
    const size_t  CHUNK_SIZE)
{
  typedef delegate<void(size_t)> next_func_t;
  auto next = std::make_shared<next_func_t> ();
  auto weak_next = std::weak_ptr<next_func_t>(next);

  *next = next_func_t::make_packed(
  [weak_next, disk, ent, write_func, callback, CHUNK_SIZE] (size_t pos) {

    // number of write calls necessary
    const size_t writes = roundup(ent.size(), CHUNK_SIZE);

    // done condition
    if (pos >= writes) {
      callback(fs::no_error, true);
      return;
    }
    auto next = weak_next.lock();
    // read chunk from file
    disk->fs().read(
      ent,
      pos * CHUNK_SIZE,
      CHUNK_SIZE,
      fs::on_read_func::make_packed(
      [next, pos, write_func, callback] (
          fs::error_t  err,
          fs::buffer_t buffer)
      {
        debug("<Async> len=%lu\n", buffer->size());
        if (err) {
          printf("%s\n", err.to_string().c_str());
          callback(err, false);
          return;
        }

        // call write callback with data
        write_func(
          buffer,
          next_func::make_packed(
          [next, pos, callback] (bool good)
          {
            // if the write succeeded, call next
            if (LIKELY(good))
              (*next)(pos+1);
            else
              // otherwise, fail
              callback({fs::error_t::E_IO, "Write failed"}, false);
          })
        );
      })
    );
  });
  // start async loop
  (*next)(0);
}
Esempio n. 5
0
  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);
      })
    );
  }
Esempio n. 6
0
  void FAT::read(const Dirent& ent, uint64_t pos, uint64_t n, on_read_func callback)
  {
    // when n=0 roundup() will return an invalid value
    if (n == 0) {
      callback({ error_t::E_IO, "Zero read length" }, buffer_t(), 0);
      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,
    [pos, n, callback, internal_ofs] (buffer_t data) {

      if (!data) {
        // general I/O error occurred
        debug("Failed to read sector %u for read()", sector);
        callback({ error_t::E_IO, "Unable to read file" }, buffer_t(), 0);
        return;
      }

      // when the offset is non-zero we aren't on a sector boundary
      if (internal_ofs != 0) {
        // so, we need to copy offset data to data buffer
        auto* result = new uint8_t[n];
        memcpy(result, data.get() + internal_ofs, n);
        data = buffer_t(result, std::default_delete<uint8_t[]>());
      }

      callback(no_error, data, n);
    });
  }