brel_ma.c revision 9f8046fc6dfc13eee2f5c363214e60b533872cac
1/*
2 * brel_ma.c
3 *
4 * Copyright (C) 1996, 1997 Theodore Ts'o.
5 *
6 * TODO: rewrite to not use a direct array!!!  (Fortunately this
7 * module isn't really used yet.)
8 *
9 * %Begin-Header%
10 * This file may be redistributed under the terms of the GNU Public
11 * License.
12 * %End-Header%
13 */
14
15#include <fcntl.h>
16#include <stdio.h>
17#include <string.h>
18#if HAVE_UNISTD_H
19#include <unistd.h>
20#endif
21#if HAVE_ERRNO_H
22#include <errno.h>
23#endif
24
25#include "ext2_fs.h"
26#include "ext2fs.h"
27#include "brel.h"
28
29static errcode_t bma_put(ext2_brel brel, blk_t old,
30			struct ext2_block_relocate_entry *ent);
31static errcode_t bma_get(ext2_brel brel, blk_t old,
32			struct ext2_block_relocate_entry *ent);
33static errcode_t bma_start_iter(ext2_brel brel);
34static errcode_t bma_next(ext2_brel brel, blk_t *old,
35			 struct ext2_block_relocate_entry *ent);
36static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new);
37static errcode_t bma_delete(ext2_brel brel, blk_t old);
38static errcode_t bma_free(ext2_brel brel);
39
40struct brel_ma {
41	__u32 magic;
42	blk_t max_block;
43	struct ext2_block_relocate_entry *entries;
44};
45
46errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
47				      ext2_brel *new_brel)
48{
49	ext2_brel		brel = 0;
50	errcode_t	retval;
51	struct brel_ma 	*ma = 0;
52	size_t		size;
53
54	*new_brel = 0;
55
56	/*
57	 * Allocate memory structures
58	 */
59	retval = ext2fs_get_mem(sizeof(struct ext2_block_relocation_table),
60				(void **) &brel);
61	if (retval)
62		goto errout;
63	memset(brel, 0, sizeof(struct ext2_block_relocation_table));
64
65	retval = ext2fs_get_mem(strlen(name)+1, (void **) &brel->name);
66	if (retval)
67		goto errout;
68	strcpy(brel->name, name);
69
70	retval = ext2fs_get_mem(sizeof(struct brel_ma), (void **) &ma);
71	if (retval)
72		goto errout;
73	memset(ma, 0, sizeof(struct brel_ma));
74	brel->priv_data = ma;
75
76	size = (size_t) (sizeof(struct ext2_block_relocate_entry) *
77			 (max_block+1));
78	retval = ext2fs_get_mem(size, (void **) &ma->entries);
79	if (retval)
80		goto errout;
81	memset(ma->entries, 0, size);
82	ma->max_block = max_block;
83
84	/*
85	 * Fill in the brel data structure
86	 */
87	brel->put = bma_put;
88	brel->get = bma_get;
89	brel->start_iter = bma_start_iter;
90	brel->next = bma_next;
91	brel->move = bma_move;
92	brel->delete = bma_delete;
93	brel->free = bma_free;
94
95	*new_brel = brel;
96	return 0;
97
98errout:
99	bma_free(brel);
100	return retval;
101}
102
103static errcode_t bma_put(ext2_brel brel, blk_t old,
104			struct ext2_block_relocate_entry *ent)
105{
106	struct brel_ma 	*ma;
107
108	ma = brel->priv_data;
109	if (old > ma->max_block)
110		return EXT2_ET_INVALID_ARGUMENT;
111	ma->entries[(unsigned)old] = *ent;
112	return 0;
113}
114
115static errcode_t bma_get(ext2_brel brel, blk_t old,
116			struct ext2_block_relocate_entry *ent)
117{
118	struct brel_ma 	*ma;
119
120	ma = brel->priv_data;
121	if (old > ma->max_block)
122		return EXT2_ET_INVALID_ARGUMENT;
123	if (ma->entries[(unsigned)old].new == 0)
124		return ENOENT;
125	*ent = ma->entries[old];
126	return 0;
127}
128
129static errcode_t bma_start_iter(ext2_brel brel)
130{
131	brel->current = 0;
132	return 0;
133}
134
135static errcode_t bma_next(ext2_brel brel, blk_t *old,
136			  struct ext2_block_relocate_entry *ent)
137{
138	struct brel_ma 	*ma;
139
140	ma = brel->priv_data;
141	while (++brel->current < ma->max_block) {
142		if (ma->entries[(unsigned)brel->current].new == 0)
143			continue;
144		*old = brel->current;
145		*ent = ma->entries[(unsigned)brel->current];
146		return 0;
147	}
148	*old = 0;
149	return 0;
150}
151
152static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new)
153{
154	struct brel_ma 	*ma;
155
156	ma = brel->priv_data;
157	if ((old > ma->max_block) || (new > ma->max_block))
158		return EXT2_ET_INVALID_ARGUMENT;
159	if (ma->entries[(unsigned)old].new == 0)
160		return ENOENT;
161	ma->entries[(unsigned)new] = ma->entries[old];
162	ma->entries[(unsigned)old].new = 0;
163	return 0;
164}
165
166static errcode_t bma_delete(ext2_brel brel, blk_t old)
167{
168	struct brel_ma 	*ma;
169
170	ma = brel->priv_data;
171	if (old > ma->max_block)
172		return EXT2_ET_INVALID_ARGUMENT;
173	if (ma->entries[(unsigned)old].new == 0)
174		return ENOENT;
175	ma->entries[(unsigned)old].new = 0;
176	return 0;
177}
178
179static errcode_t bma_free(ext2_brel brel)
180{
181	struct brel_ma 	*ma;
182
183	if (!brel)
184		return 0;
185
186	ma = brel->priv_data;
187
188	if (ma) {
189		if (ma->entries)
190			ext2fs_free_mem((void **) &ma->entries);
191		ext2fs_free_mem((void **) &ma);
192	}
193	if (brel->name)
194		ext2fs_free_mem((void **) &brel->name);
195	ext2fs_free_mem((void **) &brel);
196	return 0;
197}
198