Scanning only the direct blocks of the directory file may falsely report
an existing file as nonexisting, and worse can also lead to creation
of a duplicate entry on file creation.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/ext4/ext4_common.c | 74 +++++++++++++++++++++++----------------------------
 1 file changed, 33 insertions(+), 41 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 8d0013e..aa72b0d 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -500,64 +500,53 @@ static int search_dir(struct ext2_inode *parent_inode, 
char *dirname)
 {
        int status;
        int inodeno = 0;
-       int totalbytes;
-       int templength;
-       int direct_blk_idx;
+       int offset;
+       int blk_idx;
        long int blknr;
-       char *ptr = NULL;
        unsigned char *block_buffer = NULL;
        struct ext2_dirent *dir = NULL;
        struct ext_filesystem *fs = get_fs();
+       uint32_t directory_blocks;
 
-       /* read the block no allocated to a file */
-       for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS;
-               direct_blk_idx++) {
-               blknr = read_allocated_block(parent_inode, direct_blk_idx);
-               if (blknr == 0)
-                       goto fail;
+       directory_blocks = le32_to_cpu(g_parent_inode->size) >>
+               LOG2_BLOCK_SIZE(ext4fs_root);
 
-               /* read the blocks of parent inode */
-               block_buffer = zalloc(fs->blksz);
-               if (!block_buffer)
+       block_buffer = zalloc(fs->blksz);
+       if (!block_buffer)
+               goto fail;
+
+       /* get the block no allocated to a file */
+       for (blk_idx = 0; blk_idx < directory_blocks; blk_idx++) {
+               blknr = read_allocated_block(parent_inode, blk_idx);
+               if (blknr == 0)
                        goto fail;
 
+               /* read the directory block */
                status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk,
                                        0, fs->blksz, (char *)block_buffer);
                if (status == 0)
                        goto fail;
 
+               offset = 0;
                dir = (struct ext2_dirent *)block_buffer;
-               ptr = (char *)dir;
-               totalbytes = 0;
-               while (le16_to_cpu(dir->direntlen) >= 0) {
-                       /*
-                        * blocksize-totalbytes because last directory
-                        * length i.e.,*dir->direntlen is free availble
-                        * space in the block that means
-                        * it is a last entry of directory entry
-                        */
-                       if (dir->inode && (strlen(dirname) == dir->namelen)) {
-                               if (strncmp(dirname, ptr + sizeof(struct 
ext2_dirent), dir->namelen) == 0) {
-                                       inodeno = le32_to_cpu(dir->inode);
-                                       break;
-                               }
+               while (le16_to_cpu(dir->direntlen) >= 8) {
+                       if (dir->inode && (strlen(dirname) == dir->namelen) &&
+                           (strncmp(dirname, &dir[1], dir->namelen) == 0)) {
+                               inodeno = le32_to_cpu(dir->inode);
+                               break;
                        }
 
-                       if (fs->blksz - totalbytes == 
le16_to_cpu(dir->direntlen))
+                       offset += le16_to_cpu(dir->direntlen);
+                       if (offset >= fs->blksz)
                                break;
 
-                       /* traversing the each directory entry */
-                       templength = le16_to_cpu(dir->direntlen);
-                       totalbytes = totalbytes + templength;
-                       dir = (struct ext2_dirent *)((char *)dir + templength);
-                       ptr = (char *)dir;
+                       dir = (struct ext2_dirent *)(block_buffer + offset);
                }
 
-               free(block_buffer);
-               block_buffer = NULL;
-
-               if (inodeno > 0)
+               if (inodeno > 0) {
+                       free(block_buffer);
                        return inodeno;
+               }
        }
 
 fail:
@@ -809,14 +798,17 @@ fail:
 
 int ext4fs_filename_unlink(char *filename)
 {
-       short direct_blk_idx = 0;
+       int blk_idx;
        long int blknr = -1;
        int inodeno = -1;
+       uint32_t directory_blocks;
+
+       directory_blocks = le32_to_cpu(g_parent_inode->size) >>
+               LOG2_BLOCK_SIZE(ext4fs_root);
 
        /* read the block no allocated to a file */
-       for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS;
-               direct_blk_idx++) {
-               blknr = read_allocated_block(g_parent_inode, direct_blk_idx);
+       for (blk_idx = 0; blk_idx < directory_blocks; blk_idx++) {
+               blknr = read_allocated_block(g_parent_inode, blk_idx);
                if (blknr == 0)
                        break;
                inodeno = unlink_filename(filename, blknr);
-- 
2.9.2

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to