[git commit] hexedit: implement "[enter] goto offset" key

Denys Vlasenko vda.linux at googlemail.com
Thu Sep 14 08:51:12 UTC 2017


commit: https://git.busybox.net/busybox/commit/?id=d54f58d487bfa5d6646d9a728d503351691081bf
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

This is a must if you need to edit sector 123456789999 on your /dev/disk.

   text	   data	    bss	    dec	    hex	filename
 922745	    481	   6832	 930058	  e310a	busybox_old
 923023	    481	   6832	 930336	  e3220	busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 miscutils/hexedit.c | 79 ++++++++++++++++++++++++++++++++++++-----------------
 miscutils/less.c    |  4 +--
 2 files changed, 56 insertions(+), 27 deletions(-)

diff --git a/miscutils/hexedit.c b/miscutils/hexedit.c
index b8627e8..eaf4ba5 100644
--- a/miscutils/hexedit.c
+++ b/miscutils/hexedit.c
@@ -17,7 +17,8 @@
 
 #define ESC		"\033"
 #define HOME		ESC"[H"
-#define CLEAR		ESC"[H"ESC"[J"
+#define CLEAR		ESC"[J"
+#define CLEAR_TILL_EOL	ESC"[K"
 #define SET_ALT_SCR	ESC"[?1049h"
 #define POP_ALT_SCR	ESC"[?1049l"
 
@@ -30,7 +31,7 @@ struct globals {
 	int fd;
 	unsigned height;
 	unsigned row;
-	uint8_t *addr;
+	uint8_t *baseaddr;
 	uint8_t *current_byte;
 	uint8_t *eof_byte;
 	off_t size;
@@ -117,14 +118,15 @@ static void redraw(void)
 {
 	uint8_t *data;
 	off_t offset;
-	unsigned i;
+	unsigned i, pos;
 
-	data = G.addr;
-	offset = 0;
-	i = 0;
+	printf(HOME CLEAR);
+	data = G.baseaddr;
+	offset = G.offset;
+	pos = i = 0;
 	while (i < G.height) {
 		char buf[LINEBUF_SIZE];
-		format_line(buf, data, offset);
+		pos = format_line(buf, data, offset);
 		printf(
 			"\r\n%s" + (!i)*2, /* print \r\n only on 2nd line and later */
 			buf
@@ -133,6 +135,7 @@ static void redraw(void)
 		offset += 16;
 		i++;
 	}
+	printf(ESC"[1;%uH", pos + 1); /* position on 1st hex byte in first line */
 }
 
 static void redraw_cur_line(void)
@@ -144,7 +147,7 @@ static void redraw_cur_line(void)
 
 	column = (0xf & (uintptr_t)G.current_byte);
 	data = G.current_byte - column;
-	offset = G.offset + (data - G.addr);
+	offset = G.offset + (data - G.baseaddr);
 
 	column = column*3 + G.half;
 	column += format_line(buf, data, offset);
@@ -158,28 +161,28 @@ static void redraw_cur_line(void)
 
 static void remap(unsigned cur_pos)
 {
-	if (G.addr)
-		munmap(G.addr, G_mapsize);
+	if (G.baseaddr)
+		munmap(G.baseaddr, G_mapsize);
 
-	G.addr = mmap(NULL,
+	G.baseaddr = mmap(NULL,
 		G_mapsize,
 		PROT_READ | PROT_WRITE,
 		MAP_SHARED,
 		G.fd,
 		G.offset
 	);
-	if (G.addr == MAP_FAILED) {
+	if (G.baseaddr == MAP_FAILED) {
 		restore_term();
 		bb_perror_msg_and_die("mmap");
 	}
 
-	G.current_byte = G.addr + cur_pos;
+	G.current_byte = G.baseaddr + cur_pos;
 
-	G.eof_byte = G.addr + G_mapsize;
+	G.eof_byte = G.baseaddr + G_mapsize;
 	if ((G.size - G.offset) < G_mapsize) {
 		/* mapping covers tail of the file */
 		/* we do have a mapped byte which is past eof */
-		G.eof_byte = G.addr + (G.size - G.offset);
+		G.eof_byte = G.baseaddr + (G.size - G.offset);
 	}
 }
 static void move_mapping_further(void)
@@ -191,7 +194,7 @@ static void move_mapping_further(void)
 		return; /* can't move mapping even further, it's at the end already */
 
 	pagesize = getpagesize(); /* constant on most arches */
-	pos = G.current_byte - G.addr;
+	pos = G.current_byte - G.baseaddr;
 	if (pos >= pagesize) {
 		/* move offset up until current position is in 1st page */
 		do {
@@ -214,7 +217,7 @@ static void move_mapping_lower(void)
 		return; /* we are at 0 already */
 
 	pagesize = getpagesize(); /* constant on most arches */
-	pos = G.current_byte - G.addr;
+	pos = G.current_byte - G.baseaddr;
 
 	/* move offset down until current position is in last page */
 	pos += pagesize;
@@ -252,18 +255,15 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv)
 	G.size = xlseek(G.fd, 0, SEEK_END);
 
 	/* TERMIOS_RAW_CRNL suppresses \n -> \r\n translation, helps with down-arrow */
+	printf(SET_ALT_SCR);
 	set_termios_to_raw(STDIN_FILENO, &G.orig_termios, TERMIOS_RAW_CRNL);
 	bb_signals(BB_FATAL_SIGS, sig_catcher);
 
 	remap(0);
-
-	printf(SET_ALT_SCR);
 	redraw();
-	printf(ESC"[1;10H"); /* position on 1st hex byte in first line */
 
 //TODO: //Home/End: start/end of line; '<'/'>': start/end of file
 	//Backspace: undo
-	//Enter: goto specified position
 	//Ctrl-L: redraw
 	//Ctrl-Z: suspend
 	//'/', Ctrl-S: search
@@ -367,9 +367,9 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv)
 			}
 			if ((0xf & (uintptr_t)G.current_byte) == 0) {
 				/* leftmost pos, wrap to prev line */
-				if (G.current_byte == G.addr) {
+				if (G.current_byte == G.baseaddr) {
 					move_mapping_lower();
-					if (G.current_byte == G.addr)
+					if (G.current_byte == G.baseaddr)
 						break; /* first line, don't do anything */
 				}
 				G.half = 1;
@@ -385,9 +385,9 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv)
 			cnt = G.height;
 		case KEYCODE_UP:
  k_up:
-			if ((G.current_byte - G.addr) < 16) {
+			if ((G.current_byte - G.baseaddr) < 16) {
 				move_mapping_lower();
-				if ((G.current_byte - G.addr) < 16)
+				if ((G.current_byte - G.baseaddr) < 16)
 					break;
 			}
 			G.current_byte -= 16;
@@ -403,6 +403,35 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv)
 			if (--cnt)
 				goto k_up;
 			break;
+
+		case '\n':
+		case '\r':
+			/* [Enter]: goto specified position */
+			{
+				char buf[sizeof(G.offset)*3 + 4];
+				printf(ESC"[999;1H" CLEAR_TILL_EOL); /* go to last line */
+				if (read_line_input(NULL, "Go to (dec,0Xhex,0oct): ", buf, sizeof(buf)) >= 0) {
+					off_t t;
+					unsigned pgmask;
+
+					t = bb_strtoull(buf, NULL, 0);
+					if (t >= G.size)
+						t = G.size - 1;
+					pgmask = getpagesize() - 1;
+					cnt = t & pgmask;
+					t = t & ~(off_t)pgmask;
+					if (t < 0)
+						cnt = t = 0;
+					G.offset = t;
+					remap(0);
+					redraw();
+					cnt /= 16;
+					if (cnt)
+						goto k_down;
+					break;
+				}
+				/* EOF/error on input: fall through to exiting */
+			}
 		case CTRL('X'):
 			restore_term();
 			return EXIT_SUCCESS;
diff --git a/miscutils/less.c b/miscutils/less.c
index f869a9e..d524b6c 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -281,9 +281,9 @@ static void set_tty_cooked(void)
 
 /* Move the cursor to a position (x,y), where (0,0) is the
    top-left corner of the console */
-static void move_cursor(int line, int row)
+static void move_cursor(int line, int col)
 {
-	printf(ESC"[%u;%uH", line, row);
+	printf(ESC"[%u;%uH", line, col);
 }
 
 static void clear_line(void)


More information about the busybox-cvs mailing list