IDE::buffer_t IDE::read_sync(block_t blk) { if (blk >= _nb_blk) { // avoid reading past the disk boundaries return buffer_t(); } set_irq_mode(false); set_drive(0xE0 | _drive | ((blk >> 24) & 0x0F)); set_nbsectors(1); set_blocknum(blk); set_command(IDE_CMD_READ); auto* buffer = new uint8_t[block_size()]; wait_status_flags(IDE_DRDY, false); uint16_t* wptr = (uint16_t*) buffer; uint16_t* wend = (uint16_t*)&buffer[block_size()]; while (wptr < wend) *(wptr++) = inw(IDE_DATA); // return a shared_ptr wrapper for the buffer return buffer_t(buffer, std::default_delete<uint8_t[]>()); }
void FAT::readFile(const Dirent& ent, on_read_func callback) { // cluster -> sector uint32_t sector = this->cl_to_sector(ent.block); // number of sectors to read ahead size_t chunks = ent.size / sector_size + 1; // allocate buffer auto* buffer = new uint8_t[chunks * sector_size]; // at which sector we will stop size_t total = chunks; size_t current = 0; typedef std::function<void(uint32_t, size_t, size_t)> next_func_t; auto* next = new next_func_t; *next = [this, buffer, ent, callback, next] (uint32_t sector, size_t current, size_t total) { if (unlikely(current == total)) { // report back to HQ debug("DONE SIZE: %lu (current=%lu, total=%lu)\n", ent.size, current, total); // create shared buffer auto buffer_ptr = buffer_t(buffer, std::default_delete<uint8_t[]>()); // notify caller callback(no_error, buffer_ptr, ent.size); // cleanup (after callback) delete next; return; } device.read(sector, [this, current, total, buffer, ent, &callback, sector, next] (buffer_t data) { if (!data) { // general I/O error occurred debug("Failed to read sector %u for read()", sector); // cleanup delete next; delete[] buffer; callback(true, buffer_t(), 0); return; } // copy over data memcpy(buffer + current * sector_size, data.get(), sector_size); // continue reading next sector (*next)(sector+1, current+1, total); }); }; // start! (*next)(sector, current, total); }
MemDisk::buffer_t MemDisk::read_sync(block_t blk) { auto* loc = ((char*) image_start) + blk * block_size(); // Disallow reading memory past disk image if (unlikely(loc >= image_end)) return buffer_t(); auto* buffer = new uint8_t[block_size()]; assert( memcpy(buffer, loc, block_size()) == buffer ); return buffer_t(buffer, std::default_delete<uint8_t[]>()); }
void MemDisk::read(block_t blk, on_read_func callback) { auto* sector_loc = ((char*) image_start) + blk * block_size(); // Disallow reading memory past disk image if (unlikely(sector_loc >= image_end)) { callback(buffer_t()); return; } auto* buffer = new uint8_t[block_size()]; assert( memcpy(buffer, sector_loc, block_size()) == buffer ); callback( buffer_t(buffer, std::default_delete<uint8_t[]>()) ); }
void MemDisk::read(block_t start, block_t count, on_read_func callback) { auto* start_loc = ((char*) image_start) + start * block_size(); auto* end_loc = start_loc + count * block_size(); // Disallow reading memory past disk image if (unlikely(end_loc >= image_end)) { callback(buffer_t()); return; } auto* buffer = new uint8_t[count * block_size()]; assert( memcpy(buffer, start_loc, count * block_size()) == buffer ); callback( buffer_t(buffer, std::default_delete<uint8_t[]>()) ); }
int test_sz(int n, TCHAR value[i]) { printf("=== test %i ===\n", n); int ret = 0; TCHAR empty[4096]; memset(empty, 0xCC, sizeof(empty)); buffer_t buffer((LPBYTE)empty, sizeof(empty)); valueList_t v = ParseValues(buffer_t((LPBYTE)value, sizeof(TCHAR)*i), REG_SZ); if (memcmp(v.begin()->p, value, (i + 1) * sizeof(TCHAR))) { printf("list: got ?? expected %S [%i]\n", value, (i + 1) * sizeof(TCHAR)); ++ret; } MakeMultiSzRegString(buffer, v); if (buffer.cbBytes != sizeof(TCHAR) * (i + 1)) { printf("got %i bytes, expected %i\n", buffer.cbBytes, sizeof(TCHAR) * (i + 1)); ++ret; } if (memcmp(empty, value, (i + 1) * sizeof(TCHAR))) { printf("got ?? expected %S [%i]\n", value, (i + 1) * sizeof(TCHAR)); ++ret; } if (ret) { for (int i = 0; i < 30; ++i) { printf("%02x ", ((char*)empty)[i]& 0xFF); } printf("\n"); for (int i = 0; i < 30; ++i) { printf("%2c ", (((char*)empty)[i] ? ((char*)empty)[i] : ' ')); } printf("\n"); } return ret; }
scanline_read_iterator( Reader& reader , int pos = 0 ) : _pos( pos ) , _read_scanline( true ) , _skip_scanline( true ) , _reader( reader ) { _buffer = boost::make_shared< buffer_t >( buffer_t( _reader._scanline_length )); _buffer_start = &_buffer->front(); }
void VirtioBlk::read (block_t blk, size_t cnt, on_read_func func) { // create big buffer for collecting all the disk data buffer_t bigbuf { new uint8_t[block_size() * cnt], std::default_delete<uint8_t[]>() }; // (initialized) boolean array of partial jobs auto results = std::make_shared<size_t> (cnt); bool shipped = false; //printf("virtioblk: Enqueue blk %llu cnt %u\n", blk, cnt); //for (int i = cnt-1; i >= 0; i--) for (size_t i = 0; i < cnt; i++) { // create a special request where we collect all the data auto* vbr = new request_t( blk + i, on_read_func::make_packed( [this, i, func, results, bigbuf] (buffer_t buffer) { // if the job was already completed, return early if (*results == 0) { printf("Job cancelled? results == 0, blk=%u\n", i); return; } // validate partial result if (buffer) { *results -= 1; // copy partial block memcpy(bigbuf.get() + i * block_size(), buffer.get(), block_size()); // check if we have all blocks if (*results == 0) { // finally, call user-provided callback func(bigbuf); } } else { (*this->errors)++; // if the partial result failed, cancel all *results = 0; // callback with no data func(buffer_t()); } }) ); //printf("virtioblk: Enqueue blk %llu\n", blk + i); // if (free_space()) { shipit(vbr); shipped = true; } else jobs.push_back(vbr); } // kick when we have enqueued stuff if (shipped) req.kick(); }
void VirtioBlk::handle(request_t* hdr) { // check request response blk_resp_t& resp = hdr->resp; // only call handler with data when the request was fullfilled //printf("response: status %u blk %llu func %p buff %p\n", // resp.status, hdr->hdr.sector, resp.handler.get_ptr(), hdr->io.sector); if (resp.status == 0) { // give the whole request to user: // packaged as buffer, but deleted as request auto buf = buffer_t(hdr->io.sector, [] (uint8_t* buffer) { delete (request_t*) (buffer - sizeof(scsi_header_t)); }); // call handler with buffer only as size is implicit resp.handler(buf); } else { // return empty shared ptr resp.handler(buffer_t()); } }
MemDisk::buffer_t MemDisk::read_block(block_t blk) { FILE* f = fopen(image.c_str(), "r"); if (!f) { return buffer_t(); } fseek(f, blk * block_size(), SEEK_SET); auto* buffer = new uint8_t[block_size()]; int res = fread(buffer, block_size(), 1, f); // fail when not reading block size if (res < 0) { printf("read_block (blk=%lu) fread failed: %s\n", blk, strerror(errno)); return buffer_t(); } // call event handler for successful block read return buffer_t(buffer, std::default_delete<uint8_t[]>()); }
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); }); }
void IDE::read(block_t blk, on_read_func callback) { if (blk >= _nb_blk) { // avoid reading past the disk boundaries callback(buffer_t()); return; } set_irq_mode(true); set_drive(0xE0 | _drive | ((blk >> 24) & 0x0F)); set_nbsectors(1); set_blocknum(blk); set_command(IDE_CMD_READ); _current_callback = callback; _nb_irqs = 1; }
MemDisk::buffer_t MemDisk::read_sync(block_t blk) { // check for existing entry in cache for (auto& entry : cache) if (entry.block == blk) { return entry.data; } // make room if needed while (cache.size() >= CACHE_SIZE) free_entry(); // retrieve block from disk auto data = read_block(blk); if (!data) { printf("Failed to read block %lu\n", blk); return buffer_t(); } // save for later cache.emplace_back(blk, data); return data; }
int test_multi(int n, TCHAR *data, DWORD dataLen, TCHAR** ref, int refLen) { printf("=== test %i ===\n", n); int ret = 0; TCHAR empty[4096]; memset(empty, 0xCC, sizeof(empty)); buffer_t buffer((LPBYTE)empty, sizeof(empty)); valueList_t v = ParseValues(buffer_t((LPBYTE)data, dataLen), REG_MULTI_SZ); MakeMultiSzRegString(buffer, v); if (v.size() != refLen) { printf("got %i items, expected %i\n", v.size(), refLen); ++ret; } int i = 0; for (valueList_t::const_iterator it = v.begin(); i < refLen && it != v.end(); ++it, ++i) { if (_tcscmp(it->p, ref[i])) { printf("got mismatch at position %i\n", i); ++ret; } } if (memcmp(empty, data, dataLen)) { printf("mismatch in raw buffer\n"); ++ret; } if (ret) { for (int i = 0; i < dataLen + 2; ++i) { printf("%02x ", ((char*)empty)[i]& 0xFF); } printf("\n"); for (int i = 0; i < dataLen + 2; ++i) { printf("%2c ", (((char*)empty)[i] ? ((char*)empty)[i] : ' ')); } printf("\n"); } return ret; }
void EXT4::readFile(const std::string& strpath, on_read_func callback) { (void) strpath; callback(true, buffer_t(), 0); }
Buffer EXT4::readFile(const std::string&) { return Buffer({ error_t::E_IO, "Not implemented" }, buffer_t(), 0); }
void EXT4::readFile(const std::string& strpath, on_read_func callback) { (void) strpath; callback({ error_t::E_IO, "Not implemented" }, buffer_t(), 0); }
IDE::buffer_t IDE::read_sync(block_t blk, size_t cnt) { (void) blk; (void) cnt; // not yet implemented return buffer_t(); }
auto allocate_secondary_buffer() const { std::unique_lock<std::mutex> l(shared_data.m); return buffer_t(this, pool.get().get().allocate_secondary_buffer()); }
void EXT4::readFile(const Dirent&, on_read_func callback) { callback(true, buffer_t(), 0); }