brel_ma.c revision 65f0aab98b20b5994a726ab90d355248bcddfffd
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 Library
11 * General Public License, version 2.
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				&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, &brel->name);
66	if (retval)
67		goto errout;
68	strcpy(brel->name, name);
69
70	retval = ext2fs_get_mem(sizeof(struct brel_ma), &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_array(max_block+1,
79		sizeof(struct ext2_block_relocate_entry), &ma->entries);
80	if (retval)
81		goto errout;
82	memset(ma->entries, 0, size);
83	ma->max_block = max_block;
84
85	/*
86	 * Fill in the brel data structure
87	 */
88	brel->put = bma_put;
89	brel->get = bma_get;
90	brel->start_iter = bma_start_iter;
91	brel->next = bma_next;
92	brel->move = bma_move;
93	brel->delete = bma_delete;
94	brel->free = bma_free;
95
96	*new_brel = brel;
97	return 0;
98
99errout:
100	bma_free(brel);
101	return retval;
102}
103
104static errcode_t bma_put(ext2_brel brel, blk_t old,
105			struct ext2_block_relocate_entry *ent)
106{
107	struct brel_ma 	*ma;
108
109	ma = brel->priv_data;
110	if (old > ma->max_block)
111		return EXT2_ET_INVALID_ARGUMENT;
112	ma->entries[(unsigned)old] = *ent;
113	return 0;
114}
115
116static errcode_t bma_get(ext2_brel brel, blk_t old,
117			struct ext2_block_relocate_entry *ent)
118{
119	struct brel_ma 	*ma;
120
121	ma = brel->priv_data;
122	if (old > ma->max_block)
123		return EXT2_ET_INVALID_ARGUMENT;
124	if (ma->entries[(unsigned)old].new == 0)
125		return ENOENT;
126	*ent = ma->entries[old];
127	return 0;
128}
129
130static errcode_t bma_start_iter(ext2_brel brel)
131{
132	brel->current = 0;
133	return 0;
134}
135
136static errcode_t bma_next(ext2_brel brel, blk_t *old,
137			  struct ext2_block_relocate_entry *ent)
138{
139	struct brel_ma 	*ma;
140
141	ma = brel->priv_data;
142	while (++brel->current < ma->max_block) {
143		if (ma->entries[(unsigned)brel->current].new == 0)
144			continue;
145		*old = brel->current;
146		*ent = ma->entries[(unsigned)brel->current];
147		return 0;
148	}
149	*old = 0;
150	return 0;
151}
152
153static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new)
154{
155	struct brel_ma 	*ma;
156
157	ma = brel->priv_data;
158	if ((old > ma->max_block) || (new > ma->max_block))
159		return EXT2_ET_INVALID_ARGUMENT;
160	if (ma->entries[(unsigned)old].new == 0)
161		return ENOENT;
162	ma->entries[(unsigned)new] = ma->entries[old];
163	ma->entries[(unsigned)old].new = 0;
164	return 0;
165}
166
167static errcode_t bma_delete(ext2_brel brel, blk_t old)
168{
169	struct brel_ma 	*ma;
170
171	ma = brel->priv_data;
172	if (old > ma->max_block)
173		return EXT2_ET_INVALID_ARGUMENT;
174	if (ma->entries[(unsigned)old].new == 0)
175		return ENOENT;
176	ma->entries[(unsigned)old].new = 0;
177	return 0;
178}
179
180static errcode_t bma_free(ext2_brel brel)
181{
182	struct brel_ma 	*ma;
183
184	if (!brel)
185		return 0;
186
187	ma = brel->priv_data;
188
189	if (ma) {
190		if (ma->entries)
191			ext2fs_free_mem(&ma->entries);
192		ext2fs_free_mem(&ma);
193	}
194	if (brel->name)
195		ext2fs_free_mem(&brel->name);
196	ext2fs_free_mem(&brel);
197	return 0;
198}
199