diff --git a/libsparse/output_file.c b/libsparse/output_file.c index 6578d99b8..21159987f 100644 --- a/libsparse/output_file.c +++ b/libsparse/output_file.c @@ -63,7 +63,7 @@ struct output_file_ops { int (*open)(struct output_file *, int fd); int (*skip)(struct output_file *, int64_t); int (*pad)(struct output_file *, int64_t); - int (*write)(struct output_file *, void *, int); + int (*write)(struct output_file *, void *, size_t); void (*close)(struct output_file *); }; @@ -149,18 +149,23 @@ static int file_pad(struct output_file *out, int64_t len) return 0; } -static int file_write(struct output_file *out, void *data, int len) +static int file_write(struct output_file *out, void *data, size_t len) { - int ret; + ssize_t ret; struct output_file_normal *outn = to_output_file_normal(out); - ret = write(outn->fd, data, len); - if (ret < 0) { - error_errno("write"); - return -1; - } else if (ret < len) { - error("incomplete write"); - return -1; + while (len > 0) { + ret = write(outn->fd, data, len); + if (ret < 0) { + if (errno == EINTR) { + continue; + } + error_errno("write"); + return -1; + } + + data = (char *)data + ret; + len -= ret; } return 0; @@ -232,18 +237,20 @@ static int gz_file_pad(struct output_file *out, int64_t len) return 0; } -static int gz_file_write(struct output_file *out, void *data, int len) +static int gz_file_write(struct output_file *out, void *data, size_t len) { int ret; struct output_file_gz *outgz = to_output_file_gz(out); - ret = gzwrite(outgz->gz_fd, data, len); - if (ret < 0) { - error_errno("gzwrite"); - return -1; - } else if (ret < len) { - error("incomplete gzwrite"); - return -1; + while (len > 0) { + ret = gzwrite(outgz->gz_fd, data, + min(len, (unsigned int)INT_MAX)); + if (ret == 0) { + error("gzwrite %s", gzerror(outgz->gz_fd, NULL)); + return -1; + } + len -= ret; + data = (char *)data + ret; } return 0; @@ -293,7 +300,7 @@ static int callback_file_pad(struct output_file *out __unused, int64_t len __unu return -1; } -static int callback_file_write(struct output_file *out, void *data, int len) +static int callback_file_write(struct output_file *out, void *data, size_t len) { struct output_file_callback *outc = to_output_file_callback(out); @@ -698,14 +705,16 @@ int write_fd_chunk(struct output_file *out, unsigned int len, int ret; int64_t aligned_offset; int aligned_diff; - int buffer_size; + uint64_t buffer_size; char *ptr; aligned_offset = offset & ~(4096 - 1); aligned_diff = offset - aligned_offset; - buffer_size = len + aligned_diff; + buffer_size = (uint64_t)len + (uint64_t)aligned_diff; #ifndef _WIN32 + if (buffer_size > SIZE_MAX) + return -E2BIG; char *data = mmap64(NULL, buffer_size, PROT_READ, MAP_SHARED, fd, aligned_offset); if (data == MAP_FAILED) {