xref: /aosp_15_r20/external/e2fsprogs/contrib/android/block_range.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
1 #define _GNU_SOURCE
2 
3 #include "block_range.h"
4 #include <stdio.h>
5 
new_block_range(blk64_t start,blk64_t end)6 struct block_range *new_block_range(blk64_t start, blk64_t end)
7 {
8 	struct block_range *range = malloc(sizeof(*range));
9 	range->start = start;
10 	range->end = end;
11 	range->next = NULL;
12 	return range;
13 }
14 
add_blocks_to_range(struct block_range_list * list,blk64_t blk_start,blk64_t blk_end)15 void add_blocks_to_range(struct block_range_list *list, blk64_t blk_start,
16 			 blk64_t blk_end)
17 {
18 	if (list->head == NULL)
19 		list->head = list->tail = new_block_range(blk_start, blk_end);
20 	else if (list->tail->end + 1 == blk_start)
21 		list->tail->end += (blk_end - blk_start + 1);
22 	else {
23 		struct block_range *range = new_block_range(blk_start, blk_end);
24 		list->tail->next = range;
25 		list->tail = range;
26 	}
27 }
28 
remove_head(struct block_range_list * list)29 static void remove_head(struct block_range_list *list)
30 {
31 	struct block_range *next_range = list->head->next;
32 
33 	free(list->head);
34 	if (next_range == NULL)
35 		list->head = list->tail = NULL;
36 	else
37 		list->head = next_range;
38 }
39 
delete_block_ranges(struct block_range_list * list)40 void delete_block_ranges(struct block_range_list *list)
41 {
42 	while (list->head)
43 		remove_head(list);
44 }
45 
write_block_ranges(FILE * f,struct block_range * range,char * sep)46 int write_block_ranges(FILE *f, struct block_range *range,
47 				     char *sep)
48 {
49 	int len;
50 	char *buf;
51 
52 	while (range) {
53 		if (range->start == range->end)
54 			len = asprintf(&buf, "%llu%s", range->start, sep);
55 		else
56 			len = asprintf(&buf, "%llu-%llu%s", range->start,
57 				       range->end, sep);
58 		if (fwrite(buf, 1, len, f) != (size_t)len) {
59 			free(buf);
60 			return -1;
61 		}
62 		free(buf);
63 		range = range->next;
64 	}
65 
66 	len = strlen(sep);
67 	if (fseek(f, -len, SEEK_CUR) == -len)
68 		return -1;
69 	return 0;
70 }
71 
consume_next_block(struct block_range_list * list)72 blk64_t consume_next_block(struct block_range_list *list)
73 {
74 	blk64_t ret = list->head->start;
75 
76 	list->head->start += 1;
77 	if (list->head->start > list->head->end)
78 		remove_head(list);
79 	return ret;
80 }
81