1/*
2 * sparse.c --- find the groups in an ext2 filesystem with metadata backups
3 *
4 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
5 * Copyright (C) 2002 Andreas Dilger.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Library
9 * General Public License, version 2.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14
15#include "ext2_fs.h"
16#include "ext2fsP.h"
17
18static int test_root(int a, int b)
19{
20	if (a == 0)
21		return 1;
22	while (1) {
23		if (a == 1)
24			return 1;
25		if (a % b)
26			return 0;
27		a = a / b;
28	}
29}
30
31int ext2fs_bg_has_super(ext2_filsys fs, int group_block)
32{
33	if (!(fs->super->s_feature_ro_compat &
34	      EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
35		return 1;
36
37	if (test_root(group_block, 3) || (test_root(group_block, 5)) ||
38	    test_root(group_block, 7))
39		return 1;
40
41	return 0;
42}
43
44/*
45 * Iterate through the groups which hold BACKUP superblock/GDT copies in an
46 * ext3 filesystem.  The counters should be initialized to 1, 5, and 7 before
47 * calling this for the first time.  In a sparse filesystem it will be the
48 * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ...
49 * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ...
50 */
51unsigned int ext2fs_list_backups(ext2_filsys fs, unsigned int *three,
52				 unsigned int *five, unsigned int *seven)
53{
54	unsigned int *min = three;
55	int mult = 3;
56	unsigned int ret;
57
58	if (!(fs->super->s_feature_ro_compat &
59	      EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
60		ret = *min;
61		*min += 1;
62		return ret;
63	}
64
65	if (*five < *min) {
66		min = five;
67		mult = 5;
68	}
69	if (*seven < *min) {
70		min = seven;
71		mult = 7;
72	}
73
74	ret = *min;
75	*min *= mult;
76
77	return ret;
78}
79