char *buf;
};
+struct block_entry {
+ blk64_t physblock;
+ unsigned char sha[EXT2FS_SHA512_LENGTH];
+};
+typedef struct block_entry *block_entry_t;
+
#define BMAP_BUFFER (file->buf + fs->blocksize)
errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
errcode_t retval = 0;
unsigned int start, c, count = 0;
const char *ptr = (const char *) buf;
+ block_entry_t new_block = NULL, old_block = NULL;
+ int bmap_flags = 0;
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
fs = file->fs;
if (retval)
goto fail;
+ file->flags |= EXT2_FILE_BUF_DIRTY;
+ memcpy(file->buf+start, ptr, c);
+
/*
* OK, the physical block hasn't been allocated yet.
* Allocate it.
*/
if (!file->physblock) {
+ bmap_flags = (file->ino ? BMAP_ALLOC : 0);
+ if (fs->flags & EXT2_FLAG_SHARE_DUP) {
+ new_block = calloc(1, sizeof(*new_block));
+ if (!new_block) {
+ retval = EXT2_ET_NO_MEMORY;
+ goto fail;
+ }
+ ext2fs_sha512((const unsigned char*)file->buf,
+ fs->blocksize, new_block->sha);
+ old_block = ext2fs_hashmap_lookup(
+ fs->block_sha_map,
+ new_block->sha,
+ sizeof(new_block->sha));
+ }
+
+ if (old_block) {
+ file->physblock = old_block->physblock;
+ bmap_flags |= BMAP_SET;
+ free(new_block);
+ new_block = NULL;
+ }
+
retval = ext2fs_bmap2(fs, file->ino, &file->inode,
BMAP_BUFFER,
- file->ino ? BMAP_ALLOC : 0,
+ bmap_flags,
file->blockno, 0,
&file->physblock);
if (retval)
goto fail;
+
+ if (new_block) {
+ new_block->physblock = file->physblock;
+ ext2fs_hashmap_add(fs->block_sha_map, new_block,
+ new_block->sha, sizeof(new_block->sha));
+ }
}
- file->flags |= EXT2_FILE_BUF_DIRTY;
- memcpy(file->buf+start, ptr, c);
file->pos += c;
ptr += c;
count += c;