blob: 73979fdb2b1d1a1759741bb351776bc014bcbeb0 [file] [log] [blame]
Theodore Ts'of3db3561997-04-26 13:34:30 +00001/*
2 * rw_bitmaps.c --- routines to read and write the inode and block bitmaps.
3 *
Theodore Ts'o19c78dc1997-04-29 16:17:09 +00004 * 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%
Theodore Ts'of3db3561997-04-26 13:34:30 +000010 */
11
12#include <stdio.h>
13#include <string.h>
Theodore Ts'o4cbe8af1997-08-10 23:07:40 +000014#if HAVE_UNISTD_H
Theodore Ts'of3db3561997-04-26 13:34:30 +000015#include <unistd.h>
Theodore Ts'o4cbe8af1997-08-10 23:07:40 +000016#endif
Theodore Ts'of3db3561997-04-26 13:34:30 +000017#include <fcntl.h>
18#include <time.h>
Theodore Ts'o519ee041997-10-20 00:52:43 +000019#ifdef HAVE_SYS_STAT_H
Theodore Ts'of3db3561997-04-26 13:34:30 +000020#include <sys/stat.h>
Theodore Ts'o519ee041997-10-20 00:52:43 +000021#endif
22#ifdef HAVE_SYS_TYPES_H
Theodore Ts'of3db3561997-04-26 13:34:30 +000023#include <sys/types.h>
Theodore Ts'o519ee041997-10-20 00:52:43 +000024#endif
Theodore Ts'of3db3561997-04-26 13:34:30 +000025
Theodore Ts'ob5abe6f1998-01-19 14:47:53 +000026#if EXT2_FLAT_INCLUDES
27#include "ext2_fs.h"
28#else
Theodore Ts'of3db3561997-04-26 13:34:30 +000029#include <linux/ext2_fs.h>
Theodore Ts'ob5abe6f1998-01-19 14:47:53 +000030#endif
Theodore Ts'of3db3561997-04-26 13:34:30 +000031
32#include "ext2fs.h"
33
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000034#ifdef __powerpc__
35/*
36 * On the PowerPC, the big-endian variant of the ext2 filesystem
37 * has its bitmaps stored as 32-bit words with bit 0 as the LSB
38 * of each word. Thus a bitmap with only bit 0 set would be, as
39 * a string of bytes, 00 00 00 01 00 ...
40 * To cope with this, we byte-reverse each word of a bitmap if
41 * we have a big-endian filesystem, that is, if we are *not*
42 * byte-swapping other word-sized numbers.
43 */
44#define EXT2_BIG_ENDIAN_BITMAPS
45#endif
46
47#ifdef EXT2_BIG_ENDIAN_BITMAPS
48void ext2fs_swap_bitmap(ext2_filsys fs, char *bitmap, int nbytes)
49{
50 __u32 *p = (__u32 *) bitmap;
51 int n;
52
53 for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
54 *p = ext2fs_swab32(*p);
55}
56#endif
57
Theodore Ts'of3db3561997-04-26 13:34:30 +000058errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs)
59{
Theodore Ts'o2eb374c1998-09-03 01:22:57 +000060 dgrp_t i;
Theodore Ts'o3cb6c501997-08-11 20:29:22 +000061 size_t nbytes;
Theodore Ts'of3db3561997-04-26 13:34:30 +000062 errcode_t retval;
63 char * inode_bitmap = fs->inode_map->bitmap;
64 char * bitmap_block = NULL;
Theodore Ts'o19c78dc1997-04-29 16:17:09 +000065 blk_t blk;
Theodore Ts'of3db3561997-04-26 13:34:30 +000066
67 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
68
69 if (!(fs->flags & EXT2_FLAG_RW))
70 return EXT2_ET_RO_FILSYS;
71 if (!inode_bitmap)
72 return 0;
Theodore Ts'o3cb6c501997-08-11 20:29:22 +000073 nbytes = (size_t) ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8);
Theodore Ts'o7f88b041997-04-26 14:48:50 +000074
Theodore Ts'o7b4e4531997-10-26 03:41:24 +000075 retval = ext2fs_get_mem(fs->blocksize, (void **) &bitmap_block);
76 if (retval)
77 return retval;
Theodore Ts'of3db3561997-04-26 13:34:30 +000078 memset(bitmap_block, 0xff, fs->blocksize);
79 for (i = 0; i < fs->group_desc_count; i++) {
80 memcpy(bitmap_block, inode_bitmap, nbytes);
Theodore Ts'o19c78dc1997-04-29 16:17:09 +000081 blk = fs->group_desc[i].bg_inode_bitmap;
82 if (blk) {
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000083#ifdef EXT2_BIG_ENDIAN_BITMAPS
84 if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
85 (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
86 ext2fs_swap_bitmap(fs, bitmap_block, nbytes);
87#endif
Theodore Ts'o19c78dc1997-04-29 16:17:09 +000088 retval = io_channel_write_blk(fs->io, blk, 1,
89 bitmap_block);
90 if (retval)
91 return EXT2_ET_INODE_BITMAP_WRITE;
92 }
Theodore Ts'of3db3561997-04-26 13:34:30 +000093 inode_bitmap += nbytes;
94 }
95 fs->flags |= EXT2_FLAG_CHANGED;
96 fs->flags &= ~EXT2_FLAG_IB_DIRTY;
Theodore Ts'o7b4e4531997-10-26 03:41:24 +000097 ext2fs_free_mem((void **) &bitmap_block);
Theodore Ts'of3db3561997-04-26 13:34:30 +000098 return 0;
99}
100
101errcode_t ext2fs_write_block_bitmap (ext2_filsys fs)
102{
Theodore Ts'o2eb374c1998-09-03 01:22:57 +0000103 dgrp_t i;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000104 int j;
105 int nbytes;
106 int nbits;
107 errcode_t retval;
108 char * block_bitmap = fs->block_map->bitmap;
109 char * bitmap_block = NULL;
Theodore Ts'o19c78dc1997-04-29 16:17:09 +0000110 blk_t blk;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000111
112 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
113
114 if (!(fs->flags & EXT2_FLAG_RW))
115 return EXT2_ET_RO_FILSYS;
116 if (!block_bitmap)
117 return 0;
118 nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
Theodore Ts'o7b4e4531997-10-26 03:41:24 +0000119 retval = ext2fs_get_mem(fs->blocksize, (void **) &bitmap_block);
120 if (retval)
121 return retval;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000122 memset(bitmap_block, 0xff, fs->blocksize);
123 for (i = 0; i < fs->group_desc_count; i++) {
124 memcpy(bitmap_block, block_bitmap, nbytes);
125 if (i == fs->group_desc_count - 1) {
126 /* Force bitmap padding for the last group */
Theodore Ts'o3cb6c501997-08-11 20:29:22 +0000127 nbits = (int) ((fs->super->s_blocks_count
128 - fs->super->s_first_data_block)
129 % EXT2_BLOCKS_PER_GROUP(fs->super));
Theodore Ts'of3db3561997-04-26 13:34:30 +0000130 if (nbits)
131 for (j = nbits; j < fs->blocksize * 8; j++)
Theodore Ts'o74becf31997-04-26 14:37:06 +0000132 ext2fs_set_bit(j, bitmap_block);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000133 }
Theodore Ts'o19c78dc1997-04-29 16:17:09 +0000134 blk = fs->group_desc[i].bg_block_bitmap;
135 if (blk) {
Theodore Ts'o1c27cac1997-08-14 17:20:42 +0000136#ifdef EXT2_BIG_ENDIAN_BITMAPS
137 if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
138 (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
139 ext2fs_swap_bitmap(fs, bitmap_block, nbytes);
140#endif
Theodore Ts'o19c78dc1997-04-29 16:17:09 +0000141 retval = io_channel_write_blk(fs->io, blk, 1,
142 bitmap_block);
143 if (retval)
144 return EXT2_ET_BLOCK_BITMAP_WRITE;
145 }
Theodore Ts'of3db3561997-04-26 13:34:30 +0000146 block_bitmap += nbytes;
147 }
148 fs->flags |= EXT2_FLAG_CHANGED;
149 fs->flags &= ~EXT2_FLAG_BB_DIRTY;
Theodore Ts'o7b4e4531997-10-26 03:41:24 +0000150 ext2fs_free_mem((void **) &bitmap_block);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000151 return 0;
152}
153
154static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
155{
Theodore Ts'o2eb374c1998-09-03 01:22:57 +0000156 dgrp_t i;
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000157 char *block_bitmap = 0, *inode_bitmap = 0;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000158 char *buf;
159 errcode_t retval;
Theodore Ts'o3cb6c501997-08-11 20:29:22 +0000160 int block_nbytes = (int) EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
161 int inode_nbytes = (int) EXT2_INODES_PER_GROUP(fs->super) / 8;
Theodore Ts'o19c78dc1997-04-29 16:17:09 +0000162 blk_t blk;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000163
164 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
165
166 fs->write_bitmaps = ext2fs_write_bitmaps;
167
Theodore Ts'o7b4e4531997-10-26 03:41:24 +0000168 retval = ext2fs_get_mem(strlen(fs->device_name) + 80, (void **) &buf);
169 if (retval)
170 return retval;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000171 if (do_block) {
172 if (fs->block_map)
173 ext2fs_free_block_bitmap(fs->block_map);
174 sprintf(buf, "block bitmap for %s", fs->device_name);
175 retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
176 if (retval)
177 goto cleanup;
178 block_bitmap = fs->block_map->bitmap;
179 }
180 if (do_inode) {
181 if (fs->inode_map)
182 ext2fs_free_inode_bitmap(fs->inode_map);
183 sprintf(buf, "inode bitmap for %s", fs->device_name);
184 retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
185 if (retval)
186 goto cleanup;
187 inode_bitmap = fs->inode_map->bitmap;
188 }
Theodore Ts'o7b4e4531997-10-26 03:41:24 +0000189 ext2fs_free_mem((void **) &buf);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000190
191 for (i = 0; i < fs->group_desc_count; i++) {
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000192 if (block_bitmap) {
Theodore Ts'o19c78dc1997-04-29 16:17:09 +0000193 blk = fs->group_desc[i].bg_block_bitmap;
194 if (blk) {
195 retval = io_channel_read_blk(fs->io, blk,
196 -block_nbytes, block_bitmap);
197 if (retval) {
198 retval = EXT2_ET_BLOCK_BITMAP_READ;
199 goto cleanup;
200 }
Theodore Ts'o1c27cac1997-08-14 17:20:42 +0000201#ifdef EXT2_BIG_ENDIAN_BITMAPS
202 if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
203 (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
204 ext2fs_swap_bitmap(fs, block_bitmap, block_nbytes);
205#endif
Theodore Ts'o19c78dc1997-04-29 16:17:09 +0000206 } else
207 memset(block_bitmap, 0, block_nbytes);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000208 block_bitmap += block_nbytes;
209 }
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000210 if (inode_bitmap) {
Theodore Ts'o19c78dc1997-04-29 16:17:09 +0000211 blk = fs->group_desc[i].bg_inode_bitmap;
212 if (blk) {
213 retval = io_channel_read_blk(fs->io, blk,
214 -inode_nbytes, inode_bitmap);
215 if (retval) {
216 retval = EXT2_ET_INODE_BITMAP_READ;
217 goto cleanup;
218 }
Theodore Ts'o1c27cac1997-08-14 17:20:42 +0000219#ifdef EXT2_BIG_ENDIAN_BITMAPS
220 if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
221 (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
222 ext2fs_swap_bitmap(fs, inode_bitmap, inode_nbytes);
223#endif
Theodore Ts'o19c78dc1997-04-29 16:17:09 +0000224 } else
225 memset(inode_bitmap, 0, inode_nbytes);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000226 inode_bitmap += inode_nbytes;
227 }
228 }
Theodore Ts'of3db3561997-04-26 13:34:30 +0000229 return 0;
230
231cleanup:
232 if (do_block) {
Theodore Ts'o7b4e4531997-10-26 03:41:24 +0000233 ext2fs_free_mem((void **) &fs->block_map);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000234 fs->block_map = 0;
235 }
236 if (do_inode) {
Theodore Ts'o7b4e4531997-10-26 03:41:24 +0000237 ext2fs_free_mem((void **) &fs->inode_map);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000238 fs->inode_map = 0;
239 }
240 if (buf)
Theodore Ts'o7b4e4531997-10-26 03:41:24 +0000241 ext2fs_free_mem((void **) &buf);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000242 return retval;
243}
244
245errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs)
246{
247 return read_bitmaps(fs, 1, 0);
248}
249
250errcode_t ext2fs_read_block_bitmap(ext2_filsys fs)
251{
252 return read_bitmaps(fs, 0, 1);
253}
254
255errcode_t ext2fs_read_bitmaps(ext2_filsys fs)
256{
257
258 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
259
Theodore Ts'o9abd2ce1998-02-16 22:00:37 +0000260 if (fs->inode_map && fs->block_map)
261 return 0;
262
Theodore Ts'of3db3561997-04-26 13:34:30 +0000263 return read_bitmaps(fs, !fs->inode_map, !fs->block_map);
264}
265
266errcode_t ext2fs_write_bitmaps(ext2_filsys fs)
267{
268 errcode_t retval;
269
270 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
271
272 if (fs->block_map && ext2fs_test_bb_dirty(fs)) {
273 retval = ext2fs_write_block_bitmap(fs);
274 if (retval)
275 return retval;
276 }
277 if (fs->inode_map && ext2fs_test_ib_dirty(fs)) {
278 retval = ext2fs_write_inode_bitmap(fs);
279 if (retval)
280 return retval;
281 }
282 return 0;
283}
284