busybox/e2fsprogs/old_e2fsprogs/ext2fs/rw_bitmaps.c
<<
>>
Prefs
   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 = NULL, *inode_bitmap = NULL;
 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        EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 270
 271        if (fs->inode_map && fs->block_map)
 272                return 0;
 273
 274        return read_bitmaps(fs, !fs->inode_map, !fs->block_map);
 275}
 276
 277errcode_t ext2fs_write_bitmaps(ext2_filsys fs)
 278{
 279        errcode_t       retval;
 280
 281        EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 282
 283        if (fs->block_map && ext2fs_test_bb_dirty(fs)) {
 284                retval = ext2fs_write_block_bitmap(fs);
 285                if (retval)
 286                        return retval;
 287        }
 288        if (fs->inode_map && ext2fs_test_ib_dirty(fs)) {
 289                retval = ext2fs_write_inode_bitmap(fs);
 290                if (retval)
 291                        return retval;
 292        }
 293        return 0;
 294}
 295