diff options
Diffstat (limited to 'e2fsprogs/ext2fs/closefs.c')
-rw-r--r-- | e2fsprogs/ext2fs/closefs.c | 381 |
1 files changed, 0 insertions, 381 deletions
diff --git a/e2fsprogs/ext2fs/closefs.c b/e2fsprogs/ext2fs/closefs.c deleted file mode 100644 index 008d5f36e..000000000 --- a/e2fsprogs/ext2fs/closefs.c +++ /dev/null | |||
@@ -1,381 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * closefs.c --- close an ext2 filesystem | ||
4 | * | ||
5 | * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. | ||
6 | * | ||
7 | * %Begin-Header% | ||
8 | * This file may be redistributed under the terms of the GNU Public | ||
9 | * License. | ||
10 | * %End-Header% | ||
11 | */ | ||
12 | |||
13 | #include <stdio.h> | ||
14 | #if HAVE_UNISTD_H | ||
15 | #include <unistd.h> | ||
16 | #endif | ||
17 | #include <time.h> | ||
18 | #include <string.h> | ||
19 | |||
20 | #include "ext2_fs.h" | ||
21 | #include "ext2fsP.h" | ||
22 | |||
23 | static int test_root(int a, int b) | ||
24 | { | ||
25 | if (a == 0) | ||
26 | return 1; | ||
27 | while (1) { | ||
28 | if (a == 1) | ||
29 | return 1; | ||
30 | if (a % b) | ||
31 | return 0; | ||
32 | a = a / b; | ||
33 | } | ||
34 | } | ||
35 | |||
36 | int ext2fs_bg_has_super(ext2_filsys fs, int group_block) | ||
37 | { | ||
38 | if (!(fs->super->s_feature_ro_compat & | ||
39 | EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) | ||
40 | return 1; | ||
41 | |||
42 | if (test_root(group_block, 3) || (test_root(group_block, 5)) || | ||
43 | test_root(group_block, 7)) | ||
44 | return 1; | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | int ext2fs_super_and_bgd_loc(ext2_filsys fs, | ||
50 | dgrp_t group, | ||
51 | blk_t *ret_super_blk, | ||
52 | blk_t *ret_old_desc_blk, | ||
53 | blk_t *ret_new_desc_blk, | ||
54 | int *ret_meta_bg) | ||
55 | { | ||
56 | blk_t group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0; | ||
57 | unsigned int meta_bg, meta_bg_size; | ||
58 | int numblocks, has_super; | ||
59 | int old_desc_blocks; | ||
60 | |||
61 | group_block = fs->super->s_first_data_block + | ||
62 | (group * fs->super->s_blocks_per_group); | ||
63 | |||
64 | if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) | ||
65 | old_desc_blocks = fs->super->s_first_meta_bg; | ||
66 | else | ||
67 | old_desc_blocks = | ||
68 | fs->desc_blocks + fs->super->s_reserved_gdt_blocks; | ||
69 | |||
70 | if (group == fs->group_desc_count-1) { | ||
71 | numblocks = (fs->super->s_blocks_count - | ||
72 | fs->super->s_first_data_block) % | ||
73 | fs->super->s_blocks_per_group; | ||
74 | if (!numblocks) | ||
75 | numblocks = fs->super->s_blocks_per_group; | ||
76 | } else | ||
77 | numblocks = fs->super->s_blocks_per_group; | ||
78 | |||
79 | has_super = ext2fs_bg_has_super(fs, group); | ||
80 | |||
81 | if (has_super) { | ||
82 | super_blk = group_block; | ||
83 | numblocks--; | ||
84 | } | ||
85 | meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc)); | ||
86 | meta_bg = group / meta_bg_size; | ||
87 | |||
88 | if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) || | ||
89 | (meta_bg < fs->super->s_first_meta_bg)) { | ||
90 | if (has_super) { | ||
91 | old_desc_blk = group_block + 1; | ||
92 | numblocks -= old_desc_blocks; | ||
93 | } | ||
94 | } else { | ||
95 | if (((group % meta_bg_size) == 0) || | ||
96 | ((group % meta_bg_size) == 1) || | ||
97 | ((group % meta_bg_size) == (meta_bg_size-1))) { | ||
98 | if (has_super) | ||
99 | has_super = 1; | ||
100 | new_desc_blk = group_block + has_super; | ||
101 | numblocks--; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | numblocks -= 2 + fs->inode_blocks_per_group; | ||
106 | |||
107 | if (ret_super_blk) | ||
108 | *ret_super_blk = super_blk; | ||
109 | if (ret_old_desc_blk) | ||
110 | *ret_old_desc_blk = old_desc_blk; | ||
111 | if (ret_new_desc_blk) | ||
112 | *ret_new_desc_blk = new_desc_blk; | ||
113 | if (ret_meta_bg) | ||
114 | *ret_meta_bg = meta_bg; | ||
115 | return numblocks; | ||
116 | } | ||
117 | |||
118 | |||
119 | /* | ||
120 | * This function forces out the primary superblock. We need to only | ||
121 | * write out those fields which we have changed, since if the | ||
122 | * filesystem is mounted, it may have changed some of the other | ||
123 | * fields. | ||
124 | * | ||
125 | * It takes as input a superblock which has already been byte swapped | ||
126 | * (if necessary). | ||
127 | * | ||
128 | */ | ||
129 | static errcode_t write_primary_superblock(ext2_filsys fs, | ||
130 | struct ext2_super_block *super) | ||
131 | { | ||
132 | __u16 *old_super, *new_super; | ||
133 | int check_idx, write_idx, size; | ||
134 | errcode_t retval; | ||
135 | |||
136 | if (!fs->io->manager->write_byte || !fs->orig_super) { | ||
137 | io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET); | ||
138 | retval = io_channel_write_blk(fs->io, 1, -SUPERBLOCK_SIZE, | ||
139 | super); | ||
140 | io_channel_set_blksize(fs->io, fs->blocksize); | ||
141 | return retval; | ||
142 | } | ||
143 | |||
144 | old_super = (__u16 *) fs->orig_super; | ||
145 | new_super = (__u16 *) super; | ||
146 | |||
147 | for (check_idx = 0; check_idx < SUPERBLOCK_SIZE/2; check_idx++) { | ||
148 | if (old_super[check_idx] == new_super[check_idx]) | ||
149 | continue; | ||
150 | write_idx = check_idx; | ||
151 | for (check_idx++; check_idx < SUPERBLOCK_SIZE/2; check_idx++) | ||
152 | if (old_super[check_idx] == new_super[check_idx]) | ||
153 | break; | ||
154 | size = 2 * (check_idx - write_idx); | ||
155 | retval = io_channel_write_byte(fs->io, | ||
156 | SUPERBLOCK_OFFSET + (2 * write_idx), size, | ||
157 | new_super + write_idx); | ||
158 | if (retval) | ||
159 | return retval; | ||
160 | } | ||
161 | memcpy(fs->orig_super, super, SUPERBLOCK_SIZE); | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | |||
166 | /* | ||
167 | * Updates the revision to EXT2_DYNAMIC_REV | ||
168 | */ | ||
169 | void ext2fs_update_dynamic_rev(ext2_filsys fs) | ||
170 | { | ||
171 | struct ext2_super_block *sb = fs->super; | ||
172 | |||
173 | if (sb->s_rev_level > EXT2_GOOD_OLD_REV) | ||
174 | return; | ||
175 | |||
176 | sb->s_rev_level = EXT2_DYNAMIC_REV; | ||
177 | sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO; | ||
178 | sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE; | ||
179 | /* s_uuid is handled by e2fsck already */ | ||
180 | /* other fields should be left alone */ | ||
181 | } | ||
182 | |||
183 | static errcode_t write_backup_super(ext2_filsys fs, dgrp_t group, | ||
184 | blk_t group_block, | ||
185 | struct ext2_super_block *super_shadow) | ||
186 | { | ||
187 | dgrp_t sgrp = group; | ||
188 | |||
189 | if (sgrp > ((1 << 16) - 1)) | ||
190 | sgrp = (1 << 16) - 1; | ||
191 | #if BB_BIG_ENDIAN | ||
192 | if (fs->flags & EXT2_FLAG_SWAP_BYTES) | ||
193 | super_shadow->s_block_group_nr = ext2fs_swab16(sgrp); | ||
194 | else | ||
195 | #endif | ||
196 | fs->super->s_block_group_nr = sgrp; | ||
197 | |||
198 | return io_channel_write_blk(fs->io, group_block, -SUPERBLOCK_SIZE, | ||
199 | super_shadow); | ||
200 | } | ||
201 | |||
202 | |||
203 | errcode_t ext2fs_flush(ext2_filsys fs) | ||
204 | { | ||
205 | dgrp_t i; | ||
206 | blk_t group_block; | ||
207 | errcode_t retval; | ||
208 | unsigned long fs_state; | ||
209 | struct ext2_super_block *super_shadow = 0; | ||
210 | struct ext2_group_desc *group_shadow = 0; | ||
211 | char *group_ptr; | ||
212 | int old_desc_blocks; | ||
213 | #if BB_BIG_ENDIAN | ||
214 | dgrp_t j; | ||
215 | struct ext2_group_desc *s, *t; | ||
216 | #endif | ||
217 | |||
218 | EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | ||
219 | |||
220 | fs_state = fs->super->s_state; | ||
221 | |||
222 | fs->super->s_wtime = time(NULL); | ||
223 | fs->super->s_block_group_nr = 0; | ||
224 | #if BB_BIG_ENDIAN | ||
225 | if (fs->flags & EXT2_FLAG_SWAP_BYTES) { | ||
226 | retval = EXT2_ET_NO_MEMORY; | ||
227 | retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow); | ||
228 | if (retval) | ||
229 | goto errout; | ||
230 | retval = ext2fs_get_mem((size_t)(fs->blocksize * | ||
231 | fs->desc_blocks), | ||
232 | &group_shadow); | ||
233 | if (retval) | ||
234 | goto errout; | ||
235 | memset(group_shadow, 0, (size_t) fs->blocksize * | ||
236 | fs->desc_blocks); | ||
237 | |||
238 | /* swap the group descriptors */ | ||
239 | for (j=0, s=fs->group_desc, t=group_shadow; | ||
240 | j < fs->group_desc_count; j++, t++, s++) { | ||
241 | *t = *s; | ||
242 | ext2fs_swap_group_desc(t); | ||
243 | } | ||
244 | } else { | ||
245 | super_shadow = fs->super; | ||
246 | group_shadow = fs->group_desc; | ||
247 | } | ||
248 | #else | ||
249 | super_shadow = fs->super; | ||
250 | group_shadow = fs->group_desc; | ||
251 | #endif | ||
252 | |||
253 | /* | ||
254 | * If this is an external journal device, don't write out the | ||
255 | * block group descriptors or any of the backup superblocks | ||
256 | */ | ||
257 | if (fs->super->s_feature_incompat & | ||
258 | EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) | ||
259 | goto write_primary_superblock_only; | ||
260 | |||
261 | /* | ||
262 | * Set the state of the FS to be non-valid. (The state has | ||
263 | * already been backed up earlier, and will be restored after | ||
264 | * we write out the backup superblocks.) | ||
265 | */ | ||
266 | fs->super->s_state &= ~EXT2_VALID_FS; | ||
267 | #if BB_BIG_ENDIAN | ||
268 | if (fs->flags & EXT2_FLAG_SWAP_BYTES) { | ||
269 | *super_shadow = *fs->super; | ||
270 | ext2fs_swap_super(super_shadow); | ||
271 | } | ||
272 | #endif | ||
273 | |||
274 | /* | ||
275 | * Write out the master group descriptors, and the backup | ||
276 | * superblocks and group descriptors. | ||
277 | */ | ||
278 | group_block = fs->super->s_first_data_block; | ||
279 | group_ptr = (char *) group_shadow; | ||
280 | if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) | ||
281 | old_desc_blocks = fs->super->s_first_meta_bg; | ||
282 | else | ||
283 | old_desc_blocks = fs->desc_blocks; | ||
284 | |||
285 | for (i = 0; i < fs->group_desc_count; i++) { | ||
286 | blk_t super_blk, old_desc_blk, new_desc_blk; | ||
287 | int meta_bg; | ||
288 | |||
289 | ext2fs_super_and_bgd_loc(fs, i, &super_blk, &old_desc_blk, | ||
290 | &new_desc_blk, &meta_bg); | ||
291 | |||
292 | if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) { | ||
293 | retval = write_backup_super(fs, i, super_blk, | ||
294 | super_shadow); | ||
295 | if (retval) | ||
296 | goto errout; | ||
297 | } | ||
298 | if (fs->flags & EXT2_FLAG_SUPER_ONLY) | ||
299 | continue; | ||
300 | if ((old_desc_blk) && | ||
301 | (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) { | ||
302 | retval = io_channel_write_blk(fs->io, | ||
303 | old_desc_blk, old_desc_blocks, group_ptr); | ||
304 | if (retval) | ||
305 | goto errout; | ||
306 | } | ||
307 | if (new_desc_blk) { | ||
308 | retval = io_channel_write_blk(fs->io, new_desc_blk, | ||
309 | 1, group_ptr + (meta_bg*fs->blocksize)); | ||
310 | if (retval) | ||
311 | goto errout; | ||
312 | } | ||
313 | } | ||
314 | fs->super->s_block_group_nr = 0; | ||
315 | fs->super->s_state = fs_state; | ||
316 | #if BB_BIG_ENDIAN | ||
317 | if (fs->flags & EXT2_FLAG_SWAP_BYTES) { | ||
318 | *super_shadow = *fs->super; | ||
319 | ext2fs_swap_super(super_shadow); | ||
320 | } | ||
321 | #endif | ||
322 | |||
323 | /* | ||
324 | * If the write_bitmaps() function is present, call it to | ||
325 | * flush the bitmaps. This is done this way so that a simple | ||
326 | * program that doesn't mess with the bitmaps doesn't need to | ||
327 | * drag in the bitmaps.c code. | ||
328 | */ | ||
329 | if (fs->write_bitmaps) { | ||
330 | retval = fs->write_bitmaps(fs); | ||
331 | if (retval) | ||
332 | goto errout; | ||
333 | } | ||
334 | |||
335 | write_primary_superblock_only: | ||
336 | /* | ||
337 | * Write out master superblock. This has to be done | ||
338 | * separately, since it is located at a fixed location | ||
339 | * (SUPERBLOCK_OFFSET). We flush all other pending changes | ||
340 | * out to disk first, just to avoid a race condition with an | ||
341 | * insy-tinsy window.... | ||
342 | */ | ||
343 | retval = io_channel_flush(fs->io); | ||
344 | retval = write_primary_superblock(fs, super_shadow); | ||
345 | if (retval) | ||
346 | goto errout; | ||
347 | |||
348 | fs->flags &= ~EXT2_FLAG_DIRTY; | ||
349 | |||
350 | retval = io_channel_flush(fs->io); | ||
351 | errout: | ||
352 | fs->super->s_state = fs_state; | ||
353 | if (fs->flags & EXT2_FLAG_SWAP_BYTES) { | ||
354 | if (super_shadow) | ||
355 | ext2fs_free_mem(&super_shadow); | ||
356 | if (group_shadow) | ||
357 | ext2fs_free_mem(&group_shadow); | ||
358 | } | ||
359 | return retval; | ||
360 | } | ||
361 | |||
362 | errcode_t ext2fs_close(ext2_filsys fs) | ||
363 | { | ||
364 | errcode_t retval; | ||
365 | |||
366 | EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | ||
367 | |||
368 | if (fs->flags & EXT2_FLAG_DIRTY) { | ||
369 | retval = ext2fs_flush(fs); | ||
370 | if (retval) | ||
371 | return retval; | ||
372 | } | ||
373 | if (fs->write_bitmaps) { | ||
374 | retval = fs->write_bitmaps(fs); | ||
375 | if (retval) | ||
376 | return retval; | ||
377 | } | ||
378 | ext2fs_free(fs); | ||
379 | return 0; | ||
380 | } | ||
381 | |||