inline_data.c revision 97581d448127f95dcc968c0785f7ab3413bf0222
1416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu/* 2416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu * inline_data.c --- data in inode 3416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu * 4416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu * Copyright (C) 2012 Zheng Liu <wenqing.lz@taobao.com> 5416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu * 6416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu * %Begin-Header% 7416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu * This file may be redistributed under the terms of the GNU library 8416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu * General Public License, version 2. 9416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu * %End-Header% 10416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu */ 11416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 12416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#include "config.h" 13416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#include <stdio.h> 14416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#include <time.h> 15416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 16416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#include "ext2_fs.h" 17416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#include "ext2_ext_attr.h" 18416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 19416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#include "ext2fs.h" 20416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#include "ext2fsP.h" 21416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 22416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liustruct ext2_inline_data { 23416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ext2_filsys fs; 24416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ext2_ino_t ino; 25416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu size_t ea_size; /* the size of inline data in ea area */ 26416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu void *ea_data; 27416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu}; 28416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 29416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liustatic errcode_t ext2fs_inline_data_ea_set(struct ext2_inline_data *data) 30416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu{ 31416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu struct ext2_xattr_handle *handle; 32416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu errcode_t retval; 33416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 34416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu retval = ext2fs_xattrs_open(data->fs, data->ino, &handle); 35416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (retval) 36416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu return retval; 37416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 38416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu retval = ext2fs_xattrs_read(handle); 39416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (retval) 40416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu goto err; 41416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 42416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu retval = ext2fs_xattr_set(handle, "system.data", 43416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu data->ea_data, data->ea_size); 44416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (retval) 45416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu goto err; 46416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 47416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu retval = ext2fs_xattrs_write(handle); 48416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 49416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liuerr: 50416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu (void) ext2fs_xattrs_close(&handle); 51416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu return retval; 52416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu} 53416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 54416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liustatic errcode_t ext2fs_inline_data_ea_get(struct ext2_inline_data *data) 55416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu{ 56416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu struct ext2_xattr_handle *handle; 57416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu errcode_t retval; 58416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 59416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu data->ea_size = 0; 60416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu data->ea_data = 0; 61416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 62416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu retval = ext2fs_xattrs_open(data->fs, data->ino, &handle); 63416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (retval) 64416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu return retval; 65416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 66416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu retval = ext2fs_xattrs_read(handle); 67416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (retval) 68416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu goto err; 69416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 70416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu retval = ext2fs_xattr_get(handle, "system.data", 71416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu (void **)&data->ea_data, &data->ea_size); 72416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (retval) 73416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu goto err; 74416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 75416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liuerr: 76416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu (void) ext2fs_xattrs_close(&handle); 77416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu return retval; 78416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu} 79416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 8082e77d07ee6c9e2414233d4428887a22bf755609Zheng Liuerrcode_t ext2fs_inline_data_init(ext2_filsys fs, ext2_ino_t ino) 8182e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu{ 8282e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu struct ext2_inline_data data; 8382e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu 8482e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu data.fs = fs; 8582e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu data.ino = ino; 8682e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu data.ea_size = 0; 8782e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu data.ea_data = ""; 8882e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu return ext2fs_inline_data_ea_set(&data); 8982e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu} 9082e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu 91133e94627b01823d2555450ddd1d95401ff2227aZheng Liuerrcode_t ext2fs_inline_data_size(ext2_filsys fs, ext2_ino_t ino, size_t *size) 92133e94627b01823d2555450ddd1d95401ff2227aZheng Liu{ 93133e94627b01823d2555450ddd1d95401ff2227aZheng Liu struct ext2_inode inode; 94133e94627b01823d2555450ddd1d95401ff2227aZheng Liu struct ext2_inline_data data; 95133e94627b01823d2555450ddd1d95401ff2227aZheng Liu errcode_t retval; 96133e94627b01823d2555450ddd1d95401ff2227aZheng Liu 97133e94627b01823d2555450ddd1d95401ff2227aZheng Liu retval = ext2fs_read_inode(fs, ino, &inode); 98133e94627b01823d2555450ddd1d95401ff2227aZheng Liu if (retval) 99133e94627b01823d2555450ddd1d95401ff2227aZheng Liu return retval; 100133e94627b01823d2555450ddd1d95401ff2227aZheng Liu 101133e94627b01823d2555450ddd1d95401ff2227aZheng Liu if (!(inode.i_flags & EXT4_INLINE_DATA_FL)) 102133e94627b01823d2555450ddd1d95401ff2227aZheng Liu return EXT2_ET_NO_INLINE_DATA; 103133e94627b01823d2555450ddd1d95401ff2227aZheng Liu 104133e94627b01823d2555450ddd1d95401ff2227aZheng Liu data.fs = fs; 105133e94627b01823d2555450ddd1d95401ff2227aZheng Liu data.ino = ino; 106133e94627b01823d2555450ddd1d95401ff2227aZheng Liu retval = ext2fs_inline_data_ea_get(&data); 107133e94627b01823d2555450ddd1d95401ff2227aZheng Liu if (retval) 108133e94627b01823d2555450ddd1d95401ff2227aZheng Liu return retval; 109133e94627b01823d2555450ddd1d95401ff2227aZheng Liu 110133e94627b01823d2555450ddd1d95401ff2227aZheng Liu *size = EXT4_MIN_INLINE_DATA_SIZE + data.ea_size; 111133e94627b01823d2555450ddd1d95401ff2227aZheng Liu return ext2fs_free_mem(&data.ea_data); 112133e94627b01823d2555450ddd1d95401ff2227aZheng Liu} 113416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 114416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liuint ext2fs_inline_data_dir_iterate(ext2_filsys fs, ext2_ino_t ino, 115416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu void *priv_data) 116416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu{ 117416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu struct dir_context *ctx; 118416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu struct ext2_inode inode; 119416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu struct ext2_dir_entry dirent; 120416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu struct ext2_inline_data data; 121416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu int ret = BLOCK_ABORT; 122416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu e2_blkcnt_t blockcnt = 0; 123416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 124416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx = (struct dir_context *)priv_data; 125416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 126416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->errcode = ext2fs_read_inode(fs, ino, &inode); 127416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (ctx->errcode) 128416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu goto out; 129416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 130416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (!(inode.i_flags & EXT4_INLINE_DATA_FL)) { 131416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->errcode = EXT2_ET_NO_INLINE_DATA; 132416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu goto out; 133416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu } 134416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 135416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (!LINUX_S_ISDIR(inode.i_mode)) { 136416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->errcode = EXT2_ET_NO_DIRECTORY; 137416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu goto out; 138416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu } 139416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ret = 0; 140416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 141416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu /* we first check '.' and '..' dir */ 142416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu dirent.inode = ino; 143416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu dirent.name_len = 1; 144416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(2), &dirent); 145416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu dirent.name[0] = '.'; 146416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu dirent.name[1] = '\0'; 147416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->buf = (char *)&dirent; 148416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ext2fs_get_rec_len(fs, &dirent, &ctx->buflen); 149416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data); 150416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (ret & BLOCK_ABORT) 151416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu goto out; 152416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 153416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu dirent.inode = ext2fs_le32_to_cpu(inode.i_block[0]); 154416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu dirent.name_len = 2; 155416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(3), &dirent); 156416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu dirent.name[0] = '.'; 157416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu dirent.name[1] = '.'; 158416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu dirent.name[2] = '\0'; 159416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->buf = (char *)&dirent; 160416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ext2fs_get_rec_len(fs, &dirent, &ctx->buflen); 161416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data); 162416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (ret & BLOCK_INLINE_DATA_CHANGED) { 163416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu errcode_t err; 164416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 165416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu inode.i_block[0] = ext2fs_cpu_to_le32(dirent.inode); 166416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu err = ext2fs_write_inode(fs, ino, &inode); 167416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (err) 168416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu goto out; 169416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ret &= ~BLOCK_INLINE_DATA_CHANGED; 170416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu } 171416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (ret & BLOCK_ABORT) 172416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu goto out; 173416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 174416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->buf = (char *)inode.i_block + EXT4_INLINE_DATA_DOTDOT_SIZE; 175416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->buflen = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DATA_DOTDOT_SIZE; 176416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#ifdef WORDS_BIGENDIAN 177416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0); 178416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (ctx->errcode) { 179416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ret |= BLOCK_ABORT; 180416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu goto out; 181416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu } 182416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#endif 183416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data); 184416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (ret & BLOCK_INLINE_DATA_CHANGED) { 185416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#ifdef WORDS_BIGENDIAN 186416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf, 187416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->buflen, 0); 188416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (ctx->errcode) { 189416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ret |= BLOCK_ABORT; 190416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu goto out; 191416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu } 192416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#endif 193416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->errcode = ext2fs_write_inode(fs, ino, &inode); 194416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (ctx->errcode) 195416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ret |= BLOCK_ABORT; 196416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ret &= ~BLOCK_INLINE_DATA_CHANGED; 197416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu } 198416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (ret & BLOCK_ABORT) 199416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu goto out; 200416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 201416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu data.fs = fs; 202416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu data.ino = ino; 203416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->errcode = ext2fs_inline_data_ea_get(&data); 204416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (ctx->errcode) { 205416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ret |= BLOCK_ABORT; 206416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu goto out; 207416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu } 208416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (data.ea_size <= 0) 209416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu goto out; 210416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 211416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->buf = data.ea_data; 212416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->buflen = data.ea_size; 213416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#ifdef WORDS_BIGENDIAN 214416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx.errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0); 215416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (ctx.errcode) { 216416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ret |= BLOCK_ABORT; 217416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu goto out; 218416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu } 219416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#endif 220416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 221416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data); 222416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (ret & BLOCK_INLINE_DATA_CHANGED) { 223416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#ifdef WORDS_BIGENDIAN 224416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf, 225416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->buflen, 0); 226416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (ctx->errcode) { 227416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ret |= BLOCK_ABORT; 228416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu goto out1; 229416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu } 230416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#endif 231416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->errcode = ext2fs_inline_data_ea_set(&data); 232416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu if (ctx->errcode) 233416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ret |= BLOCK_ABORT; 234416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu } 235416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 236416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liuout1: 237416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ext2fs_free_mem(&data.ea_data); 238416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ctx->buf = 0; 239416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu 240416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liuout: 241416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu ret &= ~(BLOCK_ABORT | BLOCK_INLINE_DATA_CHANGED); 242416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu return ret; 243416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu} 24446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 24597581d448127f95dcc968c0785f7ab3413bf0222Zheng Liuerrcode_t ext2fs_inline_data_ea_remove(ext2_filsys fs, ext2_ino_t ino) 24646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu{ 24746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu struct ext2_xattr_handle *handle; 24846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu errcode_t retval; 24946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 25046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu retval = ext2fs_xattrs_open(fs, ino, &handle); 25146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (retval) 25246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu return retval; 25346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 25446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu retval = ext2fs_xattrs_read(handle); 25546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (retval) 25646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu goto err; 25746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 25846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu retval = ext2fs_xattr_remove(handle, "system.data"); 25946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (retval) 26046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu goto err; 26146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 26246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu retval = ext2fs_xattrs_write(handle); 26346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 26446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liuerr: 26546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu (void) ext2fs_xattrs_close(&handle); 26646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu return retval; 26746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu} 26846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 26946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liustatic errcode_t ext2fs_inline_data_convert_dir(ext2_filsys fs, ext2_ino_t ino, 27046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu char *bbuf, char *ibuf, int size) 27146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu{ 27246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu struct ext2_dir_entry *dir, *dir2; 27346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu struct ext2_dir_entry_tail *t; 27446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu errcode_t retval; 27546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu unsigned int offset; 27646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu int csum_size = 0; 27746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu int filetype = 0; 27846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu int rec_len; 27946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 28046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 28146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) 28246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu csum_size = sizeof(struct ext2_dir_entry_tail); 28346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 28446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu /* Create '.' and '..' */ 28546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (EXT2_HAS_INCOMPAT_FEATURE(fs->super, 28646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu EXT2_FEATURE_INCOMPAT_FILETYPE)) 28746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu filetype = EXT2_FT_DIR; 28846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 28946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu /* 29046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu * Set up entry for '.' 29146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu */ 29246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu dir = (struct ext2_dir_entry *) bbuf; 29346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu dir->inode = ino; 29446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu ext2fs_dirent_set_name_len(dir, 1); 29546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu ext2fs_dirent_set_file_type(dir, filetype); 29646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu dir->name[0] = '.'; 29746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu rec_len = (fs->blocksize - csum_size) - EXT2_DIR_REC_LEN(1); 29846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu dir->rec_len = EXT2_DIR_REC_LEN(1); 29946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 30046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu /* 30146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu * Set up entry for '..' 30246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu */ 30346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu dir = (struct ext2_dir_entry *) (bbuf + dir->rec_len); 30446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu dir->rec_len = EXT2_DIR_REC_LEN(2); 30546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu dir->inode = ext2fs_le32_to_cpu(((__u32 *)ibuf)[0]); 30646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu ext2fs_dirent_set_name_len(dir, 2); 30746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu ext2fs_dirent_set_file_type(dir, filetype); 30846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu dir->name[0] = '.'; 30946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu dir->name[1] = '.'; 31046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 31146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu /* 31246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu * Ajust the last rec_len 31346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu */ 31446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu offset = EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2); 31546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu dir = (struct ext2_dir_entry *) (bbuf + offset); 31646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu memcpy(bbuf + offset, ibuf + EXT4_INLINE_DATA_DOTDOT_SIZE, 31746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu size - EXT4_INLINE_DATA_DOTDOT_SIZE); 31846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu size += EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2) - 31946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu EXT4_INLINE_DATA_DOTDOT_SIZE; 32046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 32146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu do { 32246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu dir2 = dir; 32346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu retval = ext2fs_get_rec_len(fs, dir, &rec_len); 32446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (retval) 32546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu goto err; 32646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu offset += rec_len; 32746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu dir = (struct ext2_dir_entry *) (bbuf + offset); 32846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu } while (offset < size); 32946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu rec_len += fs->blocksize - csum_size - offset; 33046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu retval = ext2fs_set_rec_len(fs, rec_len, dir2); 33146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (retval) 33246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu goto err; 33346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 33446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (csum_size) { 33546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu t = EXT2_DIRENT_TAIL(bbuf, fs->blocksize); 33646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu ext2fs_initialize_dirent_tail(fs, t); 33746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu } 33846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 33946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liuerr: 34046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu return retval; 34146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu} 34246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 34346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liuerrcode_t ext2fs_inline_data_expand(ext2_filsys fs, ext2_ino_t ino) 34446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu{ 34546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu struct ext2_inode inode; 34646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu struct ext2_inline_data data; 34746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu errcode_t retval; 34846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu blk64_t blk; 34946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu char *inline_buf = 0; 35046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu char *blk_buf = 0; 35146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 35246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 35346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 35446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu retval = ext2fs_read_inode(fs, ino, &inode); 35546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (retval) 35646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu return retval; 35746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 35846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (!(inode.i_flags & EXT4_INLINE_DATA_FL)) 35946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu return EXT2_ET_NO_INLINE_DATA; 36046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 36146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu /* Get inline data first */ 36246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu data.fs = fs; 36346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu data.ino = ino; 36446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu retval = ext2fs_inline_data_ea_get(&data); 36546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (retval) 36646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu return retval; 36746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu retval = ext2fs_get_mem(EXT4_MIN_INLINE_DATA_SIZE + data.ea_size, 36846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu &inline_buf); 36946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (retval) 37046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu goto errout; 37146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 37246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu memcpy(inline_buf, (void *)inode.i_block, EXT4_MIN_INLINE_DATA_SIZE); 37346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (data.ea_size > 0) { 37446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu memcpy(inline_buf + EXT4_MIN_INLINE_DATA_SIZE, 37546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu data.ea_data, data.ea_size); 37646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu } 37746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 37846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu#ifdef WORDS_BIGENDIAN 37946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu retval = ext2fs_dirent_swab_in2(fs, inline_buf, 38046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu data.ea_size + EXT4_MIN_INLINE_DATA_SIZE); 38146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (retval) 38246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu goto errout; 38346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu#endif 38446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 38546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu memset((void *)inode.i_block, 0, EXT4_MIN_INLINE_DATA_SIZE); 38646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu retval = ext2fs_inline_data_ea_remove(fs, ino); 38746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (retval) 38846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu goto errout; 38946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 39046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu retval = ext2fs_get_mem(fs->blocksize, &blk_buf); 39146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (retval) 39246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu goto errout; 39346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 39446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu /* Adjust the rec_len */ 39546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu retval = ext2fs_inline_data_convert_dir(fs, ino, blk_buf, inline_buf, 39646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu EXT4_MIN_INLINE_DATA_SIZE + 39746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu data.ea_size); 39846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (retval) 39946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu goto errout; 40046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 40146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu /* Allocate a new block */ 40246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu retval = ext2fs_new_block2(fs, 0, 0, &blk); 40346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (retval) 40446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu goto errout; 40546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu retval = ext2fs_write_dir_block4(fs, blk, blk_buf, 0, ino); 40646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (retval) 40746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu goto errout; 40846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 40946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu /* Update inode */ 41046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (EXT2_HAS_INCOMPAT_FEATURE(fs->super, EXT3_FEATURE_INCOMPAT_EXTENTS)) 41146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu inode.i_flags |= EXT4_EXTENTS_FL; 41246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu inode.i_flags &= ~EXT4_INLINE_DATA_FL; 41346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu ext2fs_iblk_set(fs, &inode, 1); 41446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu inode.i_size = fs->blocksize; 41546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu retval = ext2fs_bmap2(fs, ino, &inode, 0, BMAP_SET, 0, 0, &blk); 41646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (retval) 41746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu goto errout; 41846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu retval = ext2fs_write_inode(fs, ino, &inode); 41946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (retval) 42046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu goto errout; 42146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu ext2fs_block_alloc_stats2(fs, blk, +1); 42246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu 42346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liuerrout: 42446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (blk_buf) 42546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu ext2fs_free_mem(&blk_buf); 42646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu if (inline_buf) 42746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu ext2fs_free_mem(&inline_buf); 42846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu ext2fs_free_mem(&data.ea_data); 42946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu return retval; 43046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu} 431