diff mbox

debugfs: add the commands "zap_block" and "block_dump"

Message ID 1356365195-4804-1-git-send-email-tytso@mit.edu
State Accepted, archived
Headers show

Commit Message

Theodore Ts'o Dec. 24, 2012, 4:06 p.m. UTC
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
 debugfs/Makefile.in   |   7 +-
 debugfs/debug_cmds.ct |   6 ++
 debugfs/zap.c         | 265 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 275 insertions(+), 3 deletions(-)
 create mode 100644 debugfs/zap.c
diff mbox

Patch

diff --git a/debugfs/Makefile.in b/debugfs/Makefile.in
index 4bb2d03..9a86dc6 100644
--- a/debugfs/Makefile.in
+++ b/debugfs/Makefile.in
@@ -18,16 +18,17 @@  MK_CMDS=	_SS_DIR_OVERRIDE=../lib/ss ../lib/ss/mk_cmds
 
 DEBUG_OBJS= debug_cmds.o debugfs.o util.o ncheck.o icheck.o ls.o \
 	lsdel.o dump.o set_fields.o logdump.o htree.o unused.o e2freefrag.o \
-	filefrag.o extent_cmds.o extent_inode.o
+	filefrag.o extent_cmds.o extent_inode.o zap.o
 
 RO_DEBUG_OBJS= ro_debug_cmds.o ro_debugfs.o util.o ncheck.o icheck.o ls.o \
-	lsdel.o logdump.o htree.o e2freefrag.o filefrag.o extent_inode.o
+	lsdel.o logdump.o htree.o e2freefrag.o filefrag.o extent_cmds.o \
+	extent_inode.o
 
 SRCS= debug_cmds.c $(srcdir)/debugfs.c $(srcdir)/util.c $(srcdir)/ls.c \
 	$(srcdir)/ncheck.c $(srcdir)/icheck.c $(srcdir)/lsdel.c \
 	$(srcdir)/dump.c $(srcdir)/set_fields.c ${srcdir}/logdump.c \
 	$(srcdir)/htree.c $(srcdir)/unused.c ${srcdir}/../misc/e2freefrag.c \
-	$(srcdir)/filefrag.c $(srcdir)/extent_inode.c
+	$(srcdir)/filefrag.c $(srcdir)/extent_inode.c $(srcdir)/zap.c
 
 LIBS= $(LIBEXT2FS) $(LIBE2P) $(LIBSS) $(LIBCOM_ERR) $(LIBBLKID) \
 	$(LIBUUID)
diff --git a/debugfs/debug_cmds.ct b/debugfs/debug_cmds.ct
index 7767f8f..520933a 100644
--- a/debugfs/debug_cmds.ct
+++ b/debugfs/debug_cmds.ct
@@ -181,5 +181,11 @@  request do_set_mmp_value, "Set MMP value",
 request do_extent_open, "Open inode for extent manipulation",
 	extent_open, eo;
 
+request do_zap_block, "Zap block",
+	zap_block, zap;
+
+request do_dump_block, "Zap block",
+	block_dump, bp;
+
 end;
 
diff --git a/debugfs/zap.c b/debugfs/zap.c
new file mode 100644
index 0000000..3f3620b
--- /dev/null
+++ b/debugfs/zap.c
@@ -0,0 +1,265 @@ 
+/*
+ * zap.c --- zap block
+ *
+ * Copyright (C) 2012 Theodore Ts'o.  This file may be redistributed
+ * under the terms of the GNU Public License.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <sys/types.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern int optind;
+extern char *optarg;
+#endif
+
+#include "debugfs.h"
+
+void do_zap_block(int argc, char *argv[])
+{
+	unsigned long	pattern = 0;
+	unsigned char	*buf;
+	ext2_ino_t	inode;
+	errcode_t	errcode;
+	blk64_t		block;
+	int		retval;
+	char		*file = NULL;
+	char		*in_file = NULL;
+	int		c, err;
+	int		offset = -1;
+	int		length = -1;
+	int		bit = -1;
+
+	if (check_fs_open(argv[0]))
+		return;
+	if (check_fs_read_write(argv[0]))
+		return;
+
+	reset_getopt();
+	while ((c = getopt (argc, argv, "b:f:l:o:p:")) != EOF) {
+		switch (c) {
+		case 'f':
+			file = optarg;
+			break;
+		case 'b':
+			bit = parse_ulong(optarg, argv[0],
+					  "bit", &err);
+			if (err)
+				return;
+			if (bit >= current_fs->blocksize * 8) {
+				com_err(argv[0], 0, "The bit to flip "
+					"must be within a %d block\n",
+					current_fs->blocksize);
+				return;
+			}
+			break;
+		case 'p':
+			pattern = parse_ulong(optarg, argv[0],
+					      "pattern", &err);
+			if (err)
+				return;
+			if (pattern >= 256) {
+				com_err(argv[0], 0, "The fill pattern must "
+					"be an 8-bit value\n");
+				return;
+			}
+			break;
+		case 'o':
+			offset = parse_ulong(optarg, argv[0],
+					     "offset", &err);
+			if (err)
+				return;
+			if (offset >= current_fs->blocksize) {
+				com_err(argv[0], 0, "The offset must be "
+					"within a %d block\n",
+					current_fs->blocksize);
+				return;
+			}
+			break;
+
+			break;
+		case 'l':
+			length = parse_ulong(optarg, argv[0],
+					     "length", &err);
+			if (err)
+				return;
+			break;
+		default:
+			goto print_usage;
+		}
+	}
+
+	if (bit > 0 && offset > 0) {
+		com_err(argv[0], 0, "The -o and -b options can not be mixed.");
+		return;
+	}
+
+	if (offset < 0)
+		offset = 0;
+	if (length < 0)
+		length = current_fs->blocksize - offset;
+	if ((offset + length) > current_fs->blocksize) {
+		com_err(argv[0], 0, "The specified length is too bug\n");
+		return;
+	}
+
+	if (argc != optind+1) {
+	print_usage:
+		com_err(0, 0, "Usage:\tzap_block [-f file] [-o offset] "
+			"[-l length] [-p pattern] block_num");
+		com_err(0, 0, "\tzap_block [-f file] [-b bit] "
+			"block_num");
+		return;
+	}
+
+	block = parse_ulonglong(argv[optind], argv[0], "block", &err);
+	if (err)
+		return;
+
+	if (file) {
+		inode = string_to_inode(file);
+		if (!inode)
+			return;
+		errcode = ext2fs_bmap2(current_fs, inode, 0, 0, 0,
+				       block, 0, &block);
+		if (errcode) {
+			com_err(argv[0], errcode,
+				"while mapping logical block %llu\n", block);
+			return;
+		}
+	}
+
+	buf = malloc(current_fs->blocksize);
+	if (!buf) {
+		com_err(argv[0], 0, "Couldn't allocate block buffer");
+		return;
+	}
+
+	errcode = io_channel_read_blk64(current_fs->io, block, 1, buf);
+	if (errcode) {
+		com_err(argv[0], errcode,
+			"while reading block %llu\n", block);
+		goto errout;
+	}
+
+	if (bit >= 0)
+		buf[bit >> 3] ^= 1 << (bit & 7);
+	else
+		memset(buf+offset, pattern, length);
+
+	errcode = io_channel_write_blk64(current_fs->io, block, 1, buf);
+	if (errcode) {
+		com_err(argv[0], errcode,
+			"while write block %llu\n", block);
+		goto errout;
+	}
+
+errout:
+	free(buf);
+	return;
+}
+
+void do_dump_block(int argc, char *argv[])
+{
+	unsigned long	pattern = 0;
+	unsigned char	*buf;
+	ext2_ino_t	inode;
+	errcode_t	errcode;
+	blk64_t		block;
+	int		retval;
+	char		*file = NULL;
+	char		*in_file = NULL;
+	int		c, err, i, j;
+	int		suppress = -1;
+
+	if (check_fs_open(argv[0]))
+		return;
+
+	reset_getopt();
+	while ((c = getopt (argc, argv, "f:")) != EOF) {
+		switch (c) {
+		case 'f':
+			file = optarg;
+			break;
+
+		default:
+			goto print_usage;
+		}
+	}
+
+	if (argc != optind+1) {
+	print_usage:
+		com_err(0, 0, "Usage: dump_block [-f file] "
+			" block_num");
+		return;
+	}
+
+	block = parse_ulonglong(argv[optind], argv[0], "block", &err);
+	if (err)
+		return;
+
+	if (file) {
+		inode = string_to_inode(file);
+		if (!inode)
+			return;
+		errcode = ext2fs_bmap2(current_fs, inode, 0, 0, 0,
+				       block, 0, &block);
+		if (errcode) {
+			com_err(argv[0], errcode,
+				"while mapping logical block %llu\n", block);
+			return;
+		}
+	}
+
+	buf = malloc(current_fs->blocksize);
+	if (!buf) {
+		com_err(argv[0], 0, "Couldn't allocate block buffer");
+		return;
+	}
+
+	errcode = io_channel_read_blk64(current_fs->io, block, 1, buf);
+	if (errcode) {
+		com_err(argv[0], errcode,
+			"while reading block %llu\n", block);
+		goto errout;
+	}
+
+	for (i=0; i < current_fs->blocksize; i += 16) {
+		if (suppress < 0) {
+			if (i && memcmp(buf + i, buf + i - 16, 16) == 0) {
+				suppress = i;
+				printf("*\n");
+				continue;
+			}
+		} else {
+			if (memcmp(buf + i, buf + suppress, 16) == 0)
+				continue;
+			suppress = -1;
+		}
+		printf("%04o  ", i);
+		for (j = 0; j < 16; j++) {
+			printf("%02x", buf[i+j]);
+			if ((j % 2) == 1)
+				putchar(' ');
+		}
+		putchar(' ');
+		for (j = 0; j < 16; j++)
+			printf("%c", isprint(buf[i+j]) ? buf[i+j] : '.');
+		putchar('\n');
+	}
+	putchar('\n');
+
+errout:
+	free(buf);
+	return;
+}