ext4_journal: fix JBD_FLAG_ESCAPE handling
[lwext4.git] / src / ext4.c
index b529bbde24e047b8b48b7ddfef065d3e719cb317..94744bbb4b24be97c80f5a09635703b7d4a31320 100644 (file)
@@ -395,12 +395,12 @@ int ext4_mount(const char *dev_name, const char *mount_point,
        if (!bc) {
                /*Automatic block cache alloc.*/
                mp->cache_dynamic = 1;
-               bc = malloc(sizeof(struct ext4_bcache));
+               bc = ext4_malloc(sizeof(struct ext4_bcache));
 
                r = ext4_bcache_init_dynamic(bc, CONFIG_BLOCK_DEV_CACHE_SIZE,
                                             bsize);
                if (r != EOK) {
-                       free(bc);
+                       ext4_free(bc);
                        ext4_block_fini(bd);
                        return r;
                }
@@ -416,7 +416,7 @@ int ext4_mount(const char *dev_name, const char *mount_point,
                ext4_block_fini(bd);
                if (mp->cache_dynamic) {
                        ext4_bcache_fini_dynamic(bc);
-                       free(bc);
+                       ext4_free(bc);
                }
                return r;
        }
@@ -451,7 +451,7 @@ int ext4_umount(const char *mount_point)
        ext4_bcache_cleanup(mp->fs.bdev->bc);
        if (mp->cache_dynamic) {
                ext4_bcache_fini_dynamic(mp->fs.bdev->bc);
-               free(mp->fs.bdev->bc);
+               ext4_free(mp->fs.bdev->bc);
        }
        r = ext4_block_fini(mp->fs.bdev);
 Finish:
@@ -549,7 +549,7 @@ static int __ext4_recover(const char *mount_point)
        int r = ENOTSUP;
        EXT4_MP_LOCK(mp);
        if (ext4_sb_feature_com(&mp->fs.sb, EXT4_FCOM_HAS_JOURNAL)) {
-               struct jbd_fs *jbd_fs = calloc(1, sizeof(struct jbd_fs));
+               struct jbd_fs *jbd_fs = ext4_calloc(1, sizeof(struct jbd_fs));
                if (!jbd_fs) {
                         r = ENOMEM;
                         goto Finish;
@@ -558,13 +558,13 @@ static int __ext4_recover(const char *mount_point)
 
                r = jbd_get_fs(&mp->fs, jbd_fs);
                if (r != EOK) {
-                       free(jbd_fs);
+                       ext4_free(jbd_fs);
                        goto Finish;
                }
 
                r = jbd_recover(jbd_fs);
                jbd_put_fs(jbd_fs);
-               free(jbd_fs);
+               ext4_free(jbd_fs);
        }
        if (r == EOK && !mp->fs.read_only) {
                uint32_t bgid;
@@ -2413,8 +2413,88 @@ Finish:
        return r;
 }
 
+static int ext4_mknod_set(ext4_file *f, uint32_t dev)
+{
+       struct ext4_inode_ref ref;
+       int r;
+
+       ext4_assert(f && f->mp);
+
+       r = ext4_fs_get_inode_ref(&f->mp->fs, f->inode, &ref);
+       if (r != EOK)
+               return r;
+
+       ext4_inode_set_dev(ref.inode, dev);
+
+       ext4_inode_set_size(ref.inode, 0);
+       ref.dirty = true;
+
+       f->fsize = 0;
+       f->fpos = 0;
+
+       r = ext4_fs_put_inode_ref(&ref);
+       return r;
+}
+
+int ext4_mknod(const char *path, int filetype, uint32_t dev)
+{
+       struct ext4_mountpoint *mp = ext4_get_mount(path);
+       int r;
+       ext4_file f;
+
+       if (!mp)
+               return ENOENT;
+
+       if (mp->fs.read_only)
+               return EROFS;
+
+       /*
+        * The filetype shouldn't be normal file, directory or
+        * unknown.
+        */
+       if (filetype == EXT4_DE_UNKNOWN ||
+           filetype == EXT4_DE_REG_FILE ||
+           filetype == EXT4_DE_DIR ||
+           filetype == EXT4_DE_SYMLINK)
+               return EINVAL;
+
+       /*
+        * Nor should it be any bogus value.
+        */
+       if (filetype != EXT4_DE_CHRDEV &&
+           filetype != EXT4_DE_BLKDEV &&
+           filetype != EXT4_DE_FIFO &&
+           filetype != EXT4_DE_SOCK)
+               return EINVAL;
+
+       EXT4_MP_LOCK(mp);
+       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);
+       if (r == EOK) {
+               if (filetype == EXT4_DE_CHRDEV ||
+                   filetype == EXT4_DE_BLKDEV)
+                       r = ext4_mknod_set(&f, dev);
+       } 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_MP_UNLOCK(mp);
+       return r;
+}
+
 int ext4_setxattr(const char *path, const char *name, size_t name_len,
-                 const void *data, size_t data_size, bool replace)
+                 const void *data, size_t data_size, bool replace __unused)
 {
        bool found;
        int r = EOK;
@@ -2531,7 +2611,7 @@ int ext4_listxattr(const char *path, char *list, size_t size, size_t *ret_size)
 
        r = ext4_xattr_list(&inode_ref, NULL, &list_len);
        if (r == EOK && list_len) {
-               xattr_list = malloc(list_len);
+               xattr_list = ext4_malloc(list_len);
                if (!xattr_list) {
                        ext4_fs_put_inode_ref(&inode_ref);
                        r = ENOMEM;
@@ -2578,7 +2658,7 @@ int ext4_listxattr(const char *path, char *list, size_t size, size_t *ret_size)
 Finish:
        EXT4_MP_UNLOCK(mp);
        if (xattr_list)
-               free(xattr_list);
+               ext4_free(xattr_list);
 
        return r;
 
@@ -2949,6 +3029,7 @@ const ext4_direntry *ext4_dir_entry_next(ext4_dir *d)
 #define EXT4_DIR_ENTRY_OFFSET_TERM (uint64_t)(-1)
 
        int r;
+       uint16_t name_length;
        ext4_direntry *de = 0;
        struct ext4_inode_ref dir;
        struct ext4_dir_iter it;
@@ -2971,7 +3052,18 @@ const ext4_direntry *ext4_dir_entry_next(ext4_dir *d)
                goto Finish;
        }
 
-       memcpy(&d->de, it.curr, sizeof(ext4_direntry));
+       memset(&d->de.name, 0, sizeof(d->de.name));
+       name_length = ext4_dir_en_get_name_len(&d->f.mp->fs.sb,
+                                              it.curr);
+       memcpy(&d->de.name, it.curr->name, name_length);
+
+       /* Directly copying the content isn't safe for Big-endian targets*/
+       d->de.inode = ext4_dir_en_get_inode(it.curr);
+       d->de.entry_length = ext4_dir_en_get_entry_len(it.curr);
+       d->de.name_length = name_length;
+       d->de.inode_type = ext4_dir_en_get_inode_type(&d->f.mp->fs.sb,
+                                                     it.curr);
+
        de = &d->de;
 
        ext4_dir_iterator_next(&it);