static struct buf* fetch_inode(struct dir_extent *extent, size_t *offset) { struct iso9660_dir_record *dir_rec; struct buf *bp; /* * Directory entries aren't allowed to cross a logical block boundary in * ISO 9660, so we keep searching until we find something or reach the * end of the extent. */ bp = read_extent_block(extent, *offset / v_pri.logical_block_size_l); while (bp != NULL) { dir_rec = (struct iso9660_dir_record*)(b_data(bp) + *offset % v_pri.logical_block_size_l); if (dir_rec->length == 0) { *offset -= *offset % v_pri.logical_block_size_l; *offset += v_pri.logical_block_size_l; } else { break; } lmfs_put_block(bp, FULL_DATA_BLOCK); bp = read_extent_block(extent, *offset / v_pri.logical_block_size_l); } return bp; }
ssize_t fs_read(ino_t ino_nr, struct fsdriver_data *data, size_t bytes, off_t pos, int __unused call) { size_t off, chunk, block_size, cum_io; off_t f_size; struct inode *i_node; struct buf *bp; int r; /* Try to get inode according to its index. */ if ((i_node = find_inode(ino_nr)) == NULL) return EINVAL; /* No inode found. */ f_size = i_node->i_stat.st_size; if (pos >= f_size) return 0; /* EOF */ /* Limit the request to the remainder of the file size. */ if ((off_t)bytes > f_size - pos) bytes = (size_t)(f_size - pos); block_size = v_pri.logical_block_size_l; cum_io = 0; lmfs_reset_rdwt_err(); r = OK; /* Split the transfer into chunks that don't span two blocks. */ while (bytes > 0) { off = pos % block_size; chunk = block_size - off; if (chunk > bytes) chunk = bytes; /* Read 'chunk' bytes. */ bp = read_extent_block(i_node->extent, pos / block_size); if (bp == NULL) panic("bp not valid in rw_chunk; this can't happen"); r = fsdriver_copyout(data, cum_io, b_data(bp)+off, chunk); lmfs_put_block(bp, FULL_DATA_BLOCK); if (r != OK) break; /* EOF reached. */ if (lmfs_rdwt_err() < 0) break; /* Update counters and pointers. */ bytes -= chunk; /* Bytes yet to be read. */ cum_io += chunk; /* Bytes read so far. */ pos += chunk; /* Position within the file. */ } if (lmfs_rdwt_err() != OK) r = lmfs_rdwt_err(); /* Check for disk error. */ if (lmfs_rdwt_err() == END_OF_FILE) r = OK; return (r == OK) ? cum_io : r; }
static int ext2_read_file1(int fd, void *read_start, size_t size, size_t pos, struct ext2_inode *inode) { struct ext4_extent_hdr *extent_hdr; long long blk; size_t off; int i; __u32 blk_start = pos / sb_block_size; __u32 blk_end = (pos + size + sb_block_size - 1) / sb_block_size; off = 0; #ifdef DEBUG_IDE printf("size:%d, pos:%d flags:0x%x\n", size, pos, inode->i_flags); #endif extent_hdr = (struct ext4_extent_hdr *)(inode->i_block); for(i = blk_start; i < blk_end; i++) { int skip; int len; int ret; blk = read_extent_block(fd, extent_hdr, i); #ifdef DEBUG_IDE printf("blk:%d, file_block:%d\n", blk, i); #endif if(blk < 0) return -1; if(i == pos / sb_block_size) { skip = pos % sb_block_size; len = (size <= (sb_block_size - skip) ? size : sb_block_size - skip); } else { skip = 0; len = (size <= sb_block_size ? size : sb_block_size); } if(!len) break; if(size / sb_block_size) len = sb_block_size - skip; else len = size % sb_block_size; if(!len) len = sb_block_size; /*blk = blk * sb_block_size + START_PARTION + skip * sb_block_size;*/ blk = blk * sb_block_size + START_PARTION + skip; devio_lseek(fd, blk, 0); ret = devio_read(fd, read_start + off, len); #ifdef DEBUG_IDE printf("ret:%d, size:%d, off:%d, skip:%d, len:%d \n", ret, size, off, skip, len); #endif if(ret < 0) return -1; if(ret != len) return ret + off; size -= len; off += len; } #ifdef DEBUG_IDE printf("size:%d, off:%d\n", size, off); #endif return off; }
void read_inode_extents(struct inode *i, const struct iso9660_dir_record *dir_rec, struct dir_extent *extent, size_t *offset) { struct buf *bp; struct iso9660_dir_record *extent_rec; struct dir_extent *cur_extent = i->extent; int done = FALSE; /* * No need to search extents if file is empty or has final directory * record flag set. */ if (cur_extent == NULL || ((dir_rec->file_flags & D_NOT_LAST_EXTENT) == 0)) return; while (!done) { bp = fetch_inode(extent, offset); if (bp == NULL) return; bp = read_extent_block(extent, *offset / v_pri.logical_block_size_l); extent_rec = (struct iso9660_dir_record*)(b_data(bp) + *offset % v_pri.logical_block_size_l); if (check_dir_record(dir_rec, *offset % v_pri.logical_block_size_l) != OK) { lmfs_put_block(bp, FULL_DATA_BLOCK); return; } /* Extent entries should share the same name. */ if ((dir_rec->length_file_id == extent_rec->length_file_id) && (memcmp(dir_rec->file_id, extent_rec->file_id, dir_rec->length_file_id) == 0)) { /* Add the extent at the end of the linked list. */ assert(cur_extent->next == NULL); cur_extent->next = alloc_extent(); cur_extent->next->location = dir_rec->loc_extent_l + dir_rec->ext_attr_rec_length; cur_extent->next->length = dir_rec->data_length_l / v_pri.logical_block_size_l; if (dir_rec->data_length_l % v_pri.logical_block_size_l) cur_extent->next->length++; i->i_stat.st_size += dir_rec->data_length_l; i->i_stat.st_blocks += cur_extent->next->length; cur_extent = cur_extent->next; *offset += extent_rec->length; } else done = TRUE; /* Check if not last extent bit is not set. */ if ((dir_rec->file_flags & D_NOT_LAST_EXTENT) == 0) done = TRUE; lmfs_put_block(bp, FULL_DATA_BLOCK); } }