Home | History | Annotate | Download | only in ext2fs
      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
     44 static 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 
     54 static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
     55 {
     56 	dgrp_t 		i;
     57 	unsigned int	j;
     58 	int		block_nbytes, inode_nbytes;
     59 	unsigned int	nbits;
     60 	errcode_t	retval;
     61 	char 		*block_bitmap, *inode_bitmap;
     62 	char 		*block_buf, *inode_buf;
     63 	int		lazy_flag = 0;
     64 	blk_t		blk;
     65 
     66 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
     67 
     68 	if (!(fs->flags & EXT2_FLAG_RW))
     69 		return EXT2_ET_RO_FILSYS;
     70 	if (EXT2_HAS_COMPAT_FEATURE(fs->super,
     71 				    EXT2_FEATURE_COMPAT_LAZY_BG))
     72 		lazy_flag = 1;
     73 	inode_nbytes = block_nbytes = 0;
     74 	block_bitmap = inode_bitmap = 0;
     75 	if (do_block) {
     76 		block_bitmap = fs->block_map->bitmap;
     77 		block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
     78 		retval = ext2fs_get_mem(fs->blocksize, &block_buf);
     79 		if (retval)
     80 			return retval;
     81 		memset(block_buf, 0xff, fs->blocksize);
     82 	}
     83 	if (do_inode) {
     84 		inode_bitmap = fs->inode_map->bitmap;
     85 		inode_nbytes = (size_t)
     86 			((EXT2_INODES_PER_GROUP(fs->super)+7) / 8);
     87 		retval = ext2fs_get_mem(fs->blocksize, &inode_buf);
     88 		if (retval)
     89 			return retval;
     90 		memset(inode_buf, 0xff, fs->blocksize);
     91 	}
     92 
     93 	for (i = 0; i < fs->group_desc_count; i++) {
     94 		if (!block_bitmap || !do_block)
     95 			goto skip_block_bitmap;
     96 
     97 		if (lazy_flag && fs->group_desc[i].bg_flags &
     98 		    EXT2_BG_BLOCK_UNINIT)
     99 			goto skip_this_block_bitmap;
    100 
    101 		memcpy(block_buf, block_bitmap, block_nbytes);
    102 		if (i == fs->group_desc_count - 1) {
    103 			/* Force bitmap padding for the last group */
    104 			nbits = ((fs->super->s_blocks_count
    105 				  - fs->super->s_first_data_block)
    106 				 % EXT2_BLOCKS_PER_GROUP(fs->super));
    107 			if (nbits)
    108 				for (j = nbits; j < fs->blocksize * 8; j++)
    109 					ext2fs_set_bit(j, block_buf);
    110 		}
    111 		blk = fs->group_desc[i].bg_block_bitmap;
    112 		if (blk) {
    113 #ifdef EXT2_BIG_ENDIAN_BITMAPS
    114 			if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
    115 			      (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
    116 				ext2fs_swap_bitmap(fs, block_buf,
    117 						   block_nbytes);
    118 #endif
    119 			retval = io_channel_write_blk(fs->io, blk, 1,
    120 						      block_buf);
    121 			if (retval)
    122 				return EXT2_ET_BLOCK_BITMAP_WRITE;
    123 		}
    124 	skip_this_block_bitmap:
    125 		block_bitmap += block_nbytes;
    126 	skip_block_bitmap:
    127 
    128 		if (!inode_bitmap || !do_inode)
    129 			continue;
    130 
    131 		if (lazy_flag && fs->group_desc[i].bg_flags &
    132 		    EXT2_BG_INODE_UNINIT)
    133 			goto skip_this_inode_bitmap;
    134 
    135 		memcpy(inode_buf, inode_bitmap, inode_nbytes);
    136 		blk = fs->group_desc[i].bg_inode_bitmap;
    137 		if (blk) {
    138 #ifdef EXT2_BIG_ENDIAN_BITMAPS
    139 			if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
    140 			      (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
    141 				ext2fs_swap_bitmap(fs, inode_buf,
    142 						   inode_nbytes);
    143 #endif
    144 			retval = io_channel_write_blk(fs->io, blk, 1,
    145 						      inode_buf);
    146 			if (retval)
    147 				return EXT2_ET_INODE_BITMAP_WRITE;
    148 		}
    149 	skip_this_inode_bitmap:
    150 		inode_bitmap += inode_nbytes;
    151 
    152 	}
    153 	if (do_block) {
    154 		fs->flags &= ~EXT2_FLAG_BB_DIRTY;
    155 		ext2fs_free_mem(&block_buf);
    156 	}
    157 	if (do_inode) {
    158 		fs->flags &= ~EXT2_FLAG_IB_DIRTY;
    159 		ext2fs_free_mem(&inode_buf);
    160 	}
    161 	return 0;
    162 }
    163 
    164 static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
    165 {
    166 	dgrp_t i;
    167 	char *block_bitmap = 0, *inode_bitmap = 0;
    168 	char *buf;
    169 	errcode_t retval;
    170 	int block_nbytes = (int) EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
    171 	int inode_nbytes = (int) EXT2_INODES_PER_GROUP(fs->super) / 8;
    172 	int lazy_flag = 0;
    173 	blk_t	blk;
    174 
    175 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
    176 
    177 	fs->write_bitmaps = ext2fs_write_bitmaps;
    178 
    179 	if (EXT2_HAS_COMPAT_FEATURE(fs->super,
    180 				    EXT2_FEATURE_COMPAT_LAZY_BG))
    181 		lazy_flag = 1;
    182 
    183 	retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
    184 	if (retval)
    185 		return retval;
    186 	if (do_block) {
    187 		if (fs->block_map)
    188 			ext2fs_free_block_bitmap(fs->block_map);
    189 		sprintf(buf, "block bitmap for %s", fs->device_name);
    190 		retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
    191 		if (retval)
    192 			goto cleanup;
    193 		block_bitmap = fs->block_map->bitmap;
    194 	}
    195 	if (do_inode) {
    196 		if (fs->inode_map)
    197 			ext2fs_free_inode_bitmap(fs->inode_map);
    198 		sprintf(buf, "inode bitmap for %s", fs->device_name);
    199 		retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
    200 		if (retval)
    201 			goto cleanup;
    202 		inode_bitmap = fs->inode_map->bitmap;
    203 	}
    204 	ext2fs_free_mem(&buf);
    205 
    206 	if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
    207 		if (inode_bitmap) {
    208 			blk = (fs->image_header->offset_inodemap /
    209 			       fs->blocksize);
    210 			retval = io_channel_read_blk(fs->image_io, blk,
    211 			     -(inode_nbytes * fs->group_desc_count),
    212 			     inode_bitmap);
    213 			if (retval)
    214 				goto cleanup;
    215 		}
    216 		if (block_bitmap) {
    217 			blk = (fs->image_header->offset_blockmap /
    218 			       fs->blocksize);
    219 			retval = io_channel_read_blk(fs->image_io, blk,
    220 			     -(block_nbytes * fs->group_desc_count),
    221 			     block_bitmap);
    222 			if (retval)
    223 				goto cleanup;
    224 		}
    225 		return 0;
    226 	}
    227 
    228 	for (i = 0; i < fs->group_desc_count; i++) {
    229 		if (block_bitmap) {
    230 			blk = fs->group_desc[i].bg_block_bitmap;
    231 			if (lazy_flag && fs->group_desc[i].bg_flags &
    232 			    EXT2_BG_BLOCK_UNINIT)
    233 				blk = 0;
    234 			if (blk) {
    235 				retval = io_channel_read_blk(fs->io, blk,
    236 					     -block_nbytes, block_bitmap);
    237 				if (retval) {
    238 					retval = EXT2_ET_BLOCK_BITMAP_READ;
    239 					goto cleanup;
    240 				}
    241 #ifdef EXT2_BIG_ENDIAN_BITMAPS
    242 				if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
    243 				      (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
    244 					ext2fs_swap_bitmap(fs, block_bitmap, block_nbytes);
    245 #endif
    246 			} else
    247 				memset(block_bitmap, 0xff, block_nbytes);
    248 			block_bitmap += block_nbytes;
    249 		}
    250 		if (inode_bitmap) {
    251 			blk = fs->group_desc[i].bg_inode_bitmap;
    252 			if (lazy_flag && fs->group_desc[i].bg_flags &
    253 			    EXT2_BG_INODE_UNINIT)
    254 				blk = 0;
    255 			if (blk) {
    256 				retval = io_channel_read_blk(fs->io, blk,
    257 					     -inode_nbytes, inode_bitmap);
    258 				if (retval) {
    259 					retval = EXT2_ET_INODE_BITMAP_READ;
    260 					goto cleanup;
    261 				}
    262 #ifdef EXT2_BIG_ENDIAN_BITMAPS
    263 				if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
    264 				      (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
    265 					ext2fs_swap_bitmap(fs, inode_bitmap, inode_nbytes);
    266 #endif
    267 			} else
    268 				memset(inode_bitmap, 0xff, inode_nbytes);
    269 			inode_bitmap += inode_nbytes;
    270 		}
    271 	}
    272 	return 0;
    273 
    274 cleanup:
    275 	if (do_block) {
    276 		ext2fs_free_mem(&fs->block_map);
    277 		fs->block_map = 0;
    278 	}
    279 	if (do_inode) {
    280 		ext2fs_free_mem(&fs->inode_map);
    281 		fs->inode_map = 0;
    282 	}
    283 	if (buf)
    284 		ext2fs_free_mem(&buf);
    285 	return retval;
    286 }
    287 
    288 errcode_t ext2fs_read_inode_bitmap(ext2_filsys fs)
    289 {
    290 	return read_bitmaps(fs, 1, 0);
    291 }
    292 
    293 errcode_t ext2fs_read_block_bitmap(ext2_filsys fs)
    294 {
    295 	return read_bitmaps(fs, 0, 1);
    296 }
    297 
    298 errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs)
    299 {
    300 	return write_bitmaps(fs, 1, 0);
    301 }
    302 
    303 errcode_t ext2fs_write_block_bitmap (ext2_filsys fs)
    304 {
    305 	return write_bitmaps(fs, 0, 1);
    306 }
    307 
    308 errcode_t ext2fs_read_bitmaps(ext2_filsys fs)
    309 {
    310 	if (fs->inode_map && fs->block_map)
    311 		return 0;
    312 
    313 	return read_bitmaps(fs, !fs->inode_map, !fs->block_map);
    314 }
    315 
    316 errcode_t ext2fs_write_bitmaps(ext2_filsys fs)
    317 {
    318 	int do_inode = fs->inode_map && ext2fs_test_ib_dirty(fs);
    319 	int do_block = fs->block_map && ext2fs_test_bb_dirty(fs);
    320 
    321 	if (!do_inode && !do_block)
    322 		return 0;
    323 
    324 	return write_bitmaps(fs, do_inode, do_block);
    325 }
    326