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