Add support for with empty directory blocks in 64k blocksize filesystems
The rec_len field in the directory entry is 16 bits, so if the
filesystem is completely empty, rec_len of 0 is used to designate
65536, for the case where the directory entry takes the entire 64k
block.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
diff --git a/lib/ext2fs/link.c b/lib/ext2fs/link.c
index 5e0f4f3..b283488 100644
--- a/lib/ext2fs/link.c
+++ b/lib/ext2fs/link.c
@@ -24,6 +24,7 @@
ext2_ino_t inode;
int flags;
int done;
+ unsigned int blocksize;
struct ext2_super_block *sb;
};
@@ -35,20 +36,24 @@
{
struct link_struct *ls = (struct link_struct *) priv_data;
struct ext2_dir_entry *next;
- int rec_len, min_rec_len;
+ int rec_len, min_rec_len, curr_rec_len;
int ret = 0;
rec_len = EXT2_DIR_REC_LEN(ls->namelen);
+ curr_rec_len = (dirent->rec_len || ls->blocksize < 65536) ?
+ dirent->rec_len : 65536;
+
/*
* See if the following directory entry (if any) is unused;
* if so, absorb it into this one.
*/
- next = (struct ext2_dir_entry *) (buf + offset + dirent->rec_len);
- if ((offset + dirent->rec_len < blocksize - 8) &&
+ next = (struct ext2_dir_entry *) (buf + offset + curr_rec_len);
+ if ((offset + curr_rec_len < blocksize - 8) &&
(next->inode == 0) &&
- (offset + dirent->rec_len + next->rec_len <= blocksize)) {
+ (offset + curr_rec_len + next->rec_len <= blocksize)) {
dirent->rec_len += next->rec_len;
+ curr_rec_len = dirent->rec_len;
ret = DIRENT_CHANGED;
}
@@ -59,9 +64,9 @@
*/
if (dirent->inode) {
min_rec_len = EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
- if (dirent->rec_len < (min_rec_len + rec_len))
+ if (curr_rec_len < (min_rec_len + rec_len))
return ret;
- rec_len = dirent->rec_len - min_rec_len;
+ rec_len = curr_rec_len - min_rec_len;
dirent->rec_len = min_rec_len;
next = (struct ext2_dir_entry *) (buf + offset +
dirent->rec_len);
@@ -75,7 +80,7 @@
* If we get this far, then the directory entry is not used.
* See if we can fit the request entry in. If so, do it.
*/
- if (dirent->rec_len < rec_len)
+ if (curr_rec_len < rec_len)
return ret;
dirent->inode = ls->inode;
dirent->name_len = ls->namelen;
@@ -112,6 +117,7 @@
ls.flags = flags;
ls.done = 0;
ls.sb = fs->super;
+ ls.blocksize = fs->blocksize;
retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
0, link_proc, &ls);