(
&mut self,
address: u64,
count: usize,
buf: &mut [u8],
)
| 1422 | } |
| 1423 | |
| 1424 | fn file_read( |
| 1425 | &mut self, |
| 1426 | address: u64, |
| 1427 | count: usize, |
| 1428 | buf: &mut [u8], |
| 1429 | ) -> std::io::Result<Option<()>> { |
| 1430 | let err_inval = std::io::Error::from_raw_os_error(EINVAL); |
| 1431 | if address >= self.virtual_size() { |
| 1432 | return Err(err_inval); |
| 1433 | } |
| 1434 | |
| 1435 | let l1_index = self.l1_table_index(address) as usize; |
| 1436 | let l2_addr_disk = *self |
| 1437 | .l1_table |
| 1438 | .get(l1_index) |
| 1439 | .ok_or_else(|| std::io::Error::from_raw_os_error(EINVAL))?; |
| 1440 | |
| 1441 | if l2_addr_disk == 0 { |
| 1442 | // Reading from an unallocated cluster will return zeros. |
| 1443 | return Ok(None); |
| 1444 | } |
| 1445 | |
| 1446 | let l2_index = self.l2_table_index(address) as usize; |
| 1447 | |
| 1448 | self.cache_l2_cluster(l1_index, l2_addr_disk, false)?; |
| 1449 | |
| 1450 | let l2_entry = self.l2_cache.get(l1_index).unwrap()[l2_index]; |
| 1451 | if l2_entry_is_empty(l2_entry) { |
| 1452 | // Reading from an unallocated cluster will return zeros. |
| 1453 | return Ok(None); |
| 1454 | } else if l2_entry_is_compressed(l2_entry) { |
| 1455 | // Compressed cluster. |
| 1456 | // Read it, decompress, then return slice from decompressed data. |
| 1457 | let mut decompressed_cluster = self.decompress_l2_cluster(l2_entry)?; |
| 1458 | decompressed_cluster.resize(self.raw_file.cluster_size() as usize, 0); |
| 1459 | let start = self.raw_file.cluster_offset(address) as usize; |
| 1460 | let end = start.checked_add(count); |
| 1461 | if end.is_none() || end.unwrap() > decompressed_cluster.len() { |
| 1462 | return Err(err_inval); |
| 1463 | } |
| 1464 | buf[..count].copy_from_slice(&decompressed_cluster[start..end.unwrap()]); |
| 1465 | } else if l2_entry_is_zero(l2_entry) { |
| 1466 | // Cluster with zero flag reads as zeros without accessing disk. |
| 1467 | return Ok(None); |
| 1468 | } else { |
| 1469 | let cluster_addr = l2_entry_std_cluster_addr(l2_entry); |
| 1470 | if cluster_addr & (self.raw_file.cluster_size() - 1) != 0 { |
| 1471 | self.set_corrupt_bit_best_effort(); |
| 1472 | return Err(io::Error::from_raw_os_error(EIO)); |
| 1473 | } |
| 1474 | let start = cluster_addr + self.raw_file.cluster_offset(address); |
| 1475 | let raw_file = self.raw_file.file_mut(); |
| 1476 | raw_file.seek(SeekFrom::Start(start))?; |
| 1477 | raw_file.read_exact(buf)?; |
| 1478 | } |
| 1479 | Ok(Some(())) |
| 1480 | } |
| 1481 |
no test coverage detected