[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