1. Directory opreations:
authorgkostka <kostka.grzegorz@gmail.com>
Sun, 20 Oct 2013 17:55:17 +0000 (17:55 +0000)
committergkostka <kostka.grzegorz@gmail.com>
Sun, 20 Oct 2013 17:55:17 +0000 (17:55 +0000)
 - ext4_dir_rm - delete dir recursive
 - ext4_dir_mk - make dir

2. Bugfix in ext4_dir (bad iterator behaviour).
3. Comments inr ext4.h.
4. Demo app has directory operations test.
5. Better ext4_femove implementation.
6. Most file functions base on ext4_open_generic.
7. Extent feature preprocessor switches.

demos/generic/main.c
ext4.h
lwext4/ext4.c
lwext4/ext4_dir.c
lwext4/ext4_fs.c

index 66024220cfd04549e0405baac1887f9f9e5c7069..ab24bd753b885bbca3ff24fe96e35c8c74250bc6 100644 (file)
@@ -46,6 +46,9 @@ static int rw_szie  = 1024;
 /**@brief      Read-write size*/\r
 static int rw_count = 1024;\r
 \r
+/**@brief   Directory test count*/\r
+static int dir_cnt  = 10;\r
+\r
 static bool cache_mode = false;\r
 \r
 \r
@@ -65,10 +68,11 @@ static const char *usage = "                                                                        \n\
 Welcome in ext4 generic demo.                                                                  \n\\r
 Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com) \n\\r
 Usage:                                                                                                                 \n\\r
-       -i   - input file            (default = ext2)                           \n\\r
-       -rws - single R/W size       (default = 1024)                           \n\\r
-       -rwc - R/W count             (default = 1024)                           \n\\r
-       -cache - 0 static, 1 dynamic (default = 0)                                      \n\\r
+       -i   - input file             (default = ext2)                          \n\\r
+       -rws - single R/W size        (default = 1024)                          \n\\r
+       -rwc - R/W count              (default = 1024)                          \n\\r
+       -cache - 0 static, 1 dynamic  (default = 0)                                     \n\\r
+    -dirs  - directory test count (default = 0)                 \n\\r
 \n";\r
 \r
 static char* entry_to_str(uint8_t type)\r
@@ -106,7 +110,7 @@ static void dir_ls(const char *path)
        printf("**********************************************\n");\r
 \r
        ext4_dir_open(&d, path);\r
-       de = ext4_entry_get(&d, j++);\r
+       de = ext4_dir_entry_get(&d, j++);\r
        printf("ls %s\n", path);\r
 \r
        while(de){\r
@@ -115,7 +119,7 @@ static void dir_ls(const char *path)
                printf(entry_to_str(de->inode_type));\r
                printf(sss);\r
                printf("\n");\r
-               de = ext4_entry_get(&d, j++);\r
+               de = ext4_dir_entry_get(&d, j++);\r
        }\r
        printf("**********************************************\n");\r
        ext4_dir_close(&d);\r
@@ -128,14 +132,14 @@ static void mp_stats(void)
 \r
     printf("**********************************************\n");\r
     printf("ext4_mount_point_stats\n");\r
-    printf("inodes_count        = %d\n", stats.inodes_count);\r
-    printf("free_inodes_count   = %d\n", stats.free_inodes_count);\r
-    printf("blocks_count        = %d\n", stats.blocks_count);\r
-    printf("free_blocks_count   = %d\n", stats.free_blocks_count);\r
-    printf("block_size          = %d\n", stats.block_size);\r
-    printf("block_group_count   = %d\n", stats.block_group_count);\r
-    printf("blocks_per_group    = %d\n", stats.blocks_per_group);\r
-    printf("inodes_per_group    = %d\n", stats.inodes_per_group);\r
+    printf("inodes_count        = %u\n", stats.inodes_count);\r
+    printf("free_inodes_count   = %u\n", stats.free_inodes_count);\r
+    printf("blocks_count        = %u\n", (uint32_t)stats.blocks_count);\r
+    printf("free_blocks_count   = %u\n", (uint32_t)stats.free_blocks_count);\r
+    printf("block_size          = %u\n", stats.block_size);\r
+    printf("block_group_count   = %u\n", stats.block_group_count);\r
+    printf("blocks_per_group    = %u\n", stats.blocks_per_group);\r
+    printf("inodes_per_group    = %u\n", stats.inodes_per_group);\r
     printf("volume_name         = %s\n", stats.volume_name);\r
 \r
     printf("**********************************************\n");\r
@@ -148,22 +152,22 @@ static void block_stats(void)
 \r
     printf("**********************************************\n");\r
     printf("ext4 blockdev stats\n");\r
-    printf("bdev->bread_ctr          = %d\n", bd->bread_ctr);\r
-    printf("bdev->bwrite_ctr         = %d\n", bd->bwrite_ctr);\r
+    printf("bdev->bread_ctr          = %u\n", bd->bread_ctr);\r
+    printf("bdev->bwrite_ctr         = %u\n", bd->bwrite_ctr);\r
 \r
 \r
-    printf("bcache->ref_blocks       = %d\n", bc->ref_blocks);\r
-    printf("bcache->max_ref_blocks   = %d\n", bc->max_ref_blocks);\r
-    printf("bcache->lru_ctr          = %d\n", bc->lru_ctr);\r
+    printf("bcache->ref_blocks       = %u\n", bc->ref_blocks);\r
+    printf("bcache->max_ref_blocks   = %u\n", bc->max_ref_blocks);\r
+    printf("bcache->lru_ctr          = %u\n", bc->lru_ctr);\r
 \r
     printf("\n");\r
     for (i = 0; i < bc->cnt; ++i) {\r
-        printf("bcache->refctr[%d]     = %d\n", i, bc->refctr[i]);\r
+        printf("bcache->refctr[%d]     = %u\n", i, bc->refctr[i]);\r
     }\r
 \r
     printf("\n");\r
     for (i = 0; i < bc->cnt; ++i) {\r
-        printf("bcache->lru_id[%d]     = %d\n", i, bc->lru_id[i]);\r
+        printf("bcache->lru_id[%d]     = %u\n", i, bc->lru_id[i]);\r
     }\r
 \r
     printf("\n");\r
@@ -173,7 +177,7 @@ static void block_stats(void)
 \r
     printf("\n");\r
     for (i = 0; i < bc->cnt; ++i) {\r
-        printf("bcache->lba[%d]        = %d\n", i, bc->lba[i]);\r
+        printf("bcache->lba[%d]        = %u\n", i, (uint32_t)bc->lba[i]);\r
     }\r
 \r
 \r
@@ -181,6 +185,59 @@ static void block_stats(void)
     printf("**********************************************\n");\r
 }\r
 \r
+static bool dir_test(int len)\r
+{\r
+    ext4_file f;\r
+    int       r;\r
+    int       i;\r
+    char path[64];\r
+\r
+    printf("Remove directory /mp/dir1\n");\r
+    ext4_dir_rm("/mp/dir1");\r
+\r
+\r
+    printf("Directory create: /mp/dir1\n");\r
+    r = ext4_dir_mk("/mp/dir1");\r
+    if(r != EOK){\r
+        printf("Unable to create directory: /mp/dir1\n");\r
+        return false;\r
+    }\r
+\r
+\r
+    printf("Add files to: /mp/dir1\n");\r
+    for (i = 0; i < len; ++i) {\r
+        sprintf(path, "/mp/dir1/f%d", i);\r
+        r = ext4_fopen(&f, path, "wb");\r
+        if(r != EOK){\r
+            printf("Unable to create file in directory: /mp/dir1\n");\r
+            return false;\r
+        }\r
+    }\r
+\r
+    printf("Add directories to: /mp/dir1\n");\r
+    for (i = 0; i < len; ++i) {\r
+        sprintf(path, "/mp/dir1/d%d", i);\r
+        r = ext4_dir_mk(path);\r
+        if(r != EOK){\r
+            printf("Unable to create directory in directory: /mp/dir1\n");\r
+            return false;\r
+        }\r
+    }\r
+\r
+    printf("Add file directories in: /mp/dir1\n");\r
+\r
+    for (i = 0; i < len; ++i) {\r
+        sprintf(path, "/mp/dir1/d%d/ff", i);\r
+        r = ext4_fopen(&f, path, "wb");\r
+        if(r != EOK){\r
+            printf("Unable to create file in directory: /mp/dir1\n");\r
+            return false;\r
+        }\r
+    }\r
+\r
+    dir_ls("/mp/dir1");\r
+    return true;\r
+}\r
 \r
 int main(int argc, char **argv)\r
 {\r
@@ -197,10 +254,11 @@ int main(int argc, char **argv)
         {"rws",     required_argument, 0, 'b'},\r
         {"rwc",                required_argument, 0, 'c'},\r
         {"cache",   required_argument, 0, 'd'},\r
+        {"dirs",   required_argument,  0, 'e'},\r
         {0, 0, 0, 0}\r
       };\r
 \r
-    while(-1 != (c = getopt_long (argc, argv, "a:b:c:d:", long_options, &option_index))) {\r
+    while(-1 != (c = getopt_long (argc, argv, "a:b:c:d:e:", long_options, &option_index))) {\r
 \r
        switch(c){\r
                case 'a':\r
@@ -215,6 +273,9 @@ int main(int argc, char **argv)
                case 'd':\r
                        cache_mode = atoi(optarg);\r
                        break;\r
+            case 'e':\r
+                dir_cnt = atoi(optarg);\r
+                break;\r
                default:\r
                        printf(usage);\r
                        return EXIT_FAILURE;\r
@@ -262,6 +323,7 @@ int main(int argc, char **argv)
                return EXIT_FAILURE;\r
        }\r
 \r
+       dir_test(dir_cnt);\r
 \r
        ext4_fremove("/mp/hello.txt");\r
        ext4_fremove("/mp/test1");\r
diff --git a/ext4.h b/ext4.h
index 3d0cc2ad3724caa48a291caf4e6f33cc6e6fb336..730d73fd0624a01cae7b279b4985ffcc685e054c 100644 (file)
--- a/ext4.h
+++ b/ext4.h
 #include <ext4_blockdev.h>\r
 #include <stdint.h>\r
 \r
-/********************************FILE OPEN FLAGS********************************/\r
+/********************************FILE OPEN FLAGS*****************************/\r
 \r
 #ifndef O_RDONLY\r
-#define O_RDONLY       00\r
+#define O_RDONLY    00\r
 #endif\r
 \r
 #ifndef O_WRONLY\r
-#define O_WRONLY       01\r
+#define O_WRONLY    01\r
 #endif\r
 \r
 #ifndef O_RDWR\r
-#define O_RDWR         02\r
+#define O_RDWR      02\r
 #endif\r
 \r
 #ifndef O_CREAT\r
-#define O_CREAT            0100\r
+#define O_CREAT     0100\r
 #endif\r
 \r
 #ifndef O_EXCL\r
-#define O_EXCL         0200\r
+#define O_EXCL      0200\r
 #endif\r
 \r
 #ifndef O_TRUNC\r
-#define O_TRUNC                01000\r
+#define O_TRUNC     01000\r
 #endif\r
 \r
 #ifndef O_APPEND\r
-#define O_APPEND       02000\r
+#define O_APPEND    02000\r
 #endif\r
 \r
 /********************************FILE SEEK FLAGS*****************************/\r
@@ -133,7 +133,7 @@ enum  {
     EXT4_DIRENTRY_SYMLINK\r
 };\r
 \r
-/**@brief      Directory entry descriptor. Copy from ext4_types.h*/\r
+/**@brief   Directory entry descriptor. Copy from ext4_types.h*/\r
 typedef struct {\r
     uint32_t inode;\r
     uint16_t entry_length;\r
@@ -182,7 +182,7 @@ int ext4_mount(const char * dev_name,  char *mount_point);
 int    ext4_umount(char *mount_point);\r
 \r
 \r
-/**@brief   Some of the filesystem params.*/\r
+/**@brief   Some of the filesystem stats.*/\r
 struct ext4_mount_stats {\r
     uint32_t inodes_count;\r
     uint32_t free_inodes_count;\r
@@ -197,12 +197,18 @@ struct ext4_mount_stats {
     char volume_name[16];\r
 };\r
 \r
+/**@brief   Get file system params.\r
+ * @param   mount_point mount path\r
+ * @param   stats ext fs stats\r
+ * @return  standard error code */\r
 int ext4_mount_point_stats(const char *mount_point,\r
     struct ext4_mount_stats *stats);\r
 \r
 /********************************FILE OPERATIONS*****************************/\r
 \r
-/**@brief      */\r
+/**@brief      Remove file by path.\r
+ * @param   path path to file\r
+ * @return  standard error code */\r
 int ext4_fremove(const char *path);\r
 \r
 /**@brief      File open function.\r
@@ -226,39 +232,76 @@ int ext4_fremove(const char *path);
  * @return     standard error code*/\r
 int ext4_fopen (ext4_file *f, const char *path, const char *flags);\r
 \r
-/**@brief      */\r
+/**@brief      File close function.\r
+ * @param   f file handle\r
+ * @return  standard error code*/\r
 int ext4_fclose(ext4_file *f);\r
 \r
-/**@brief      */\r
+/**@brief   Read data from file.\r
+ * @param   f file handle\r
+ * @param   buf output buffer\r
+ * @param   size bytes to read\r
+ * @param   rcnt readed bytes (may be NULL)\r
+ * @return  standard error code*/\r
 int ext4_fread (ext4_file *f, void *buf, uint32_t size, uint32_t *rcnt);\r
 \r
-/**@brief      */\r
+/**@brief      Write data to file.\r
+ * @param   f file handle\r
+ * @param   buf data to write\r
+ * @param   size write length\r
+ * @param   wcnt bytes written (may be NULL)\r
+ * @return  standard error code*/\r
 int ext4_fwrite(ext4_file *f, void *buf, uint32_t size, uint32_t *wcnt);\r
 \r
-/**@brief      */\r
+/**@brief      File seek operation.\r
+ * @param   f file handle\r
+ * @param   offset offset to seek\r
+ * @param   origin seek type:\r
+ *              @ref SEEK_SET\r
+ *              @ref SEEK_CUR\r
+ *              @ref SEEK_END\r
+ * @return  standard error code*/\r
 int ext4_fseek (ext4_file *f, uint64_t offset, uint32_t origin);\r
 \r
-/**@brief      */\r
+/**@brief      Get file position.\r
+ * @param   f file handle\r
+ * @return  actual file position */\r
 uint64_t ext4_ftell (ext4_file *f);\r
 \r
-/**@brief      */\r
+/**@brief      Get file size.\r
+ * @param   f file handle\r
+ * @return  file size */\r
 uint64_t ext4_fsize (ext4_file *f);\r
 \r
 /*********************************DIRECTORY OPERATION***********************/\r
-/**@brief      */\r
-int ext4_mkdir(const char *path);\r
 \r
-/**@brief      */\r
-int ext4_rmdir(const char *path);\r
+/**@brief      Recursive directory remove.\r
+ * @param   path directory path to remove\r
+ * @return  standard error code*/\r
+int ext4_dir_rm(const char *path);\r
 \r
-/**@brief      */\r
+/**@brief   Create new directory.\r
+ * @param   name new directory name\r
+ * @return  standard error code*/\r
+int ext4_dir_mk(const char *path);\r
+\r
+/**@brief      Directory open.\r
+ * @param   d directory handle\r
+ * @param   path directory path\r
+ * @return  standard error code*/\r
 int ext4_dir_open (ext4_dir *d, const char *path);\r
 \r
-/**@brief      */\r
+/**@brief      Directory close.\r
+ * @param   d directory handle\r
+ * @return  standard error code*/\r
 int ext4_dir_close(ext4_dir *d);\r
 \r
-/**@brief      */\r
-ext4_direntry* ext4_entry_get(ext4_dir *d, uint32_t id);\r
+\r
+/**@brief      Return directory entry by id.\r
+ * @param   d directory handle\r
+ * @param   id entry id\r
+ * @return  directory entry id (NULL id no entry)*/\r
+ext4_direntry* ext4_dir_entry_get(ext4_dir *d, uint32_t id);\r
 \r
 #endif /* EXT4_H_ */\r
 \r
index a0ceecfb668b843e55559d311a71df19cd858ff9..5136fde2269e292f1fa8346687f7a28ca2cd76e0 100644 (file)
 \r
 /**@brief      Mount point OS dependent lock*/\r
 #define EXT4_MP_LOCK(_m)    \\r
-        do { (_m)->os_locks ? (_m)->os_locks->lock()   : 0; }while(0)\r
+        do { (_m)->os_locks ? (_m)->os_locks->lock() : 0; }while(0)\r
 \r
 /**@brief      Mount point OS dependent unlock*/\r
 #define EXT4_MP_UNLOCK(_m)  \\r
-        do { (_m)->os_locks ? (_m)->os_locks->unlock() : 0;    }while(0)\r
+        do { (_m)->os_locks ? (_m)->os_locks->unlock() : 0; }while(0)\r
 \r
 /**@brief      Mount point descrpitor.*/\r
 struct ext4_mountpoint {\r
@@ -491,7 +491,6 @@ static int ext4_path_check(const char *path, bool* is_goal)
     return 0;\r
 }\r
 \r
-\r
 static bool ext4_parse_flags(const char *flags, uint32_t *file_flags)\r
 {\r
     if(!flags)\r
@@ -533,7 +532,7 @@ static bool ext4_parse_flags(const char *flags, uint32_t *file_flags)
 /****************************************************************************/\r
 \r
 static int ext4_generic_open (ext4_file *f, const char *path,\r
-        const char *flags, bool file_expect)\r
+        const char *flags, bool file_expect, uint32_t *parent_inode, uint32_t *name_off)\r
 {\r
     struct ext4_mountpoint *mp = ext4_get_mount(path);\r
     struct ext4_directory_search_result result;\r
@@ -554,7 +553,8 @@ static int ext4_generic_open (ext4_file *f, const char *path,
     /*Skip mount point*/\r
     path += strlen(mp->name);\r
 \r
-    EXT4_MP_LOCK(mp);\r
+    if(name_off)\r
+        *name_off = strlen(mp->name);\r
 \r
     /*Load root*/\r
     r = ext4_fs_get_inode_ref(&mp->fs, EXT4_INODE_ROOT_INDEX, &ref);\r
@@ -562,17 +562,20 @@ static int ext4_generic_open (ext4_file *f, const char *path,
     if(r != EOK)\r
         return r;\r
 \r
-    int len = ext4_path_check(path, &is_goal);\r
+    if(parent_inode)\r
+        *parent_inode = ref.index;\r
 \r
-    /*If root open was request.*/\r
-    if(!len && is_goal)\r
-        goto IsGoal;\r
+    int len = ext4_path_check(path, &is_goal);\r
 \r
     while(1){\r
 \r
         len = ext4_path_check(path, &is_goal);\r
 \r
         if(!len){\r
+            /*If root open was request.*/\r
+            if(is_goal && !file_expect)\r
+                break;\r
+\r
             r = ENOENT;\r
             break;\r
         }\r
@@ -586,9 +589,9 @@ static int ext4_generic_open (ext4_file *f, const char *path,
             if(!(f->flags & O_CREAT))\r
                 break;\r
 \r
-            /*O_CREAT allows to create new entry*/\r
+            /*O_CREAT allows create new entry*/\r
             struct ext4_inode_ref      child_ref;\r
-            r = ext4_fs_alloc_inode(&mp->fs, &child_ref, !is_goal);\r
+            r = ext4_fs_alloc_inode(&mp->fs, &child_ref, is_goal ? !file_expect : true);\r
             if(r != EOK)\r
                 break;\r
 \r
@@ -612,6 +615,9 @@ static int ext4_generic_open (ext4_file *f, const char *path,
             continue;\r
         }\r
 \r
+        if(parent_inode)\r
+            *parent_inode = ref.index;\r
+\r
         next_inode = result.dentry->inode;\r
         inode_type = ext4_dir_entry_ll_get_inode_type(&mp->fs.sb, result.dentry);\r
 \r
@@ -645,18 +651,20 @@ static int ext4_generic_open (ext4_file *f, const char *path,
             break;\r
 \r
         path += len + 1;\r
+\r
+        if(name_off)\r
+            *name_off += len + 1;\r
     };\r
 \r
     if(r != EOK){\r
         ext4_fs_put_inode_ref(&ref);\r
-        EXT4_MP_UNLOCK(mp);\r
         return r;\r
     }\r
 \r
-    IsGoal:\r
     if(is_goal){\r
 \r
-        if(f->flags & O_TRUNC){\r
+        if((f->flags & O_TRUNC) &&\r
+                (inode_type == EXT4_DIRECTORY_FILETYPE_REG_FILE)){\r
             /*Turncate.*/\r
             ext4_block_delay_cache_flush(mp->fs.bdev, 1);\r
             /*Truncate may be IO heavy.\r
@@ -666,7 +674,6 @@ static int ext4_generic_open (ext4_file *f, const char *path,
 \r
             if(r != EOK){\r
                 ext4_fs_put_inode_ref(&ref);\r
-                EXT4_MP_UNLOCK(mp);\r
                 return r;\r
             }\r
         }\r
@@ -682,7 +689,6 @@ static int ext4_generic_open (ext4_file *f, const char *path,
     }\r
 \r
     r = ext4_fs_put_inode_ref(&ref);\r
-    EXT4_MP_UNLOCK(mp);\r
     return r;\r
 }\r
 \r
@@ -690,97 +696,37 @@ static int ext4_generic_open (ext4_file *f, const char *path,
 \r
 int ext4_fremove(const char *path)\r
 {\r
+    ext4_file   f;\r
+    uint32_t    parent_inode;\r
+    uint32_t    name_off;\r
+    int     r;\r
+    int     len;\r
+    bool    is_goal;\r
     struct ext4_mountpoint *mp = ext4_get_mount(path);\r
-    struct ext4_directory_search_result result;\r
-    bool       is_goal = false;\r
-    uint8_t    inode_type;\r
-    int                r = ENOENT;\r
-    uint32_t next_inode;\r
 \r
-    struct ext4_inode_ref      parent;\r
-    struct ext4_inode_ref      child;\r
-    int len = 0;\r
+    struct ext4_inode_ref child;\r
+    struct ext4_inode_ref parent;\r
 \r
     if(!mp)\r
         return ENOENT;\r
 \r
-\r
-    /*Skip mount point*/\r
-    path += strlen(mp->name);\r
-\r
-    /*Lock mountpoint*/\r
     EXT4_MP_LOCK(mp);\r
-\r
-    /*Load root*/\r
-    r = ext4_fs_get_inode_ref(&mp->fs, EXT4_INODE_ROOT_INDEX, &parent);\r
-\r
+    r = ext4_generic_open(&f, path, "r", true, &parent_inode, &name_off);\r
     if(r != EOK){\r
         EXT4_MP_UNLOCK(mp);\r
         return r;\r
     }\r
 \r
-    while(1){\r
-\r
-        len = ext4_path_check(path, &is_goal);\r
-\r
-        if(!len){\r
-            r = ENOENT;\r
-            break;\r
-        }\r
-\r
-        r = ext4_dir_find_entry(&result, &parent, path, len);\r
-        if(r != EOK){\r
-            ext4_dir_destroy_result(&parent, &result);\r
-            break;\r
-        }\r
-\r
-        next_inode = result.dentry->inode;\r
-        inode_type = ext4_dir_entry_ll_get_inode_type(&mp->fs.sb,\r
-                result.dentry);\r
-\r
-        r = ext4_dir_destroy_result(&parent, &result);\r
-        if(r != EOK)\r
-            break;\r
-\r
-        /*If expected file error*/\r
-        if((inode_type == EXT4_DIRECTORY_FILETYPE_REG_FILE) && !is_goal){\r
-            r = ENOENT;\r
-            break;\r
-        }\r
-\r
-        /*If expected directory error*/\r
-        if((inode_type == EXT4_DIRECTORY_FILETYPE_DIR) && is_goal){\r
-            r = ENOENT;\r
-            break;\r
-        }\r
-\r
-        if(is_goal)\r
-            break;\r
-\r
-        r = ext4_fs_put_inode_ref(&parent);\r
-        if(r != EOK)\r
-            break;\r
-\r
-\r
-        r = ext4_fs_get_inode_ref(&mp->fs, next_inode, &parent);\r
-        if(r != EOK)\r
-            break;\r
-\r
-        path += len + 1;\r
-    };\r
-\r
+    /*Load parent*/\r
+    r = ext4_fs_get_inode_ref(&mp->fs, parent_inode, &parent);\r
     if(r != EOK){\r
-        /*No entry or other error.*/\r
-        ext4_fs_put_inode_ref(&parent);\r
         EXT4_MP_UNLOCK(mp);\r
         return r;\r
     }\r
 \r
-\r
     /*We have file to delete. Load it.*/\r
-    r = ext4_fs_get_inode_ref(&mp->fs, next_inode, &child);\r
+    r = ext4_fs_get_inode_ref(&mp->fs, f.inode, &child);\r
     if(r != EOK){\r
-        /*Parent free*/\r
         ext4_fs_put_inode_ref(&parent);\r
         EXT4_MP_UNLOCK(mp);\r
         return r;\r
@@ -788,14 +734,18 @@ int ext4_fremove(const char *path)
 \r
     /*Turncate.*/\r
     ext4_block_delay_cache_flush(mp->fs.bdev, 1);\r
-\r
     /*Truncate may be IO heavy. Do it with delayed cache flush mode.*/\r
     r = ext4_fs_truncate_inode(&child, 0);\r
-\r
     ext4_block_delay_cache_flush(mp->fs.bdev, 0);\r
+\r
     if(r != EOK)\r
         goto Finish;\r
 \r
+    /*Set path*/\r
+    path += name_off;\r
+\r
+    len = ext4_path_check(path, &is_goal);\r
+\r
     /*Unlink from parent.*/\r
     r = ext4_unlink(mp, &parent, &child, path, len);\r
     if(r != EOK)\r
@@ -805,7 +755,6 @@ int ext4_fremove(const char *path)
     if(r != EOK)\r
         goto Finish;\r
 \r
-\r
     Finish:\r
     ext4_fs_put_inode_ref(&child);\r
     ext4_fs_put_inode_ref(&parent);\r
@@ -816,7 +765,16 @@ int ext4_fremove(const char *path)
 \r
 int    ext4_fopen (ext4_file *f, const char *path, const char *flags)\r
 {\r
-    return ext4_generic_open(f, path, flags, true);\r
+    struct ext4_mountpoint *mp = ext4_get_mount(path);\r
+    int r;\r
+\r
+    if(!mp)\r
+        return ENOENT;\r
+\r
+    EXT4_MP_LOCK(mp);\r
+    r = ext4_generic_open(f, path, flags, true, 0, 0);\r
+    EXT4_MP_UNLOCK(mp);\r
+    return r;\r
 }\r
 \r
 int    ext4_fclose(ext4_file *f)\r
@@ -1144,9 +1102,222 @@ uint64_t ext4_fsize (ext4_file *f)
 \r
 /*********************************DIRECTORY OPERATION************************/\r
 \r
+int ext4_dir_rm(const char *path)\r
+{\r
+    int         r;\r
+    int         len;\r
+    ext4_file   f;\r
+    struct ext4_mountpoint *mp = ext4_get_mount(path);\r
+    struct ext4_inode_ref   current;\r
+    struct ext4_inode_ref   child;\r
+\r
+    struct ext4_directory_iterator it;\r
+    uint32_t name_off;\r
+    uint32_t inode_up;\r
+    uint32_t inode_current;\r
+    uint32_t depth = 1;\r
+    bool     has_children;\r
+    bool     is_goal;\r
+    bool     dir_end;\r
+\r
+    if(!mp)\r
+        return ENOENT;\r
+\r
+    EXT4_MP_LOCK(mp);\r
+\r
+    /*Check if exist.*/\r
+    r = ext4_generic_open(&f, path, "r", false, &inode_up, &name_off);\r
+    if(r != EOK){\r
+        EXT4_MP_UNLOCK(mp);\r
+        return r;\r
+    }\r
+\r
+    path += name_off;\r
+    len = ext4_path_check(path, &is_goal);\r
+\r
+    inode_current = f.inode;\r
+    dir_end = false;\r
+    do {\r
+        /*Load directory node.*/\r
+        r = ext4_fs_get_inode_ref(&f.mp->fs, inode_current, &current);\r
+        if(r != EOK){\r
+            break;\r
+        }\r
+\r
+        /*Initialize iterator.*/\r
+        r = ext4_dir_iterator_init(&it, &current, 0);\r
+        if(r != EOK){\r
+            ext4_fs_put_inode_ref(&current);\r
+            break;\r
+        }\r
+\r
+        while(r == EOK){\r
+\r
+            if(!it.current){\r
+                dir_end = true;\r
+                break;\r
+            }\r
+\r
+            /*Get up directory inode when ".." entry*/\r
+            if((it.current->name_length == 2) &&\r
+                    ext4_is_dots(it.current->name, it.current->name_length)){\r
+                inode_up = it.current->inode;\r
+            }\r
+\r
+            /*If directory or file entry,  but not "." ".." entry*/\r
+            if(!ext4_is_dots(it.current->name, it.current->name_length)){\r
+\r
+                /*Get child inode reference do unlink directory/file.*/\r
+                r = ext4_fs_get_inode_ref(&f.mp->fs, it.current->inode, &child);\r
+                if(r != EOK)\r
+                    break;\r
+\r
+                /*If directory with no leaf children*/\r
+                r = ext4_has_children(&has_children, &child);\r
+                if(r != EOK){\r
+                    ext4_fs_put_inode_ref(&child);\r
+                    break;\r
+                }\r
+\r
+                if(has_children){\r
+                    /*Has directory children. Go into this tirectory.*/\r
+                    inode_up = inode_current;\r
+                    inode_current = it.current->inode;\r
+                    depth++;\r
+                    ext4_fs_put_inode_ref(&child);\r
+                    break;\r
+                }\r
+\r
+                /*Directory is empty. Truncate it.*/\r
+                r = ext4_fs_truncate_inode(&child, 0);\r
+                if(r != EOK){\r
+                    ext4_fs_put_inode_ref(&child);\r
+                    break;\r
+                }\r
+\r
+                /*No children in child directory or file. Just unlink.*/\r
+                r = ext4_unlink(f.mp, &current, &child,\r
+                        (char *)it.current->name, it.current->name_length);\r
+                if(r != EOK){\r
+                    ext4_fs_put_inode_ref(&child);\r
+                    break;\r
+                }\r
+\r
+                r = ext4_fs_free_inode(&child);\r
+                if(r != EOK){\r
+                    ext4_fs_put_inode_ref(&child);\r
+                    break;\r
+                }\r
+\r
+                r = ext4_fs_put_inode_ref(&child);\r
+                if(r != EOK)\r
+                    break;\r
+            }\r
+\r
+            r = ext4_dir_iterator_next(&it);\r
+        }\r
+\r
+        if(dir_end){\r
+            /*Directory iterator reached last entry*/\r
+            ext4_has_children(&has_children, &current);\r
+            if(!has_children){\r
+                inode_current = inode_up;\r
+                if(depth)\r
+                    depth--;\r
+            }\r
+            /*Last unlink*/\r
+            if(!depth){\r
+                /*Load parent.*/\r
+                struct ext4_inode_ref parent;\r
+                r = ext4_fs_get_inode_ref(&f.mp->fs, inode_up, &parent);\r
+                if(r != EOK)\r
+                    goto End;\r
+\r
+                r = ext4_fs_truncate_inode(&current, 0);\r
+                if(r != EOK){\r
+                    ext4_fs_put_inode_ref(&parent);\r
+                    goto End;\r
+                }\r
+\r
+                /* In this place all directories should be unlinked.\r
+                 * Last unlink from root of current directory*/\r
+                r = ext4_unlink(f.mp, &parent, &current, (char *)path, len);\r
+                if(r != EOK){\r
+                    ext4_fs_put_inode_ref(&parent);\r
+                    goto End;\r
+                }\r
+\r
+                r = ext4_fs_free_inode(&current);\r
+                if(r != EOK){\r
+                    ext4_fs_put_inode_ref(&parent);\r
+                    goto End;\r
+                }\r
+\r
+                r = ext4_fs_put_inode_ref(&parent);\r
+                if(r != EOK)\r
+                    goto End;\r
+            }\r
+        }\r
+\r
+        End:\r
+        ext4_dir_iterator_fini(&it);\r
+        ext4_fs_put_inode_ref(&current);\r
+        dir_end = false;\r
+\r
+        /*When something goes wrong. End loop.*/\r
+        if(r != EOK)\r
+            break;\r
+\r
+    }while(depth);\r
+\r
+\r
+    EXT4_MP_UNLOCK(mp);\r
+    return r;\r
+}\r
+\r
+int ext4_dir_mk(const char *path)\r
+{\r
+    int r;\r
+    ext4_file   f;\r
+\r
+    struct ext4_mountpoint *mp = ext4_get_mount(path);\r
+\r
+    if(!mp)\r
+        return ENOENT;\r
+\r
+    EXT4_MP_LOCK(mp);\r
+\r
+    /*Check if exist.*/\r
+    r = ext4_generic_open(&f, path, "r", false, 0, 0);\r
+    if(r == EOK){\r
+        /*Directory already created*/\r
+        EXT4_MP_UNLOCK(mp);\r
+        return r;\r
+    }\r
+\r
+    /*Create new dir*/\r
+    r = ext4_generic_open(&f, path, "w", false, 0, 0);\r
+    if(r != EOK){\r
+        EXT4_MP_UNLOCK(mp);\r
+        return r;\r
+    }\r
+\r
+    EXT4_MP_UNLOCK(mp);\r
+    return r;\r
+}\r
+\r
 int    ext4_dir_open (ext4_dir *d, const char *path)\r
 {\r
-    return ext4_generic_open(&d->f, path, "r", false);\r
+    struct ext4_mountpoint *mp = ext4_get_mount(path);\r
+    int r;\r
+\r
+    if(!mp)\r
+        return ENOENT;\r
+\r
+    EXT4_MP_LOCK(mp);\r
+    r = ext4_generic_open(&d->f, path, "r", false, 0, 0);\r
+    EXT4_MP_UNLOCK(mp);\r
+    return r;\r
 }\r
 \r
 int    ext4_dir_close(ext4_dir *d)\r
@@ -1154,7 +1325,7 @@ int       ext4_dir_close(ext4_dir *d)
     return ext4_fclose(&d->f);\r
 }\r
 \r
-ext4_direntry* ext4_entry_get(ext4_dir *d, uint32_t id)\r
+ext4_direntry* ext4_dir_entry_get(ext4_dir *d, uint32_t id)\r
 {\r
     int         r;\r
     uint32_t i;\r
@@ -1187,7 +1358,6 @@ ext4_direntry*    ext4_entry_get(ext4_dir *d, uint32_t id)
             break;\r
         }\r
 \r
-\r
         i++;\r
         r = ext4_dir_iterator_next(&it);\r
     }\r
index 4f0211976430064ffcd7c2f227ce1f14e1aa5d63..ecce197c8df94f1dc29c3cb6a1a54f5653da030b 100644 (file)
@@ -228,9 +228,21 @@ int ext4_dir_iterator_init(struct ext4_directory_iterator *it,
 \r
 int ext4_dir_iterator_next(struct ext4_directory_iterator *it)\r
 {\r
-    uint16_t skip = ext4_dir_entry_ll_get_entry_length(it->current);\r
+    int r = EOK;\r
+    uint16_t skip;\r
 \r
-    return ext4_dir_iterator_seek(it, it->current_offset + skip);\r
+    while(r == EOK){\r
+        skip = ext4_dir_entry_ll_get_entry_length(it->current);\r
+        r = ext4_dir_iterator_seek(it, it->current_offset + skip);\r
+\r
+        if(!it->current)\r
+            break;\r
+               /*Skip NULL referenced entry*/\r
+        if(it->current->inode != 0)\r
+            break;\r
+    }\r
+\r
+    return r;\r
 }\r
 \r
 int ext4_dir_iterator_fini(struct ext4_directory_iterator *it)\r
index 677780fc3cb5bb74f30e3c04843258678c537019..1516f6ad32380b23d9fec089a454d6d9ecace7f1 100644 (file)
@@ -546,7 +546,7 @@ int ext4_fs_alloc_inode(struct ext4_fs *fs, struct ext4_inode_ref *inode_ref,
     for (i = 0; i < EXT4_INODE_BLOCKS; i++)
         inode->blocks[i] = 0;
 
-#if 0
+#if CONFIG_EXTENT_ENABLE
     /* Initialize extents if needed */
     if (ext4_sb_check_feature_incompatible(
             &fs->sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
@@ -577,6 +577,7 @@ int ext4_fs_free_inode(struct ext4_inode_ref *inode_ref)
     struct ext4_fs *fs = inode_ref->fs;
     uint32_t offset;
     uint32_t suboffset;
+#if CONFIG_EXTENT_ENABLE
     /* For extents must be data block destroyed by other way */
     if ((ext4_sb_check_feature_incompatible(&fs->sb,
             EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
@@ -584,7 +585,7 @@ int ext4_fs_free_inode(struct ext4_inode_ref *inode_ref)
         /* Data structures are released during truncate operation... */
         goto finish;
     }
-
+#endif
     /* Release all indirect (no data) blocks */
 
     /* 1) Single indirect */
@@ -739,18 +740,20 @@ int ext4_fs_truncate_inode(struct ext4_inode_ref *inode_ref,
     uint32_t old_blocks_count = old_size / block_size;
     if (old_size % block_size != 0)
         old_blocks_count++;
-
+#if CONFIG_EXTENT_ENABLE
     if ((ext4_sb_check_feature_incompatible(sb,
             EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
             (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
-#if 0
+
         /* Extents require special operation */
         int rc = ext4_extent_release_blocks_from(inode_ref,
                 old_blocks_count - diff_blocks_count);
         if (rc != EOK)
             return rc;
+
+    } else
 #endif
-    } else {
+    {
         /* Release data blocks from the end of file */
 
         /* Starting from 1 because of logical blocks are numbered from 0 */
@@ -781,21 +784,21 @@ int ext4_fs_get_inode_data_block_index(struct ext4_inode_ref *inode_ref,
     }
 
     uint32_t current_block;
-
+#if CONFIG_EXTENT_ENABLE
     /* Handle i-node using extents */
     if ((ext4_sb_check_feature_incompatible(&fs->sb,
             EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
             (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
 
-#if 0
+
         int rc = ext4_extent_find_block(inode_ref, iblock, &current_block);
         if (rc != EOK)
             return rc;
 
         *fblock = current_block;
         return EOK;
-#endif
     }
+#endif
 
     struct ext4_inode *inode = inode_ref->inode;
 
@@ -882,6 +885,7 @@ int ext4_fs_set_inode_data_block_index(struct ext4_inode_ref *inode_ref,
 {
     struct ext4_fs *fs = inode_ref->fs;
 
+#if CONFIG_EXTENT_ENABLE
     /* Handle inode using extents */
     if ((ext4_sb_check_feature_incompatible(&fs->sb,
             EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
@@ -889,6 +893,7 @@ int ext4_fs_set_inode_data_block_index(struct ext4_inode_ref *inode_ref,
         /* Not reachable */
         return ENOTSUP;
     }
+#endif
 
     /* Handle simple case when we are dealing with direct reference */
     if (iblock < EXT4_INODE_DIRECT_BLOCK_COUNT) {
@@ -1136,16 +1141,14 @@ int ext4_fs_release_inode_block(struct ext4_inode_ref *inode_ref,
 int ext4_fs_append_inode_block(struct ext4_inode_ref *inode_ref,
     uint32_t *fblock, uint32_t *iblock)
 {
+#if CONFIG_EXTENT_ENABLE
     /* Handle extents separately */
     if ((ext4_sb_check_feature_incompatible(&inode_ref->fs->sb,
             EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
             (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))){
-
-#if 0
         return ext4_extent_append_block(inode_ref, iblock, fblock, true);
-#endif
     }
-
+#endif
     struct ext4_sblock *sb = &inode_ref->fs->sb;
 
     /* Compute next block index and allocate data block */