From 875ce094cf2d421ba05bed6cfd6c948084d52abe Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 14 May 2019 17:46:18 +0200 Subject: [PATCH] dd: fix handling of short result of full_write(), closes 11711 $ dd bs=1G --- coreutils/dd.c | 26 +++++++++++++------------- libbb/full_write.c | 3 ++- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/coreutils/dd.c b/coreutils/dd.c index 2fb9da77c..b5f3cbec5 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -192,23 +192,15 @@ static void dd_output_status(int UNUSED_PARAM cur_signal) #endif } -static ssize_t full_write_or_warn(const void *buf, size_t len, - const char *const filename) -{ - ssize_t n = full_write(ofd, buf, len); - if (n < 0) - bb_perror_msg("writing '%s'", filename); - return n; -} - static bool write_and_stats(const void *buf, size_t len, size_t obs, const char *filename) { - ssize_t n = full_write_or_warn(buf, len, filename); - if (n < 0) - return 1; + ssize_t n; + + n = full_write(ofd, buf, len); #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE - G.total_bytes += n; + if (n > 0) + G.total_bytes += n; #endif if ((size_t)n == obs) { G.out_full++; @@ -218,6 +210,14 @@ static bool write_and_stats(const void *buf, size_t len, size_t obs, G.out_part++; return 0; } + /* n is < len (and possibly is -1). + * Even if n >= 0, errno is usually set correctly. + * For example, if writing to block device and getting ENOSPC, + * full_write() first sees a short write, then tries to write + * the remainder and gets errno set to ENOSPC. + * It returns n > 0 (the amount which it did write). + */ + bb_perror_msg("error writing '%s'", filename); return 1; } diff --git a/libbb/full_write.c b/libbb/full_write.c index 2b7983f4c..15766fc6c 100644 --- a/libbb/full_write.c +++ b/libbb/full_write.c @@ -11,7 +11,8 @@ /* * Write all of the supplied buffer out to a file. * This does multiple writes as necessary. - * Returns the amount written, or -1 on an error. + * Returns the amount written, or -1 if error was seen + * on the very first write. */ ssize_t FAST_FUNC full_write(int fd, const void *buf, size_t len) {