From a295f58338b1e0d5dfb2eed57026cafacf266d7d Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Sun, 7 Jul 2019 01:32:19 +0200 Subject: Actually encode/decode directory inode difference as signed The directory listing stores a signed difference of the inode number. Actually treating it as signed saves emitting extra headers if hard links or file deduplication are finally implemented. Signed-off-by: David Oberhollenzer --- include/squashfs.h | 2 +- lib/sqfs/readdir.c | 5 ++++- lib/sqfs/write_dir.c | 13 ++++++++++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/include/squashfs.h b/include/squashfs.h index 01047cf..545756c 100644 --- a/include/squashfs.h +++ b/include/squashfs.h @@ -150,7 +150,7 @@ typedef struct { typedef struct { uint16_t offset; - uint16_t inode_number; + int16_t inode_diff; uint16_t type; uint16_t size; uint8_t name[]; diff --git a/lib/sqfs/readdir.c b/lib/sqfs/readdir.c index 142bafb..71beedc 100644 --- a/lib/sqfs/readdir.c +++ b/lib/sqfs/readdir.c @@ -19,12 +19,15 @@ int meta_reader_read_dir_header(meta_reader_t *m, sqfs_dir_header_t *hdr) sqfs_dir_entry_t *meta_reader_read_dir_ent(meta_reader_t *m) { sqfs_dir_entry_t ent, *out; + uint16_t *diff_u16; if (meta_reader_read(m, &ent, sizeof(ent))) return NULL; + diff_u16 = (uint16_t *)&ent.inode_diff; + *diff_u16 = le16toh(*diff_u16); + ent.offset = le16toh(ent.offset); - ent.inode_number = le16toh(ent.inode_number); ent.type = le16toh(ent.type); ent.size = le16toh(ent.size); diff --git a/lib/sqfs/write_dir.c b/lib/sqfs/write_dir.c index b334864..9f8923b 100644 --- a/lib/sqfs/write_dir.c +++ b/lib/sqfs/write_dir.c @@ -55,8 +55,10 @@ int meta_writer_write_dir(meta_writer_t *dm, dir_info_t *dir, sqfs_dir_header_t hdr; sqfs_dir_entry_t ent; tree_node_t *c, *d; + uint16_t *diff_u16; uint32_t offset; uint64_t block; + int32_t diff; c = dir->children; dir->size = 0; @@ -73,8 +75,9 @@ int meta_writer_write_dir(meta_writer_t *dm, dir_info_t *dir, if ((d->inode_ref >> 16) != (c->inode_ref >> 16)) break; - /* XXX: difference is actually signed */ - if ((d->inode_num - c->inode_num) > 0x7FFF) + diff = d->inode_num - c->inode_num; + + if (diff > 32767 || diff < -32767) break; size += sizeof(ent) + strlen(c->name); @@ -109,8 +112,12 @@ int meta_writer_write_dir(meta_writer_t *dm, dir_info_t *dir, d = c; for (i = 0; i < count; ++i) { + ent.inode_diff = c->inode_num - d->inode_num; + + diff_u16 = (uint16_t *)&ent.inode_diff; + *diff_u16 = htole16(*diff_u16); + ent.offset = htole16(c->inode_ref & 0x0000FFFF); - ent.inode_number = htole16(c->inode_num - d->inode_num); ent.type = htole16(get_type(c->mode)); ent.size = htole16(strlen(c->name) - 1); dir->size += sizeof(ent) + strlen(c->name); -- cgit v1.2.3