summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-06-09 17:10:32 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-06-09 17:10:32 +0200
commit39839acc9601c1b36d1b43f4ead05ee6fdfebf45 (patch)
tree58e8da5a57e362585c5f47f29d4a95bf87b57b48
parent05330a1d31228d930d54f5422b6a9ff1542e5225 (diff)
Add workaround to make empty directories with xattrs work
The problem: SquashFS uses extended inode types for inodes with xattrs, so for directories we need to generate an ldir inode. The ldir inode type includes a directory index which cannot be empty (the counter is off by 1, so 0 means 1 entry) and the entry is expected to contain a file name with the same issue (must be at least 1 byte). This has probably not really been thought through. What the mksquashfs actually does is generating an ldir inode without an index. The kernel does not bother to read the index, since the size of the directory is 0. Its a hack that just so happens to work. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--README2
-rw-r--r--mkfs/meta.c10
2 files changed, 8 insertions, 4 deletions
diff --git a/README b/README
index ff08801..ad555ff 100644
--- a/README
+++ b/README
@@ -47,8 +47,6 @@ At the moment, the following things still require some work:
- rdsquashfs ignores them entirely
- SquashFS supports deduplicating values through "out of line"
storage but this is currently not used yet.
- - empty directories cannot have xattrs. The way I understand it, this is a
- design flaw in SquashFS. I hope I'm missing something here.
- sparse files (not implemented yet; lots of zeros compress good anyway :P)
- hard links (not implemented yet; do we even want this?)
- File deduplication (not implemented; do we even need this?)
diff --git a/mkfs/meta.c b/mkfs/meta.c
index 4ef570d..8f344ef 100644
--- a/mkfs/meta.c
+++ b/mkfs/meta.c
@@ -187,7 +187,7 @@ static int write_inode(sqfs_info_t *info, meta_writer_t *im, meta_writer_t *dm,
return -1;
if ((di->start_block) > 0xFFFFFFFFUL || di->size > 0xFFFF ||
- (node->xattr != NULL && di->size != 0)) {
+ node->xattr != NULL) {
type = SQFS_INODE_EXT_DIR;
} else {
type = SQFS_INODE_DIR;
@@ -344,7 +344,7 @@ static int write_inode(sqfs_info_t *info, meta_writer_t *im, meta_writer_t *dm,
.start_block = htole32(node->data.dir->start_block),
.parent_inode = node->parent ?
htole32(node->parent->inode_num) : htole32(1),
- .inodex_count = htole32(diridx->num_nodes - 1),
+ .inodex_count = htole32(0),
.offset = htole16(node->data.dir->block_offset),
.xattr_idx = htole32(0xFFFFFFFF),
};
@@ -357,6 +357,12 @@ static int write_inode(sqfs_info_t *info, meta_writer_t *im, meta_writer_t *dm,
return -1;
}
+ /* HACK: truncated index for empty directories */
+ if (node->data.dir->size == 0)
+ break;
+
+ ext.inodex_count = htole32(diridx->num_nodes - 1);
+
for (i = 0; i < diridx->num_nodes; ++i) {
idx.start_block = htole32(diridx->idx_nodes[i].block);