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