tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: humanize_number(3) for dd(1) summary?
On 02.11.2011 15:39, Izumi Tsutsui wrote:
The attached patch extends dd(1) in a way that permits specifying either:
- a msgfmt, with "human", "quiet", "posix" currently in place
- an arbitrary format, when passed as msgfmt=... to command line by user.
It's better to have #ifdef option which disables the new feature
(as current #ifdef NO_CONV via SMALLPROG in Makefile)
for crunched binaries on poor install media.
Done. The option is NO_MSGFMT.
Total binary size:
new dd: 29920
new dd, with SMALLPROG: 24864
old dd: 26677
old dd, with SMALLPROG: 22028
The increase is therefore ~2.5kiB with the modifications when compared
with the old binary.
--
Jean-Yves Migeon
jeanyves.migeon%free.fr@localhost
? .gdbinit
? dd
? dd.cat1
? dd.html1
? rump.dd
Index: Makefile
===================================================================
RCS file: /cvsroot/src/bin/dd/Makefile,v
retrieving revision 1.15
diff -u -p -r1.15 Makefile
--- Makefile 4 Feb 2011 19:42:12 -0000 1.15
+++ Makefile 2 Nov 2011 22:21:55 -0000
@@ -8,7 +8,7 @@ DPADD+= ${LIBUTIL}
LDADD+= -lutil
.ifdef SMALLPROG
-CPPFLAGS+= -DNO_CONV -DSMALL
+CPPFLAGS+= -DNO_CONV -DNO_MSGFMT -DSMALL
.else
SRCS+= conv_tab.c
.ifndef CRUNCHEDPROG
Index: args.c
===================================================================
RCS file: /cvsroot/src/bin/dd/args.c,v
retrieving revision 1.35
diff -u -p -r1.35 args.c
--- args.c 16 Sep 2011 16:06:23 -0000 1.35
+++ args.c 2 Nov 2011 22:21:55 -0000
@@ -64,11 +64,13 @@ static void f_cbs(char *);
#ifdef NO_CONV
__dead
#endif
+
static void f_conv(char *);
static void f_count(char *);
static void f_files(char *);
static void f_ibs(char *);
static void f_if(char *);
+static void f_msgfmt(char *);
static void f_obs(char *);
static void f_of(char *);
static void f_seek(char *);
@@ -90,6 +92,7 @@ static const struct arg {
{ "ibs", f_ibs, C_IBS, C_BS|C_IBS },
{ "if", f_if, C_IF, C_IF },
{ "iseek", f_skip, C_SKIP, C_SKIP },
+ { "msgfmt", f_msgfmt, C_SKIP, C_SKIP },
{ "obs", f_obs, C_OBS, C_BS|C_OBS },
{ "of", f_of, C_OF, C_OF },
{ "oseek", f_seek, C_SEEK, C_SEEK },
@@ -105,6 +108,7 @@ void
jcl(char **argv)
{
struct arg *ap, tmp;
+ //struct dd_msgfmt *fmt;
char *oper, *arg;
in.dbsz = out.dbsz = 512;
@@ -252,6 +256,24 @@ f_if(char *arg)
in.name = arg;
}
+#ifdef NO_MSGFMT
+/* Build a small version (i.e. for a ramdisk root) */
+static void
+f_msgfmt(char *arg)
+{
+
+ errx(EXIT_FAILURE, "msgfmt option disabled");
+ /* NOTREACHED */
+}
+#else /* NO_MSGFMT */
+static void
+f_msgfmt(char *arg)
+{
+
+ msgfmt = arg;
+}
+#endif /* NO_MSGFMT */
+
static void
f_obs(char *arg)
{
Index: dd.c
===================================================================
RCS file: /cvsroot/src/bin/dd/dd.c,v
retrieving revision 1.47
diff -u -p -r1.47 dd.c
--- dd.c 4 Feb 2011 19:42:12 -0000 1.47
+++ dd.c 2 Nov 2011 22:21:55 -0000
@@ -86,6 +86,7 @@ u_int files_cnt = 1; /* # of files to
uint64_t progress = 0; /* display sign of life */
const u_char *ctab; /* conversion table */
sigset_t infoset; /* a set blocking SIGINFO */
+const char *msgfmt = "posix"; /* specifies summary() message format */
/*
* Ops for stdin/stdout and crunch'd dd. These are always host ops.
Index: extern.h
===================================================================
RCS file: /cvsroot/src/bin/dd/extern.h,v
retrieving revision 1.20
diff -u -p -r1.20 extern.h
--- extern.h 16 Sep 2011 16:06:23 -0000 1.20
+++ extern.h 2 Nov 2011 22:21:55 -0000
@@ -74,3 +74,4 @@ extern const u_char a2e_32V[], a2e_POSIX
extern const u_char e2a_32V[], e2a_POSIX[];
extern const u_char a2ibm_32V[], a2ibm_POSIX[];
extern u_char casetab[];
+extern const char *msgfmt;
Index: misc.c
===================================================================
RCS file: /cvsroot/src/bin/dd/misc.c,v
retrieving revision 1.21
diff -u -p -r1.21 misc.c
--- misc.c 5 Oct 2007 07:23:09 -0000 1.21
+++ misc.c 2 Nov 2011 22:21:55 -0000
@@ -59,50 +59,104 @@ __RCSID("$NetBSD: misc.c,v 1.21 2007/10/
#define tv2mS(tv) ((tv).tv_sec * 1000LL + ((tv).tv_usec + 500) / 1000)
+static void posix_summary(void);
+static int dd_snprintf(char *, size_t, const char *);
+
+#ifndef NO_MSGFMT
+static void custom_summary(void);
+static void human_summary(void);
+static void quiet_summary(void);
+
+static void
+custom_summary(void)
+{
+ char buf[1024];
+
+ dd_snprintf(buf, sizeof(buf), msgfmt);
+
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+}
+
+static void
+human_summary(void)
+{
+ char buf[100];
+
+ /* Use snprintf(3) so that we don't reenter stdio(3). */
+ (void)dd_snprintf(buf, sizeof(buf),
+ "%I+%i records in\n%O+%o records out\n");
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+ if (st.swab) {
+ (void)dd_snprintf(buf, sizeof(buf), "%w odd length swab %W\n");
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+ }
+ if (st.trunc) {
+ (void)dd_snprintf(buf, sizeof(buf), "%t truncated %T\n");
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+ }
+ if (st.sparse) {
+ (void)dd_snprintf(buf, sizeof(buf), "%p sparse output %P\n");
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+ }
+ (void)dd_snprintf(buf, sizeof(buf),
+ "%b bytes (%B) transferred in %s secs (%e bytes/sec - %E)\n");
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+}
+
+static void
+quiet_summary(void)
+{
+
+ /* stay quiet */
+}
+#endif /* NO_MSGFMT */
+
void
summary(void)
{
- char buf[100];
- int64_t mS;
- struct timeval tv;
if (progress)
(void)write(STDERR_FILENO, "\n", 1);
- (void)gettimeofday(&tv, NULL);
- mS = tv2mS(tv) - tv2mS(st.start);
- if (mS == 0)
- mS = 1;
+#ifdef NO_MSGFMT
+ return posix_summary();
+#else /* NO_MSGFMT */
+ if (strncmp(msgfmt, "human", sizeof("human")) == 0)
+ return human_summary();
+
+ if (strncmp(msgfmt, "posix", sizeof("posix")) == 0)
+ return posix_summary();
+
+ if (strncmp(msgfmt, "quiet", sizeof("quiet")) == 0)
+ return quiet_summary();
+
+ return custom_summary();
+#endif /* NO_MSGFMT */
+}
+
+static void
+posix_summary(void)
+{
+ char buf[100];
+
/* Use snprintf(3) so that we don't reenter stdio(3). */
- (void)snprintf(buf, sizeof(buf),
- "%llu+%llu records in\n%llu+%llu records out\n",
- (unsigned long long)st.in_full, (unsigned long long)st.in_part,
- (unsigned long long)st.out_full, (unsigned long long)st.out_part);
+ (void)dd_snprintf(buf, sizeof(buf),
+ "%I+%i records in\n%O+%o records out\n");
(void)write(STDERR_FILENO, buf, strlen(buf));
if (st.swab) {
- (void)snprintf(buf, sizeof(buf), "%llu odd length swab %s\n",
- (unsigned long long)st.swab,
- (st.swab == 1) ? "block" : "blocks");
+ (void)dd_snprintf(buf, sizeof(buf), "%w odd length swab %W\n");
(void)write(STDERR_FILENO, buf, strlen(buf));
}
if (st.trunc) {
- (void)snprintf(buf, sizeof(buf), "%llu truncated %s\n",
- (unsigned long long)st.trunc,
- (st.trunc == 1) ? "block" : "blocks");
+ (void)dd_snprintf(buf, sizeof(buf), "%t truncated %T\n");
(void)write(STDERR_FILENO, buf, strlen(buf));
}
if (st.sparse) {
- (void)snprintf(buf, sizeof(buf), "%llu sparse output %s\n",
- (unsigned long long)st.sparse,
- (st.sparse == 1) ? "block" : "blocks");
+ (void)dd_snprintf(buf, sizeof(buf), "%p sparse output %P\n");
(void)write(STDERR_FILENO, buf, strlen(buf));
}
- (void)snprintf(buf, sizeof(buf),
- "%llu bytes transferred in %lu.%03d secs (%llu bytes/sec)\n",
- (unsigned long long) st.bytes,
- (long) (mS / 1000),
- (int) (mS % 1000),
- (unsigned long long) (st.bytes * 1000LL / mS));
+ (void)dd_snprintf(buf, sizeof(buf),
+ "%b bytes transferred in %s secs (%e bytes/sec)\n");
(void)write(STDERR_FILENO, buf, strlen(buf));
}
@@ -123,3 +177,124 @@ terminate(int signo)
(void)raise_default_signal(signo);
_exit(127);
}
+
+static int
+dd_snprintf(char *sbuf, size_t len, const char *fmt)
+{
+ char nbuf[64], hbuf[7];
+ char *ebuf = &sbuf[len - 1], *buf = sbuf;
+ const char *ptr, *s;
+ int64_t mS;
+ struct timeval tv;
+
+ (void)gettimeofday(&tv, NULL);
+ mS = tv2mS(tv) - tv2mS(st.start);
+ if (mS == 0)
+ mS = 1;
+
+#define ADDC(c) do { if (buf < ebuf) *buf++ = c; else buf++; } \
+ while (/*CONSTCOND*/0)
+#define ADDS(p) do { for (s = p; *s; s++) ADDC(*s); } \
+ while (/*CONSTCOND*/0)
+
+ for (ptr = fmt; *ptr; ptr++) {
+ if (*ptr != '%') {
+ ADDC(*ptr);
+ continue;
+ }
+
+ switch (*++ptr) {
+ case 'b':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long)st.bytes);
+ ADDS(nbuf);
+ break;
+ case 'B':
+ if (humanize_number(hbuf, sizeof(hbuf),
+ st.bytes, "B",
+ HN_AUTOSCALE, HN_DECIMAL) == -1)
+ warnx("humanize_number (bytes transferred)");
+ ADDS(hbuf);
+ break;
+ case 'e':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long) (st.bytes * 1000LL / mS));
+ ADDS(nbuf);
+ break;
+ case 'E':
+ if (humanize_number(hbuf, sizeof(hbuf),
+ st.bytes * 1000LL / mS, "B",
+ HN_AUTOSCALE, HN_DECIMAL) == -1)
+ warnx("humanize_number (bytes per second)");
+ ADDS(hbuf); ADDS("/sec");
+ break;
+ case 'i':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long)st.in_part);
+ ADDS(nbuf);
+ break;
+ case 'I':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long)st.in_full);
+ ADDS(nbuf);
+ break;
+ case 'o':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long)st.out_part);
+ ADDS(nbuf);
+ break;
+ case 'O':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long)st.out_full);
+ ADDS(nbuf);
+ break;
+ case 's':
+ (void)snprintf(nbuf, sizeof(nbuf), "%li.%03d",
+ (long) (mS / 1000), (int) (mS % 1000));
+ ADDS(nbuf);
+ break;
+ case 'p':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long)st.sparse);
+ ADDS(nbuf);
+ break;
+ case 't':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long)st.trunc);
+ ADDS(nbuf);
+ break;
+ case 'w':
+ (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+ (unsigned long long)st.swab);
+ ADDS(nbuf);
+ break;
+ case 'P':
+ ADDS("record");
+ if (st.sparse != 1) ADDS("s");
+ break;
+ case 'T':
+ ADDS("record");
+ if (st.trunc != 1) ADDS("s");
+ break;
+ case 'W':
+ ADDS("record");
+ if (st.swab != 1) ADDS("s");
+ break;
+ default:
+ ADDC('%');
+ if (*ptr == '\0')
+ goto done;
+ /*FALLTHROUGH*/
+ case '%':
+ ADDC(*ptr);
+ break;
+ }
+ }
+
+done:
+ if (buf < ebuf)
+ *buf = '\0';
+ else if (len != 0)
+ sbuf[len - 1] = '\0';
+ return (int)(buf - sbuf);
+}
Home |
Main Index |
Thread Index |
Old Index