closefs.c revision 4cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3
1/* 2 * closefs.c --- close an ext2 filesystem 3 * 4 * Copyright (C) 1993, 1994, 1995, 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#if HAVE_UNISTD_H 14#include <unistd.h> 15#endif 16#include <stdlib.h> 17#include <time.h> 18#include <string.h> 19#ifdef HAVE_ERRNO_H 20#include <errno.h> 21#endif 22 23#include <linux/ext2_fs.h> 24 25#include "ext2fsP.h" 26 27static int test_root(int a, int b) 28{ 29 if (a == 0) 30 return 1; 31 while (1) { 32 if (a == 1) 33 return 1; 34 if (a % b) 35 return 0; 36 a = a / b; 37 } 38} 39 40int ext2fs_bg_has_super(ext2_filsys fs, int group_block) 41{ 42#ifdef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 43 struct ext2fs_sb *s; 44 45 s = (struct ext2fs_sb *) fs->super; 46 if (!(s->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) 47 return 1; 48 49 if (test_root(group_block, 3) || (test_root(group_block, 5)) || 50 test_root(group_block, 7)) 51 return 1; 52 53 return 0; 54#else 55 return 1; 56#endif 57} 58 59errcode_t ext2fs_flush(ext2_filsys fs) 60{ 61 int i,j,maxgroup; 62 int group_block; 63 errcode_t retval; 64 char *group_ptr; 65 unsigned long fs_state; 66 struct ext2_super_block *super_shadow = 0; 67 struct ext2_group_desc *group_shadow = 0; 68 struct ext2_group_desc *s, *t; 69 70 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 71 72 fs_state = fs->super->s_state; 73 74 fs->super->s_wtime = time(NULL); 75 if (fs->flags & EXT2_FLAG_SWAP_BYTES) { 76 retval = ENOMEM; 77 if (!(super_shadow = malloc(SUPERBLOCK_SIZE))) 78 goto errout; 79 if (!(group_shadow = malloc(fs->blocksize*fs->desc_blocks))) 80 goto errout; 81 memset(group_shadow, 0, fs->blocksize*fs->desc_blocks); 82 83 /* swap the superblock */ 84 *super_shadow = *fs->super; 85 ext2fs_swap_super(super_shadow); 86 87 /* swap the group descriptors */ 88 for (j=0, s=fs->group_desc, t=group_shadow; 89 j < fs->group_desc_count; j++, t++, s++) { 90 *t = *s; 91 ext2fs_swap_group_desc(t); 92 } 93 } else { 94 super_shadow = fs->super; 95 group_shadow = fs->group_desc; 96 } 97 98 /* 99 * Write out master superblock. This has to be done 100 * separately, since it is located at a fixed location 101 * (SUPERBLOCK_OFFSET). 102 */ 103 io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET); 104 retval = io_channel_write_blk(fs->io, 1, -SUPERBLOCK_SIZE, 105 super_shadow); 106 if (retval) 107 goto errout; 108 io_channel_set_blksize(fs->io, fs->blocksize); 109 110 /* 111 * Set the state of the FS to be non-valid. (The state has 112 * already been backed up earlier, and will be restored when 113 * we exit.) 114 */ 115 fs->super->s_state &= ~EXT2_VALID_FS; 116 if (fs->flags & EXT2_FLAG_SWAP_BYTES) { 117 *super_shadow = *fs->super; 118 ext2fs_swap_super(super_shadow); 119 } 120 121 /* 122 * Write out the master group descriptors, and the backup 123 * superblocks and group descriptors. 124 */ 125 group_block = fs->super->s_first_data_block; 126 maxgroup = (fs->flags & EXT2_FLAG_MASTER_SB_ONLY) ? 1 : 127 fs->group_desc_count; 128 for (i = 0; i < maxgroup; i++) { 129 if (!ext2fs_bg_has_super(fs, i)) 130 goto next_group; 131 132 if (i !=0 ) { 133 retval = io_channel_write_blk(fs->io, group_block, 134 -SUPERBLOCK_SIZE, 135 super_shadow); 136 if (retval) 137 goto errout; 138 } 139 group_ptr = (char *) group_shadow; 140 for (j=0; j < fs->desc_blocks; j++) { 141 retval = io_channel_write_blk(fs->io, 142 group_block+1+j, 1, 143 group_ptr); 144 if (retval) 145 goto errout; 146 group_ptr += fs->blocksize; 147 } 148 next_group: 149 group_block += EXT2_BLOCKS_PER_GROUP(fs->super); 150 } 151 152 /* 153 * If the write_bitmaps() function is present, call it to 154 * flush the bitmaps. This is done this way so that a simple 155 * program that doesn't mess with the bitmaps doesn't need to 156 * drag in the bitmaps.c code. 157 */ 158 if (fs->write_bitmaps) { 159 retval = fs->write_bitmaps(fs); 160 if (retval) 161 goto errout; 162 } 163 retval = 0; 164errout: 165 fs->super->s_state = fs_state; 166 if (fs->flags & EXT2_FLAG_SWAP_BYTES) { 167 if (super_shadow) 168 free(super_shadow); 169 if (group_shadow) 170 free(group_shadow); 171 } 172 return retval; 173} 174 175errcode_t ext2fs_close(ext2_filsys fs) 176{ 177 errcode_t retval; 178 179 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 180 181 if (fs->flags & EXT2_FLAG_DIRTY) { 182 retval = ext2fs_flush(fs); 183 if (retval) 184 return retval; 185 } 186 if (fs->write_bitmaps) { 187 retval = fs->write_bitmaps(fs); 188 if (retval) 189 return retval; 190 } 191 ext2fs_free(fs); 192 return 0; 193} 194 195