diff options
Diffstat (limited to 'libsparse')
-rw-r--r-- | libsparse/output_file.c | 51 |
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 | ||
152 | static int file_write(struct output_file *out, void *data, int len) | 152 | static 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 | ||
235 | static int gz_file_write(struct output_file *out, void *data, int len) | 240 | static 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 | ||
296 | static int callback_file_write(struct output_file *out, void *data, int len) | 303 | static 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) { |