summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libsparse/output_file.c51
1 files changed, 30 insertions, 21 deletions
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 {
63 int (*open)(struct output_file *, int fd); 63 int (*open)(struct output_file *, int fd);
64 int (*skip)(struct output_file *, int64_t); 64 int (*skip)(struct output_file *, int64_t);
65 int (*pad)(struct output_file *, int64_t); 65 int (*pad)(struct output_file *, int64_t);
66 int (*write)(struct output_file *, void *, int); 66 int (*write)(struct output_file *, void *, size_t);
67 void (*close)(struct output_file *); 67 void (*close)(struct output_file *);
68}; 68};
69 69
@@ -149,18 +149,23 @@ static int file_pad(struct output_file *out, int64_t len)
149 return 0; 149 return 0;
150} 150}
151 151
152static int file_write(struct output_file *out, void *data, int len) 152static int file_write(struct output_file *out, void *data, size_t len)
153{ 153{
154 int ret; 154 ssize_t ret;
155 struct output_file_normal *outn = to_output_file_normal(out); 155 struct output_file_normal *outn = to_output_file_normal(out);
156 156
157 ret = write(outn->fd, data, len); 157 while (len > 0) {
158 if (ret < 0) { 158 ret = write(outn->fd, data, len);
159 error_errno("write"); 159 if (ret < 0) {
160 return -1; 160 if (errno == EINTR) {
161 } else if (ret < len) { 161 continue;
162 error("incomplete write"); 162 }
163 return -1; 163 error_errno("write");
164 return -1;
165 }
166
167 data = (char *)data + ret;
168 len -= ret;
164 } 169 }
165 170
166 return 0; 171 return 0;
@@ -232,18 +237,20 @@ static int gz_file_pad(struct output_file *out, int64_t len)
232 return 0; 237 return 0;
233} 238}
234 239
235static int gz_file_write(struct output_file *out, void *data, int len) 240static int gz_file_write(struct output_file *out, void *data, size_t len)
236{ 241{
237 int ret; 242 int ret;
238 struct output_file_gz *outgz = to_output_file_gz(out); 243 struct output_file_gz *outgz = to_output_file_gz(out);
239 244
240 ret = gzwrite(outgz->gz_fd, data, len); 245 while (len > 0) {
241 if (ret < 0) { 246 ret = gzwrite(outgz->gz_fd, data,
242 error_errno("gzwrite"); 247 min(len, (unsigned int)INT_MAX));
243 return -1; 248 if (ret == 0) {
244 } else if (ret < len) { 249 error("gzwrite %s", gzerror(outgz->gz_fd, NULL));
245 error("incomplete gzwrite"); 250 return -1;
246 return -1; 251 }
252 len -= ret;
253 data = (char *)data + ret;
247 } 254 }
248 255
249 return 0; 256 return 0;
@@ -293,7 +300,7 @@ static int callback_file_pad(struct output_file *out __unused, int64_t len __unu
293 return -1; 300 return -1;
294} 301}
295 302
296static int callback_file_write(struct output_file *out, void *data, int len) 303static int callback_file_write(struct output_file *out, void *data, size_t len)
297{ 304{
298 struct output_file_callback *outc = to_output_file_callback(out); 305 struct output_file_callback *outc = to_output_file_callback(out);
299 306
@@ -698,14 +705,16 @@ int write_fd_chunk(struct output_file *out, unsigned int len,
698 int ret; 705 int ret;
699 int64_t aligned_offset; 706 int64_t aligned_offset;
700 int aligned_diff; 707 int aligned_diff;
701 int buffer_size; 708 uint64_t buffer_size;
702 char *ptr; 709 char *ptr;
703 710
704 aligned_offset = offset & ~(4096 - 1); 711 aligned_offset = offset & ~(4096 - 1);
705 aligned_diff = offset - aligned_offset; 712 aligned_diff = offset - aligned_offset;
706 buffer_size = len + aligned_diff; 713 buffer_size = (uint64_t)len + (uint64_t)aligned_diff;
707 714
708#ifndef _WIN32 715#ifndef _WIN32
716 if (buffer_size > SIZE_MAX)
717 return -E2BIG;
709 char *data = mmap64(NULL, buffer_size, PROT_READ, MAP_SHARED, fd, 718 char *data = mmap64(NULL, buffer_size, PROT_READ, MAP_SHARED, fd,
710 aligned_offset); 719 aligned_offset);
711 if (data == MAP_FAILED) { 720 if (data == MAP_FAILED) {