/* Read LEN bytes from the file described by DATA starting with byte POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_hfs_read_file (struct grub_hfs_data *data, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), grub_off_t pos, grub_size_t len, char *buf) { grub_off_t i; grub_off_t blockcnt; blockcnt = grub_divmod64 (((len + pos) + data->blksz - 1), data->blksz, 0); for (i = grub_divmod64 (pos, data->blksz, 0); i < blockcnt; i++) { grub_disk_addr_t blknr; grub_off_t blockoff; grub_off_t blockend = data->blksz; int skipfirst = 0; grub_divmod64 (pos, data->blksz, &blockoff); blknr = grub_hfs_block (data, data->extents, data->fileid, i, 1); if (grub_errno) return -1; /* Last block. */ if (i == blockcnt - 1) { grub_divmod64 ((len + pos), data->blksz, &blockend); /* The last portion is exactly EXT2_BLOCK_SIZE (data). */ if (! blockend) blockend = data->blksz; } /* First block. */ if (i == grub_divmod64 (pos, data->blksz, 0)) { skipfirst = blockoff; blockend -= skipfirst; } /* If the block number is 0 this block is not stored on disk but is zero filled instead. */ if (blknr) { data->disk->read_hook = read_hook; grub_disk_read (data->disk, blknr, skipfirst, blockend, buf); data->disk->read_hook = 0; if (grub_errno) return -1; } buf += data->blksz - skipfirst; } return len; }
/* Read LEN bytes from the file described by DATA starting with byte POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_hfs_read_file (struct grub_hfs_data *data, void (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length, void *closure), void *closure, int pos, grub_size_t len, char *buf) { int i; int blockcnt; blockcnt = ((len + pos) + data->blksz - 1) / data->blksz; for (i = pos / data->blksz; i < blockcnt; i++) { int blknr; int blockoff = pos % data->blksz; int blockend = data->blksz; int skipfirst = 0; blknr = grub_hfs_block (data, data->extents, data->fileid, i, 1); if (grub_errno) return -1; /* Last block. */ if (i == blockcnt - 1) { blockend = (len + pos) % data->blksz; /* The last portion is exactly EXT2_BLOCK_SIZE (data). */ if (! blockend) blockend = data->blksz; } /* First block. */ if (i == pos / data->blksz) { skipfirst = blockoff; blockend -= skipfirst; } /* If the block number is 0 this block is not stored on disk but is zero filled instead. */ if (blknr) { data->disk->read_hook = read_hook; data->disk->closure = closure; grub_disk_read (data->disk, blknr, skipfirst, blockend, buf); data->disk->read_hook = 0; if (grub_errno) return -1; } buf += data->blksz - skipfirst; } return len; }
/* Read LEN bytes from the file described by DATA starting with byte POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_hfs_read_file (struct grub_hfs_data *data, grub_disk_read_hook_t read_hook, void *read_hook_data, grub_uint32_t pos, grub_size_t len, char *buf) { grub_off_t i; grub_off_t blockcnt; /* Files are at most 2G/4G - 1 bytes on hfs. Avoid 64-bit division. Moreover len > 0 as checked in upper layer. */ blockcnt = (len + pos - 1) / data->blksz + 1; for (i = pos / data->blksz; i < blockcnt; i++) { grub_disk_addr_t blknr; grub_off_t blockoff; grub_off_t blockend = data->blksz; int skipfirst = 0; blockoff = pos % data->blksz; blknr = grub_hfs_block (data, data->extents, data->fileid, i, 1); if (grub_errno) return -1; /* Last block. */ if (i == blockcnt - 1) { blockend = (len + pos) % data->blksz; /* The last portion is exactly EXT2_BLOCK_SIZE (data). */ if (! blockend) blockend = data->blksz; } /* First block. */ if (i == pos / data->blksz) { skipfirst = blockoff; blockend -= skipfirst; } /* If the block number is 0 this block is not stored on disk but is zero filled instead. */ if (blknr) { data->disk->read_hook = read_hook; data->disk->read_hook_data = read_hook_data; grub_disk_read (data->disk, blknr, skipfirst, blockend, buf); data->disk->read_hook = 0; if (grub_errno) return -1; } buf += data->blksz - skipfirst; } return len; }