diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2021-07-21 09:41:47 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2021-07-21 09:56:31 +0200 |
commit | 248494992442fbde7eb6ca3979a778d82fa86016 (patch) | |
tree | 3ba8d5100aef7cf0d1f1aeae9f306fd5e6053503 /include/sqfs/inode.h | |
parent | 5333fbe46bcbf70b4888bcc6655681f2cd0f161b (diff) |
Fix libsquashfs directory writer size accounting
The squashfs readdir() implementation in the Linux kernel returns
non-existing "." and ".." entries for offsets 0 and 1, and after
that reads from disk. For convenience, it was decided to store an
off-by-3 value on disk instead of doing complex primary school math
to adjust for this. This didn't show up until now, because the kernel
implementation trusts the value from the directory header more than
the actual size in the inode and happily reads 3 more than the inode
would allow it to. This only showed up with 7-zip which subtracts 3
from the size and expects the result to be exact and bails if the
directory headers suggest otherwise.
And yes, I did consider making a "Holy Hand Granade of Antioch"
reference, but consciously decided not to.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'include/sqfs/inode.h')
-rw-r--r-- | include/sqfs/inode.h | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/include/sqfs/inode.h b/include/sqfs/inode.h index 0bc33db..8df7158 100644 --- a/include/sqfs/inode.h +++ b/include/sqfs/inode.h @@ -400,6 +400,15 @@ struct sqfs_inode_dir_t { /** * @brief Combined size of all directory entries and headers in bytes. + * + * The value stored here is off by 3 bytes, i.e. 3 bytes larger than + * the actual listing on disk. The Linux implementation of SquashFS + * uses readdir() offsets 0 and 1 to synthesize "." and ".." entries, + * and after that looks into the actual directory. + * + * Why store an off-by-3 value on disk instead of faking it in the + * kernel and have something consistent here? Beats me, but that's + * how it is implemented. */ sqfs_u16 size; @@ -428,7 +437,7 @@ struct sqfs_inode_dir_ext_t { sqfs_u32 nlink; /** - * @brief Combined size of all directory entries and headers in bytes. + * @brief Size of all directory entries and headers in bytes plus 3. */ sqfs_u32 size; |