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