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