diff --git c/builtin/index-pack.c w/builtin/index-pack.c
index a3a37bd215..a54cb07a35 100644
--- c/builtin/index-pack.c
+++ w/builtin/index-pack.c
@@ -1570,13 +1570,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
 		 * Let's just mimic git-unpack-objects here and write
 		 * the last part of the input buffer to stdout.
 		 */
-		while (input_len) {
-			err = xwrite(1, input_buffer + input_offset, input_len);
-			if (err <= 0)
-				break;
-			input_len -= err;
-			input_offset += err;
-		}
+		write_in_full(1, input_buffer + input_offset, input_len);
 	}
 
 	strbuf_release(&rev_index_name);


--------------------
builtin/receive-pack.c:report_message() has a call to xwrite() that
will lead to message truncation if the underlying write(2) returns
early.

diff --git c/builtin/receive-pack.c w/builtin/receive-pack.c
index 56d8a77ed7..4d8ed3f7a3 100644
--- c/builtin/receive-pack.c
+++ w/builtin/receive-pack.c
@@ -456,7 +456,7 @@ static void report_message(const char *prefix, const char *err, va_list params)
 	if (use_sideband)
 		send_sideband(1, 2, msg, sz, use_sideband);
 	else
-		xwrite(2, msg, sz);
+		write_in_full(2, msg, sz);
 }
 
 __attribute__((format (printf, 1, 2)))



--------------------
builtin/repack.c:write_oid() feeds a line with an object name on it
to a subprocess, but it can suffer from a short write(2).

diff --git c/builtin/repack.c w/builtin/repack.c
index ede36328a3..1a516a6bed 100644
--- c/builtin/repack.c
+++ w/builtin/repack.c
@@ -314,8 +314,10 @@ static int write_oid(const struct object_id *oid,
 			die(_("could not start pack-objects to repack promisor objects"));
 	}
 
-	xwrite(cmd->in, oid_to_hex(oid), the_hash_algo->hexsz);
-	xwrite(cmd->in, "\n", 1);
+	if (write_in_full(cmd->in, oid_to_hex(oid), the_hash_algo->hexsz) ||
+	    write_in_full(cmd->in, "\n", 1))
+		die(_("failed to feed promisor objects to pack-objects"));
+
 	return 0;
 }
 

--------------------
builtin/unpack-objects.c:cmd_unpack_objects() has the same xwrite()
loop as we saw in builtin/index-pack.c:final().  It is a correct
implementation that does not need to be touched, but we could
replace the loop with a single call to write_in_full().

diff --git i/builtin/unpack-objects.c w/builtin/unpack-objects.c
index e0a701f2b3..f1c85a00ae 100644
--- i/builtin/unpack-objects.c
+++ w/builtin/unpack-objects.c
@@ -679,13 +679,7 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix UNUSED)
 	use(the_hash_algo->rawsz);
 
 	/* Write the last part of the buffer to stdout */
-	while (len) {
-		int ret = xwrite(1, buffer + offset, len);
-		if (ret <= 0)
-			break;
-		len -= ret;
-		offset += ret;
-	}
+	write_in_full(1, buffer + offset, len);
 
 	/* All done */
 	return has_errors;


--------------------
http.c:fwrite_sha1_file() has xwrite() loop that is prepared to see
a short write(2).  The loop could be replaced with write_in_full() but
the semantics of the value returned upon failure could become different,
so I'd rather not to touch it.

http.c-	do {
http.c:		ssize_t retval = xwrite(freq->localfile,
http.c-					(char *) ptr + posn, size - posn);
http.c-		if (retval < 0)
http.c-			return posn / eltsize;
http.c-		posn += retval;
http.c-	} while (posn < size);

--------------------
sideband.c:demultiplex_sideband() uses xwrite() that does not retry
for its progress eye-candy.  write_in_full() may be overkill for
them, I suspect.

sideband.c-			strbuf_addch(scratch, *brk);
sideband.c:			xwrite(2, scratch->buf, scratch->len);
sideband.c-			strbuf_reset(scratch);
sideband.c ...
sideband.c-	if (scratch->len) {
sideband.c-		strbuf_addch(scratch, '\n');
sideband.c:		xwrite(2, scratch->buf, scratch->len);
sideband.c-	}


--------------------
streaming.c:stream_blob_to_fd() keeps track of the "hole" at the end
of the output file by refraining from writing series of NULs, and
instead uses lseek() to move the write pointer to 1-byte before the
desired end of file, and then uses xwrite() to write a single NUL at
the end.  This should not result in a short write(2), and it handles
write error correctly already, but it would be OK to update it to
write_in_full() for consistency.

diff --git c/streaming.c w/streaming.c
index 10adf625b2..38925ea9fd 100644
--- c/streaming.c
+++ w/streaming.c
@@ -538,7 +538,7 @@ int stream_blob_to_fd(int fd, const struct object_id *oid, struct stream_filter
 			goto close_and_exit;
 	}
 	if (kept && (lseek(fd, kept - 1, SEEK_CUR) == (off_t) -1 ||
-		     xwrite(fd, "", 1) != 1))
+		     write_in_full(fd, "", 1) != 1))
 		goto close_and_exit;
 	result = 0;
 
