13034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o/*
2a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o * gen_bitmap.c --- Generic (32-bit) bitmap routines
3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
43034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o * Copyright (C) 2001 Theodore Ts'o.
53034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o *
63034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o * %Begin-Header%
7543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library
8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2.
93034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o * %End-Header%
103034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o */
113034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o
123034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o
133034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o#include <stdio.h>
143034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o#include <string.h>
153034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o#if HAVE_UNISTD_H
163034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o#include <unistd.h>
173034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o#endif
183034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o#include <fcntl.h>
193034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o#include <time.h>
203034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o#if HAVE_SYS_STAT_H
213034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o#include <sys/stat.h>
223034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o#endif
233034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o#if HAVE_SYS_TYPES_H
243034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o#include <sys/types.h>
253034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o#endif
263034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o
273034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o#include "ext2_fs.h"
28e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "ext2fsP.h"
293034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o
30f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'ostruct ext2fs_struct_generic_bitmap {
31f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o	errcode_t	magic;
32f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o	ext2_filsys 	fs;
33f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o	__u32		start, end;
34f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o	__u32		real_end;
35f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o	char	*	description;
36f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o	char	*	bitmap;
37f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o	errcode_t	base_error_code;
38f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o	__u32		reserved[7];
39f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o};
40f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o
41e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define EXT2FS_IS_32_BITMAP(bmap) \
42e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	(((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP) || \
43e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 ((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP) || \
44e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 ((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP))
45e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
46e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define EXT2FS_IS_64_BITMAP(bmap) \
47e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	(((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP64) || \
48e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 ((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP64) || \
49e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 ((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP64))
50e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
51efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o/*
52a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o * Used by previously inlined function, so we have to export this and
53a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o * not change the function signature
54a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o */
55a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'ovoid ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
56a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o			    int code, unsigned long arg)
57a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o{
58a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o#ifndef OMIT_COM_ERR
59a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	if (bitmap->description)
60a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		com_err(0, bitmap->base_error_code+code,
61a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o			"#%lu for %s", arg, bitmap->description);
62a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	else
63a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		com_err(0, bitmap->base_error_code + code, "#%lu", arg);
64a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o#endif
65a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o}
66a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o
67a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'ostatic errcode_t check_magic(ext2fs_generic_bitmap bitmap)
68a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o{
69a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	if (!bitmap || !((bitmap->magic == EXT2_ET_MAGIC_GENERIC_BITMAP) ||
70a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o			 (bitmap->magic == EXT2_ET_MAGIC_INODE_BITMAP) ||
71a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o			 (bitmap->magic == EXT2_ET_MAGIC_BLOCK_BITMAP)))
72a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		return EXT2_ET_MAGIC_GENERIC_BITMAP;
73a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	return 0;
74a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o}
75a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o
76efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'oerrcode_t ext2fs_make_generic_bitmap(errcode_t magic, ext2_filsys fs,
77a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o				     __u32 start, __u32 end, __u32 real_end,
78a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o				     const char *descr, char *init_map,
79a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o				     ext2fs_generic_bitmap *ret)
80a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o{
81a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	ext2fs_generic_bitmap	bitmap;
82a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	errcode_t		retval;
83a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	size_t			size;
84a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o
85efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap),
86a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o				&bitmap);
87a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	if (retval)
88a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		return retval;
89a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o
90a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	bitmap->magic = magic;
91a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	bitmap->fs = fs;
92a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	bitmap->start = start;
93a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	bitmap->end = end;
94a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	bitmap->real_end = real_end;
95a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	switch (magic) {
96a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	case EXT2_ET_MAGIC_INODE_BITMAP:
97a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
98a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		break;
99a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	case EXT2_ET_MAGIC_BLOCK_BITMAP:
100a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
101a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		break;
102a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	default:
103a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
104a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	}
105a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	if (descr) {
106a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description);
107a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		if (retval) {
108a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o			ext2fs_free_mem(&bitmap);
109a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o			return retval;
110a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		}
111a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		strcpy(bitmap->description, descr);
112a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	} else
113a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		bitmap->description = 0;
114a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o
115a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
11651e64594919c986f87267b895504322a38ec4facTheodore Ts'o	/* Round up to allow for the BT x86 instruction */
11751e64594919c986f87267b895504322a38ec4facTheodore Ts'o	size = (size + 7) & ~3;
118a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	retval = ext2fs_get_mem(size, &bitmap->bitmap);
119a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	if (retval) {
120a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		ext2fs_free_mem(&bitmap->description);
121a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		ext2fs_free_mem(&bitmap);
122a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		return retval;
123a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	}
124a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o
125a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	if (init_map)
126a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		memcpy(bitmap->bitmap, init_map, size);
127a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	else
128a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		memset(bitmap->bitmap, 0, size);
129a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	*ret = bitmap;
130a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	return 0;
131a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o}
132a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o
133a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'oerrcode_t ext2fs_allocate_generic_bitmap(__u32 start,
134a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o					 __u32 end,
135a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o					 __u32 real_end,
136a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o					 const char *descr,
137a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o					 ext2fs_generic_bitmap *ret)
138a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o{
139efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	return ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_GENERIC_BITMAP, 0,
140a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o					  start, end, real_end, descr, 0, ret);
141a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o}
142a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o
143a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'oerrcode_t ext2fs_copy_generic_bitmap(ext2fs_generic_bitmap src,
144a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o				     ext2fs_generic_bitmap *dest)
145a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o{
146a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	return (ext2fs_make_generic_bitmap(src->magic, src->fs,
147efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o					   src->start, src->end,
148a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o					   src->real_end,
149a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o					   src->description, src->bitmap,
150a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o					   dest));
151a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o}
152a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o
153a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'ovoid ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap)
154a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o{
155a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	if (check_magic(bitmap))
156a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		return;
157a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o
158a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	bitmap->magic = 0;
159a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	if (bitmap->description) {
160a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		ext2fs_free_mem(&bitmap->description);
161a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		bitmap->description = 0;
162a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	}
163a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	if (bitmap->bitmap) {
164a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		ext2fs_free_mem(&bitmap->bitmap);
165a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		bitmap->bitmap = 0;
166a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	}
167a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	ext2fs_free_mem(&bitmap);
168a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o}
169a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o
170b15beaaf386a13d9fbaf716aac2df44748261af1Theodore Ts'oint ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
171b15beaaf386a13d9fbaf716aac2df44748261af1Theodore Ts'o					blk_t bitno)
172b15beaaf386a13d9fbaf716aac2df44748261af1Theodore Ts'o{
173e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (!EXT2FS_IS_32_BITMAP(bitmap)) {
174e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (EXT2FS_IS_64_BITMAP(bitmap)) {
175e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_warn_bitmap32(bitmap, __func__);
176e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			return ext2fs_test_generic_bmap(bitmap, bitno);
177e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		}
178e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef OMIT_COM_ERR
179e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
180e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			"test_bitmap(%lu)", (unsigned long) bitno);
181e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif
182e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		return 0;
183e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
184e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
185b15beaaf386a13d9fbaf716aac2df44748261af1Theodore Ts'o	if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
186b15beaaf386a13d9fbaf716aac2df44748261af1Theodore Ts'o		ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno);
187b15beaaf386a13d9fbaf716aac2df44748261af1Theodore Ts'o		return 0;
188b15beaaf386a13d9fbaf716aac2df44748261af1Theodore Ts'o	}
189b15beaaf386a13d9fbaf716aac2df44748261af1Theodore Ts'o	return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
190b15beaaf386a13d9fbaf716aac2df44748261af1Theodore Ts'o}
191b15beaaf386a13d9fbaf716aac2df44748261af1Theodore Ts'o
1923034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'oint ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
1933034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o					 __u32 bitno)
1943034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o{
195e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (!EXT2FS_IS_32_BITMAP(bitmap)) {
196e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (EXT2FS_IS_64_BITMAP(bitmap)) {
197e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_warn_bitmap32(bitmap, __func__);
198e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			return ext2fs_mark_generic_bmap(bitmap, bitno);
199e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		}
200e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef OMIT_COM_ERR
201e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
202e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			"mark_bitmap(%lu)", (unsigned long) bitno);
203e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif
204e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		return 0;
205e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
206e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
2073034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o	if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
2083034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o		ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno);
2093034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o		return 0;
2103034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o	}
2113034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o	return ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap);
2123034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o}
2133034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o
2143034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'oint ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
2153034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o					   blk_t bitno)
2163034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o{
217e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (!EXT2FS_IS_32_BITMAP(bitmap)) {
218e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (EXT2FS_IS_64_BITMAP(bitmap)) {
219e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_warn_bitmap32(bitmap, __func__);
220e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			return ext2fs_unmark_generic_bmap(bitmap, bitno);
221e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		}
222e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef OMIT_COM_ERR
223e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
224e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			"mark_bitmap(%lu)", (unsigned long) bitno);
225e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif
226e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		return 0;
227e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
228e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
2293034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o	if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
2303034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o		ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
2313034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o		return 0;
2323034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o	}
2333034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o	return ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap);
2343034f62a0f9c31e6dce8bd1237cffd3851847250Theodore Ts'o}
2358df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o
236271a375b596240866b4a2967e3b6f38ff7cecdf8Theodore Ts'o__u32 ext2fs_get_generic_bitmap_start(ext2fs_generic_bitmap bitmap)
237271a375b596240866b4a2967e3b6f38ff7cecdf8Theodore Ts'o{
238e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (!EXT2FS_IS_32_BITMAP(bitmap)) {
239e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (EXT2FS_IS_64_BITMAP(bitmap)) {
240e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_warn_bitmap32(bitmap, __func__);
241e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			return ext2fs_get_generic_bmap_start(bitmap);
242e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		}
243e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef OMIT_COM_ERR
244e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
245e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			"get_bitmap_start");
246e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif
247e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		return 0;
248e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
250271a375b596240866b4a2967e3b6f38ff7cecdf8Theodore Ts'o	return bitmap->start;
251271a375b596240866b4a2967e3b6f38ff7cecdf8Theodore Ts'o}
252271a375b596240866b4a2967e3b6f38ff7cecdf8Theodore Ts'o
253271a375b596240866b4a2967e3b6f38ff7cecdf8Theodore Ts'o__u32 ext2fs_get_generic_bitmap_end(ext2fs_generic_bitmap bitmap)
254271a375b596240866b4a2967e3b6f38ff7cecdf8Theodore Ts'o{
255e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (!EXT2FS_IS_32_BITMAP(bitmap)) {
256e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (EXT2FS_IS_64_BITMAP(bitmap)) {
257e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_warn_bitmap32(bitmap, __func__);
258e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			return ext2fs_get_generic_bmap_end(bitmap);
259e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		}
260e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef OMIT_COM_ERR
261e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
262e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			"get_bitmap_end");
263e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif
264e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		return 0;
265e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
266271a375b596240866b4a2967e3b6f38ff7cecdf8Theodore Ts'o	return bitmap->end;
267271a375b596240866b4a2967e3b6f38ff7cecdf8Theodore Ts'o}
268271a375b596240866b4a2967e3b6f38ff7cecdf8Theodore Ts'o
269a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'ovoid ext2fs_clear_generic_bitmap(ext2fs_generic_bitmap bitmap)
270a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o{
271e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (!EXT2FS_IS_32_BITMAP(bitmap)) {
272e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (EXT2FS_IS_64_BITMAP(bitmap)) {
273e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_warn_bitmap32(bitmap, __func__);
274e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_clear_generic_bmap(bitmap);
275e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			return;
276e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		}
277e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef OMIT_COM_ERR
278e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
279e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			"clear_generic_bitmap");
280e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif
281a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		return;
282e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
283a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o
284a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	memset(bitmap->bitmap, 0,
285a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	       (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
286a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o}
287a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o
288a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'oerrcode_t ext2fs_fudge_generic_bitmap_end(ext2fs_inode_bitmap bitmap,
289a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o					  errcode_t magic, errcode_t neq,
290a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o					  ext2_ino_t end, ext2_ino_t *oend)
291a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o{
292a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	EXT2_CHECK_MAGIC(bitmap, magic);
293efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
294a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	if (end > bitmap->real_end)
295a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		return neq;
296a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	if (oend)
297a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		*oend = bitmap->end;
298a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	bitmap->end = end;
299a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	return 0;
300a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o}
301a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o
30250448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'oerrcode_t ext2fs_resize_generic_bitmap(errcode_t magic,
30350448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o				       __u32 new_end, __u32 new_real_end,
30450448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o				       ext2fs_generic_bitmap bmap)
30550448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o{
30650448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	errcode_t	retval;
30750448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	size_t		size, new_size;
30850448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	__u32		bitno;
30950448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o
31050448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	if (!bmap || (bmap->magic != magic))
31150448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o		return magic;
31250448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o
31350448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	/*
31450448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	 * If we're expanding the bitmap, make sure all of the new
31550448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	 * parts of the bitmap are zero.
31650448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	 */
31750448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	if (new_end > bmap->end) {
31850448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o		bitno = bmap->real_end;
31950448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o		if (bitno > new_end)
32050448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o			bitno = new_end;
32150448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o		for (; bitno > bmap->end; bitno--)
32250448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o			ext2fs_clear_bit(bitno - bmap->start, bmap->bitmap);
32350448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	}
32450448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	if (new_real_end == bmap->real_end) {
32550448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o		bmap->end = new_end;
32650448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o		return 0;
32750448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	}
328efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
32950448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	size = ((bmap->real_end - bmap->start) / 8) + 1;
33050448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	new_size = ((new_real_end - bmap->start) / 8) + 1;
33150448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o
33250448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	if (size != new_size) {
33350448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o		retval = ext2fs_resize_mem(size, new_size, &bmap->bitmap);
33450448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o		if (retval)
33550448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o			return retval;
33650448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	}
33750448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	if (new_size > size)
33850448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o		memset(bmap->bitmap + size, 0, new_size - size);
33950448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o
34050448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	bmap->end = new_end;
34150448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	bmap->real_end = new_real_end;
34250448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	return 0;
34350448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o}
34450448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o
34550448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'oerrcode_t ext2fs_compare_generic_bitmap(errcode_t magic, errcode_t neq,
34650448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o					ext2fs_generic_bitmap bm1,
34750448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o					ext2fs_generic_bitmap bm2)
34850448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o{
34950448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	blk_t	i;
350efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
35150448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	if (!bm1 || bm1->magic != magic)
35250448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o		return magic;
35350448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	if (!bm2 || bm2->magic != magic)
35450448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o		return magic;
35550448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o
35650448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	if ((bm1->start != bm2->start) ||
35750448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	    (bm1->end != bm2->end) ||
35850448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	    (memcmp(bm1->bitmap, bm2->bitmap,
35950448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o		    (size_t) (bm1->end - bm1->start)/8)))
36050448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o		return neq;
36150448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o
36250448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
36350448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o		if (ext2fs_fast_test_block_bitmap(bm1, i) !=
36450448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o		    ext2fs_fast_test_block_bitmap(bm2, i))
36550448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o			return neq;
36650448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o
36750448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o	return 0;
36850448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o}
36950448d3dffc66f86592ee0d4b16e4bbe9d08449eTheodore Ts'o
370a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'ovoid ext2fs_set_generic_bitmap_padding(ext2fs_generic_bitmap map)
371a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o{
372a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	__u32	i, j;
373a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o
374a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	/* Protect loop from wrap-around if map->real_end is maxed */
375efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	for (i=map->end+1, j = i - map->start;
376efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	     i <= map->real_end && i > map->end;
377a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o	     i++, j++)
378a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o		ext2fs_set_bit(j, map->bitmap);
379f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o}
380f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o
381f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'oerrcode_t ext2fs_get_generic_bitmap_range(ext2fs_generic_bitmap bmap,
382f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o					  errcode_t magic,
383f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o					  __u32 start, __u32 num,
384f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o					  void *out)
385f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o{
386f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o	if (!bmap || (bmap->magic != magic))
387f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o		return magic;
388f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o
389f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o	if ((start < bmap->start) || (start+num-1 > bmap->real_end))
390f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o		return EXT2_ET_INVALID_ARGUMENT;
391f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o
392f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o	memcpy(out, bmap->bitmap + (start >> 3), (num+7) >> 3);
393f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o	return 0;
394f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o}
395f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o
396f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'oerrcode_t ext2fs_set_generic_bitmap_range(ext2fs_generic_bitmap bmap,
397f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o					  errcode_t magic,
398f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o					  __u32 start, __u32 num,
399f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o					  void *in)
400f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o{
401f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o	if (!bmap || (bmap->magic != magic))
402f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o		return magic;
403f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o
404f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o	if ((start < bmap->start) || (start+num-1 > bmap->real_end))
405f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o		return EXT2_ET_INVALID_ARGUMENT;
406f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o
407f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o	memcpy(bmap->bitmap + (start >> 3), in, (num+7) >> 3);
408f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o	return 0;
409f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o}
410a0553c9d6e8dd6f538f18ae447c45e52f3c40eb6Theodore Ts'o
411ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o/*
412ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o * Compare @mem to zero buffer by 256 bytes.
413ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o * Return 1 if @mem is zeroed memory, otherwise return 0.
414ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o */
415e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallint ext2fs_mem_is_zero(const char *mem, size_t len)
416ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o{
417ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	static const char zero_buf[256];
418ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o
419ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	while (len >= sizeof(zero_buf)) {
420ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		if (memcmp(mem, zero_buf, sizeof(zero_buf)))
421ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o			return 0;
422ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		len -= sizeof(zero_buf);
423ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		mem += sizeof(zero_buf);
424ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	}
425ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	/* Deal with leftover bytes. */
426ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	if (len)
427ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		return !memcmp(mem, zero_buf, len);
428ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	return 1;
429ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o}
430ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o
431ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o/*
432ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o * Return true if all of the bits in a specified range are clear
433ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o */
434ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'ostatic int ext2fs_test_clear_generic_bitmap_range(ext2fs_generic_bitmap bitmap,
435ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o						  unsigned int start,
436ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o						  unsigned int len)
437ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o{
438ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	size_t start_byte, len_byte = len >> 3;
43925c7e0c3042cb92a71d25cb3c2709a55b9f120a6Theodore Ts'o	unsigned int start_bit, len_bit = len % 8;
440ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	int first_bit = 0;
441ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	int last_bit  = 0;
442ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	int mark_count = 0;
443ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	int mark_bit = 0;
444ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	int i;
445ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	const char *ADDR = bitmap->bitmap;
446ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o
447ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	start -= bitmap->start;
448ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	start_byte = start >> 3;
449ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	start_bit = start % 8;
450ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o
451ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	if (start_bit != 0) {
452ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		/*
453ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		 * The compared start block number or start inode number
454ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		 * is not the first bit in a byte.
455ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		 */
456ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		mark_count = 8 - start_bit;
457ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		if (len < 8 - start_bit) {
458ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o			mark_count = (int)len;
459ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o			mark_bit = len + start_bit - 1;
460ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		} else
461ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o			mark_bit = 7;
462ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o
463ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		for (i = mark_count; i > 0; i--, mark_bit--)
464ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o			first_bit |= 1 << mark_bit;
465ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o
466ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		/*
467ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		 * Compare blocks or inodes in the first byte.
468ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		 * If there is any marked bit, this function returns 0.
469ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		 */
470ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		if (first_bit & ADDR[start_byte])
471ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o			return 0;
472ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		else if (len <= 8 - start_bit)
473ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o			return 1;
474ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o
475ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		start_byte++;
476ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		len_bit = (len - mark_count) % 8;
477ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		len_byte = (len - mark_count) >> 3;
478ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	}
479ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o
480ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	/*
481ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	 * The compared start block number or start inode number is
482ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	 * the first bit in a byte.
483ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	 */
484ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	if (len_bit != 0) {
485ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		/*
486ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		 * The compared end block number or end inode number is
487ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		 * not the last bit in a byte.
488ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		 */
489ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		for (mark_bit = len_bit - 1; mark_bit >= 0; mark_bit--)
490ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o			last_bit |= 1 << mark_bit;
491ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o
492ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		/*
493ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		 * Compare blocks or inodes in the last byte.
494ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		 * If there is any marked bit, this function returns 0.
495ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		 */
496ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		if (last_bit & ADDR[start_byte + len_byte])
497ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o			return 0;
498ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		else if (len_byte == 0)
499ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o			return 1;
500ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	}
501ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o
502ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	/* Check whether all bytes are 0 */
503e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return ext2fs_mem_is_zero(ADDR + start_byte, len_byte);
504ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o}
505ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o
506e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_find_first_zero_generic_bitmap(ext2fs_generic_bitmap bitmap,
507e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall						__u32 start, __u32 end,
508e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall						__u32 *out)
509e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
510e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk_t b;
511e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
512e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (start < bitmap->start || end > bitmap->end || start > end) {
513e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
514e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		return EINVAL;
515e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
516e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
517e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	while (start <= end) {
518e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		b = ext2fs_test_bit(start - bitmap->start, bitmap->bitmap);
519e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (!b) {
520e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			*out = start;
521e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			return 0;
522e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		}
523e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		start++;
524e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
525e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
526e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return ENOENT;
527e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
528e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
529e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
5308df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'oint ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
5318df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o				   blk_t block, int num)
5328df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o{
533ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
534f1f115a78f5ea599fc5f8815a741d43fedd5840dTheodore Ts'o	if ((block < bitmap->start) || (block+num-1 > bitmap->real_end)) {
5358df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
5368df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o				   block, bitmap->description);
5378df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o		return 0;
5388df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o	}
539ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	return ext2fs_test_clear_generic_bitmap_range((ext2fs_generic_bitmap)
540ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o						      bitmap, block, num);
541ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o}
542ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o
543ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'oint ext2fs_test_inode_bitmap_range(ext2fs_inode_bitmap bitmap,
544ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o				   ino_t inode, int num)
545ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o{
546ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_INODE_BITMAP);
547ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	if ((inode < bitmap->start) || (inode+num-1 > bitmap->real_end)) {
548ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_TEST,
549ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o				   inode, bitmap->description);
550ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o		return 0;
5518df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o	}
552ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o	return ext2fs_test_clear_generic_bitmap_range((ext2fs_generic_bitmap)
553ef1a526dfbe663bb80ab75c2e7985ae8d9021b76Theodore Ts'o						      bitmap, inode, num);
5548df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o}
5558df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o
5568df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'ovoid ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
5578df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o				    blk_t block, int num)
5588df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o{
5598df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o	int	i;
560efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
5618df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o	if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
5628df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
5638df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o				   bitmap->description);
5648df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o		return;
5658df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o	}
5668df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o	for (i=0; i < num; i++)
5678df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o		ext2fs_fast_set_bit(block + i - bitmap->start, bitmap->bitmap);
5688df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o}
5698df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o
5708df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'ovoid ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
5718df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o					       blk_t block, int num)
5728df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o{
5738df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o	int	i;
574efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
5758df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o	if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
5768df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
5778df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o				   bitmap->description);
5788df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o		return;
5798df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o	}
5808df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o	for (i=0; i < num; i++)
581efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		ext2fs_fast_clear_bit(block + i - bitmap->start,
5828df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o				      bitmap->bitmap);
5838df1827b55f11321bfe508c89b94591bdb97c3a6Theodore Ts'o}
584e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
585