Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 Apr 2016 07:34:31 +0000 (UTC)
From:      Thomas Quinot <thomas@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r298258 - stable/10/bin/dd
Message-ID:  <201604190734.u3J7YVJg001981@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: thomas
Date: Tue Apr 19 07:34:31 2016
New Revision: 298258
URL: https://svnweb.freebsd.org/changeset/base/298258

Log:
  MFC r295749:
  
  Reorganize the handling all-zeroes terminal block in sparse mode
  
  PR: 189284
  (original PR whose fix introduced this bug)
  
  PR: 207092

Added:
  stable/10/bin/dd/ref.obs_zeroes
     - copied unchanged from r295749, head/bin/dd/ref.obs_zeroes
Modified:
  stable/10/bin/dd/Makefile
  stable/10/bin/dd/dd.c
  stable/10/bin/dd/dd.h
  stable/10/bin/dd/gen.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/bin/dd/Makefile
==============================================================================
--- stable/10/bin/dd/Makefile	Tue Apr 19 07:28:39 2016	(r298257)
+++ stable/10/bin/dd/Makefile	Tue Apr 19 07:34:31 2016	(r298258)
@@ -24,7 +24,18 @@ test: ${PROG} gen
 	    LC_ALL=en_US.US-ASCII hexdump -C | \
 	    diff -I FreeBSD - ${.CURDIR}/ref.${conv}
 .endfor
-	@rm -f gen
+	@${ECHO} "testing sparse file (obs zeroes)"
+	@./gen 189284 | ./dd ibs=16 obs=8 conv=sparse of=obs_zeroes 2> /dev/null
+	@hexdump -C obs_zeroes | diff -I FreeBSD - ${.CURDIR}/ref.obs_zeroes
+
+	@${ECHO} "testing spase file (all zeroes)"
+	@./dd if=/dev/zero of=1M_zeroes bs=1048576 count=1 2> /dev/null
+	@./dd if=1M_zeroes of=1M_zeroes.1 bs=1048576 conv=sparse 2> /dev/null
+	@./dd if=1M_zeroes of=1M_zeroes.2 bs=1048576 2> /dev/null
+	@diff 1M_zeroes 1M_zeroes.1
+	@diff 1M_zeroes 1M_zeroes.2
+
+	@rm -f gen 1M_zeroes* obs_zeroes
 
 .if ${MK_TESTS} != "no"
 SUBDIR+=	tests

Modified: stable/10/bin/dd/dd.c
==============================================================================
--- stable/10/bin/dd/dd.c	Tue Apr 19 07:28:39 2016	(r298257)
+++ stable/10/bin/dd/dd.c	Tue Apr 19 07:34:31 2016	(r298258)
@@ -77,7 +77,6 @@ STAT	st;			/* statistics */
 void	(*cfunc)(void);		/* conversion function */
 uintmax_t cpy_cnt;		/* # of blocks to copy */
 static off_t	pending = 0;	/* pending seek if sparse */
-static off_t	last_sp = 0;	/* size of last added sparse block */
 u_int	ddflags = 0;		/* conversion options */
 size_t	cbsz;			/* conversion block size */
 uintmax_t files_cnt = 1;	/* # of files to copy */
@@ -410,6 +409,15 @@ dd_close(void)
 	}
 	if (out.dbcnt || pending)
 		dd_out(1);
+
+	/*
+	 * If the file ends with a hole, ftruncate it to extend its size
+	 * up to the end of the hole (without having to write any data).
+	 */
+	if (out.seek_offset > 0 && (out.flags & ISTRUNC)) {
+		if (ftruncate(out.fd, out.seek_offset) == -1)
+			err(1, "truncating %s", out.name);
+	}
 }
 
 void
@@ -458,29 +466,27 @@ dd_out(int force)
 			}
 			if (sparse && !force) {
 				pending += cnt;
-				last_sp = cnt;
 				nw = cnt;
 			} else {
 				if (pending != 0) {
-					/* If forced to write, and we have no
-					 * data left, we need to write the last
-					 * sparse block explicitly.
+					/*
+					 * Seek past hole.  Note that we need to record the
+					 * reached offset, because we might have no more data
+					 * to write, in which case we'll need to call
+					 * ftruncate to extend the file size.
 					 */
-					if (force && cnt == 0) {
-						pending -= last_sp;
-						assert(outp == out.db);
-						memset(outp, 0, cnt);
-					}
-					if (lseek(out.fd, pending, SEEK_CUR) ==
-					    -1)
+					out.seek_offset = lseek(out.fd, pending, SEEK_CUR);
+					if (out.seek_offset == -1)
 						err(2, "%s: seek error creating sparse file",
 						    out.name);
-					pending = last_sp = 0;
+					pending = 0;
 				}
-				if (cnt)
+				if (cnt) {
 					nw = write(out.fd, outp, cnt);
-				else
+					out.seek_offset = 0;
+				} else {
 					return;
+				}
 			}
 
 			if (nw <= 0) {

Modified: stable/10/bin/dd/dd.h
==============================================================================
--- stable/10/bin/dd/dd.h	Tue Apr 19 07:28:39 2016	(r298257)
+++ stable/10/bin/dd/dd.h	Tue Apr 19 07:34:31 2016	(r298258)
@@ -54,6 +54,7 @@ typedef struct {
 	const char	*name;		/* name */
 	int		fd;		/* file descriptor */
 	off_t		offset;		/* # of blocks to skip */
+	off_t		seek_offset;	/* offset of last seek past output hole */
 } IO;
 
 typedef struct {

Modified: stable/10/bin/dd/gen.c
==============================================================================
--- stable/10/bin/dd/gen.c	Tue Apr 19 07:28:39 2016	(r298257)
+++ stable/10/bin/dd/gen.c	Tue Apr 19 07:34:31 2016	(r298258)
@@ -5,13 +5,20 @@
  */
 
 #include <stdio.h>
+#include <string.h>
 
 int
-main(int argc __unused, char **argv __unused)
+main(int argc, char **argv)
 {
 	int i;
 
-	for (i = 0; i < 256; i++)
-		putchar(i);
+	if (argc > 1 && !strcmp(argv[1], "189284")) {
+		fputs("ABCDEFGH", stdout);
+		for (i = 0; i < 8; i++)
+			putchar(0);
+	} else {
+		for (i = 0; i < 256; i++)
+			putchar(i);
+	}
 	return (0);
 }

Copied: stable/10/bin/dd/ref.obs_zeroes (from r295749, head/bin/dd/ref.obs_zeroes)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/10/bin/dd/ref.obs_zeroes	Tue Apr 19 07:34:31 2016	(r298258, copy of r295749, head/bin/dd/ref.obs_zeroes)
@@ -0,0 +1,3 @@
+$FreeBSD$
+00000000  41 42 43 44 45 46 47 48  00 00 00 00 00 00 00 00  |ABCDEFGH........|
+00000010



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201604190734.u3J7YVJg001981>