OSDN Git Service

Fix calculation of dentry size
authorColin Cross <ccross@android.com>
Thu, 5 Aug 2010 18:56:38 +0000 (11:56 -0700)
committerColin Cross <ccross@android.com>
Thu, 5 Aug 2010 21:38:47 +0000 (14:38 -0700)
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

ext4_utils/contents.c
ext4_utils/ext4_utils.h

index 9fcd3b3..0ecdfd4 100644 (file)
@@ -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");
index 294c8c5..0a2b542 100644 (file)
@@ -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