[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox
Subject:    [PATCH] Add conv=swab support to dd
From:       Álvaro_Fernández_Rojas <noltari () gmail ! com>
Date:       2013-07-27 17:22:28
Message-ID: 51F401D4.9000407 () gmail ! com
[Download RAW message or body]

This patch adds support for swapping the endiannes of a file.
It's based on GNU coreutils "dd.c".

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
diff --git a/coreutils/dd.c b/coreutils/dd.c
index 96602eb..038fc4a 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -10,7 +10,7 @@
 
 //usage:#define dd_trivial_usage
 //usage:       "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") \
                "[bs=N] [count=N] [skip=N]\n"
-//usage:       "	[seek=N]" IF_FEATURE_DD_IBS_OBS(" \
[conv=notrunc|noerror|sync|fsync]") +//usage:       "	[seek=N]" \
IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync|swab]")  //usage:#define \
dd_full_usage "\n\n"  //usage:       "Copy a file with converting and formatting\n"
 //usage:     "\n	if=FILE		Read from FILE instead of stdin"
@@ -30,6 +30,7 @@
 //usage:     "\n	conv=noerror	Continue after read errors"
 //usage:     "\n	conv=sync	Pad blocks with zeros"
 //usage:     "\n	conv=fsync	Physically write data out before finishing"
+//usage:     "\n	conv=swab	Swap the order of every pair of input bytes"
 //usage:	)
 //usage:     "\n"
 //usage:     "\nNumbers may be suffixed by c (x1), w (x2), b (x512), kD (x1000), k \
(x1024)," @@ -42,6 +43,8 @@
 
 #include "libbb.h"
 
+#define SWAB_ALIGN_OFFSET 2
+
 /* This is a NOEXEC applet. Be very careful! */
 
 
@@ -139,6 +142,42 @@ static bool write_and_stats(const void *buf, size_t len, size_t \
obs,  return 0;
 }
 
+/* If true, the last char from the previous call to 'swab_buffer'
+	is saved in 'saved_char'. */
+static bool char_is_saved = false;
+/* Odd char from previous call. */
+static char saved_char;
+/* Swap NREAD bytes in BUF, plus possibly an initial char from the
+	previous call. If NREAD is odd, save the last char for the
+	next call. Return the new start of the BUF buffer. */
+static char *swab_buffer(char *buf, size_t *nread)
+{
+	char *bufstart = buf, *cp;
+	size_t i;
+
+	/* Is a char left from last time? */
+	if (char_is_saved) {
+		*--bufstart = saved_char;
+		(*nread)++;
+		char_is_saved = false;
+    }
+
+	if (*nread & 1) {
+		/* An odd number of chars are in the buffer. */
+		saved_char = bufstart[--*nread];
+		char_is_saved = true;
+	}
+
+	/* Do the byte-swapping by moving every second character two
+		positions toward the end, working from the end of the buffer
+		toward the beginning. This way we only move half of the data. */
+	cp = bufstart + *nread;	/* Start one char past the last. */
+	for (i = *nread / 2; i; i--, cp -= 2)
+		*cp = *(cp - 2);
+
+	return ++bufstart;
+}
+
 #if ENABLE_LFS
 # define XATOU_SFX xatoull_sfx
 #else
@@ -155,9 +194,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
 		FLAG_SYNC    = 1 << 1,
 		FLAG_NOERROR = 1 << 2,
 		FLAG_FSYNC   = 1 << 3,
+		FLAG_SWAB    = 1 << 4,
 		/* end of conv flags */
-		FLAG_TWOBUFS = 1 << 4,
-		FLAG_COUNT   = 1 << 5,
+		FLAG_TWOBUFS = 1 << 5,
+		FLAG_COUNT   = 1 << 6,
 	};
 	static const char keywords[] ALIGN1 =
 		"bs\0""count\0""seek\0""skip\0""if\0""of\0"
@@ -167,7 +207,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
 		;
 #if ENABLE_FEATURE_DD_IBS_OBS
 	static const char conv_words[] ALIGN1 =
-		"notrunc\0""sync\0""noerror\0""fsync\0";
+		"notrunc\0""sync\0""noerror\0""fsync\0""swab\0";
 #endif
 	enum {
 		OP_bs = 0,
@@ -185,11 +225,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
 		OP_conv_sync,
 		OP_conv_noerror,
 		OP_conv_fsync,
+		OP_conv_swab,
 	/* Unimplemented conv=XXX: */
 	//nocreat       do not create the output file
 	//excl          fail if the output file already exists
 	//fdatasync     physically write output file data before finishing
-	//swab          swap every pair of input bytes
 	//lcase         change upper case to lower case
 	//ucase         change lower case to upper case
 	//block         pad newline-terminated records with spaces to cbs-size
@@ -303,7 +343,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
 	} /* end of "for (argv[n])" */
 
 //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever
-	ibuf = obuf = xmalloc(ibs);
+	ibuf = obuf = xmalloc(ibs + SWAB_ALIGN_OFFSET * 2);
+	ibuf += SWAB_ALIGN_OFFSET;	/* allow space for swab */
 	if (ibs != obs) {
 		flags |= FLAG_TWOBUFS;
 		obuf = xmalloc(obs);
@@ -384,6 +425,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
 				n = ibs;
 			}
 		}
+
+		if (flags & FLAG_SWAB) {
+			ibuf = swab_buffer(ibuf, &n);
+		}
+
 		if (flags & FLAG_TWOBUFS) {
 			char *tmp = ibuf;
 			while (n) {
_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic