📄 inode.c
字号:
} /* * This is done outside the above if statement so that the * check can be done for block group #0. */ if (scan->current_block == 0) { if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) { goto force_new_group; } else return EXT2_ET_MISSING_INODE_TABLE; } /* * Have we run out of space in the inode buffer? If so, we * need to read in more blocks. */ if (scan->bytes_left < scan->inode_size) { memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left); extra_bytes = scan->bytes_left; retval = get_next_blocks(scan); if (retval) return retval;#if 0 /* * XXX test Need check for used inode somehow. * (Note: this is hard.) */ if (is_empty_scan(scan)) goto force_new_group;#endif } retval = 0; if (extra_bytes) { memcpy(scan->temp_buffer+extra_bytes, scan->ptr, scan->inode_size - extra_bytes); scan->ptr += scan->inode_size - extra_bytes; scan->bytes_left -= scan->inode_size - extra_bytes;#if BB_BIG_ENDIAN if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) || (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) ext2fs_swap_inode_full(scan->fs, (struct ext2_inode_large *) inode, (struct ext2_inode_large *) scan->temp_buffer, 0, bufsize); else#endif *inode = *((struct ext2_inode *) scan->temp_buffer); if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES) retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE; scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES; } else {#if BB_BIG_ENDIAN if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) || (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) ext2fs_swap_inode_full(scan->fs, (struct ext2_inode_large *) inode, (struct ext2_inode_large *) scan->ptr, 0, bufsize); else#endif memcpy(inode, scan->ptr, bufsize); scan->ptr += scan->inode_size; scan->bytes_left -= scan->inode_size; if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE; } scan->inodes_left--; scan->current_inode++; *ino = scan->current_inode; return retval;}errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino, struct ext2_inode *inode){ return ext2fs_get_next_inode_full(scan, ino, inode, sizeof(struct ext2_inode));}/* * Functions to read and write a single inode. */errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode * inode, int bufsize){ unsigned long group, block, block_nr, offset; char *ptr; errcode_t retval; int clen, i, inodes_per_block, length; io_channel io; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); /* Check to see if user has an override function */ if (fs->read_inode) { retval = (fs->read_inode)(fs, ino, inode); if (retval != EXT2_ET_CALLBACK_NOTHANDLED) return retval; } /* Create inode cache if not present */ if (!fs->icache) { retval = create_icache(fs); if (retval) return retval; } /* Check to see if it's in the inode cache */ if (bufsize == sizeof(struct ext2_inode)) { /* only old good inode can be retrieve from the cache */ for (i=0; i < fs->icache->cache_size; i++) { if (fs->icache->cache[i].ino == ino) { *inode = fs->icache->cache[i].inode; return 0; } } } if ((ino == 0) || (ino > fs->super->s_inodes_count)) return EXT2_ET_BAD_INODE_NUM; if (fs->flags & EXT2_FLAG_IMAGE_FILE) { inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super); block_nr = fs->image_header->offset_inode / fs->blocksize; block_nr += (ino - 1) / inodes_per_block; offset = ((ino - 1) % inodes_per_block) * EXT2_INODE_SIZE(fs->super); io = fs->image_io; } else { group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * EXT2_INODE_SIZE(fs->super); block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); if (!fs->group_desc[(unsigned)group].bg_inode_table) return EXT2_ET_MISSING_INODE_TABLE; block_nr = fs->group_desc[(unsigned)group].bg_inode_table + block; io = fs->io; } offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); length = EXT2_INODE_SIZE(fs->super); if (bufsize < length) length = bufsize; ptr = (char *) inode; while (length) { clen = length; if ((offset + length) > fs->blocksize) clen = fs->blocksize - offset; if (block_nr != fs->icache->buffer_blk) { retval = io_channel_read_blk(io, block_nr, 1, fs->icache->buffer); if (retval) return retval; fs->icache->buffer_blk = block_nr; } memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset, clen); offset = 0; length -= clen; ptr += clen; block_nr++; }#if BB_BIG_ENDIAN if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) inode, (struct ext2_inode_large *) inode, 0, length);#endif /* Update the inode cache */ fs->icache->cache_last = (fs->icache->cache_last + 1) % fs->icache->cache_size; fs->icache->cache[fs->icache->cache_last].ino = ino; fs->icache->cache[fs->icache->cache_last].inode = *inode; return 0;}errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode * inode){ return ext2fs_read_inode_full(fs, ino, inode, sizeof(struct ext2_inode));}errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode * inode, int bufsize){ unsigned long group, block, block_nr, offset; errcode_t retval = 0; struct ext2_inode_large temp_inode, *w_inode; char *ptr; int clen, i, length; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); /* Check to see if user provided an override function */ if (fs->write_inode) { retval = (fs->write_inode)(fs, ino, inode); if (retval != EXT2_ET_CALLBACK_NOTHANDLED) return retval; } /* Check to see if the inode cache needs to be updated */ if (fs->icache) { for (i=0; i < fs->icache->cache_size; i++) { if (fs->icache->cache[i].ino == ino) { fs->icache->cache[i].inode = *inode; break; } } } else { retval = create_icache(fs); if (retval) return retval; } if (!(fs->flags & EXT2_FLAG_RW)) return EXT2_ET_RO_FILSYS; if ((ino == 0) || (ino > fs->super->s_inodes_count)) return EXT2_ET_BAD_INODE_NUM; length = bufsize; if (length < EXT2_INODE_SIZE(fs->super)) length = EXT2_INODE_SIZE(fs->super); if (length > (int) sizeof(struct ext2_inode_large)) { w_inode = xmalloc(length); } else w_inode = &temp_inode; memset(w_inode, 0, length);#if BB_BIG_ENDIAN if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) ext2fs_swap_inode_full(fs, w_inode, (struct ext2_inode_large *) inode, 1, bufsize); else#endif memcpy(w_inode, inode, bufsize); group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * EXT2_INODE_SIZE(fs->super); block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); if (!fs->group_desc[(unsigned) group].bg_inode_table) return EXT2_ET_MISSING_INODE_TABLE; block_nr = fs->group_desc[(unsigned) group].bg_inode_table + block; offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); length = EXT2_INODE_SIZE(fs->super); if (length > bufsize) length = bufsize; ptr = (char *) w_inode; while (length) { clen = length; if ((offset + length) > fs->blocksize) clen = fs->blocksize - offset; if (fs->icache->buffer_blk != block_nr) { retval = io_channel_read_blk(fs->io, block_nr, 1, fs->icache->buffer); if (retval) goto errout; fs->icache->buffer_blk = block_nr; } memcpy((char *) fs->icache->buffer + (unsigned) offset, ptr, clen); retval = io_channel_write_blk(fs->io, block_nr, 1, fs->icache->buffer); if (retval) goto errout; offset = 0; ptr += clen; length -= clen; block_nr++; } fs->flags |= EXT2_FLAG_CHANGED;errout: if (w_inode && w_inode != &temp_inode) free(w_inode); return retval;}errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode){ return ext2fs_write_inode_full(fs, ino, inode, sizeof(struct ext2_inode));}/* * This function should be called when writing a new inode. It makes * sure that extra part of large inodes is initialized properly. */errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode){ struct ext2_inode *buf; int size = EXT2_INODE_SIZE(fs->super); struct ext2_inode_large *large_inode; if (size == sizeof(struct ext2_inode)) return ext2fs_write_inode_full(fs, ino, inode, sizeof(struct ext2_inode)); buf = xmalloc(size); memset(buf, 0, size); *buf = *inode; large_inode = (struct ext2_inode_large *) buf; large_inode->i_extra_isize = sizeof(struct ext2_inode_large) - EXT2_GOOD_OLD_INODE_SIZE; return ext2fs_write_inode_full(fs, ino, buf, size);}errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks){ struct ext2_inode inode; int i; errcode_t retval; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); if (ino > fs->super->s_inodes_count) return EXT2_ET_BAD_INODE_NUM; if (fs->get_blocks) { if (!(*fs->get_blocks)(fs, ino, blocks)) return 0; } retval = ext2fs_read_inode(fs, ino, &inode); if (retval) return retval; for (i=0; i < EXT2_N_BLOCKS; i++) blocks[i] = inode.i_block[i]; return 0;}errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino){ struct ext2_inode inode; errcode_t retval; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); if (ino > fs->super->s_inodes_count) return EXT2_ET_BAD_INODE_NUM; if (fs->check_directory) { retval = (fs->check_directory)(fs, ino); if (retval != EXT2_ET_CALLBACK_NOTHANDLED) return retval; } retval = ext2fs_read_inode(fs, ino, &inode); if (retval) return retval; if (!LINUX_S_ISDIR(inode.i_mode)) return EXT2_ET_NO_DIRECTORY; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -