119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o/* 219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * irel_ma.c 3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * Copyright (C) 1996, 1997 Theodore Ts'o. 519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %Begin-Header% 7543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library 8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2. 919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %End-Header% 1019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 1119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 1219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#include <fcntl.h> 1319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#include <stdio.h> 1419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#include <string.h> 154cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#if HAVE_UNISTD_H 1619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#include <unistd.h> 174cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#endif 184cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#if HAVE_ERRNO_H 1919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#include <errno.h> 204cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#endif 2119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 22b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h" 2319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#include "ext2fs.h" 2419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#include "irel.h" 2519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 2631dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic errcode_t ima_put(ext2_irel irel, ext2_ino_t old, 2719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct ext2_inode_relocate_entry *ent); 2831dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic errcode_t ima_get(ext2_irel irel, ext2_ino_t old, 2919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct ext2_inode_relocate_entry *ent); 3031dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, 3119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct ext2_inode_relocate_entry *ent); 3219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic errcode_t ima_start_iter(ext2_irel irel); 3331dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic errcode_t ima_next(ext2_irel irel, ext2_ino_t *old, 3419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct ext2_inode_relocate_entry *ent); 3531dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino, 3619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct ext2_inode_reference *ref); 3731dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino); 3819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic errcode_t ima_next_ref(ext2_irel irel, struct ext2_inode_reference *ref); 3931dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new); 4031dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic errcode_t ima_delete(ext2_irel irel, ext2_ino_t old); 4119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic errcode_t ima_free(ext2_irel irel); 4219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 4319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o/* 4419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * This data structure stores the array of inode references; there is 4519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * a structure for each inode. 4619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 4719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostruct inode_reference_entry { 4819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o __u16 num; 4919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct ext2_inode_reference *refs; 5019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o}; 5119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 5219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostruct irel_ma { 5319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o __u32 magic; 5431dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o ext2_ino_t max_inode; 5531dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o ext2_ino_t ref_current; 5619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o int ref_iter; 5731dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o ext2_ino_t *orig_map; 5819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct ext2_inode_relocate_entry *entries; 5919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct inode_reference_entry *ref_entries; 6019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o}; 6119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 6231dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'oerrcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode, 6319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ext2_irel *new_irel) 6419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 6519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ext2_irel irel = 0; 6619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o errcode_t retval; 6719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct irel_ma *ma = 0; 6819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o size_t size; 6919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 7019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o *new_irel = 0; 7119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 7219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o /* 7319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * Allocate memory structures 7419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 757b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o retval = ext2fs_get_mem(sizeof(struct ext2_inode_relocation_table), 76c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o &irel); 777b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 7819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o goto errout; 7919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o memset(irel, 0, sizeof(struct ext2_inode_relocation_table)); 80efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 81c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(strlen(name)+1, &irel->name); 827b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 8319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o goto errout; 8419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o strcpy(irel->name, name); 85efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 86c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(sizeof(struct irel_ma), &ma); 877b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 8819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o goto errout; 8919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o memset(ma, 0, sizeof(struct irel_ma)); 90b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o irel->priv_data = ma; 91efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 9231dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o size = (size_t) (sizeof(ext2_ino_t) * (max_inode+1)); 93ee01079a17bfecd17292ccd60058056fb3a8ba6cTheodore Ts'o retval = ext2fs_get_array(max_inode+1, sizeof(ext2_ino_t), 94ee01079a17bfecd17292ccd60058056fb3a8ba6cTheodore Ts'o &ma->orig_map); 957b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 9619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o goto errout; 9719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o memset(ma->orig_map, 0, size); 9819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 993cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o size = (size_t) (sizeof(struct ext2_inode_relocate_entry) * 1003cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o (max_inode+1)); 101ee01079a17bfecd17292ccd60058056fb3a8ba6cTheodore Ts'o retval = ext2fs_get_array((max_inode+1, 102ee01079a17bfecd17292ccd60058056fb3a8ba6cTheodore Ts'o sizeof(struct ext2_inode_relocate_entry), &ma->entries); 1037b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 10419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o goto errout; 10519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o memset(ma->entries, 0, size); 10619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 1073cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o size = (size_t) (sizeof(struct inode_reference_entry) * 1083cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o (max_inode+1)); 109ee01079a17bfecd17292ccd60058056fb3a8ba6cTheodore Ts'o retval = ext2fs_get_mem(max_inode+1, 110ee01079a17bfecd17292ccd60058056fb3a8ba6cTheodore Ts'o sizeof(struct inode_reference_entry), &ma->ref_entries); 1117b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 11219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o goto errout; 11319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o memset(ma->ref_entries, 0, size); 11419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ma->max_inode = max_inode; 11519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 11619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o /* 11719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * Fill in the irel data structure 11819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 11919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o irel->put = ima_put; 12019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o irel->get = ima_get; 12119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o irel->get_by_orig = ima_get_by_orig; 12219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o irel->start_iter = ima_start_iter; 12319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o irel->next = ima_next; 12419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o irel->add_ref = ima_add_ref; 12519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o irel->start_iter_ref = ima_start_iter_ref; 12619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o irel->next_ref = ima_next_ref; 12719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o irel->move = ima_move; 12819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o irel->delete = ima_delete; 12919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o irel->free = ima_free; 130efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 13119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o *new_irel = irel; 13219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 13319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 13419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'oerrout: 13519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ima_free(irel); 13619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return retval; 13719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 13819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 13931dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic errcode_t ima_put(ext2_irel irel, ext2_ino_t old, 14019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct ext2_inode_relocate_entry *ent) 14119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 1427b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o struct inode_reference_entry *ref_ent; 1437b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o struct irel_ma *ma; 1447b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o errcode_t retval; 14576f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o size_t size, old_size; 14619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 147b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o ma = irel->priv_data; 14819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (old > ma->max_inode) 1491f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_INVALID_ARGUMENT; 15019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 15119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o /* 15219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * Force the orig field to the correct value; the application 15319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * program shouldn't be messing with this field. 15419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 1553cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o if (ma->entries[(unsigned) old].new == 0) 15619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ent->orig = old; 15719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o else 1583cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o ent->orig = ma->entries[(unsigned) old].orig; 159efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 16019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o /* 16119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * If max_refs has changed, reallocate the refs array 16219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 1633cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o ref_ent = ma->ref_entries + (unsigned) old; 1643cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o if (ref_ent->refs && ent->max_refs != 1653cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o ma->entries[(unsigned) old].max_refs) { 16619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o size = (sizeof(struct ext2_inode_reference) * ent->max_refs); 16776f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o old_size = (sizeof(struct ext2_inode_reference) * 16876f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o ma->entries[(unsigned) old].max_refs); 169c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_resize_mem(old_size, size, &ref_ent->refs); 1707b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 1717b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 17219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 17319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 1743cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o ma->entries[(unsigned) old] = *ent; 1753cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o ma->orig_map[(unsigned) ent->orig] = old; 17619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 17719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 17819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 17931dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic errcode_t ima_get(ext2_irel irel, ext2_ino_t old, 18019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct ext2_inode_relocate_entry *ent) 18119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 18219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct irel_ma *ma; 18319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 184b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o ma = irel->priv_data; 18519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (old > ma->max_inode) 1861f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_INVALID_ARGUMENT; 1873cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o if (ma->entries[(unsigned) old].new == 0) 18819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return ENOENT; 1893cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o *ent = ma->entries[(unsigned) old]; 19019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 19119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 19219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 19331dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, 19419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct ext2_inode_relocate_entry *ent) 19519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 19619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct irel_ma *ma; 19731dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o ext2_ino_t ino; 19819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 199b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o ma = irel->priv_data; 20019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (orig > ma->max_inode) 2011f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_INVALID_ARGUMENT; 2023cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o ino = ma->orig_map[(unsigned) orig]; 20319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ino == 0) 20419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return ENOENT; 20519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o *old = ino; 2063cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o *ent = ma->entries[(unsigned) ino]; 20719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 20819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 20919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 21019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic errcode_t ima_start_iter(ext2_irel irel) 21119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 21219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o irel->current = 0; 21319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 21419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 21519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 21631dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic errcode_t ima_next(ext2_irel irel, ext2_ino_t *old, 21719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct ext2_inode_relocate_entry *ent) 21819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 21919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct irel_ma *ma; 22019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 221b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o ma = irel->priv_data; 22219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o while (++irel->current < ma->max_inode) { 2233cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o if (ma->entries[(unsigned) irel->current].new == 0) 22419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o continue; 22519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o *old = irel->current; 2263cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o *ent = ma->entries[(unsigned) irel->current]; 22719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 22819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 22919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o *old = 0; 23019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 23119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 23219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 23331dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino, 23419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct ext2_inode_reference *ref) 23519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 23619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct irel_ma *ma; 23719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o size_t size; 23819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct inode_reference_entry *ref_ent; 23919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct ext2_inode_relocate_entry *ent; 2407b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o errcode_t retval; 24119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 242b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o ma = irel->priv_data; 24319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ino > ma->max_inode) 2441f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_INVALID_ARGUMENT; 24519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 2463cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o ref_ent = ma->ref_entries + (unsigned) ino; 2473cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o ent = ma->entries + (unsigned) ino; 248efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 24919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o /* 25019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * If the inode reference array doesn't exist, create it. 25119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 25219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ref_ent->refs == 0) { 253efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o size = (size_t) ((sizeof(struct ext2_inode_reference) * 2543cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o ent->max_refs)); 255ee01079a17bfecd17292ccd60058056fb3a8ba6cTheodore Ts'o retval = ext2fs_get_array(ent->max_refs, 256ee01079a17bfecd17292ccd60058056fb3a8ba6cTheodore Ts'o sizeof(struct ext2_inode_reference), &ref_ent->refs); 2577b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 2587b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 25919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o memset(ref_ent->refs, 0, size); 26019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ref_ent->num = 0; 26119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 26219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 26319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ref_ent->num >= ent->max_refs) 2641f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_TOO_MANY_REFS; 26519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 2663cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o ref_ent->refs[(unsigned) ref_ent->num++] = *ref; 26719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 26819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 26919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 27031dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino) 27119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 27219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct irel_ma *ma; 27319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 274b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o ma = irel->priv_data; 27519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ino > ma->max_inode) 2761f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_INVALID_ARGUMENT; 2773cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o if (ma->entries[(unsigned) ino].new == 0) 27819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return ENOENT; 27919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ma->ref_current = ino; 28019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ma->ref_iter = 0; 28119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 28219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 28319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 28419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic errcode_t ima_next_ref(ext2_irel irel, 28519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct ext2_inode_reference *ref) 28619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 28719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct irel_ma *ma; 28819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct inode_reference_entry *ref_ent; 28919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 290b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o ma = irel->priv_data; 291efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 29219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ref_ent = ma->ref_entries + ma->ref_current; 29319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 29419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if ((ref_ent->refs == NULL) || 29519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o (ma->ref_iter >= ref_ent->num)) { 29619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ref->block = 0; 29719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ref->offset = 0; 29819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 29919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 30019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o *ref = ref_ent->refs[ma->ref_iter++]; 30119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 30219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 30319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 30419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 30531dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new) 30619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 30719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct irel_ma *ma; 30819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 309b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o ma = irel->priv_data; 31019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if ((old > ma->max_inode) || (new > ma->max_inode)) 3111f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_INVALID_ARGUMENT; 3123cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o if (ma->entries[(unsigned) old].new == 0) 31319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return ENOENT; 314efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 3153cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o ma->entries[(unsigned) new] = ma->entries[(unsigned) old]; 3163cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o if (ma->ref_entries[(unsigned) new].refs) 317c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&ma->ref_entries[(unsigned) new].refs); 3183cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o ma->ref_entries[(unsigned) new] = ma->ref_entries[(unsigned) old]; 319efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 3203cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o ma->entries[(unsigned) old].new = 0; 3213cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o ma->ref_entries[(unsigned) old].num = 0; 3223cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o ma->ref_entries[(unsigned) old].refs = 0; 32319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 32419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ma->orig_map[ma->entries[new].orig] = new; 32519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 32619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 32719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 32831dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic errcode_t ima_delete(ext2_irel irel, ext2_ino_t old) 32919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 33019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct irel_ma *ma; 33119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 332b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o ma = irel->priv_data; 33319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (old > ma->max_inode) 3341f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_INVALID_ARGUMENT; 3353cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o if (ma->entries[(unsigned) old].new == 0) 33619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return ENOENT; 337efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 33819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ma->entries[old].new = 0; 3393cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o if (ma->ref_entries[(unsigned) old].refs) 340c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&ma->ref_entries[(unsigned) old].refs); 3413cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o ma->orig_map[ma->entries[(unsigned) old].orig] = 0; 342efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 3431c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o ma->ref_entries[(unsigned) old].num = 0; 3443cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o ma->ref_entries[(unsigned) old].refs = 0; 34519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 34619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 34719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 34819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic errcode_t ima_free(ext2_irel irel) 34919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 35019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct irel_ma *ma; 35131dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o ext2_ino_t ino; 35219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 35319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (!irel) 35419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 35519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 356b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o ma = irel->priv_data; 35719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 35819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ma) { 35919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ma->orig_map) 360c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&ma->orig_map); 36119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ma->entries) 362c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&ma->entries); 36319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ma->ref_entries) { 36419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o for (ino = 0; ino <= ma->max_inode; ino++) { 3653cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o if (ma->ref_entries[(unsigned) ino].refs) 366c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&ma->ref_entries[(unsigned) ino].refs); 36719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 368c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&ma->ref_entries); 36919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 370c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&ma); 37119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 37219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (irel->name) 373c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&irel->name); 374c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&irel); 37519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 37619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 377