Ah, yes.  I did forget to add an EINTR check to the write side.

Attached patch should fix "tar cf"

Thanks for your careful testing...


Anonymous wrote:
Anonymous <swel...@gmail.com> writes:

Tim Kientzle <kient...@freebsd.org> writes:

Please try the attached patch and let me know if it fixes it for you...

Cheers,

Tim
[...]

It fixes the issue. Thanks.

I'm afraid not. Similar issue affects `tar cf - blah | tar xf -'.
It's a little bit harder to reproduce. Caught after using pkg_add(1).

  # pkg_add gtk-2.20.1_1.tbz
  load: 0.21  cmd: bsdtar 3351 [running] 0.06r 0.02u 0.00s 1% 6348k
  In: 307200 bytes, compression 76%;  Out: 161 files, 1316787 bytes
  Current: include/gtk-2.0/gtk/gtklabel.h (8627 bytes)
  load: 0.16  cmd: bsdtar 3354 [tx->tx_quiesce_done_cv)] 4.08r 0.00u 0.14s 1% 
2712k
  In: 544 files, 36359168 bytes; Out: 36352000 bytes, compression 0%
  Current: share/locale/hi/LC_MESSAGES/gtk20-properties.mo (131072/234342 bytes)
  load: 0.16  cmd: bsdtar 3354 [tx->tx_quiesce_done_cv)] 4.86r 0.00u 0.14s 1% 
2712k
  tar: Write error
  In: 36341760 bytes, compression 0%;  Out: 544 files, 36341760 bytes
  Current: share/locale/hi/LC_MESSAGES/gtk20-properties.mo (234342 bytes)
  share/locale/hi/LC_MESSAGES/gtk20-properties.mo: Truncated tar archive
  tar: Error exit delayed from previous errors.
  pkg_add: leave_playpen: can't chdir back to ''
  zsh: exit 2     sudo -E pkg_add gtk-x11-2.20.1_1.tbz

Workaround is the same - svn diff -c207790 | patch -R

--
I don't remember svn revision (newvers.sh doesn't work here). But it was
after you committed that patch.

  $ uname -vm
  FreeBSD 9.0-CURRENT #0: Fri May 21 15:32:05 UTC 2010 ...:.../PHOENIX  amd64


Index: archive_write_open_fd.c
===================================================================
--- archive_write_open_fd.c	(revision 2413)
+++ archive_write_open_fd.c	(working copy)
@@ -51,7 +51,6 @@
 #include "archive.h"
 
 struct write_fd_data {
-	off_t		offset;
 	int		fd;
 };
 
@@ -122,12 +121,16 @@
 	ssize_t	bytesWritten;
 
 	mine = (struct write_fd_data *)client_data;
-	bytesWritten = write(mine->fd, buff, length);
-	if (bytesWritten <= 0) {
-		archive_set_error(a, errno, "Write error");
-		return (-1);
+	for (;;) {
+		bytesWritten = write(mine->fd, buff, length);
+		if (bytesWritten <= 0) {
+			if (errno == EINTR)
+				continue;
+			archive_set_error(a, errno, "Write error");
+			return (-1);
+		}
+		return (bytesWritten);
 	}
-	return (bytesWritten);
 }
 
 static int
Index: archive_write_open_file.c
===================================================================
--- archive_write_open_file.c	(revision 2413)
+++ archive_write_open_file.c	(working copy)
@@ -86,12 +86,16 @@
 	size_t	bytesWritten;
 
 	mine = client_data;
-	bytesWritten = fwrite(buff, 1, length, mine->f);
-	if (bytesWritten < length) {
-		archive_set_error(a, errno, "Write error");
-		return (-1);
+	for (;;) {
+		bytesWritten = fwrite(buff, 1, length, mine->f);
+		if (bytesWritten <= 0) {
+			if (errno == EINTR)
+				continue;
+			archive_set_error(a, errno, "Write error");
+			return (-1);
+		}
+		return (bytesWritten);
 	}
-	return (bytesWritten);
 }
 
 static int
Index: archive_write_open_filename.c
===================================================================
--- archive_write_open_filename.c	(revision 2413)
+++ archive_write_open_filename.c	(working copy)
@@ -142,12 +142,16 @@
 	ssize_t	bytesWritten;
 
 	mine = (struct write_file_data *)client_data;
-	bytesWritten = write(mine->fd, buff, length);
-	if (bytesWritten <= 0) {
-		archive_set_error(a, errno, "Write error");
-		return (-1);
+	for (;;) {
+		bytesWritten = write(mine->fd, buff, length);
+		if (bytesWritten <= 0) {
+			if (errno == EINTR)
+				continue;
+			archive_set_error(a, errno, "Write error");
+			return (-1);
+		}
+		return (bytesWritten);
 	}
-	return (bytesWritten);
 }
 
 static int
Index: archive_write.c
===================================================================
--- archive_write.c	(revision 2413)
+++ archive_write.c	(working copy)
@@ -361,11 +361,20 @@
                 remaining -= to_copy;
                 /* ... if it's full, write it out. */
                 if (state->avail == 0) {
-                        bytes_written = (a->client_writer)(&a->archive,
-                            a->client_data, state->buffer, state->buffer_size);
-                        if (bytes_written <= 0)
-                                return (ARCHIVE_FATAL);
-                        /* XXX TODO: if bytes_written < state->buffer_size */
+			char *p = state->buffer;
+			size_t remaining = state->buffer_size;
+			while (remaining > 0) {
+				bytes_written = (a->client_writer)(&a->archive,
+				    a->client_data, p, remaining);
+				if (bytes_written <= 0)
+					return (ARCHIVE_FATAL);
+				if (bytes_remaining > remaining) {
+					archive_set_error(a, -1, "write overrun");
+					return (ARCHIVE_FATAL);
+				}
+				p += bytes_written;
+				remaining -= bytes_written;
+			}
                         state->next = state->buffer;
                         state->avail = state->buffer_size;
                 }
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to