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:
parent
f032f7b307
commit
4767c42c11
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
14
bin/dd/dd.c
14
bin/dd/dd.c
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user