summaryrefslogtreecommitdiff
path: root/ext4_utils
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2010-08-05 11:56:38 -0700
committerColin Cross <ccross@android.com>2010-08-05 14:38:47 -0700
commit6bd2b5d80db5630cb73e3e5a4be3b38afa241c5a (patch)
treeeb95b397af1cbfc69091324f65173f88862b81af /ext4_utils
parent7eb4165b83ca3724b64c8925fa530362b6072bc2 (diff)
downloadextras-6bd2b5d80db5630cb73e3e5a4be3b38afa241c5a.tar.gz
Fix calculation of dentry size
The PAD_TO function was incorrectly handling values that were already aligned, which could lead to overruns of the dentry block. Fix the function, rename it to ALIGN, move it to ext4_utils.h, and use it everywhere the dentry size is calculated. Change-Id: Ie9778d2c6f72d3db9a3162e52882377a71b8420a
Diffstat (limited to 'ext4_utils')
-rw-r--r--ext4_utils/contents.c22
-rw-r--r--ext4_utils/ext4_utils.h1
2 files changed, 14 insertions, 9 deletions
diff --git a/ext4_utils/contents.c b/ext4_utils/contents.c
index 9fcd3b30..0ecdfd43 100644
--- a/ext4_utils/contents.c
+++ b/ext4_utils/contents.c
@@ -30,10 +30,10 @@ static u32 dentry_size(u32 entries, struct dentry *dentries)
{
u32 len = 24;
unsigned int i;
+ unsigned int dentry_len;
for (i = 0; i < entries; i++) {
- unsigned int dentry_len = 8 + 4 *
- DIV_ROUND_UP(strlen(dentries[i].filename), 4);
+ dentry_len = 8 + ALIGN(strlen(dentries[i].filename), 4);
if (len % info.block_size + dentry_len > info.block_size)
len += info.block_size - (len % info.block_size);
len += dentry_len;
@@ -42,14 +42,12 @@ static u32 dentry_size(u32 entries, struct dentry *dentries)
return len;
}
-#define PAD_TO(x, y) (x + (y - (x % y)))
-
static struct ext4_dir_entry_2 *add_dentry(u8 *data, u32 *offset,
struct ext4_dir_entry_2 *prev, u32 inode, const char *name,
u8 file_type)
{
u8 name_len = strlen(name);
- u16 rec_len = 8 + PAD_TO(name_len, 4);
+ u16 rec_len = 8 + ALIGN(name_len, 4);
struct ext4_dir_entry_2 *dentry;
u32 start_block = *offset / info.block_size;
@@ -84,14 +82,17 @@ u32 make_directory(u32 dir_inode_num, u32 entries, struct dentry *dentries,
u32 dirs)
{
struct ext4_inode *inode;
- u32 blocks = DIV_ROUND_UP(dentry_size(entries, dentries), info.block_size);
- u64 len = (u64)blocks * info.block_size;
+ u32 blocks;
+ u32 len;
u32 offset = 0;
u32 inode_num;
u8 *data;
unsigned int i;
struct ext4_dir_entry_2 *dentry;
+ blocks = DIV_ROUND_UP(dentry_size(entries, dentries), info.block_size);
+ len = blocks * info.block_size;
+
if (dir_inode_num) {
inode_num = allocate_inode(info);
} else {
@@ -137,8 +138,11 @@ u32 make_directory(u32 dir_inode_num, u32 entries, struct dentry *dentries,
}
for (i = 0; i < entries; i++) {
- dentry = add_dentry(data, &offset, dentry, 0, dentries[i].filename,
- dentries[i].file_type);
+ dentry = add_dentry(data, &offset, dentry, 0,
+ dentries[i].filename, dentries[i].file_type);
+ if (offset > len || (offset == len && i != entries - 1))
+ critical_error("internal error: dentry for %s ends at %d, past %d\n",
+ dentries[i].filename, offset, len);
dentries[i].inode = &dentry->inode;
if (!dentry) {
error("failed to add directory");
diff --git a/ext4_utils/ext4_utils.h b/ext4_utils/ext4_utils.h
index 294c8c5e..0a2b542a 100644
--- a/ext4_utils/ext4_utils.h
+++ b/ext4_utils/ext4_utils.h
@@ -38,6 +38,7 @@ extern int force;
#define min(a, b) ((a) < (b) ? (a) : (b))
#define DIV_ROUND_UP(x, y) (((x) + (y) - 1)/(y))
+#define ALIGN(x, y) ((y) * DIV_ROUND_UP((x), (y)))
#define __le64 u64
#define __le32 u32