Merge "libsparse: output_file.c, fix large data chunk issue" am: 62c9101646
am: faaeda8e12
Change-Id: I167d7d8083e8e15f89f21b5838fc5b4e97121b10
diff --git a/libsparse/output_file.c b/libsparse/output_file.c
index 6578d99..2115998 100644
--- a/libsparse/output_file.c
+++ b/libsparse/output_file.c
@@ -63,7 +63,7 @@
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 @@
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 @@
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 @@
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 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) {