• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 Library
8  * General Public License, version 2.
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 
write_bitmaps(ext2_filsys fs,int do_inode,int do_block)30 static 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		csum_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 
48 	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
49 				       EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
50 		csum_flag = 1;
51 
52 	inode_nbytes = block_nbytes = 0;
53 	if (do_block) {
54 		block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
55 		retval = ext2fs_get_memalign(fs->blocksize, fs->blocksize,
56 					     &block_buf);
57 		if (retval)
58 			return retval;
59 		memset(block_buf, 0xff, fs->blocksize);
60 	}
61 	if (do_inode) {
62 		inode_nbytes = (size_t)
63 			((EXT2_INODES_PER_GROUP(fs->super)+7) / 8);
64 		retval = ext2fs_get_memalign(fs->blocksize, fs->blocksize,
65 					     &inode_buf);
66 		if (retval)
67 			return retval;
68 		memset(inode_buf, 0xff, fs->blocksize);
69 	}
70 
71 	for (i = 0; i < fs->group_desc_count; i++) {
72 		if (!do_block)
73 			goto skip_block_bitmap;
74 
75 		if (csum_flag && fs->group_desc[i].bg_flags &
76 		    EXT2_BG_BLOCK_UNINIT)
77 			goto skip_this_block_bitmap;
78 
79 		retval = ext2fs_get_block_bitmap_range(fs->block_map,
80 				blk_itr, block_nbytes << 3, block_buf);
81 		if (retval)
82 			return retval;
83 
84 		if (i == fs->group_desc_count - 1) {
85 			/* Force bitmap padding for the last group */
86 			nbits = ((fs->super->s_blocks_count
87 				  - fs->super->s_first_data_block)
88 				 % EXT2_BLOCKS_PER_GROUP(fs->super));
89 			if (nbits)
90 				for (j = nbits; j < fs->blocksize * 8; j++)
91 					ext2fs_set_bit(j, block_buf);
92 		}
93 		blk = fs->group_desc[i].bg_block_bitmap;
94 		if (blk) {
95 			retval = io_channel_write_blk(fs->io, blk, 1,
96 						      block_buf);
97 			if (retval)
98 				return EXT2_ET_BLOCK_BITMAP_WRITE;
99 		}
100 	skip_this_block_bitmap:
101 		blk_itr += block_nbytes << 3;
102 	skip_block_bitmap:
103 
104 		if (!do_inode)
105 			continue;
106 
107 		if (csum_flag && fs->group_desc[i].bg_flags &
108 		    EXT2_BG_INODE_UNINIT)
109 			goto skip_this_inode_bitmap;
110 
111 		retval = ext2fs_get_inode_bitmap_range(fs->inode_map,
112 				ino_itr, inode_nbytes << 3, inode_buf);
113 		if (retval)
114 			return retval;
115 
116 		blk = fs->group_desc[i].bg_inode_bitmap;
117 		if (blk) {
118 			retval = io_channel_write_blk(fs->io, blk, 1,
119 						      inode_buf);
120 			if (retval)
121 				return EXT2_ET_INODE_BITMAP_WRITE;
122 		}
123 	skip_this_inode_bitmap:
124 		ino_itr += inode_nbytes << 3;
125 
126 	}
127 	if (do_block) {
128 		fs->flags &= ~EXT2_FLAG_BB_DIRTY;
129 		ext2fs_free_mem(&block_buf);
130 	}
131 	if (do_inode) {
132 		fs->flags &= ~EXT2_FLAG_IB_DIRTY;
133 		ext2fs_free_mem(&inode_buf);
134 	}
135 	return 0;
136 }
137 
read_bitmaps(ext2_filsys fs,int do_inode,int do_block)138 static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
139 {
140 	dgrp_t i;
141 	char *block_bitmap = 0, *inode_bitmap = 0;
142 	char *buf;
143 	errcode_t retval;
144 	int block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
145 	int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
146 	int csum_flag = 0;
147 	int do_image = fs->flags & EXT2_FLAG_IMAGE_FILE;
148 	unsigned int	cnt;
149 	blk_t	blk;
150 	blk_t	blk_itr = fs->super->s_first_data_block;
151 	blk_t   blk_cnt;
152 	ext2_ino_t ino_itr = 1;
153 	ext2_ino_t ino_cnt;
154 
155 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
156 
157 	fs->write_bitmaps = ext2fs_write_bitmaps;
158 
159 	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
160 				       EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
161 		csum_flag = 1;
162 
163 	retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
164 	if (retval)
165 		return retval;
166 	if (do_block) {
167 		if (fs->block_map)
168 			ext2fs_free_block_bitmap(fs->block_map);
169 		strcpy(buf, "block bitmap for ");
170 		strcat(buf, fs->device_name);
171 		retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
172 		if (retval)
173 			goto cleanup;
174 		if (do_image)
175 			retval = ext2fs_get_mem(fs->blocksize, &block_bitmap);
176 		else
177 			retval = ext2fs_get_memalign((unsigned) block_nbytes,
178 						     fs->blocksize,
179 						     &block_bitmap);
180 
181 		if (retval)
182 			goto cleanup;
183 	} else
184 		block_nbytes = 0;
185 	if (do_inode) {
186 		if (fs->inode_map)
187 			ext2fs_free_inode_bitmap(fs->inode_map);
188 		strcpy(buf, "inode bitmap for ");
189 		strcat(buf, fs->device_name);
190 		retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
191 		if (retval)
192 			goto cleanup;
193 		retval = ext2fs_get_mem(do_image ? fs->blocksize :
194 					(unsigned) inode_nbytes, &inode_bitmap);
195 		if (retval)
196 			goto cleanup;
197 	} else
198 		inode_nbytes = 0;
199 	ext2fs_free_mem(&buf);
200 
201 	if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
202 		blk = (fs->image_header->offset_inodemap / fs->blocksize);
203 		ino_cnt = fs->super->s_inodes_count;
204 		while (inode_nbytes > 0) {
205 			retval = io_channel_read_blk(fs->image_io, blk++,
206 						     1, inode_bitmap);
207 			if (retval)
208 				goto cleanup;
209 			cnt = fs->blocksize << 3;
210 			if (cnt > ino_cnt)
211 				cnt = ino_cnt;
212 			retval = ext2fs_set_inode_bitmap_range(fs->inode_map,
213 					       ino_itr, cnt, inode_bitmap);
214 			if (retval)
215 				goto cleanup;
216 			ino_itr += fs->blocksize << 3;
217 			ino_cnt -= fs->blocksize << 3;
218 			inode_nbytes -= fs->blocksize;
219 		}
220 		blk = (fs->image_header->offset_blockmap /
221 		       fs->blocksize);
222 		blk_cnt = EXT2_BLOCKS_PER_GROUP(fs->super) *
223 			fs->group_desc_count;
224 		while (block_nbytes > 0) {
225 			retval = io_channel_read_blk(fs->image_io, blk++,
226 						     1, block_bitmap);
227 			if (retval)
228 				goto cleanup;
229 			cnt = fs->blocksize << 3;
230 			if (cnt > blk_cnt)
231 				cnt = blk_cnt;
232 			retval = ext2fs_set_block_bitmap_range(fs->block_map,
233 				       blk_itr, cnt, block_bitmap);
234 			if (retval)
235 				goto cleanup;
236 			blk_itr += fs->blocksize << 3;
237 			blk_cnt -= fs->blocksize << 3;
238 			block_nbytes -= fs->blocksize;
239 		}
240 		goto success_cleanup;
241 	}
242 
243 	for (i = 0; i < fs->group_desc_count; i++) {
244 		if (block_bitmap) {
245 			blk = fs->group_desc[i].bg_block_bitmap;
246 			if (csum_flag && fs->group_desc[i].bg_flags &
247 			    EXT2_BG_BLOCK_UNINIT &&
248 			    ext2fs_group_desc_csum_verify(fs, i))
249 				blk = 0;
250 			if (blk) {
251 				retval = io_channel_read_blk(fs->io, blk,
252 					     -block_nbytes, block_bitmap);
253 				if (retval) {
254 					retval = EXT2_ET_BLOCK_BITMAP_READ;
255 					goto cleanup;
256 				}
257 			} else
258 				memset(block_bitmap, 0, block_nbytes);
259 			cnt = block_nbytes << 3;
260 			retval = ext2fs_set_block_bitmap_range(fs->block_map,
261 					       blk_itr, cnt, block_bitmap);
262 			if (retval)
263 				goto cleanup;
264 			blk_itr += block_nbytes << 3;
265 		}
266 		if (inode_bitmap) {
267 			blk = fs->group_desc[i].bg_inode_bitmap;
268 			if (csum_flag && fs->group_desc[i].bg_flags &
269 			    EXT2_BG_INODE_UNINIT &&
270 			    ext2fs_group_desc_csum_verify(fs, i))
271 				blk = 0;
272 			if (blk) {
273 				retval = io_channel_read_blk(fs->io, blk,
274 					     -inode_nbytes, inode_bitmap);
275 				if (retval) {
276 					retval = EXT2_ET_INODE_BITMAP_READ;
277 					goto cleanup;
278 				}
279 			} else
280 				memset(inode_bitmap, 0, inode_nbytes);
281 			cnt = inode_nbytes << 3;
282 			retval = ext2fs_set_inode_bitmap_range(fs->inode_map,
283 					       ino_itr, cnt, inode_bitmap);
284 			if (retval)
285 				goto cleanup;
286 			ino_itr += inode_nbytes << 3;
287 		}
288 	}
289 success_cleanup:
290 	if (inode_bitmap)
291 		ext2fs_free_mem(&inode_bitmap);
292 	if (block_bitmap)
293 		ext2fs_free_mem(&block_bitmap);
294 	return 0;
295 
296 cleanup:
297 	if (do_block) {
298 		ext2fs_free_mem(&fs->block_map);
299 		fs->block_map = 0;
300 	}
301 	if (do_inode) {
302 		ext2fs_free_mem(&fs->inode_map);
303 		fs->inode_map = 0;
304 	}
305 	if (inode_bitmap)
306 		ext2fs_free_mem(&inode_bitmap);
307 	if (block_bitmap)
308 		ext2fs_free_mem(&block_bitmap);
309 	if (buf)
310 		ext2fs_free_mem(&buf);
311 	return retval;
312 }
313 
ext2fs_read_inode_bitmap(ext2_filsys fs)314 errcode_t ext2fs_read_inode_bitmap(ext2_filsys fs)
315 {
316 	return read_bitmaps(fs, 1, 0);
317 }
318 
ext2fs_read_block_bitmap(ext2_filsys fs)319 errcode_t ext2fs_read_block_bitmap(ext2_filsys fs)
320 {
321 	return read_bitmaps(fs, 0, 1);
322 }
323 
ext2fs_write_inode_bitmap(ext2_filsys fs)324 errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs)
325 {
326 	return write_bitmaps(fs, 1, 0);
327 }
328 
ext2fs_write_block_bitmap(ext2_filsys fs)329 errcode_t ext2fs_write_block_bitmap (ext2_filsys fs)
330 {
331 	return write_bitmaps(fs, 0, 1);
332 }
333 
ext2fs_read_bitmaps(ext2_filsys fs)334 errcode_t ext2fs_read_bitmaps(ext2_filsys fs)
335 {
336 	if (fs->inode_map && fs->block_map)
337 		return 0;
338 
339 	return read_bitmaps(fs, !fs->inode_map, !fs->block_map);
340 }
341 
ext2fs_write_bitmaps(ext2_filsys fs)342 errcode_t ext2fs_write_bitmaps(ext2_filsys fs)
343 {
344 	int do_inode = fs->inode_map && ext2fs_test_ib_dirty(fs);
345 	int do_block = fs->block_map && ext2fs_test_bb_dirty(fs);
346 
347 	if (!do_inode && !do_block)
348 		return 0;
349 
350 	return write_bitmaps(fs, do_inode, do_block);
351 }
352