aboutsummaryrefslogtreecommitdiff
path: root/e2fsck/swapfs.c
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>1997-04-29 14:53:37 +0000
committerTheodore Ts'o <tytso@mit.edu>1997-04-29 14:53:37 +0000
commit1e3472c5f37ca3686dd69b079d4d02a302f5798d (patch)
treef8c01b8e3875f425d9de9b3ef6171f739d1273e8 /e2fsck/swapfs.c
parentfc6d9d519aef67735918bf02c0fa8c9222008f76 (diff)
downloade2fsprogs-1e3472c5f37ca3686dd69b079d4d02a302f5798d.tar.gz
Many files:
Checked in e2fsprogs 1.05
Diffstat (limited to 'e2fsck/swapfs.c')
-rw-r--r--e2fsck/swapfs.c199
1 files changed, 199 insertions, 0 deletions
diff --git a/e2fsck/swapfs.c b/e2fsck/swapfs.c
new file mode 100644
index 00000000..291fcb3d
--- /dev/null
+++ b/e2fsck/swapfs.c
@@ -0,0 +1,199 @@
+/*
+ * swapfs.c --- byte-swap an ext2 filesystem
+ */
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <et/com_err.h>
+#include "e2fsck.h"
+
+struct swap_block_struct {
+ ino_t ino;
+ int isdir;
+ errcode_t errcode;
+ char *dir_buf;
+ struct ext2_inode *inode;
+};
+
+/*
+ * This is a helper function for block_iterate. We mark all of the
+ * indirect and direct blocks as changed, so that block_iterate will
+ * write them out.
+ */
+static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
+ void *private)
+{
+ errcode_t retval;
+
+ struct swap_block_struct *sb = (struct swap_block_struct *) private;
+
+ if (sb->isdir && (blockcnt >= 0) && *block_nr) {
+ retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
+ if (retval) {
+ sb->errcode = retval;
+ return BLOCK_ABORT;
+ }
+ retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
+ if (retval) {
+ sb->errcode = retval;
+ return BLOCK_ABORT;
+ }
+ }
+ if (blockcnt >= 0) {
+ if (blockcnt < EXT2_NDIR_BLOCKS)
+ return 0;
+ return BLOCK_CHANGED;
+ }
+ if (blockcnt == BLOCK_COUNT_IND) {
+ if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
+ return 0;
+ return BLOCK_CHANGED;
+ }
+ if (blockcnt == BLOCK_COUNT_DIND) {
+ if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
+ return 0;
+ return BLOCK_CHANGED;
+ }
+ if (blockcnt == BLOCK_COUNT_TIND) {
+ if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
+ return 0;
+ return BLOCK_CHANGED;
+ }
+ return BLOCK_CHANGED;
+}
+
+/*
+ * This function is responsible for byte-swapping all of the indirect,
+ * block pointers. It is also responsible for byte-swapping directories.
+ */
+static void swap_inode_blocks(ext2_filsys fs, ino_t ino, char *block_buf,
+ struct ext2_inode *inode)
+{
+ errcode_t retval;
+ struct swap_block_struct sb;
+
+ sb.ino = ino;
+ sb.inode = inode;
+ sb.dir_buf = block_buf + fs->blocksize*3;
+ sb.errcode = 0;
+ sb.isdir = 0;
+ if (LINUX_S_ISDIR(inode->i_mode))
+ sb.isdir = 1;
+
+ retval = ext2fs_block_iterate(fs, ino, 0, block_buf, swap_block, &sb);
+ if (retval) {
+ com_err("swap_inode_blocks", retval,
+ "while calling ext2fs_block_iterate");
+ fatal_error(0);
+ }
+ if (sb.errcode) {
+ com_err("swap_inode_blocks", sb.errcode,
+ "while calling iterator function");
+ fatal_error(0);
+ }
+}
+
+static void swap_inodes(ext2_filsys fs)
+{
+ int i, group;
+ ino_t ino = 1;
+ char *buf, *block_buf;
+ errcode_t retval;
+ struct ext2_inode * inode;
+
+ fs->read_inode = pass1_read_inode;
+ fs->get_blocks = pass1_get_blocks;
+
+
+ buf = malloc(fs->blocksize * fs->inode_blocks_per_group);
+ if (!buf) {
+ com_err("swap_inodes", ENOMEM,
+ "while allocating inode buffer");
+ fatal_error(0);
+ }
+ block_buf = allocate_memory(fs->blocksize * 4,
+ "block interate buffer");
+ for (group = 0; group < fs->group_desc_count; group++) {
+ retval = io_channel_read_blk(fs->io,
+ fs->group_desc[group].bg_inode_table,
+ fs->inode_blocks_per_group, buf);
+ if (retval) {
+ com_err("swap_inodes", retval,
+ "while reading inode table (group %d)",
+ group);
+ fatal_error(0);
+ }
+ inode = (struct ext2_inode *) buf;
+ for (i=0; i < fs->super->s_inodes_per_group; i++, ino++) {
+ if (fs->flags & EXT2_SWAP_BYTES_READ)
+ ext2fs_swap_inode(fs, inode, inode, 0);
+ stashed_ino = ino;
+ stashed_inode = inode;
+
+ if (inode->i_block[EXT2_IND_BLOCK] ||
+ inode->i_block[EXT2_DIND_BLOCK] ||
+ inode->i_block[EXT2_TIND_BLOCK] ||
+ LINUX_S_ISDIR(inode->i_mode))
+ swap_inode_blocks(fs, ino, block_buf, inode);
+
+ if (fs->flags & EXT2_SWAP_BYTES_WRITE)
+ ext2fs_swap_inode(fs, inode, inode, 1);
+ inode++;
+ }
+ retval = io_channel_write_blk(fs->io,
+ fs->group_desc[group].bg_inode_table,
+ fs->inode_blocks_per_group, buf);
+ if (retval) {
+ com_err("swap_inodes", retval,
+ "while writing inode table (group %d)",
+ group);
+ fatal_error(0);
+ }
+ }
+ free(buf);
+ free(block_buf);
+ fs->read_inode = 0;
+ fs->get_blocks = 0;
+}
+
+void swap_filesys(ext2_filsys fs)
+{
+ struct resource_track rtrack;
+
+ init_resource_track(&rtrack);
+
+ if (!preen)
+ printf("Pass 0: Doing byte-swap of filesystem\n");
+
+#ifdef MTRACE
+ mtrace_print("Byte swap");
+#endif
+
+ if (fs->super->s_mnt_count) {
+ fprintf(stderr, "%s: the filesystem must be freshly "
+ "checked using fsck\n"
+ "and not mounted before trying to "
+ "byte-swap it.\n", device_name);
+ fatal_error(0);
+ }
+ if (fs->flags & EXT2_SWAP_BYTES) {
+ fs->flags &= ~(EXT2_SWAP_BYTES|EXT2_SWAP_BYTES_WRITE);
+ fs->flags |= EXT2_SWAP_BYTES_READ;
+ } else {
+ fs->flags &= ~EXT2_SWAP_BYTES_READ;
+ fs->flags |= EXT2_SWAP_BYTES_WRITE;
+ }
+ swap_inodes(fs);
+ if (fs->flags & EXT2_SWAP_BYTES_WRITE)
+ fs->flags |= EXT2_SWAP_BYTES;
+ fs->flags &= ~(EXT2_SWAP_BYTES_READ|EXT2_SWAP_BYTES_WRITE);
+ ext2fs_flush(fs);
+
+ if (tflag > 1) {
+ printf("Byte swap: ");
+ print_resource_track(&rtrack);
+ }
+}
+
+