diff options
Diffstat (limited to 'bin/dd/dd.c')
-rw-r--r-- | bin/dd/dd.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/bin/dd/dd.c b/bin/dd/dd.c index 4c31a5e..56f8efe 100644 --- a/bin/dd/dd.c +++ b/bin/dd/dd.c @@ -82,6 +82,7 @@ size_t cbsz; /* conversion block size */ uintmax_t files_cnt = 1; /* # of files to copy */ 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; int @@ -276,6 +277,29 @@ getfdtype(IO *io) io->flags |= ISSEEK; } +/* + * Limit the speed by adding a delay before every block read. + * The delay (t_usleep) is equal to the time computed from block + * size and the specified speed limit (t_target) minus the time + * spent on actual read and write operations (t_io). + */ +static void +speed_limit(void) +{ + static double t_prev, t_usleep; + double t_now, t_io, t_target; + + t_now = secs_elapsed(); + t_io = t_now - t_prev - t_usleep; + t_target = (double)in.dbsz / (double)speed; + t_usleep = t_target - t_io; + if (t_usleep > 0) + usleep(t_usleep * 1000000); + else + t_usleep = 0; + t_prev = t_now; +} + static void dd_in(void) { @@ -293,6 +317,9 @@ dd_in(void) break; } + if (speed > 0) + speed_limit(); + /* * Zero the buffer first if sync; if doing block operations, * use spaces. |