rw_bitmaps.c revision 544349270e4c74a6feb971123884a8cf5052a7ee
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 30#if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS) 31/* 32 * On the PowerPC, the big-endian variant of the ext2 filesystem 33 * has its bitmaps stored as 32-bit words with bit 0 as the LSB 34 * of each word. Thus a bitmap with only bit 0 set would be, as 35 * a string of bytes, 00 00 00 01 00 ... 36 * To cope with this, we byte-reverse each word of a bitmap if 37 * we have a big-endian filesystem, that is, if we are *not* 38 * byte-swapping other word-sized numbers. 39 */ 40#define EXT2_BIG_ENDIAN_BITMAPS 41#endif 42 43#ifdef EXT2_BIG_ENDIAN_BITMAPS 44static void ext2fs_swap_bitmap(ext2_filsys fs, char *bitmap, int nbytes) 45{ 46 __u32 *p = (__u32 *) bitmap; 47 int n; 48 49 for (n = nbytes / sizeof(__u32); n > 0; --n, ++p) 50 *p = ext2fs_swab32(*p); 51} 52#endif 53 54errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs) 55{ 56 dgrp_t i; 57 size_t nbytes; 58 errcode_t retval; 59 char * inode_bitmap = fs->inode_map->bitmap; 60 char * bitmap_block = NULL; 61 blk_t blk; 62 63 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 64 65 if (!(fs->flags & EXT2_FLAG_RW)) 66 return EXT2_ET_RO_FILSYS; 67 if (!inode_bitmap) 68 return 0; 69 nbytes = (size_t) ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8); 70 71 retval = ext2fs_get_mem(fs->blocksize, &bitmap_block); 72 if (retval) 73 return retval; 74 memset(bitmap_block, 0xff, fs->blocksize); 75 for (i = 0; i < fs->group_desc_count; i++) { 76 memcpy(bitmap_block, inode_bitmap, nbytes); 77 blk = fs->group_desc[i].bg_inode_bitmap; 78 if (blk) { 79#ifdef EXT2_BIG_ENDIAN_BITMAPS 80 if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || 81 (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))) 82 ext2fs_swap_bitmap(fs, bitmap_block, nbytes); 83#endif 84 retval = io_channel_write_blk(fs->io, blk, 1, 85 bitmap_block); 86 if (retval) 87 return EXT2_ET_INODE_BITMAP_WRITE; 88 } 89 inode_bitmap += nbytes; 90 } 91 fs->flags &= ~EXT2_FLAG_IB_DIRTY; 92 ext2fs_free_mem(&bitmap_block); 93 return 0; 94} 95 96errcode_t ext2fs_write_block_bitmap (ext2_filsys fs) 97{ 98 dgrp_t i; 99 unsigned int j; 100 int nbytes; 101 unsigned int nbits; 102 errcode_t retval; 103 char * block_bitmap = fs->block_map->bitmap; 104 char * bitmap_block = NULL; 105 blk_t blk; 106 107 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 108 109 if (!(fs->flags & EXT2_FLAG_RW)) 110 return EXT2_ET_RO_FILSYS; 111 if (!block_bitmap) 112 return 0; 113 nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; 114 retval = ext2fs_get_mem(fs->blocksize, &bitmap_block); 115 if (retval) 116 return retval; 117 memset(bitmap_block, 0xff, fs->blocksize); 118 for (i = 0; i < fs->group_desc_count; i++) { 119 memcpy(bitmap_block, block_bitmap, nbytes); 120 if (i == fs->group_desc_count - 1) { 121 /* Force bitmap padding for the last group */ 122 nbits = ((fs->super->s_blocks_count 123 - fs->super->s_first_data_block) 124 % EXT2_BLOCKS_PER_GROUP(fs->super)); 125 if (nbits) 126 for (j = nbits; j < fs->blocksize * 8; j++) 127 ext2fs_set_bit(j, bitmap_block); 128 } 129 blk = fs->group_desc[i].bg_block_bitmap; 130 if (blk) { 131#ifdef EXT2_BIG_ENDIAN_BITMAPS 132 if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || 133 (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))) 134 ext2fs_swap_bitmap(fs, bitmap_block, nbytes); 135#endif 136 retval = io_channel_write_blk(fs->io, blk, 1, 137 bitmap_block); 138 if (retval) 139 return EXT2_ET_BLOCK_BITMAP_WRITE; 140 } 141 block_bitmap += nbytes; 142 } 143 fs->flags &= ~EXT2_FLAG_BB_DIRTY; 144 ext2fs_free_mem(&bitmap_block); 145 return 0; 146} 147 148static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) 149{ 150 dgrp_t i; 151 char *block_bitmap = 0, *inode_bitmap = 0; 152 char *buf; 153 errcode_t retval; 154 int block_nbytes = (int) EXT2_BLOCKS_PER_GROUP(fs->super) / 8; 155 int inode_nbytes = (int) EXT2_INODES_PER_GROUP(fs->super) / 8; 156 blk_t blk; 157 158 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 159 160 fs->write_bitmaps = ext2fs_write_bitmaps; 161 162 retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf); 163 if (retval) 164 return retval; 165 if (do_block) { 166 if (fs->block_map) 167 ext2fs_free_block_bitmap(fs->block_map); 168 sprintf(buf, "block bitmap for %s", fs->device_name); 169 retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map); 170 if (retval) 171 goto cleanup; 172 block_bitmap = fs->block_map->bitmap; 173 } 174 if (do_inode) { 175 if (fs->inode_map) 176 ext2fs_free_inode_bitmap(fs->inode_map); 177 sprintf(buf, "inode bitmap for %s", fs->device_name); 178 retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map); 179 if (retval) 180 goto cleanup; 181 inode_bitmap = fs->inode_map->bitmap; 182 } 183 ext2fs_free_mem(&buf); 184 185 if (fs->flags & EXT2_FLAG_IMAGE_FILE) { 186 if (inode_bitmap) { 187 blk = (fs->image_header->offset_inodemap / 188 fs->blocksize); 189 retval = io_channel_read_blk(fs->io, blk, 190 -(inode_nbytes * fs->group_desc_count), 191 inode_bitmap); 192 if (retval) 193 goto cleanup; 194 } 195 if (block_bitmap) { 196 blk = (fs->image_header->offset_blockmap / 197 fs->blocksize); 198 retval = io_channel_read_blk(fs->io, blk, 199 -(block_nbytes * fs->group_desc_count), 200 block_bitmap); 201 if (retval) 202 goto cleanup; 203 } 204 return 0; 205 } 206 207 for (i = 0; i < fs->group_desc_count; i++) { 208 if (block_bitmap) { 209 blk = fs->group_desc[i].bg_block_bitmap; 210 if (blk) { 211 retval = io_channel_read_blk(fs->io, blk, 212 -block_nbytes, block_bitmap); 213 if (retval) { 214 retval = EXT2_ET_BLOCK_BITMAP_READ; 215 goto cleanup; 216 } 217#ifdef EXT2_BIG_ENDIAN_BITMAPS 218 if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || 219 (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))) 220 ext2fs_swap_bitmap(fs, block_bitmap, block_nbytes); 221#endif 222 } else 223 memset(block_bitmap, 0, block_nbytes); 224 block_bitmap += block_nbytes; 225 } 226 if (inode_bitmap) { 227 blk = fs->group_desc[i].bg_inode_bitmap; 228 if (blk) { 229 retval = io_channel_read_blk(fs->io, blk, 230 -inode_nbytes, inode_bitmap); 231 if (retval) { 232 retval = EXT2_ET_INODE_BITMAP_READ; 233 goto cleanup; 234 } 235#ifdef EXT2_BIG_ENDIAN_BITMAPS 236 if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || 237 (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))) 238 ext2fs_swap_bitmap(fs, inode_bitmap, inode_nbytes); 239#endif 240 } else 241 memset(inode_bitmap, 0, inode_nbytes); 242 inode_bitmap += inode_nbytes; 243 } 244 } 245 return 0; 246 247cleanup: 248 if (do_block) { 249 ext2fs_free_mem(&fs->block_map); 250 fs->block_map = 0; 251 } 252 if (do_inode) { 253 ext2fs_free_mem(&fs->inode_map); 254 fs->inode_map = 0; 255 } 256 if (buf) 257 ext2fs_free_mem(&buf); 258 return retval; 259} 260 261errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs) 262{ 263 return read_bitmaps(fs, 1, 0); 264} 265 266errcode_t ext2fs_read_block_bitmap(ext2_filsys fs) 267{ 268 return read_bitmaps(fs, 0, 1); 269} 270 271errcode_t ext2fs_read_bitmaps(ext2_filsys fs) 272{ 273 274 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 275 276 if (fs->inode_map && fs->block_map) 277 return 0; 278 279 return read_bitmaps(fs, !fs->inode_map, !fs->block_map); 280} 281 282errcode_t ext2fs_write_bitmaps(ext2_filsys fs) 283{ 284 errcode_t retval; 285 286 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 287 288 if (fs->block_map && ext2fs_test_bb_dirty(fs)) { 289 retval = ext2fs_write_block_bitmap(fs); 290 if (retval) 291 return retval; 292 } 293 if (fs->inode_map && ext2fs_test_ib_dirty(fs)) { 294 retval = ext2fs_write_inode_bitmap(fs); 295 if (retval) 296 return retval; 297 } 298 return 0; 299} 300 301