rw_bitmaps.c revision d4f34d41be97e23db07d5ed606fcc1a26f5a3c76
1/*
2 * rw_bitmaps.c --- routines to read and write the  inode and block bitmaps.
3 *
4 * Copyright (C) 1993, 1994, 1994, 1996 Theodore Ts'o.
5 *
6 * %Begin-Header%
7 * This file may be redistributed under the terms of the GNU Public
8 * License.
9 * %End-Header%
10 */
11
12#include <stdio.h>
13#include <string.h>
14#if HAVE_UNISTD_H
15#include <unistd.h>
16#endif
17#include <fcntl.h>
18#include <time.h>
19#ifdef HAVE_SYS_STAT_H
20#include <sys/stat.h>
21#endif
22#ifdef HAVE_SYS_TYPES_H
23#include <sys/types.h>
24#endif
25
26#include "ext2_fs.h"
27#include "ext2fs.h"
28#include "e2image.h"
29
30static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
31{
32	dgrp_t 		i;
33	unsigned int	j;
34	int		block_nbytes, inode_nbytes;
35	unsigned int	nbits;
36	errcode_t	retval;
37	char 		*block_buf, *inode_buf;
38	int		lazy_flag = 0;
39	blk_t		blk;
40	blk_t		blk_itr = fs->super->s_first_data_block;
41	ext2_ino_t	ino_itr = 1;
42
43	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
44
45	if (!(fs->flags & EXT2_FLAG_RW))
46		return EXT2_ET_RO_FILSYS;
47	if (EXT2_HAS_COMPAT_FEATURE(fs->super,
48				    EXT2_FEATURE_COMPAT_LAZY_BG))
49		lazy_flag = 1;
50	inode_nbytes = block_nbytes = 0;
51	if (do_block) {
52		block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
53		retval = ext2fs_get_mem(fs->blocksize, &block_buf);
54		if (retval)
55			return retval;
56		memset(block_buf, 0xff, fs->blocksize);
57	}
58	if (do_inode) {
59		inode_nbytes = (size_t)
60			((EXT2_INODES_PER_GROUP(fs->super)+7) / 8);
61		retval = ext2fs_get_mem(fs->blocksize, &inode_buf);
62		if (retval)
63			return retval;
64		memset(inode_buf, 0xff, fs->blocksize);
65	}
66
67	for (i = 0; i < fs->group_desc_count; i++) {
68		if (!do_block)
69			goto skip_block_bitmap;
70
71		if (lazy_flag && fs->group_desc[i].bg_flags &
72		    EXT2_BG_BLOCK_UNINIT)
73			goto skip_this_block_bitmap;
74
75		retval = ext2fs_get_block_bitmap_range(fs->block_map,
76				blk_itr, block_nbytes << 3, block_buf);
77		if (retval)
78			return retval;
79
80		if (i == fs->group_desc_count - 1) {
81			/* Force bitmap padding for the last group */
82			nbits = ((fs->super->s_blocks_count
83				  - fs->super->s_first_data_block)
84				 % EXT2_BLOCKS_PER_GROUP(fs->super));
85			if (nbits)
86				for (j = nbits; j < fs->blocksize * 8; j++)
87					ext2fs_set_bit(j, block_buf);
88		}
89		blk = fs->group_desc[i].bg_block_bitmap;
90		if (blk) {
91			retval = io_channel_write_blk(fs->io, blk, 1,
92						      block_buf);
93			if (retval)
94				return EXT2_ET_BLOCK_BITMAP_WRITE;
95		}
96	skip_this_block_bitmap:
97		blk_itr += block_nbytes << 3;
98	skip_block_bitmap:
99
100		if (!do_inode)
101			continue;
102
103		if (lazy_flag && fs->group_desc[i].bg_flags &
104		    EXT2_BG_INODE_UNINIT)
105			goto skip_this_inode_bitmap;
106
107		retval = ext2fs_get_inode_bitmap_range(fs->inode_map,
108				ino_itr, inode_nbytes << 3, inode_buf);
109		if (retval)
110			return retval;
111
112		blk = fs->group_desc[i].bg_inode_bitmap;
113		if (blk) {
114			retval = io_channel_write_blk(fs->io, blk, 1,
115						      inode_buf);
116			if (retval)
117				return EXT2_ET_INODE_BITMAP_WRITE;
118		}
119	skip_this_inode_bitmap:
120		ino_itr += inode_nbytes << 3;
121
122	}
123	if (do_block) {
124		fs->flags &= ~EXT2_FLAG_BB_DIRTY;
125		ext2fs_free_mem(&block_buf);
126	}
127	if (do_inode) {
128		fs->flags &= ~EXT2_FLAG_IB_DIRTY;
129		ext2fs_free_mem(&inode_buf);
130	}
131	return 0;
132}
133
134static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
135{
136	dgrp_t i;
137	char *block_bitmap = 0, *inode_bitmap = 0;
138	char *buf;
139	errcode_t retval;
140	unsigned int block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
141	unsigned inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
142	int lazy_flag = 0;
143	int do_image = fs->flags & EXT2_FLAG_IMAGE_FILE;
144	unsigned int	cnt;
145	blk_t	blk;
146	blk_t	blk_itr = fs->super->s_first_data_block;
147	blk_t   blk_cnt;
148	ext2_ino_t ino_itr = 1;
149	ext2_ino_t ino_cnt;
150
151	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
152
153	fs->write_bitmaps = ext2fs_write_bitmaps;
154
155	if (EXT2_HAS_COMPAT_FEATURE(fs->super,
156				    EXT2_FEATURE_COMPAT_LAZY_BG) ||
157	    EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
158				       EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
159		lazy_flag = 1;
160
161	retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
162	if (retval)
163		return retval;
164	if (do_block) {
165		if (fs->block_map)
166			ext2fs_free_block_bitmap(fs->block_map);
167		sprintf(buf, "block bitmap for %s", fs->device_name);
168		retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
169		if (retval)
170			goto cleanup;
171		retval = ext2fs_get_mem(do_image ? fs->blocksize :
172					block_nbytes, &block_bitmap);
173		if (retval)
174			goto cleanup;
175	} else
176		block_nbytes = 0;
177	if (do_inode) {
178		if (fs->inode_map)
179			ext2fs_free_inode_bitmap(fs->inode_map);
180		sprintf(buf, "inode bitmap for %s", fs->device_name);
181		retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
182		if (retval)
183			goto cleanup;
184		retval = ext2fs_get_mem(do_image ? fs->blocksize :
185					inode_nbytes, &inode_bitmap);
186		if (retval)
187			goto cleanup;
188	} else
189		inode_nbytes = 0;
190	ext2fs_free_mem(&buf);
191
192	if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
193		blk = (fs->image_header->offset_inodemap / fs->blocksize);
194		ino_cnt = fs->super->s_inodes_count;
195		while (inode_nbytes > 0) {
196			retval = io_channel_read_blk(fs->image_io, blk++,
197						     1, inode_bitmap);
198			if (retval)
199				goto cleanup;
200			cnt = fs->blocksize << 3;
201			if (cnt > ino_cnt)
202				cnt = ino_cnt;
203			retval = ext2fs_set_inode_bitmap_range(fs->inode_map,
204					       ino_itr, cnt, inode_bitmap);
205			if (retval)
206				goto cleanup;
207			ino_itr += fs->blocksize << 3;
208			ino_cnt -= fs->blocksize << 3;
209			inode_nbytes -= fs->blocksize;
210		}
211		blk = (fs->image_header->offset_blockmap /
212		       fs->blocksize);
213		blk_cnt = EXT2_BLOCKS_PER_GROUP(fs->super) *
214			fs->group_desc_count;
215		while (block_nbytes > 0) {
216			retval = io_channel_read_blk(fs->image_io, blk++,
217						     1, block_bitmap);
218			if (retval)
219				goto cleanup;
220			cnt = fs->blocksize << 3;
221			if (cnt > blk_cnt)
222				cnt = blk_cnt;
223			retval = ext2fs_set_block_bitmap_range(fs->block_map,
224				       blk_itr, cnt, block_bitmap);
225			if (retval)
226				goto cleanup;
227			blk_itr += fs->blocksize << 3;
228			blk_cnt -= fs->blocksize << 3;
229			block_nbytes -= fs->blocksize;
230		}
231		goto success_cleanup;
232	}
233
234	for (i = 0; i < fs->group_desc_count; i++) {
235		if (block_bitmap) {
236			blk = fs->group_desc[i].bg_block_bitmap;
237			if (lazy_flag && fs->group_desc[i].bg_flags &
238			    EXT2_BG_BLOCK_UNINIT &&
239			    ext2fs_group_desc_csum_verify(fs, i))
240				blk = 0;
241			if (blk) {
242				retval = io_channel_read_blk(fs->io, blk,
243					     -block_nbytes, block_bitmap);
244				if (retval) {
245					retval = EXT2_ET_BLOCK_BITMAP_READ;
246					goto cleanup;
247				}
248			} else
249				memset(block_bitmap, 0xff, block_nbytes);
250			cnt = block_nbytes << 3;
251			retval = ext2fs_set_block_bitmap_range(fs->block_map,
252					       blk_itr, cnt, block_bitmap);
253			if (retval)
254				goto cleanup;
255			blk_itr += block_nbytes << 3;
256		}
257		if (inode_bitmap) {
258			blk = fs->group_desc[i].bg_inode_bitmap;
259			if (lazy_flag && fs->group_desc[i].bg_flags &
260			    EXT2_BG_INODE_UNINIT &&
261			    ext2fs_group_desc_csum_verify(fs, i))
262				blk = 0;
263			if (blk) {
264				retval = io_channel_read_blk(fs->io, blk,
265					     -inode_nbytes, inode_bitmap);
266				if (retval) {
267					retval = EXT2_ET_INODE_BITMAP_READ;
268					goto cleanup;
269				}
270			} else
271				memset(inode_bitmap, 0xff, inode_nbytes);
272			cnt = inode_nbytes << 3;
273			retval = ext2fs_set_inode_bitmap_range(fs->inode_map,
274					       ino_itr, cnt, inode_bitmap);
275			if (retval)
276				goto cleanup;
277			ino_itr += inode_nbytes << 3;
278		}
279	}
280success_cleanup:
281	if (inode_bitmap)
282		ext2fs_free_mem(&inode_bitmap);
283	if (block_bitmap)
284		ext2fs_free_mem(&block_bitmap);
285	return 0;
286
287cleanup:
288	if (do_block) {
289		ext2fs_free_mem(&fs->block_map);
290		fs->block_map = 0;
291	}
292	if (do_inode) {
293		ext2fs_free_mem(&fs->inode_map);
294		fs->inode_map = 0;
295	}
296	if (inode_bitmap)
297		ext2fs_free_mem(&inode_bitmap);
298	if (block_bitmap)
299		ext2fs_free_mem(&block_bitmap);
300	if (buf)
301		ext2fs_free_mem(&buf);
302	return retval;
303}
304
305errcode_t ext2fs_read_inode_bitmap(ext2_filsys fs)
306{
307	return read_bitmaps(fs, 1, 0);
308}
309
310errcode_t ext2fs_read_block_bitmap(ext2_filsys fs)
311{
312	return read_bitmaps(fs, 0, 1);
313}
314
315errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs)
316{
317	return write_bitmaps(fs, 1, 0);
318}
319
320errcode_t ext2fs_write_block_bitmap (ext2_filsys fs)
321{
322	return write_bitmaps(fs, 0, 1);
323}
324
325errcode_t ext2fs_read_bitmaps(ext2_filsys fs)
326{
327	if (fs->inode_map && fs->block_map)
328		return 0;
329
330	return read_bitmaps(fs, !fs->inode_map, !fs->block_map);
331}
332
333errcode_t ext2fs_write_bitmaps(ext2_filsys fs)
334{
335	int do_inode = fs->inode_map && ext2fs_test_ib_dirty(fs);
336	int do_block = fs->block_map && ext2fs_test_bb_dirty(fs);
337
338	if (!do_inode && !do_block)
339		return 0;
340
341	return write_bitmaps(fs, do_inode, do_block);
342}
343