Whamcloud - gitweb
tests: add test for e2fsck of verity file
[tools/e2fsprogs.git] / lib / ext2fs / inline_data.c
index 7a81da0..b62fb67 100644 (file)
@@ -12,6 +12,7 @@
 #include "config.h"
 #include <stdio.h>
 #include <time.h>
+#include <limits.h> /* for PATH_MAX */
 
 #include "ext2_fs.h"
 #include "ext2_ext_attr.h"
@@ -41,11 +42,6 @@ static errcode_t ext2fs_inline_data_ea_set(struct ext2_inline_data *data)
 
        retval = ext2fs_xattr_set(handle, "system.data",
                                  data->ea_data, data->ea_size);
-       if (retval)
-               goto err;
-
-       retval = ext2fs_xattrs_write(handle);
-
 err:
        (void) ext2fs_xattrs_close(&handle);
        return retval;
@@ -69,7 +65,11 @@ static errcode_t ext2fs_inline_data_ea_get(struct ext2_inline_data *data)
 
        retval = ext2fs_xattr_get(handle, "system.data",
                                  (void **)&data->ea_data, &data->ea_size);
-       if (retval)
+       if (retval == EXT2_ET_EA_KEY_NOT_FOUND) {
+               data->ea_size = 0;
+               data->ea_data = NULL;
+               retval = 0;
+       } else if (retval)
                goto err;
 
 err:
@@ -80,11 +80,12 @@ err:
 errcode_t ext2fs_inline_data_init(ext2_filsys fs, ext2_ino_t ino)
 {
        struct ext2_inline_data data;
+       char empty[1] = { '\0' };
 
        data.fs = fs;
        data.ino = ino;
        data.ea_size = 0;
-       data.ea_data = "";
+       data.ea_data = empty;
        return ext2fs_inline_data_ea_set(&data);
 }
 
@@ -213,7 +214,7 @@ int ext2fs_inline_data_dir_iterate(ext2_filsys fs, ext2_ino_t ino,
                goto out;
        }
        if (data.ea_size <= 0)
-               goto out;
+               goto out1;
 
        ctx->buf = data.ea_data;
        ctx->buflen = data.ea_size;
@@ -221,7 +222,7 @@ int ext2fs_inline_data_dir_iterate(ext2_filsys fs, ext2_ino_t ino,
        ctx->errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0);
        if (ctx->errcode) {
                ret |= BLOCK_ABORT;
-               goto out;
+               goto out1;
        }
 #endif
 
@@ -264,11 +265,6 @@ errcode_t ext2fs_inline_data_ea_remove(ext2_filsys fs, ext2_ino_t ino)
                goto err;
 
        retval = ext2fs_xattr_remove(handle, "system.data");
-       if (retval)
-               goto err;
-
-       retval = ext2fs_xattrs_write(handle);
-
 err:
        (void) ext2fs_xattrs_close(&handle);
        return retval;
@@ -280,18 +276,16 @@ static errcode_t ext2fs_inline_data_convert_dir(ext2_filsys fs, ext2_ino_t ino,
        struct ext2_dir_entry *dir, *dir2;
        struct ext2_dir_entry_tail *t;
        errcode_t retval;
-       unsigned int offset;
+       int offset;
+       unsigned int rec_len;
        int csum_size = 0;
        int filetype = 0;
-       int rec_len;
 
-       if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext2fs_has_feature_metadata_csum(fs->super))
                csum_size = sizeof(struct ext2_dir_entry_tail);
 
        /* Create '.' and '..' */
-       if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-                                     EXT2_FEATURE_INCOMPAT_FILETYPE))
+       if (ext2fs_has_feature_filetype(fs->super))
                filetype = EXT2_FT_DIR;
 
        /*
@@ -317,7 +311,7 @@ static errcode_t ext2fs_inline_data_convert_dir(ext2_filsys fs, ext2_ino_t ino,
        dir->name[1] = '.';
 
        /*
-        * Ajust the last rec_len
+        * Adjust the last rec_len
         */
        offset = EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2);
        dir = (struct ext2_dir_entry *) (bbuf + offset);
@@ -361,13 +355,16 @@ ext2fs_inline_data_dir_expand(ext2_filsys fs, ext2_ino_t ino,
                return retval;
 
 #ifdef WORDS_BIGENDIAN
-       retval = ext2fs_dirent_swab_in2(fs, buf, size, 0);
+       retval = ext2fs_dirent_swab_in2(fs, buf + EXT4_INLINE_DATA_DOTDOT_SIZE,
+                                       size, 0);
        if (retval)
                goto errout;
 #endif
 
        /* Adjust the rec_len */
        retval = ext2fs_inline_data_convert_dir(fs, ino, blk_buf, buf, size);
+       if (retval)
+               goto errout;
        /* Allocate a new block */
        retval = ext2fs_new_block2(fs, 0, 0, &blk);
        if (retval)
@@ -377,7 +374,7 @@ ext2fs_inline_data_dir_expand(ext2_filsys fs, ext2_ino_t ino,
                goto errout;
 
        /* Update inode */
-       if (EXT2_HAS_INCOMPAT_FEATURE(fs->super, EXT3_FEATURE_INCOMPAT_EXTENTS))
+       if (ext2fs_has_feature_extents(fs->super))
                inode->i_flags |= EXT4_EXTENTS_FL;
        inode->i_flags &= ~EXT4_INLINE_DATA_FL;
        retval = ext2fs_iblk_add_blocks(fs, inode, 1);
@@ -405,19 +402,15 @@ ext2fs_inline_data_file_expand(ext2_filsys fs, ext2_ino_t ino,
        errcode_t retval;
 
        /* Update inode */
-       if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
-                                     EXT3_FEATURE_INCOMPAT_EXTENTS)) {
-               int i;
-               struct ext3_extent_header *eh;
-
-               eh = (struct ext3_extent_header *) &inode->i_block[0];
-               eh->eh_depth = 0;
-               eh->eh_entries = 0;
-               eh->eh_magic = EXT3_EXT_MAGIC;
-               i = (sizeof(inode->i_block) - sizeof(*eh)) /
-                       sizeof(struct ext3_extent);
-               eh->eh_max = ext2fs_cpu_to_le16(i);
-               inode->i_flags |= EXT4_EXTENTS_FL;
+       memset(inode->i_block, 0, sizeof(inode->i_block));
+       if (ext2fs_has_feature_extents(fs->super)) {
+               ext2_extent_handle_t handle;
+
+               inode->i_flags &= ~EXT4_EXTENTS_FL;
+               retval = ext2fs_extent_open2(fs, ino, inode, &handle);
+               if (retval)
+                       return retval;
+               ext2fs_extent_free(handle);
        }
        inode->i_flags &= ~EXT4_INLINE_DATA_FL;
        inode->i_size = 0;
@@ -528,7 +521,7 @@ errcode_t ext2fs_inline_data_get(ext2_filsys fs, ext2_ino_t ino,
 
        memcpy(buf, (void *)inode->i_block, EXT4_MIN_INLINE_DATA_SIZE);
        if (data.ea_size > 0)
-               memcpy(buf + EXT4_MIN_INLINE_DATA_SIZE,
+               memcpy((char *) buf + EXT4_MIN_INLINE_DATA_SIZE,
                       data.ea_data, data.ea_size);
 
        if (size)
@@ -542,7 +535,10 @@ errcode_t ext2fs_inline_data_set(ext2_filsys fs, ext2_ino_t ino,
                                 void *buf, size_t size)
 {
        struct ext2_inode inode_buf;
-       struct ext2_inline_data data;
+       struct ext2_inline_data data = {
+               .fs = fs,
+               .ino = ino,
+       };
        errcode_t retval;
        size_t free_ea_size, existing_size, free_inode_size;
 
@@ -555,33 +551,34 @@ errcode_t ext2fs_inline_data_set(ext2_filsys fs, ext2_ino_t ino,
 
        if (size <= EXT4_MIN_INLINE_DATA_SIZE) {
                memcpy((void *)inode->i_block, buf, size);
-               return ext2fs_write_inode(fs, ino, inode);
-       }
-
-       retval = ext2fs_xattr_inode_max_size(fs, ino, &free_ea_size);
-       if (retval)
-               return retval;
+       } else {
+               retval = ext2fs_xattr_inode_max_size(fs, ino, &free_ea_size);
+               if (retval)
+                       return retval;
 
-       retval = ext2fs_inline_data_size(fs, ino, &existing_size);
-       if (retval)
-               return retval;
+               retval = ext2fs_inline_data_size(fs, ino, &existing_size);
+               if (retval)
+                       return retval;
 
-       if (existing_size < EXT4_MIN_INLINE_DATA_SIZE)
-               free_inode_size = EXT4_MIN_INLINE_DATA_SIZE - existing_size;
-       else
-               free_inode_size = 0;
+               if (existing_size < EXT4_MIN_INLINE_DATA_SIZE) {
+                       free_inode_size = EXT4_MIN_INLINE_DATA_SIZE -
+                                         existing_size;
+               } else {
+                       free_inode_size = 0;
+               }
 
-       if (size > existing_size + free_ea_size + free_inode_size)
-               return EXT2_ET_INLINE_DATA_NO_SPACE;
+               if (size != existing_size &&
+                   size > existing_size + free_ea_size + free_inode_size)
+                       return EXT2_ET_INLINE_DATA_NO_SPACE;
 
-       memcpy((void *)inode->i_block, buf, EXT4_MIN_INLINE_DATA_SIZE);
+               memcpy((void *)inode->i_block, buf, EXT4_MIN_INLINE_DATA_SIZE);
+               if (size > EXT4_MIN_INLINE_DATA_SIZE)
+                       data.ea_size = size - EXT4_MIN_INLINE_DATA_SIZE;
+               data.ea_data = (char *) buf + EXT4_MIN_INLINE_DATA_SIZE;
+       }
        retval = ext2fs_write_inode(fs, ino, inode);
        if (retval)
                return retval;
-       data.fs = fs;
-       data.ino = ino;
-       data.ea_size = size - EXT4_MIN_INLINE_DATA_SIZE;
-       data.ea_data = buf + EXT4_MIN_INLINE_DATA_SIZE;
        return ext2fs_inline_data_ea_set(&data);
 }
 
@@ -602,12 +599,11 @@ static errcode_t file_test(ext2_filsys fs)
        errcode_t retval;
        size_t size;
        char *buf = 0, *cmpbuf = 0;
-       int i;
 
        /* create a new file */
        retval = ext2fs_new_inode(fs, 2, 010755, 0, &newfile);
        if (retval) {
-               com_err("file_test", retval, "while allocaing a new inode");
+               com_err("file_test", retval, "while allocating a new inode");
                return 1;
        }
 
@@ -617,7 +613,7 @@ static errcode_t file_test(ext2_filsys fs)
        inode.i_mode = LINUX_S_IFREG;
        retval = ext2fs_write_new_inode(fs, newfile, &inode);
        if (retval) {
-               com_err("file_test", retval, "while writting a new inode");
+               com_err("file_test", retval, "while writing a new inode");
                return 1;
        }
 
@@ -657,7 +653,7 @@ static errcode_t file_test(ext2_filsys fs)
 
        if (size != BUFF_SIZE) {
                fprintf(stderr,
-                       "tst_inline_data: size %lu != buflen %lu\n",
+                       "tst_inline_data: size %lu != buflen %u\n",
                        size, BUFF_SIZE);
                retval = 1;
                goto err;
@@ -697,7 +693,7 @@ static errcode_t dir_test(ext2_filsys fs)
        const char *parent_name = "test";
        ext2_ino_t parent, dir, tmp;
        errcode_t retval;
-       char dirname[PATH_MAX];
+       char dirname[32];
        int i;
 
        retval = ext2fs_mkdir(fs, 11, 11, stub_name);
@@ -730,14 +726,14 @@ static errcode_t dir_test(ext2_filsys fs)
        }
 
        if (parent != tmp) {
-               fprintf(stderr, "tst_inline_data: parent (%lu) != tmp (%lu)\n",
+               fprintf(stderr, "tst_inline_data: parent (%u) != tmp (%u)\n",
                        parent, tmp);
                return 1;
        }
 
        for (i = 0, dir = 13; i < 4; i++, dir++) {
                tmp = 0;
-               snprintf(dirname, PATH_MAX, "%d", i);
+               snprintf(dirname, sizeof(dirname), "%d", i);
                retval = ext2fs_mkdir(fs, parent, 0, dirname);
                if (retval) {
                        com_err("dir_test", retval,
@@ -754,13 +750,14 @@ static errcode_t dir_test(ext2_filsys fs)
                }
 
                if (dir != tmp) {
-                       fprintf(stderr, "tst_inline_data: dir (%lu) != tmp (%lu)\n",
+                       fprintf(stderr,
+                               "tst_inline_data: dir (%u) != tmp (%u)\n",
                                dir, tmp);
                        return 1;
                }
        }
 
-       snprintf(dirname, PATH_MAX, "%d", i);
+       snprintf(dirname, sizeof(dirname), "%d", i);
        retval = ext2fs_mkdir(fs, parent, 0, dirname);
        if (retval && retval != EXT2_ET_DIR_NO_SPACE) {
                com_err("dir_test", retval, "while creating %s dir", dirname);
@@ -781,7 +778,6 @@ int main(int argc, char *argv[])
        ext2_filsys             fs;
        struct ext2_super_block param;
        errcode_t               retval;
-       int                     i;
 
        /* setup */
        initialize_ext2_error_table();
@@ -805,13 +801,12 @@ int main(int argc, char *argv[])
        retval = ext2fs_allocate_tables(fs);
        if (retval) {
                com_err("setup", retval,
-                       "while allocating tables for test filesysmte");
+                       "while allocating tables for test filesystem");
                exit(1);
        }
 
        /* initialize inode cache */
        if (!fs->icache) {
-               struct ext2_inode inode;
                ext2_ino_t first_ino = EXT2_FIRST_INO(fs->super);
                int i;
 
@@ -840,6 +835,7 @@ int main(int argc, char *argv[])
                return 1;
        }
        printf("tst_inline_data(DIR): OK\n");
+       ext2fs_free(fs);
 
        return 0;
 }