summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'libsparse')
-rw-r--r--libsparse/output_file.c39
-rw-r--r--libsparse/output_file.h2
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
171int 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
171static int write_sparse_skip_chunk(struct output_file *out, int64_t skip_len) 193static 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,
36int write_skip_chunk(struct output_file *out, int64_t len); 36int write_skip_chunk(struct output_file *out, int64_t len);
37void close_output_file(struct output_file *out); 37void close_output_file(struct output_file *out);
38 38
39int read_all(int fd, void *buf, size_t len);
40
39#endif 41#endif