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 04.11.2011 12:11, Izumi Tsutsui wrote:
On 03.11.2011 18:53, Jean-Yves Migeon wrote:
Can't dd_snprintf() be also optional if it occupies ~2.5KiB?
I can; there's one trade off though:
- the SMALLPROG dd(1) becomes smaller (by about 2.2kiB), which is still
approx. 200 bytes bigger than the original SMALLPROG dd(1)
- the normal dd(1) becomes bigger (approx. 600B), as we don't factor
posix/human/quiet summary() anymore.
Forgot to ask -- which way you prefer? I don't mind, personally.
I'd like smaller SMALLPROG one, for people who want dd(1)
on rescue media to zap leftover labels on their disks etc.
okay, last call, this time with an updated dd(1).
If nobody objects I'll commit it in a few days.
--
Jean-Yves Migeon
jeanyves.migeon%free.fr@localhost
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 5 Nov 2011 01:42:13 -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 5 Nov 2011 01:42:13 -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 },
@@ -252,6 +255,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.1
===================================================================
RCS file: /cvsroot/src/bin/dd/dd.1,v
retrieving revision 1.23
diff -u -p -r1.23 dd.1
--- dd.1 22 Dec 2010 09:42:53 -0000 1.23
+++ dd.1 5 Nov 2011 01:42:14 -0000
@@ -32,7 +32,7 @@
.\"
.\" @(#)dd.1 8.2 (Berkeley) 1/13/94
.\"
-.Dd December 22, 2010
+.Dd November 05, 2011
.Dt DD 1
.Os
.Sh NAME
@@ -97,6 +97,74 @@ Seek on the input file
blocks.
This is synonymous with
.Cm skip= Ns Ar n .
+.It Cm msgfmt= Ns Ar fmt
+Specify the message format
+.Ar fmt
+to be used when writing information to standard output.
+Possible values are:
+.Bl -tag -width xxxxx -offset indent -compact
+.It quiet
+turns off information summary report except for errors and
+.Cm progress .
+.It posix
+default information summary report as specified by POSIX.
+.It human
+default information summary report extended with human-readable
+values.
+.El
+.Pp
+When
+.Ar fmt
+does not correspond to any value given above,
+it contains a string that will be used as format specifier
+for the information summary output.
+Each conversion specification is introduced by the character
+.Cm % .
+The following ones are available:
+.Bl -tag -width xx -offset indent -compact
+.It b
+total number of bytes transferred
+.It B
+total number of bytes transferred in
+.Xr humanize_number 3
+format
+.It e
+speed transfer
+.It E
+speed transfer in
+.Xr humanize_number 3
+format
+.It i
+number of partial input block(s)
+.It I
+number of full input block(s)
+.It o
+number of partial output block(s)
+.It O
+number of full output block(s)
+.It s
+time elapsed since the beginning in
+.Do seconds.ms Dc
+format
+.It p
+number of sparse output blocks
+.It t
+number of truncated blocks
+.It w
+number of odd-length swab blocks
+.It P
+singular/plural of
+.Do block Dc ,
+depending on number of sparse blocks
+.It T
+singular/plural of
+.Do block Dc ,
+depending on number of truncated blocks
+.It W
+singular/plural of
+.Do block Dc ,
+depending on number of swab blocks
+.El
.It Cm obs= Ns Ar n
Set the output block size to
.Va n
@@ -370,6 +438,18 @@ will exit.
The
.Nm
utility exits 0 on success and \*[Gt]0 if an error occurred.
+.Sh EXAMPLES
+To print summary information in human-readable form:
+.Pp
+.Dl dd if=/dev/zero of=/dev/null count=1 msgfmt=human
+.Pp
+To customize the information summary output and print it through
+.Xr unvis 3 :
+.Pp
+.Bd -literal -offset indent
+dd if=/dev/zero of=/dev/null count=1 \e
+ msgfmt='speed:%E, in %s seconds\en' 2\*[Gt]\*[Am]1 | unvis
+.Ed
.Sh SEE ALSO
.Xr cp 1 ,
.Xr mt 1 ,
@@ -382,7 +462,9 @@ utility is expected to be a superset of
standard.
The
.Cm files
-operand and the
+and
+.Cm msgfmt
+operands and the
.Cm ascii ,
.Cm ebcdic ,
.Cm ibm ,
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 5 Nov 2011 01:42:14 -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"; /* default 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 5 Nov 2011 01:42:14 -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 5 Nov 2011 01:42:14 -0000
@@ -59,9 +59,41 @@ __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);
+#ifndef NO_MSGFMT
+static void custom_summary(void);
+static void human_summary(void);
+static void quiet_summary(void);
+
+static int dd_snprintf(char *, size_t, const char *);
+#endif /* NO_MSGFMT */
+
void
summary(void)
{
+
+ if (progress)
+ (void)write(STDERR_FILENO, "\n", 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];
int64_t mS;
struct timeval tv;
@@ -123,3 +155,169 @@ terminate(int signo)
(void)raise_default_signal(signo);
_exit(127);
}
+
+#ifndef NO_MSGFMT
+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("block");
+ if (st.sparse != 1) ADDS("s");
+ break;
+ case 'T':
+ ADDS("block");
+ if (st.trunc != 1) ADDS("s");
+ break;
+ case 'W':
+ ADDS("block");
+ 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);
+}
+
+static void
+custom_summary(void)
+{
+ char buf[1024];
+
+ (void)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 */
Home |
Main Index |
Thread Index |
Old Index