dd: add status=progress support

This reports the current status on a single line every second, mirroring
similar functionality in GNU dd, and carefully interacts with SIGINFO.

PR:		229615
Submitted by:	Thomas Hurst <tom@hur.st> (modified for style(9) nits by me)
MFC after:	1 week
This commit is contained in:
Kyle Evans 2018-08-08 21:37:02 +00:00
parent f032f7b307
commit 4767c42c11
6 changed files with 59 additions and 2 deletions

View File

@ -306,6 +306,8 @@ f_status(char *arg)
ddflags |= C_NOINFO;
else if (strcmp(arg, "noxfer") == 0)
ddflags |= C_NOXFER;
else if (strcmp(arg, "progress") == 0)
ddflags |= C_PROGRESS;
else
errx(1, "unknown status %s", arg);
}

View File

@ -32,7 +32,7 @@
.\" @(#)dd.1 8.2 (Berkeley) 1/13/94
.\" $FreeBSD$
.\"
.Dd April 2, 2017
.Dd August 8, 2018
.Dt DD 1
.Os
.Sh NAME
@ -164,12 +164,14 @@ bytes per second.
Where
.Cm value
is one of the symbols from the following list.
.Bl -tag -width "noxfer"
.Bl -tag -width "progress"
.It Cm noxfer
Do not print the transfer statistics as the last line of status output.
.It Cm none
Do not print the status output.
Error messages are shown; informational messages are not.
.It Cm progress
Print basic transfer statistics once per second.
.El
.It Cm conv Ns = Ns Ar value Ns Op , Ns Ar value ...
Where

View File

@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <sys/disklabel.h>
#include <sys/filio.h>
#include <sys/mtio.h>
#include <sys/time.h>
#include <assert.h>
#include <capsicum_helpers.h>
@ -89,6 +90,7 @@ const u_char *ctab; /* conversion table */
char fill_char; /* Character to fill with if defined */
size_t speed = 0; /* maximum speed, in bytes per second */
volatile sig_atomic_t need_summary;
volatile sig_atomic_t need_progress;
int
main(int argc __unused, char *argv[])
@ -102,6 +104,7 @@ main(int argc __unused, char *argv[])
err(1, "unable to enter capability mode");
(void)signal(SIGINFO, siginfo_handler);
(void)signal(SIGALRM, sigalrm_handler);
(void)signal(SIGINT, terminate);
atexit(summary);
@ -281,6 +284,14 @@ setup(void)
ctab = casetab;
}
if ((ddflags & C_PROGRESS)) {
struct itimerval timer = {
.it_interval = { .tv_sec = 1, .tv_usec = 0 },
.it_value = { .tv_sec = 1, .tv_usec = 0 },
};
setitimer(ITIMER_REAL, &timer, NULL);
}
if (clock_gettime(CLOCK_MONOTONIC, &st.start))
err(1, "clock_gettime");
}
@ -461,6 +472,9 @@ dd_in(void)
if (need_summary) {
summary();
}
if (need_progress) {
progress();
}
}
}

View File

@ -100,5 +100,6 @@ typedef struct {
#define C_STATUS 0x08000000
#define C_NOXFER 0x10000000
#define C_NOINFO 0x20000000
#define C_PROGRESS 0x40000000
#define C_PARITY (C_PAREVEN | C_PARODD | C_PARNONE | C_PARSET)

View File

@ -46,7 +46,9 @@ void pos_in(void);
void pos_out(void);
double secs_elapsed(void);
void summary(void);
void progress(void);
void siginfo_handler(int);
void sigalrm_handler(int);
void terminate(int);
void unblock(void);
void unblock_close(void);
@ -66,3 +68,4 @@ extern const u_char a2ibm_32V[], a2ibm_POSIX[];
extern u_char casetab[];
extern char fill_char;
extern volatile sig_atomic_t need_summary;
extern volatile sig_atomic_t need_progress;

View File

@ -56,6 +56,8 @@ __FBSDID("$FreeBSD$");
#include "dd.h"
#include "extern.h"
static int need_newline;
double
secs_elapsed(void)
{
@ -83,6 +85,9 @@ summary(void)
if (ddflags & C_NOINFO)
return;
if (need_newline && !need_summary)
fprintf(stderr, "\n");
secs = secs_elapsed();
(void)fprintf(stderr,
@ -102,6 +107,28 @@ summary(void)
need_summary = 0;
}
void
progress(void)
{
double secs;
static int lastlen;
int len;
secs = secs_elapsed();
len = fprintf(stderr,
"\r%ju bytes transferred in %.0f secs (%.0f bytes/sec)",
st.bytes, secs, st.bytes / secs);
if (len > 0) {
if (len < lastlen)
(void)fprintf(stderr, "%*s", len - lastlen, "");
lastlen = len;
}
need_newline = 1;
need_progress = 0;
}
/* ARGSUSED */
void
siginfo_handler(int signo __unused)
@ -110,6 +137,14 @@ siginfo_handler(int signo __unused)
need_summary = 1;
}
/* ARGSUSED */
void
sigalrm_handler(int signo __unused)
{
need_progress = 1;
}
/* ARGSUSED */
void
terminate(int sig)