2 * inline_data.c --- data in inode
4 * Copyright (C) 2012 Zheng Liu <wenqing.lz@taobao.com>
7 * This file may be redistributed under the terms of the GNU library
8 * General Public License, version 2.
17 #include "ext2_ext_attr.h"
22 struct ext2_inline_data {
25 size_t ea_size; /* the size of inline data in ea area */
29 static errcode_t ext2fs_inline_data_ea_set(struct ext2_inline_data *data)
31 struct ext2_xattr_handle *handle;
34 retval = ext2fs_xattrs_open(data->fs, data->ino, &handle);
38 retval = ext2fs_xattrs_read(handle);
42 retval = ext2fs_xattr_set(handle, "system.data",
43 data->ea_data, data->ea_size);
47 retval = ext2fs_xattrs_write(handle);
50 (void) ext2fs_xattrs_close(&handle);
54 static errcode_t ext2fs_inline_data_ea_get(struct ext2_inline_data *data)
56 struct ext2_xattr_handle *handle;
62 retval = ext2fs_xattrs_open(data->fs, data->ino, &handle);
66 retval = ext2fs_xattrs_read(handle);
70 retval = ext2fs_xattr_get(handle, "system.data",
71 (void **)&data->ea_data, &data->ea_size);
76 (void) ext2fs_xattrs_close(&handle);
81 int ext2fs_inline_data_dir_iterate(ext2_filsys fs, ext2_ino_t ino,
84 struct dir_context *ctx;
85 struct ext2_inode inode;
86 struct ext2_dir_entry dirent;
87 struct ext2_inline_data data;
88 int ret = BLOCK_ABORT;
89 e2_blkcnt_t blockcnt = 0;
91 ctx = (struct dir_context *)priv_data;
93 ctx->errcode = ext2fs_read_inode(fs, ino, &inode);
97 if (!(inode.i_flags & EXT4_INLINE_DATA_FL)) {
98 ctx->errcode = EXT2_ET_NO_INLINE_DATA;
102 if (!LINUX_S_ISDIR(inode.i_mode)) {
103 ctx->errcode = EXT2_ET_NO_DIRECTORY;
108 /* we first check '.' and '..' dir */
111 ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(2), &dirent);
112 dirent.name[0] = '.';
113 dirent.name[1] = '\0';
114 ctx->buf = (char *)&dirent;
115 ext2fs_get_rec_len(fs, &dirent, &ctx->buflen);
116 ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
117 if (ret & BLOCK_ABORT)
120 dirent.inode = ext2fs_le32_to_cpu(inode.i_block[0]);
122 ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(3), &dirent);
123 dirent.name[0] = '.';
124 dirent.name[1] = '.';
125 dirent.name[2] = '\0';
126 ctx->buf = (char *)&dirent;
127 ext2fs_get_rec_len(fs, &dirent, &ctx->buflen);
128 ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
129 if (ret & BLOCK_INLINE_DATA_CHANGED) {
132 inode.i_block[0] = ext2fs_cpu_to_le32(dirent.inode);
133 err = ext2fs_write_inode(fs, ino, &inode);
136 ret &= ~BLOCK_INLINE_DATA_CHANGED;
138 if (ret & BLOCK_ABORT)
141 ctx->buf = (char *)inode.i_block + EXT4_INLINE_DATA_DOTDOT_SIZE;
142 ctx->buflen = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DATA_DOTDOT_SIZE;
143 #ifdef WORDS_BIGENDIAN
144 ctx->errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0);
150 ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
151 if (ret & BLOCK_INLINE_DATA_CHANGED) {
152 #ifdef WORDS_BIGENDIAN
153 ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf,
160 ctx->errcode = ext2fs_write_inode(fs, ino, &inode);
163 ret &= ~BLOCK_INLINE_DATA_CHANGED;
165 if (ret & BLOCK_ABORT)
170 ctx->errcode = ext2fs_inline_data_ea_get(&data);
175 if (data.ea_size <= 0)
178 ctx->buf = data.ea_data;
179 ctx->buflen = data.ea_size;
180 #ifdef WORDS_BIGENDIAN
181 ctx.errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0);
188 ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
189 if (ret & BLOCK_INLINE_DATA_CHANGED) {
190 #ifdef WORDS_BIGENDIAN
191 ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf,
198 ctx->errcode = ext2fs_inline_data_ea_set(&data);
204 ext2fs_free_mem(&data.ea_data);
208 ret &= ~(BLOCK_ABORT | BLOCK_INLINE_DATA_CHANGED);