import the very fat e2fsck/fsck applets
diff --git a/e2fsprogs/e2fsck/swapfs.c b/e2fsprogs/e2fsck/swapfs.c
new file mode 100644
index 0000000..8d46404
--- /dev/null
+++ b/e2fsprogs/e2fsck/swapfs.c
@@ -0,0 +1,269 @@
+/*
+ * swapfs.c --- byte-swap an ext2 filesystem
+ *
+ * Copyright 1996, 1997 by Theodore Ts'o
+ * 
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ * 
+ */
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <et/com_err.h>
+#include "e2fsck.h"
+
+#ifdef ENABLE_SWAPFS
+
+struct swap_block_struct {
+	ext2_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 *priv_data)
+{
+	errcode_t	retval;
+	
+	struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
+
+	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(e2fsck_t ctx, ext2_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 + ctx->fs->blocksize*3;
+	sb.errcode = 0;
+	sb.isdir = 0;
+	if (LINUX_S_ISDIR(inode->i_mode))
+		sb.isdir = 1;
+
+	retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
+				      swap_block, &sb);
+	if (retval) {
+		com_err("swap_inode_blocks", retval,
+			_("while calling ext2fs_block_iterate"));
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+	if (sb.errcode) {
+		com_err("swap_inode_blocks", sb.errcode,
+			_("while calling iterator function"));
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+}
+
+static void swap_inodes(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	dgrp_t			group;
+	unsigned int		i;
+	ext2_ino_t		ino = 1;
+	char 			*buf, *block_buf;
+	errcode_t		retval;
+	struct ext2_inode *	inode;
+
+	e2fsck_use_inode_shortcuts(ctx, 1);
+	
+	retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
+				&buf);
+	if (retval) {
+		com_err("swap_inodes", retval,
+			_("while allocating inode buffer"));
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+	block_buf = (char *) e2fsck_allocate_memory(ctx, 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);
+			ctx->flags |= E2F_FLAG_ABORT;
+			return;
+		}
+		inode = (struct ext2_inode *) buf;
+		for (i=0; i < fs->super->s_inodes_per_group;
+		     i++, ino++, inode++) {
+			ctx->stashed_ino = ino;
+			ctx->stashed_inode = inode;
+			
+			if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
+				ext2fs_swap_inode(fs, inode, inode, 0);
+			
+			/*
+			 * Skip deleted files.
+			 */
+			if (inode->i_links_count == 0)
+				continue;
+			
+			if (LINUX_S_ISDIR(inode->i_mode) ||
+			    ((inode->i_block[EXT2_IND_BLOCK] ||
+			      inode->i_block[EXT2_DIND_BLOCK] ||
+			      inode->i_block[EXT2_TIND_BLOCK]) &&
+			     ext2fs_inode_has_valid_blocks(inode)))
+				swap_inode_blocks(ctx, ino, block_buf, inode);
+
+			if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+				return;
+			
+			if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
+				ext2fs_swap_inode(fs, inode, inode, 1);
+		}
+		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);
+			ctx->flags |= E2F_FLAG_ABORT;
+			return;
+		}
+	}
+	ext2fs_free_mem(&buf);
+	ext2fs_free_mem(&block_buf);
+	e2fsck_use_inode_shortcuts(ctx, 0);
+	ext2fs_flush_icache(fs);
+}
+
+#if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS)
+/*
+ * On the PowerPC, the big-endian variant of the ext2 filesystem
+ * has its bitmaps stored as 32-bit words with bit 0 as the LSB
+ * of each word.  Thus a bitmap with only bit 0 set would be, as
+ * a string of bytes, 00 00 00 01 00 ...
+ * To cope with this, we byte-reverse each word of a bitmap if
+ * we have a big-endian filesystem, that is, if we are *not*
+ * byte-swapping other word-sized numbers.
+ */
+#define EXT2_BIG_ENDIAN_BITMAPS
+#endif
+
+#ifdef EXT2_BIG_ENDIAN_BITMAPS
+static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
+{
+	__u32 *p = (__u32 *) bmap->bitmap;
+	int n, nbytes = (bmap->end - bmap->start + 7) / 8;
+		
+	for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
+		*p = ext2fs_swab32(*p);
+}
+#endif
+
+
+void swap_filesys(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+#ifdef RESOURCE_TRACK
+	struct resource_track	rtrack;
+
+	init_resource_track(&rtrack);
+#endif
+
+	if (!(ctx->options & E2F_OPT_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"), ctx->device_name);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+	if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
+		fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
+			       EXT2_FLAG_SWAP_BYTES_WRITE);
+		fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
+	} else {
+		fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
+		fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
+	}
+	swap_inodes(ctx);
+	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+		return;
+	if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
+		fs->flags |= EXT2_FLAG_SWAP_BYTES;
+	fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
+		       EXT2_FLAG_SWAP_BYTES_WRITE);
+
+#ifdef EXT2_BIG_ENDIAN_BITMAPS
+	e2fsck_read_bitmaps(ctx);
+	ext2fs_swap_bitmap(fs->inode_map);
+	ext2fs_swap_bitmap(fs->block_map);
+	fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
+#endif
+	fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
+	ext2fs_flush(fs);
+	fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
+	
+#ifdef RESOURCE_TRACK
+	if (ctx->options & E2F_OPT_TIME2)
+		print_resource_track(_("Byte swap"), &rtrack);
+#endif
+}
+
+#endif