+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, ¤t);\r
+ if(r != EOK){\r
+ break;\r
+ }\r
+\r
+ /*Initialize iterator.*/\r
+ r = ext4_dir_iterator_init(&it, ¤t, 0);\r
+ if(r != EOK){\r
+ ext4_fs_put_inode_ref(¤t);\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, ¤t, &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, ¤t);\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(¤t, 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, ¤t, (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(¤t);\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(¤t);\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