aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2019-05-14 17:46:18 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2019-05-14 17:49:14 +0200
commit875ce094cf2d421ba05bed6cfd6c948084d52abe (patch)
tree90bff2304d2bb604d170a16715e924b2a6947597
parent8c317f03f6d4d89fd7b0cc1e6eaf515040b8e701 (diff)
downloadbusybox-w32-875ce094cf2d421ba05bed6cfd6c948084d52abe.tar.gz
busybox-w32-875ce094cf2d421ba05bed6cfd6c948084d52abe.tar.bz2
busybox-w32-875ce094cf2d421ba05bed6cfd6c948084d52abe.zip
dd: fix handling of short result of full_write(), closes 11711
$ dd bs=1G <sda1 of=/dev/sda1 dd: error writing '/dev/sda1': No space left on device 1+0 records in 0+0 records out 999292928 bytes (953.0MB) copied, 0.784617 seconds, 1.2GB/s function old new delta write_and_stats 99 102 +3 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--coreutils/dd.c26
-rw-r--r--libbb/full_write.c3
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)
192#endif 192#endif
193} 193}
194 194
195static ssize_t full_write_or_warn(const void *buf, size_t len,
196 const char *const filename)
197{
198 ssize_t n = full_write(ofd, buf, len);
199 if (n < 0)
200 bb_perror_msg("writing '%s'", filename);
201 return n;
202}
203
204static bool write_and_stats(const void *buf, size_t len, size_t obs, 195static bool write_and_stats(const void *buf, size_t len, size_t obs,
205 const char *filename) 196 const char *filename)
206{ 197{
207 ssize_t n = full_write_or_warn(buf, len, filename); 198 ssize_t n;
208 if (n < 0) 199
209 return 1; 200 n = full_write(ofd, buf, len);
210#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE 201#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
211 G.total_bytes += n; 202 if (n > 0)
203 G.total_bytes += n;
212#endif 204#endif
213 if ((size_t)n == obs) { 205 if ((size_t)n == obs) {
214 G.out_full++; 206 G.out_full++;
@@ -218,6 +210,14 @@ static bool write_and_stats(const void *buf, size_t len, size_t obs,
218 G.out_part++; 210 G.out_part++;
219 return 0; 211 return 0;
220 } 212 }
213 /* n is < len (and possibly is -1).
214 * Even if n >= 0, errno is usually set correctly.
215 * For example, if writing to block device and getting ENOSPC,
216 * full_write() first sees a short write, then tries to write
217 * the remainder and gets errno set to ENOSPC.
218 * It returns n > 0 (the amount which it did write).
219 */
220 bb_perror_msg("error writing '%s'", filename);
221 return 1; 221 return 1;
222} 222}
223 223
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 @@
11/* 11/*
12 * Write all of the supplied buffer out to a file. 12 * Write all of the supplied buffer out to a file.
13 * This does multiple writes as necessary. 13 * This does multiple writes as necessary.
14 * Returns the amount written, or -1 on an error. 14 * Returns the amount written, or -1 if error was seen
15 * on the very first write.
15 */ 16 */
16ssize_t FAST_FUNC full_write(int fd, const void *buf, size_t len) 17ssize_t FAST_FUNC full_write(int fd, const void *buf, size_t len)
17{ 18{