]>
Commit | Line | Data |
---|---|---|
f3db3566 TT |
1 | /* |
2 | * rw_bitmaps.c --- routines to read and write the inode and block bitmaps. | |
3 | * | |
19c78dc0 TT |
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% | |
f3db3566 TT |
10 | */ |
11 | ||
12 | #include <stdio.h> | |
13 | #include <string.h> | |
4cbe8af4 | 14 | #if HAVE_UNISTD_H |
f3db3566 | 15 | #include <unistd.h> |
4cbe8af4 | 16 | #endif |
f3db3566 TT |
17 | #include <fcntl.h> |
18 | #include <time.h> | |
519ee043 | 19 | #ifdef HAVE_SYS_STAT_H |
f3db3566 | 20 | #include <sys/stat.h> |
519ee043 TT |
21 | #endif |
22 | #ifdef HAVE_SYS_TYPES_H | |
f3db3566 | 23 | #include <sys/types.h> |
519ee043 | 24 | #endif |
f3db3566 | 25 | |
b5abe6fa | 26 | #include "ext2_fs.h" |
f3db3566 | 27 | #include "ext2fs.h" |
a78926ef | 28 | #include "e2image.h" |
f3db3566 | 29 | |
1f2da2c0 | 30 | static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block) |
f3db3566 | 31 | { |
2eb374c9 | 32 | dgrp_t i; |
54434927 | 33 | unsigned int j; |
1f2da2c0 | 34 | int block_nbytes, inode_nbytes; |
54434927 | 35 | unsigned int nbits; |
f3db3566 | 36 | errcode_t retval; |
1f2da2c0 | 37 | char *block_buf, *inode_buf; |
16b851cd | 38 | int csum_flag = 0; |
19c78dc0 | 39 | blk_t blk; |
8f82ef98 | 40 | blk64_t blk_itr = fs->super->s_first_data_block; |
f1f115a7 | 41 | ext2_ino_t ino_itr = 1; |
f3db3566 TT |
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; | |
16b851cd TT |
47 | |
48 | if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, | |
49 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) | |
50 | csum_flag = 1; | |
51 | ||
1f2da2c0 | 52 | inode_nbytes = block_nbytes = 0; |
1f2da2c0 | 53 | if (do_block) { |
1f2da2c0 TT |
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) { | |
efc6f628 | 61 | inode_nbytes = (size_t) |
1f2da2c0 TT |
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 | ||
f3db3566 | 69 | for (i = 0; i < fs->group_desc_count; i++) { |
f1f115a7 | 70 | if (!do_block) |
1f2da2c0 | 71 | goto skip_block_bitmap; |
f5fa2007 | 72 | |
732c8cd5 TT |
73 | if (csum_flag && ext2fs_bg_flag_test(fs, i, EXT2_BG_BLOCK_UNINIT) |
74 | ) | |
f5fa2007 | 75 | goto skip_this_block_bitmap; |
efc6f628 | 76 | |
8f82ef98 | 77 | retval = ext2fs_get_block_bitmap_range2(fs->block_map, |
f1f115a7 TT |
78 | blk_itr, block_nbytes << 3, block_buf); |
79 | if (retval) | |
80 | return retval; | |
81 | ||
f3db3566 TT |
82 | if (i == fs->group_desc_count - 1) { |
83 | /* Force bitmap padding for the last group */ | |
4efbac6f VAH |
84 | nbits = ((ext2fs_blocks_count(fs->super) |
85 | - (__u64) fs->super->s_first_data_block) | |
86 | % (__u64) EXT2_BLOCKS_PER_GROUP(fs->super)); | |
f3db3566 TT |
87 | if (nbits) |
88 | for (j = nbits; j < fs->blocksize * 8; j++) | |
1f2da2c0 | 89 | ext2fs_set_bit(j, block_buf); |
f3db3566 | 90 | } |
19c78dc0 TT |
91 | blk = fs->group_desc[i].bg_block_bitmap; |
92 | if (blk) { | |
24a117ab VAH |
93 | retval = io_channel_write_blk64(fs->io, blk, 1, |
94 | block_buf); | |
19c78dc0 TT |
95 | if (retval) |
96 | return EXT2_ET_BLOCK_BITMAP_WRITE; | |
97 | } | |
f5fa2007 | 98 | skip_this_block_bitmap: |
f1f115a7 | 99 | blk_itr += block_nbytes << 3; |
1f2da2c0 TT |
100 | skip_block_bitmap: |
101 | ||
f1f115a7 | 102 | if (!do_inode) |
1f2da2c0 TT |
103 | continue; |
104 | ||
732c8cd5 TT |
105 | if (csum_flag && ext2fs_bg_flag_test(fs, i, EXT2_BG_INODE_UNINIT) |
106 | ) | |
f5fa2007 | 107 | goto skip_this_inode_bitmap; |
efc6f628 | 108 | |
8f82ef98 | 109 | retval = ext2fs_get_inode_bitmap_range2(fs->inode_map, |
f1f115a7 TT |
110 | ino_itr, inode_nbytes << 3, inode_buf); |
111 | if (retval) | |
112 | return retval; | |
113 | ||
1f2da2c0 TT |
114 | blk = fs->group_desc[i].bg_inode_bitmap; |
115 | if (blk) { | |
24a117ab | 116 | retval = io_channel_write_blk64(fs->io, blk, 1, |
1f2da2c0 TT |
117 | inode_buf); |
118 | if (retval) | |
119 | return EXT2_ET_INODE_BITMAP_WRITE; | |
120 | } | |
f5fa2007 | 121 | skip_this_inode_bitmap: |
f1f115a7 | 122 | ino_itr += inode_nbytes << 3; |
1f2da2c0 TT |
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); | |
f3db3566 | 132 | } |
f3db3566 TT |
133 | return 0; |
134 | } | |
135 | ||
136 | static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) | |
137 | { | |
2eb374c9 | 138 | dgrp_t i; |
50e1e10f | 139 | char *block_bitmap = 0, *inode_bitmap = 0; |
f3db3566 TT |
140 | char *buf; |
141 | errcode_t retval; | |
57fd39e9 TT |
142 | int block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; |
143 | int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; | |
16b851cd | 144 | int csum_flag = 0; |
f1f115a7 TT |
145 | int do_image = fs->flags & EXT2_FLAG_IMAGE_FILE; |
146 | unsigned int cnt; | |
19c78dc0 | 147 | blk_t blk; |
8f82ef98 | 148 | blk64_t blk_itr = fs->super->s_first_data_block; |
f1f115a7 TT |
149 | blk_t blk_cnt; |
150 | ext2_ino_t ino_itr = 1; | |
151 | ext2_ino_t ino_cnt; | |
f3db3566 TT |
152 | |
153 | EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | |
154 | ||
155 | fs->write_bitmaps = ext2fs_write_bitmaps; | |
156 | ||
16b851cd | 157 | if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, |
d4f34d41 | 158 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) |
16b851cd | 159 | csum_flag = 1; |
f5fa2007 | 160 | |
c4e3d3f3 | 161 | retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf); |
7b4e4534 TT |
162 | if (retval) |
163 | return retval; | |
f3db3566 TT |
164 | if (do_block) { |
165 | if (fs->block_map) | |
166 | ext2fs_free_block_bitmap(fs->block_map); | |
2d40a91e TT |
167 | strcpy(buf, "block bitmap for "); |
168 | strcat(buf, fs->device_name); | |
f3db3566 TT |
169 | retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map); |
170 | if (retval) | |
171 | goto cleanup; | |
efc6f628 | 172 | retval = ext2fs_get_mem(do_image ? fs->blocksize : |
57fd39e9 | 173 | (unsigned) block_nbytes, &block_bitmap); |
f1f115a7 TT |
174 | if (retval) |
175 | goto cleanup; | |
176 | } else | |
177 | block_nbytes = 0; | |
f3db3566 TT |
178 | if (do_inode) { |
179 | if (fs->inode_map) | |
180 | ext2fs_free_inode_bitmap(fs->inode_map); | |
2d40a91e TT |
181 | strcpy(buf, "inode bitmap for "); |
182 | strcat(buf, fs->device_name); | |
f3db3566 TT |
183 | retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map); |
184 | if (retval) | |
185 | goto cleanup; | |
efc6f628 | 186 | retval = ext2fs_get_mem(do_image ? fs->blocksize : |
57fd39e9 | 187 | (unsigned) inode_nbytes, &inode_bitmap); |
f1f115a7 TT |
188 | if (retval) |
189 | goto cleanup; | |
190 | } else | |
191 | inode_nbytes = 0; | |
c4e3d3f3 | 192 | ext2fs_free_mem(&buf); |
f3db3566 | 193 | |
a78926ef | 194 | if (fs->flags & EXT2_FLAG_IMAGE_FILE) { |
f1f115a7 TT |
195 | blk = (fs->image_header->offset_inodemap / fs->blocksize); |
196 | ino_cnt = fs->super->s_inodes_count; | |
197 | while (inode_nbytes > 0) { | |
24a117ab | 198 | retval = io_channel_read_blk64(fs->image_io, blk++, |
f1f115a7 TT |
199 | 1, inode_bitmap); |
200 | if (retval) | |
201 | goto cleanup; | |
202 | cnt = fs->blocksize << 3; | |
203 | if (cnt > ino_cnt) | |
204 | cnt = ino_cnt; | |
8f82ef98 | 205 | retval = ext2fs_set_inode_bitmap_range2(fs->inode_map, |
f1f115a7 | 206 | ino_itr, cnt, inode_bitmap); |
a78926ef TT |
207 | if (retval) |
208 | goto cleanup; | |
f1f115a7 TT |
209 | ino_itr += fs->blocksize << 3; |
210 | ino_cnt -= fs->blocksize << 3; | |
211 | inode_nbytes -= fs->blocksize; | |
a78926ef | 212 | } |
f1f115a7 TT |
213 | blk = (fs->image_header->offset_blockmap / |
214 | fs->blocksize); | |
c5b7b6ba | 215 | blk_cnt = (blk64_t)EXT2_BLOCKS_PER_GROUP(fs->super) * |
f1f115a7 TT |
216 | fs->group_desc_count; |
217 | while (block_nbytes > 0) { | |
24a117ab | 218 | retval = io_channel_read_blk64(fs->image_io, blk++, |
f1f115a7 TT |
219 | 1, block_bitmap); |
220 | if (retval) | |
221 | goto cleanup; | |
222 | cnt = fs->blocksize << 3; | |
223 | if (cnt > blk_cnt) | |
224 | cnt = blk_cnt; | |
8f82ef98 | 225 | retval = ext2fs_set_block_bitmap_range2(fs->block_map, |
f1f115a7 | 226 | blk_itr, cnt, block_bitmap); |
a78926ef TT |
227 | if (retval) |
228 | goto cleanup; | |
f1f115a7 TT |
229 | blk_itr += fs->blocksize << 3; |
230 | blk_cnt -= fs->blocksize << 3; | |
231 | block_nbytes -= fs->blocksize; | |
a78926ef | 232 | } |
f1f115a7 | 233 | goto success_cleanup; |
a78926ef TT |
234 | } |
235 | ||
f3db3566 | 236 | for (i = 0; i < fs->group_desc_count; i++) { |
50e1e10f | 237 | if (block_bitmap) { |
19c78dc0 | 238 | blk = fs->group_desc[i].bg_block_bitmap; |
732c8cd5 TT |
239 | if (csum_flag && |
240 | ext2fs_bg_flag_test(fs, i, EXT2_BG_BLOCK_UNINIT) && | |
d4f34d41 | 241 | ext2fs_group_desc_csum_verify(fs, i)) |
f5fa2007 | 242 | blk = 0; |
19c78dc0 | 243 | if (blk) { |
24a117ab | 244 | retval = io_channel_read_blk64(fs->io, blk, |
19c78dc0 TT |
245 | -block_nbytes, block_bitmap); |
246 | if (retval) { | |
247 | retval = EXT2_ET_BLOCK_BITMAP_READ; | |
248 | goto cleanup; | |
249 | } | |
250 | } else | |
f4240c8d | 251 | memset(block_bitmap, 0, block_nbytes); |
f1f115a7 | 252 | cnt = block_nbytes << 3; |
8f82ef98 | 253 | retval = ext2fs_set_block_bitmap_range2(fs->block_map, |
f1f115a7 TT |
254 | blk_itr, cnt, block_bitmap); |
255 | if (retval) | |
256 | goto cleanup; | |
257 | blk_itr += block_nbytes << 3; | |
f3db3566 | 258 | } |
50e1e10f | 259 | if (inode_bitmap) { |
19c78dc0 | 260 | blk = fs->group_desc[i].bg_inode_bitmap; |
732c8cd5 TT |
261 | if (csum_flag && |
262 | ext2fs_bg_flag_test(fs, i, EXT2_BG_INODE_UNINIT) && | |
d4f34d41 | 263 | ext2fs_group_desc_csum_verify(fs, i)) |
f5fa2007 | 264 | blk = 0; |
19c78dc0 | 265 | if (blk) { |
24a117ab | 266 | retval = io_channel_read_blk64(fs->io, blk, |
19c78dc0 TT |
267 | -inode_nbytes, inode_bitmap); |
268 | if (retval) { | |
269 | retval = EXT2_ET_INODE_BITMAP_READ; | |
270 | goto cleanup; | |
271 | } | |
272 | } else | |
f4240c8d | 273 | memset(inode_bitmap, 0, inode_nbytes); |
f1f115a7 | 274 | cnt = inode_nbytes << 3; |
8f82ef98 | 275 | retval = ext2fs_set_inode_bitmap_range2(fs->inode_map, |
f1f115a7 TT |
276 | ino_itr, cnt, inode_bitmap); |
277 | if (retval) | |
278 | goto cleanup; | |
279 | ino_itr += inode_nbytes << 3; | |
f3db3566 TT |
280 | } |
281 | } | |
f1f115a7 TT |
282 | success_cleanup: |
283 | if (inode_bitmap) | |
284 | ext2fs_free_mem(&inode_bitmap); | |
285 | if (block_bitmap) | |
286 | ext2fs_free_mem(&block_bitmap); | |
f3db3566 | 287 | return 0; |
efc6f628 | 288 | |
f3db3566 TT |
289 | cleanup: |
290 | if (do_block) { | |
c4e3d3f3 | 291 | ext2fs_free_mem(&fs->block_map); |
f3db3566 TT |
292 | fs->block_map = 0; |
293 | } | |
294 | if (do_inode) { | |
c4e3d3f3 | 295 | ext2fs_free_mem(&fs->inode_map); |
f3db3566 TT |
296 | fs->inode_map = 0; |
297 | } | |
f1f115a7 TT |
298 | if (inode_bitmap) |
299 | ext2fs_free_mem(&inode_bitmap); | |
300 | if (block_bitmap) | |
301 | ext2fs_free_mem(&block_bitmap); | |
f3db3566 | 302 | if (buf) |
c4e3d3f3 | 303 | ext2fs_free_mem(&buf); |
f3db3566 TT |
304 | return retval; |
305 | } | |
306 | ||
1f2da2c0 | 307 | errcode_t ext2fs_read_inode_bitmap(ext2_filsys fs) |
f3db3566 TT |
308 | { |
309 | return read_bitmaps(fs, 1, 0); | |
310 | } | |
311 | ||
312 | errcode_t ext2fs_read_block_bitmap(ext2_filsys fs) | |
313 | { | |
314 | return read_bitmaps(fs, 0, 1); | |
315 | } | |
316 | ||
1f2da2c0 | 317 | errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs) |
f3db3566 | 318 | { |
1f2da2c0 TT |
319 | return write_bitmaps(fs, 1, 0); |
320 | } | |
f3db3566 | 321 | |
1f2da2c0 TT |
322 | errcode_t ext2fs_write_block_bitmap (ext2_filsys fs) |
323 | { | |
324 | return write_bitmaps(fs, 0, 1); | |
325 | } | |
f3db3566 | 326 | |
1f2da2c0 TT |
327 | errcode_t ext2fs_read_bitmaps(ext2_filsys fs) |
328 | { | |
9abd2ce9 TT |
329 | if (fs->inode_map && fs->block_map) |
330 | return 0; | |
331 | ||
f3db3566 TT |
332 | return read_bitmaps(fs, !fs->inode_map, !fs->block_map); |
333 | } | |
334 | ||
335 | errcode_t ext2fs_write_bitmaps(ext2_filsys fs) | |
336 | { | |
1f2da2c0 TT |
337 | int do_inode = fs->inode_map && ext2fs_test_ib_dirty(fs); |
338 | int do_block = fs->block_map && ext2fs_test_bb_dirty(fs); | |
f3db3566 | 339 | |
1f2da2c0 TT |
340 | if (!do_inode && !do_block) |
341 | return 0; | |
f3db3566 | 342 | |
1f2da2c0 TT |
343 | return write_bitmaps(fs, do_inode, do_block); |
344 | } |