diff options
Diffstat (limited to 'libsparse')
-rw-r--r-- | libsparse/output_file.c | 39 | ||||
-rw-r--r-- | libsparse/output_file.h | 2 |
2 files changed, 38 insertions, 3 deletions
diff --git a/libsparse/output_file.c b/libsparse/output_file.c index 4193fd17d..5e8a68c54 100644 --- a/libsparse/output_file.c +++ b/libsparse/output_file.c | |||
@@ -168,6 +168,28 @@ static struct output_file_ops gz_file_ops = { | |||
168 | .close = gz_file_close, | 168 | .close = gz_file_close, |
169 | }; | 169 | }; |
170 | 170 | ||
171 | int read_all(int fd, void *buf, size_t len) | ||
172 | { | ||
173 | size_t total = 0; | ||
174 | int ret; | ||
175 | char *ptr = buf; | ||
176 | |||
177 | while (total < len) { | ||
178 | ret = read(fd, ptr, len - total); | ||
179 | |||
180 | if (ret < 0) | ||
181 | return -errno; | ||
182 | |||
183 | if (ret == 0) | ||
184 | return -EINVAL; | ||
185 | |||
186 | ptr += ret; | ||
187 | total += ret; | ||
188 | } | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
171 | static int write_sparse_skip_chunk(struct output_file *out, int64_t skip_len) | 193 | static int write_sparse_skip_chunk(struct output_file *out, int64_t skip_len) |
172 | { | 194 | { |
173 | chunk_header_t chunk_header; | 195 | chunk_header_t chunk_header; |
@@ -518,6 +540,7 @@ int write_fd_chunk(struct output_file *out, unsigned int len, | |||
518 | int64_t aligned_offset; | 540 | int64_t aligned_offset; |
519 | int aligned_diff; | 541 | int aligned_diff; |
520 | int buffer_size; | 542 | int buffer_size; |
543 | char *ptr; | ||
521 | 544 | ||
522 | aligned_offset = offset & ~(4096 - 1); | 545 | aligned_offset = offset & ~(4096 - 1); |
523 | aligned_diff = offset - aligned_offset; | 546 | aligned_diff = offset - aligned_offset; |
@@ -529,15 +552,25 @@ int write_fd_chunk(struct output_file *out, unsigned int len, | |||
529 | if (data == MAP_FAILED) { | 552 | if (data == MAP_FAILED) { |
530 | return -errno; | 553 | return -errno; |
531 | } | 554 | } |
555 | ptr = data + aligned_diff; | ||
532 | #else | 556 | #else |
533 | char *data = malloc(buffer_size); | 557 | off64_t pos; |
558 | char *data = malloc(len); | ||
534 | if (!data) { | 559 | if (!data) { |
535 | return -errno; | 560 | return -errno; |
536 | } | 561 | } |
537 | memset(data, 0, buffer_size); | 562 | pos = lseek64(fd, offset, SEEK_SET); |
563 | if (pos < 0) { | ||
564 | return -errno; | ||
565 | } | ||
566 | ret = read_all(fd, data, len); | ||
567 | if (ret < 0) { | ||
568 | return ret; | ||
569 | } | ||
570 | ptr = data; | ||
538 | #endif | 571 | #endif |
539 | 572 | ||
540 | ret = out->sparse_ops->write_data_chunk(out, len, data + aligned_diff); | 573 | ret = out->sparse_ops->write_data_chunk(out, len, ptr); |
541 | 574 | ||
542 | #ifndef USE_MINGW | 575 | #ifndef USE_MINGW |
543 | munmap(data, buffer_size); | 576 | munmap(data, buffer_size); |
diff --git a/libsparse/output_file.h b/libsparse/output_file.h index d23abf381..b86528b44 100644 --- a/libsparse/output_file.h +++ b/libsparse/output_file.h | |||
@@ -36,4 +36,6 @@ int write_fd_chunk(struct output_file *out, unsigned int len, | |||
36 | int write_skip_chunk(struct output_file *out, int64_t len); | 36 | int write_skip_chunk(struct output_file *out, int64_t len); |
37 | void close_output_file(struct output_file *out); | 37 | void close_output_file(struct output_file *out); |
38 | 38 | ||
39 | int read_all(int fd, void *buf, size_t len); | ||
40 | |||
39 | #endif | 41 | #endif |