]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Handle EINTR in write calls:
authorTim Kientzle <kientzle@gmail.com>
Mon, 31 May 2010 18:20:46 +0000 (14:20 -0400)
committerTim Kientzle <kientzle@gmail.com>
Mon, 31 May 2010 18:20:46 +0000 (14:20 -0400)
  * In low-level writers, just retry after EINTR
  * In archive_write, handle short writes by generating additional writes for the remainder of the block.

In particular, this fixes a problem with bsdtar failing if you try to use the SIGINT handler.

SVN-Revision: 2431

libarchive/archive_write.c
libarchive/archive_write_open_fd.c
libarchive/archive_write_open_file.c
libarchive/archive_write_open_filename.c

index b9ce507496a29c5546086bf6c8f081553bce063c..06033f35c1f1d5c0b02e9e41597cc2b045f471a1 100644 (file)
@@ -361,11 +361,21 @@ archive_write_client_write(struct archive_write_filter *f,
                 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 to_write = state->buffer_size;
+                       while (to_write > 0) {
+                               bytes_written = (a->client_writer)(&a->archive,
+                                   a->client_data, p, to_write);
+                               if (bytes_written <= 0)
+                                       return (ARCHIVE_FATAL);
+                               if (bytes_written > to_write) {
+                                       archive_set_error(&(a->archive),
+                                           -1, "write overrun");
+                                       return (ARCHIVE_FATAL);
+                               }
+                               p += bytes_written;
+                               to_write -= bytes_written;
+                       }
                         state->next = state->buffer;
                         state->avail = state->buffer_size;
                 }
index 3a60398710b2b06623744d58c1c96d77f2ab2b16..d5c426cf978c116da96ba556999f16dbe8fb9286 100644 (file)
@@ -51,7 +51,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_open_fd.c 201093 2009-12-2
 #include "archive.h"
 
 struct write_fd_data {
-       off_t           offset;
        int             fd;
 };
 
@@ -122,12 +121,16 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length
        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 5c0c737f8580d6a7fc74851d57e2bcec75c2ecea..f6b141239ffee2ba1c4bd0032cd3e19b16af6076 100644 (file)
@@ -86,12 +86,16 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length
        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 6a9c77816fd99f56bc7f38350b826728529934ee..8a4cd3522196917b64e63dccbfaa2e1172d17746 100644 (file)
@@ -142,12 +142,16 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length
        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