* @brief Ext4 high level operations (file, directory, mountpoints...)
*/
-#include "ext4_config.h"
-#include "ext4_types.h"
-#include "ext4_misc.h"
-#include "ext4_errno.h"
-#include "ext4_oflags.h"
-#include "ext4_debug.h"
-
-#include "ext4.h"
-#include "ext4_trans.h"
-#include "ext4_blockdev.h"
-#include "ext4_fs.h"
-#include "ext4_dir.h"
-#include "ext4_inode.h"
-#include "ext4_super.h"
-#include "ext4_block_group.h"
-#include "ext4_dir_idx.h"
-#include "ext4_xattr.h"
-#include "ext4_journal.h"
+#include <ext4_config.h>
+#include <ext4_types.h>
+#include <ext4_misc.h>
+#include <ext4_errno.h>
+#include <ext4_oflags.h>
+#include <ext4_debug.h>
+
+#include <ext4.h>
+#include <ext4_trans.h>
+#include <ext4_blockdev.h>
+#include <ext4_fs.h>
+#include <ext4_dir.h>
+#include <ext4_inode.h>
+#include <ext4_super.h>
+#include <ext4_block_group.h>
+#include <ext4_dir_idx.h>
+#include <ext4_xattr.h>
+#include <ext4_journal.h>
#include <stdlib.h>
return ENOTSUP;
for (size_t i = 0; i < CONFIG_EXT4_BLOCKDEVS_COUNT; ++i) {
- if (s_bdevices[i].name) {
- if (!strcmp(dev_name, s_bdevices[i].name)) {
- bd = s_bdevices[i].bd;
- break;
- }
+ if (!strcmp(dev_name, s_bdevices[i].name)) {
+ bd = s_bdevices[i].bd;
+ break;
}
}
if (parent_inode)
*parent_inode = ref.index;
- if (flags & O_CREAT)
- ext4_trans_start(mp);
-
len = ext4_path_check(path, &is_goal);
while (1) {
struct ext4_inode_ref child_ref;
r = ext4_fs_alloc_inode(fs, &child_ref,
is_goal ? ftype : EXT4_DE_DIR);
+
if (r != EOK)
break;
+ ext4_fs_inode_blocks_init(fs, &child_ref);
/*Link with root dir.*/
r = ext4_link(mp, &ref, &child_ref, path, len, false);
if (name_off)
*name_off += len + 1;
- };
+ }
if (r != EOK) {
ext4_fs_put_inode_ref(&ref);
if (f->flags & O_APPEND)
f->fpos = f->fsize;
-
}
- r = ext4_fs_put_inode_ref(&ref);
- if (flags & O_CREAT) {
- if (r == EOK)
- ext4_trans_stop(mp);
- else
- ext4_trans_abort(mp);
-
- }
-
- return r;
+ return ext4_fs_put_inode_ref(&ref);
}
/****************************************************************************/
{
uint32_t iflags;
int filetype;
+ int r;
+ struct ext4_mountpoint *mp = ext4_get_mount(path);
+
if (ext4_parse_flags(flags, &iflags) == false)
return EINVAL;
else
filetype = EXT4_DE_DIR;
- return ext4_generic_open2(f, path, iflags, filetype, parent_inode,
- name_off);
+ if (iflags & O_CREAT)
+ ext4_trans_start(mp);
+
+ r = ext4_generic_open2(f, path, iflags, filetype, parent_inode,
+ name_off);
+
+ if (iflags & O_CREAT) {
+ if (r == EOK)
+ ext4_trans_stop(mp);
+ else
+ ext4_trans_abort(mp);
+ }
+
+ return r;
}
static int ext4_create_hardlink(const char *path,
return EINVAL;
EXT4_MP_LOCK(mp);
- ext4_trans_start(mp);
-
r = ext4_generic_open2(&f, path, O_RDONLY, EXT4_DE_UNKNOWN,
&parent_inode, &name_off);
- if (r != EOK)
- goto Finish;
+ if (r != EOK) {
+ EXT4_MP_UNLOCK(mp);
+ return r;
+ }
child_inode = f.inode;
ext4_fclose(&f);
+ ext4_trans_start(mp);
/*We have file to unlink. Load it.*/
r = ext4_fs_get_inode_ref(&mp->fs, child_inode, &child_ref);
return EROFS;
EXT4_MP_LOCK(mp);
- ext4_trans_start(mp);
r = ext4_generic_open2(&f, path, O_RDONLY, EXT4_DE_UNKNOWN,
&parent_inode, &name_off);
- if (r != EOK)
- goto Finish;
+ if (r != EOK) {
+ EXT4_MP_UNLOCK(mp);
+ return r;
+ }
child_inode = f.inode;
ext4_fclose(&f);
+ ext4_trans_start(mp);
/*Load parent*/
r = ext4_fs_get_inode_ref(&mp->fs, parent_inode, &parent_ref);
{
ext4_file f;
uint32_t parent_inode;
+ uint32_t child_inode;
uint32_t name_off;
bool is_goal;
int r;
return EROFS;
EXT4_MP_LOCK(mp);
- ext4_trans_start(mp);
-
- r = ext4_generic_open2(&f, path, O_RDWR, EXT4_DE_UNKNOWN,
+ r = ext4_generic_open2(&f, path, O_RDONLY, EXT4_DE_UNKNOWN,
&parent_inode, &name_off);
if (r != EOK) {
- ext4_trans_abort(mp);
EXT4_MP_UNLOCK(mp);
return r;
}
+ child_inode = f.inode;
+ ext4_fclose(&f);
+ ext4_trans_start(mp);
+
/*Load parent*/
r = ext4_fs_get_inode_ref(&mp->fs, parent_inode, &parent);
if (r != EOK) {
}
/*We have file to delete. Load it.*/
- r = ext4_fs_get_inode_ref(&mp->fs, f.inode, &child);
+ r = ext4_fs_get_inode_ref(&mp->fs, child_inode, &child);
if (r != EOK) {
ext4_fs_put_inode_ref(&parent);
ext4_trans_abort(mp);
filetype = EXT4_DE_REG_FILE;
EXT4_MP_LOCK(mp);
-
ext4_block_cache_write_back(mp->fs.bdev, 1);
+
+ if (flags & O_CREAT)
+ ext4_trans_start(mp);
+
r = ext4_generic_open2(file, path, flags, filetype, NULL, NULL);
- ext4_block_cache_write_back(mp->fs.bdev, 0);
+ if (flags & O_CREAT) {
+ if (r == EOK)
+ ext4_trans_stop(mp);
+ else
+ ext4_trans_abort(mp);
+ }
+
+ ext4_block_cache_write_back(mp->fs.bdev, 0);
EXT4_MP_UNLOCK(mp);
+
return r;
}
return r;
}
-int ext4_fseek(ext4_file *file, uint64_t offset, uint32_t origin)
+int ext4_fseek(ext4_file *file, int64_t offset, uint32_t origin)
{
switch (origin) {
case SEEK_SET:
- if (offset > file->fsize)
+ if (offset < 0 || (uint64_t)offset > file->fsize)
return EINVAL;
file->fpos = offset;
return EOK;
case SEEK_CUR:
- if ((offset + file->fpos) > file->fsize)
+ if ((offset < 0 && (uint64_t)(-offset) > file->fpos) ||
+ (offset > 0 &&
+ (uint64_t)offset > (file->fsize - file->fpos)))
return EINVAL;
file->fpos += offset;
return EOK;
case SEEK_END:
- if (offset > file->fsize)
+ if (offset < 0 || (uint64_t)offset > file->fsize)
return EINVAL;
file->fpos = file->fsize - offset;
int r;
ext4_file f;
- ext4_trans_start(mp);
- r = ext4_generic_open2(&f, path, O_RDWR, EXT4_DE_UNKNOWN, NULL, NULL);
- if (r != EOK) {
- ext4_trans_abort(mp);
+ r = ext4_generic_open2(&f, path, O_RDONLY, EXT4_DE_UNKNOWN, NULL, NULL);
+ if (r != EOK)
return r;
- }
+
+ ext4_trans_start(mp);
r = ext4_fs_get_inode_ref(&mp->fs, f.inode, inode_ref);
if (r != EOK) {
return r;
}
+int ext4_inode_exist(const char *path, int type)
+{
+ int r;
+ ext4_file f;
+ struct ext4_mountpoint *mp = ext4_get_mount(path);
+
+ if (!mp)
+ return ENOENT;
+
+ EXT4_MP_LOCK(mp);
+ r = ext4_generic_open2(&f, path, O_RDONLY, type, NULL, NULL);
+ EXT4_MP_UNLOCK(mp);
+
+ return r;
+}
+
int ext4_mode_set(const char *path, uint32_t mode)
{
int r;
memcpy(ref.inode->blocks, buf, size);
ext4_inode_clear_flag(ref.inode, EXT4_INODE_FLAG_EXTENTS);
} else {
+ uint64_t off;
ext4_fs_inode_blocks_init(&f->mp->fs, &ref);
r = ext4_fs_append_inode_dblk(&ref, &fblock, &sblock);
if (r != EOK)
goto Finish;
- r = ext4_block_writebytes(f->mp->fs.bdev, 0, buf, size);
+ off = fblock * block_size;
+ r = ext4_block_writebytes(f->mp->fs.bdev, off, buf, size);
if (r != EOK)
goto Finish;
-
}
/*Stop write back cache mode*/
filetype = EXT4_DE_SYMLINK;
EXT4_MP_LOCK(mp);
+ ext4_block_cache_write_back(mp->fs.bdev, 1);
ext4_trans_start(mp);
- ext4_block_cache_write_back(mp->fs.bdev, 1);
- r = ext4_generic_open2(&f, path, O_RDWR|O_CREAT, filetype, NULL, NULL);
+ r = ext4_generic_open2(&f, path, O_RDWR | O_CREAT, filetype, NULL, NULL);
if (r == EOK)
r = ext4_fsymlink_set(&f, target, strlen(target));
else
ext4_fclose(&f);
Finish:
- ext4_block_cache_write_back(mp->fs.bdev, 0);
-
if (r != EOK)
ext4_trans_abort(mp);
else
ext4_trans_stop(mp);
+ ext4_block_cache_write_back(mp->fs.bdev, 0);
EXT4_MP_UNLOCK(mp);
return r;
}
Finish:
ext4_block_cache_write_back(mp->fs.bdev, 0);
- if (r != EOK)
- ext4_trans_abort(mp);
- else
- ext4_trans_stop(mp);
-
EXT4_MP_UNLOCK(mp);
return r;
}
return EINVAL;
EXT4_MP_LOCK(mp);
+ ext4_block_cache_write_back(mp->fs.bdev, 1);
ext4_trans_start(mp);
- ext4_block_cache_write_back(mp->fs.bdev, 1);
- r = ext4_generic_open2(&f, path, O_RDWR|O_CREAT, filetype, NULL, NULL);
+ r = ext4_generic_open2(&f, path, O_RDWR | O_CREAT, filetype, NULL, NULL);
if (r == EOK) {
if (filetype == EXT4_DE_CHRDEV ||
filetype == EXT4_DE_BLKDEV)
r = ext4_mknod_set(&f, dev);
- } else
+ } else {
goto Finish;
+ }
ext4_fclose(&f);
Finish:
- ext4_block_cache_write_back(mp->fs.bdev, 0);
-
if (r != EOK)
ext4_trans_abort(mp);
else
ext4_trans_stop(mp);
+ ext4_block_cache_write_back(mp->fs.bdev, 0);
EXT4_MP_UNLOCK(mp);
return r;
}
return EINVAL;
EXT4_MP_LOCK(mp);
- ext4_trans_start(mp);
+ r = ext4_generic_open2(&f, path, O_RDONLY, EXT4_DE_UNKNOWN, NULL, NULL);
+ if (r != EOK) {
+ EXT4_MP_UNLOCK(mp);
+ return r;
+ }
- r = ext4_generic_open2(&f, path, O_RDWR, EXT4_DE_UNKNOWN, NULL, NULL);
- if (r != EOK)
- goto Finish;
inode = f.inode;
ext4_fclose(&f);
+ ext4_trans_start(mp);
r = ext4_fs_get_inode_ref(&mp->fs, inode, &inode_ref);
if (r != EOK)
return EINVAL;
EXT4_MP_LOCK(mp);
- r = ext4_generic_open2(&f, path, O_RDWR, EXT4_DE_UNKNOWN, NULL, NULL);
+ r = ext4_generic_open2(&f, path, O_RDONLY, EXT4_DE_UNKNOWN, NULL, NULL);
if (r != EOK)
goto Finish;
+
inode = f.inode;
ext4_fclose(&f);
return ENOENT;
EXT4_MP_LOCK(mp);
- r = ext4_generic_open2(&f, path, O_RDWR, EXT4_DE_UNKNOWN, NULL, NULL);
+ r = ext4_generic_open2(&f, path, O_RDONLY, EXT4_DE_UNKNOWN, NULL, NULL);
if (r != EOK)
goto Finish;
inode = f.inode;
return EINVAL;
EXT4_MP_LOCK(mp);
- ext4_trans_start(mp);
+ r = ext4_generic_open2(&f, path, O_RDONLY, EXT4_DE_UNKNOWN, NULL, NULL);
+ if (r != EOK) {
+ EXT4_MP_LOCK(mp);
+ return r;
+ }
- r = ext4_generic_open2(&f, path, O_RDWR, EXT4_DE_UNKNOWN, NULL, NULL);
- if (r != EOK)
- goto Finish;
inode = f.inode;
ext4_fclose(&f);
+ ext4_trans_start(mp);
r = ext4_fs_get_inode_ref(&mp->fs, inode, &inode_ref);
if (r != EOK)
/*Check if exist.*/
r = ext4_generic_open(&f, path, "r", false, &inode_up, &name_off);
if (r != EOK) {
- ext4_trans_abort(mp);
EXT4_MP_UNLOCK(mp);
return r;
}
path += name_off;
len = ext4_path_check(path, &is_goal);
-
inode_current = f.inode;
ext4_block_cache_write_back(mp->fs.bdev, 1);
{
int r;
ext4_file f;
-
struct ext4_mountpoint *mp = ext4_get_mount(path);
if (!mp)
return EROFS;
EXT4_MP_LOCK(mp);
- ext4_trans_start(mp);
/*Check if exist.*/
r = ext4_generic_open(&f, path, "r", false, 0, 0);
- if (r == EOK) {
- /*Directory already created*/
- ext4_trans_stop(mp);
- EXT4_MP_UNLOCK(mp);
- return r;
- }
+ if (r == EOK)
+ goto Finish;
- /*Create new dir*/
+ /*Create new directory.*/
r = ext4_generic_open(&f, path, "w", false, 0, 0);
- if (r != EOK) {
- ext4_trans_abort(mp);
- EXT4_MP_UNLOCK(mp);
- return r;
- }
- ext4_trans_stop(mp);
+Finish:
EXT4_MP_UNLOCK(mp);
return r;
}