xref: /aosp_15_r20/external/e2fsprogs/e2fsck/region.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker  * region.c --- code which manages allocations within a region.
3*6a54128fSAndroid Build Coastguard Worker  *
4*6a54128fSAndroid Build Coastguard Worker  * Copyright (C) 2001 Theodore Ts'o.
5*6a54128fSAndroid Build Coastguard Worker  *
6*6a54128fSAndroid Build Coastguard Worker  * %Begin-Header%
7*6a54128fSAndroid Build Coastguard Worker  * This file may be redistributed under the terms of the GNU Public
8*6a54128fSAndroid Build Coastguard Worker  * License.
9*6a54128fSAndroid Build Coastguard Worker  * %End-Header%
10*6a54128fSAndroid Build Coastguard Worker  */
11*6a54128fSAndroid Build Coastguard Worker 
12*6a54128fSAndroid Build Coastguard Worker #include "config.h"
13*6a54128fSAndroid Build Coastguard Worker #if HAVE_UNISTD_H
14*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
15*6a54128fSAndroid Build Coastguard Worker #endif
16*6a54128fSAndroid Build Coastguard Worker #include <string.h>
17*6a54128fSAndroid Build Coastguard Worker 
18*6a54128fSAndroid Build Coastguard Worker #ifdef TEST_PROGRAM
19*6a54128fSAndroid Build Coastguard Worker #undef ENABLE_NLS
20*6a54128fSAndroid Build Coastguard Worker #endif
21*6a54128fSAndroid Build Coastguard Worker #include "e2fsck.h"
22*6a54128fSAndroid Build Coastguard Worker 
23*6a54128fSAndroid Build Coastguard Worker struct region_el {
24*6a54128fSAndroid Build Coastguard Worker 	region_addr_t	start;
25*6a54128fSAndroid Build Coastguard Worker 	region_addr_t	end;
26*6a54128fSAndroid Build Coastguard Worker 	struct region_el *next;
27*6a54128fSAndroid Build Coastguard Worker };
28*6a54128fSAndroid Build Coastguard Worker 
29*6a54128fSAndroid Build Coastguard Worker struct region_struct {
30*6a54128fSAndroid Build Coastguard Worker 	region_addr_t	min;
31*6a54128fSAndroid Build Coastguard Worker 	region_addr_t	max;
32*6a54128fSAndroid Build Coastguard Worker 	struct region_el *allocated;
33*6a54128fSAndroid Build Coastguard Worker 	struct region_el *last;
34*6a54128fSAndroid Build Coastguard Worker };
35*6a54128fSAndroid Build Coastguard Worker 
region_create(region_addr_t min,region_addr_t max)36*6a54128fSAndroid Build Coastguard Worker region_t region_create(region_addr_t min, region_addr_t max)
37*6a54128fSAndroid Build Coastguard Worker {
38*6a54128fSAndroid Build Coastguard Worker 	region_t	region;
39*6a54128fSAndroid Build Coastguard Worker 	errcode_t	retval;
40*6a54128fSAndroid Build Coastguard Worker 
41*6a54128fSAndroid Build Coastguard Worker 	retval = ext2fs_get_memzero(sizeof(struct region_struct), &region);
42*6a54128fSAndroid Build Coastguard Worker 	if (retval)
43*6a54128fSAndroid Build Coastguard Worker 		return NULL;
44*6a54128fSAndroid Build Coastguard Worker 
45*6a54128fSAndroid Build Coastguard Worker 	region->min = min;
46*6a54128fSAndroid Build Coastguard Worker 	region->max = max;
47*6a54128fSAndroid Build Coastguard Worker 	region->last = NULL;
48*6a54128fSAndroid Build Coastguard Worker 	return region;
49*6a54128fSAndroid Build Coastguard Worker }
50*6a54128fSAndroid Build Coastguard Worker 
region_free(region_t region)51*6a54128fSAndroid Build Coastguard Worker void region_free(region_t region)
52*6a54128fSAndroid Build Coastguard Worker {
53*6a54128fSAndroid Build Coastguard Worker 	struct region_el	*r, *next;
54*6a54128fSAndroid Build Coastguard Worker 
55*6a54128fSAndroid Build Coastguard Worker 	for (r = region->allocated; r; r = next) {
56*6a54128fSAndroid Build Coastguard Worker 		next = r->next;
57*6a54128fSAndroid Build Coastguard Worker 		ext2fs_free_mem(&r);
58*6a54128fSAndroid Build Coastguard Worker 	}
59*6a54128fSAndroid Build Coastguard Worker 	memset(region, 0, sizeof(struct region_struct));
60*6a54128fSAndroid Build Coastguard Worker 	ext2fs_free_mem(&region);
61*6a54128fSAndroid Build Coastguard Worker }
62*6a54128fSAndroid Build Coastguard Worker 
region_allocate(region_t region,region_addr_t start,int n)63*6a54128fSAndroid Build Coastguard Worker int region_allocate(region_t region, region_addr_t start, int n)
64*6a54128fSAndroid Build Coastguard Worker {
65*6a54128fSAndroid Build Coastguard Worker 	struct region_el	*r, *new_region, *prev, *next;
66*6a54128fSAndroid Build Coastguard Worker 	region_addr_t end;
67*6a54128fSAndroid Build Coastguard Worker 	errcode_t retval;
68*6a54128fSAndroid Build Coastguard Worker 
69*6a54128fSAndroid Build Coastguard Worker 	end = start+n;
70*6a54128fSAndroid Build Coastguard Worker 	if ((start < region->min) || (end > region->max))
71*6a54128fSAndroid Build Coastguard Worker 		return -1;
72*6a54128fSAndroid Build Coastguard Worker 	if (n == 0)
73*6a54128fSAndroid Build Coastguard Worker 		return 1;
74*6a54128fSAndroid Build Coastguard Worker 
75*6a54128fSAndroid Build Coastguard Worker 	if (region->last && region->last->end == start &&
76*6a54128fSAndroid Build Coastguard Worker 	    !region->last->next) {
77*6a54128fSAndroid Build Coastguard Worker 		region->last->end = end;
78*6a54128fSAndroid Build Coastguard Worker 		return 0;
79*6a54128fSAndroid Build Coastguard Worker 	}
80*6a54128fSAndroid Build Coastguard Worker 	if (region->last && start > region->last->end &&
81*6a54128fSAndroid Build Coastguard Worker 	    !region->last->next) {
82*6a54128fSAndroid Build Coastguard Worker 		r = NULL;
83*6a54128fSAndroid Build Coastguard Worker 		prev = region->last;
84*6a54128fSAndroid Build Coastguard Worker 		goto append_to_list;
85*6a54128fSAndroid Build Coastguard Worker 	}
86*6a54128fSAndroid Build Coastguard Worker 
87*6a54128fSAndroid Build Coastguard Worker 	/*
88*6a54128fSAndroid Build Coastguard Worker 	 * Search through the linked list.  If we find that it
89*6a54128fSAndroid Build Coastguard Worker 	 * conflicts with something that's already allocated, return
90*6a54128fSAndroid Build Coastguard Worker 	 * 1; if we can find an existing region which we can grow, do
91*6a54128fSAndroid Build Coastguard Worker 	 * so.  Otherwise, stop when we find the appropriate place
92*6a54128fSAndroid Build Coastguard Worker 	 * insert a new region element into the linked list.
93*6a54128fSAndroid Build Coastguard Worker 	 */
94*6a54128fSAndroid Build Coastguard Worker 	for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
95*6a54128fSAndroid Build Coastguard Worker 		if (((start >= r->start) && (start < r->end)) ||
96*6a54128fSAndroid Build Coastguard Worker 		    ((end > r->start) && (end <= r->end)) ||
97*6a54128fSAndroid Build Coastguard Worker 		    ((start <= r->start) && (end >= r->end)))
98*6a54128fSAndroid Build Coastguard Worker 			return 1;
99*6a54128fSAndroid Build Coastguard Worker 		if (end == r->start) {
100*6a54128fSAndroid Build Coastguard Worker 			r->start = start;
101*6a54128fSAndroid Build Coastguard Worker 			return 0;
102*6a54128fSAndroid Build Coastguard Worker 		}
103*6a54128fSAndroid Build Coastguard Worker 		if (start == r->end) {
104*6a54128fSAndroid Build Coastguard Worker 			if ((next = r->next)) {
105*6a54128fSAndroid Build Coastguard Worker 				if (end > next->start)
106*6a54128fSAndroid Build Coastguard Worker 					return 1;
107*6a54128fSAndroid Build Coastguard Worker 				if (end == next->start) {
108*6a54128fSAndroid Build Coastguard Worker 					r->end = next->end;
109*6a54128fSAndroid Build Coastguard Worker 					r->next = next->next;
110*6a54128fSAndroid Build Coastguard Worker 					ext2fs_free_mem(&next);
111*6a54128fSAndroid Build Coastguard Worker 					if (!r->next)
112*6a54128fSAndroid Build Coastguard Worker 						region->last = r;
113*6a54128fSAndroid Build Coastguard Worker 					return 0;
114*6a54128fSAndroid Build Coastguard Worker 				}
115*6a54128fSAndroid Build Coastguard Worker 			}
116*6a54128fSAndroid Build Coastguard Worker 			r->end = end;
117*6a54128fSAndroid Build Coastguard Worker 			return 0;
118*6a54128fSAndroid Build Coastguard Worker 		}
119*6a54128fSAndroid Build Coastguard Worker 		if (start < r->start)
120*6a54128fSAndroid Build Coastguard Worker 			break;
121*6a54128fSAndroid Build Coastguard Worker 	}
122*6a54128fSAndroid Build Coastguard Worker 	/*
123*6a54128fSAndroid Build Coastguard Worker 	 * Insert a new region element structure into the linked list
124*6a54128fSAndroid Build Coastguard Worker 	 */
125*6a54128fSAndroid Build Coastguard Worker append_to_list:
126*6a54128fSAndroid Build Coastguard Worker 	retval = ext2fs_get_mem(sizeof(struct region_el), &new_region);
127*6a54128fSAndroid Build Coastguard Worker 	if (retval)
128*6a54128fSAndroid Build Coastguard Worker 		return -1;
129*6a54128fSAndroid Build Coastguard Worker 	new_region->start = start;
130*6a54128fSAndroid Build Coastguard Worker 	new_region->end = start + n;
131*6a54128fSAndroid Build Coastguard Worker 	new_region->next = r;
132*6a54128fSAndroid Build Coastguard Worker 	if (!new_region->next)
133*6a54128fSAndroid Build Coastguard Worker 		region->last = new_region;
134*6a54128fSAndroid Build Coastguard Worker 	if (prev)
135*6a54128fSAndroid Build Coastguard Worker 		prev->next = new_region;
136*6a54128fSAndroid Build Coastguard Worker 	else
137*6a54128fSAndroid Build Coastguard Worker 		region->allocated = new_region;
138*6a54128fSAndroid Build Coastguard Worker 	return 0;
139*6a54128fSAndroid Build Coastguard Worker }
140*6a54128fSAndroid Build Coastguard Worker 
141*6a54128fSAndroid Build Coastguard Worker #ifdef TEST_PROGRAM
142*6a54128fSAndroid Build Coastguard Worker #include <stdio.h>
143*6a54128fSAndroid Build Coastguard Worker 
144*6a54128fSAndroid Build Coastguard Worker #define BCODE_END	0
145*6a54128fSAndroid Build Coastguard Worker #define BCODE_CREATE	1
146*6a54128fSAndroid Build Coastguard Worker #define BCODE_FREE	2
147*6a54128fSAndroid Build Coastguard Worker #define BCODE_ALLOCATE	3
148*6a54128fSAndroid Build Coastguard Worker #define BCODE_PRINT	4
149*6a54128fSAndroid Build Coastguard Worker 
150*6a54128fSAndroid Build Coastguard Worker int bcode_program[] = {
151*6a54128fSAndroid Build Coastguard Worker 	BCODE_CREATE, 1, 1001,
152*6a54128fSAndroid Build Coastguard Worker 	BCODE_PRINT,
153*6a54128fSAndroid Build Coastguard Worker 	BCODE_ALLOCATE, 10, 10,
154*6a54128fSAndroid Build Coastguard Worker 	BCODE_ALLOCATE, 30, 10,
155*6a54128fSAndroid Build Coastguard Worker 	BCODE_PRINT,
156*6a54128fSAndroid Build Coastguard Worker 	BCODE_ALLOCATE, 1, 15,
157*6a54128fSAndroid Build Coastguard Worker 	BCODE_ALLOCATE, 15, 8,
158*6a54128fSAndroid Build Coastguard Worker 	BCODE_ALLOCATE, 1, 20,
159*6a54128fSAndroid Build Coastguard Worker 	BCODE_ALLOCATE, 1, 8,
160*6a54128fSAndroid Build Coastguard Worker 	BCODE_PRINT,
161*6a54128fSAndroid Build Coastguard Worker 	BCODE_ALLOCATE, 40, 10,
162*6a54128fSAndroid Build Coastguard Worker 	BCODE_PRINT,
163*6a54128fSAndroid Build Coastguard Worker 	BCODE_ALLOCATE, 22, 5,
164*6a54128fSAndroid Build Coastguard Worker 	BCODE_PRINT,
165*6a54128fSAndroid Build Coastguard Worker 	BCODE_ALLOCATE, 27, 3,
166*6a54128fSAndroid Build Coastguard Worker 	BCODE_PRINT,
167*6a54128fSAndroid Build Coastguard Worker 	BCODE_ALLOCATE, 20, 2,
168*6a54128fSAndroid Build Coastguard Worker 	BCODE_PRINT,
169*6a54128fSAndroid Build Coastguard Worker 	BCODE_ALLOCATE, 49, 1,
170*6a54128fSAndroid Build Coastguard Worker 	BCODE_ALLOCATE, 50, 5,
171*6a54128fSAndroid Build Coastguard Worker 	BCODE_ALLOCATE, 9, 2,
172*6a54128fSAndroid Build Coastguard Worker 	BCODE_ALLOCATE, 9, 1,
173*6a54128fSAndroid Build Coastguard Worker 	BCODE_PRINT,
174*6a54128fSAndroid Build Coastguard Worker 	BCODE_FREE,
175*6a54128fSAndroid Build Coastguard Worker 	BCODE_END
176*6a54128fSAndroid Build Coastguard Worker };
177*6a54128fSAndroid Build Coastguard Worker 
region_print(region_t region,FILE * f)178*6a54128fSAndroid Build Coastguard Worker void region_print(region_t region, FILE *f)
179*6a54128fSAndroid Build Coastguard Worker {
180*6a54128fSAndroid Build Coastguard Worker 	struct region_el	*r;
181*6a54128fSAndroid Build Coastguard Worker 	int	i = 0;
182*6a54128fSAndroid Build Coastguard Worker 
183*6a54128fSAndroid Build Coastguard Worker 	fprintf(f, "Printing region (min=%llu. max=%llu)\n\t",
184*6a54128fSAndroid Build Coastguard Worker 		(unsigned long long) region->min,
185*6a54128fSAndroid Build Coastguard Worker 		(unsigned long long) region->max);
186*6a54128fSAndroid Build Coastguard Worker 	for (r = region->allocated; r; r = r->next) {
187*6a54128fSAndroid Build Coastguard Worker 		fprintf(f, "(%llu, %llu)  ",
188*6a54128fSAndroid Build Coastguard Worker 			(unsigned long long) r->start,
189*6a54128fSAndroid Build Coastguard Worker 			(unsigned long long) r->end);
190*6a54128fSAndroid Build Coastguard Worker 		if (++i >= 8)
191*6a54128fSAndroid Build Coastguard Worker 			fprintf(f, "\n\t");
192*6a54128fSAndroid Build Coastguard Worker 	}
193*6a54128fSAndroid Build Coastguard Worker 	fprintf(f, "\n");
194*6a54128fSAndroid Build Coastguard Worker }
195*6a54128fSAndroid Build Coastguard Worker 
main(int argc,char ** argv)196*6a54128fSAndroid Build Coastguard Worker int main(int argc, char **argv)
197*6a54128fSAndroid Build Coastguard Worker {
198*6a54128fSAndroid Build Coastguard Worker 	region_t	r = NULL;
199*6a54128fSAndroid Build Coastguard Worker 	int		pc = 0, ret;
200*6a54128fSAndroid Build Coastguard Worker 	region_addr_t	start, end;
201*6a54128fSAndroid Build Coastguard Worker 
202*6a54128fSAndroid Build Coastguard Worker 
203*6a54128fSAndroid Build Coastguard Worker 	while (1) {
204*6a54128fSAndroid Build Coastguard Worker 		switch (bcode_program[pc++]) {
205*6a54128fSAndroid Build Coastguard Worker 		case BCODE_END:
206*6a54128fSAndroid Build Coastguard Worker 			exit(0);
207*6a54128fSAndroid Build Coastguard Worker 		case BCODE_CREATE:
208*6a54128fSAndroid Build Coastguard Worker 			start = bcode_program[pc++];
209*6a54128fSAndroid Build Coastguard Worker 			end = bcode_program[pc++];
210*6a54128fSAndroid Build Coastguard Worker 			printf("Creating region with args(%llu, %llu)\n",
211*6a54128fSAndroid Build Coastguard Worker 			       (unsigned long long) start,
212*6a54128fSAndroid Build Coastguard Worker 			       (unsigned long long) end);
213*6a54128fSAndroid Build Coastguard Worker 			r = region_create(start, end);
214*6a54128fSAndroid Build Coastguard Worker 			if (!r) {
215*6a54128fSAndroid Build Coastguard Worker 				fprintf(stderr, "Couldn't create region.\n");
216*6a54128fSAndroid Build Coastguard Worker 				exit(1);
217*6a54128fSAndroid Build Coastguard Worker 			}
218*6a54128fSAndroid Build Coastguard Worker 			break;
219*6a54128fSAndroid Build Coastguard Worker 		case BCODE_ALLOCATE:
220*6a54128fSAndroid Build Coastguard Worker 			start = bcode_program[pc++];
221*6a54128fSAndroid Build Coastguard Worker 			end = bcode_program[pc++];
222*6a54128fSAndroid Build Coastguard Worker 			ret = region_allocate(r, start, end);
223*6a54128fSAndroid Build Coastguard Worker 			printf("Region_allocate(%llu, %llu) returns %d\n",
224*6a54128fSAndroid Build Coastguard Worker 			       (unsigned long long) start,
225*6a54128fSAndroid Build Coastguard Worker 			       (unsigned long long) end, ret);
226*6a54128fSAndroid Build Coastguard Worker 			break;
227*6a54128fSAndroid Build Coastguard Worker 		case BCODE_PRINT:
228*6a54128fSAndroid Build Coastguard Worker 			region_print(r, stdout);
229*6a54128fSAndroid Build Coastguard Worker 			break;
230*6a54128fSAndroid Build Coastguard Worker 		}
231*6a54128fSAndroid Build Coastguard Worker 	}
232*6a54128fSAndroid Build Coastguard Worker 	if (r)
233*6a54128fSAndroid Build Coastguard Worker 		region_free(r);
234*6a54128fSAndroid Build Coastguard Worker }
235*6a54128fSAndroid Build Coastguard Worker 
236*6a54128fSAndroid Build Coastguard Worker #endif /* TEST_PROGRAM */
237