summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColin Cross2012-04-25 20:31:39 -0500
committerColin Cross2012-07-10 00:09:37 -0500
commit9e1f17e926fa20255c5f4b4d2f68aa98a964253a (patch)
tree142907cdec91851c3e162bdfc23638df9a0d675b /libsparse
parentb55dceea986ab24f8b836b5116b389ed619c816e (diff)
downloadplatform-system-core-9e1f17e926fa20255c5f4b4d2f68aa98a964253a.tar.gz
platform-system-core-9e1f17e926fa20255c5f4b4d2f68aa98a964253a.tar.xz
platform-system-core-9e1f17e926fa20255c5f4b4d2f68aa98a964253a.zip
libsparse: add support for including fds
Add sparse_file_add_fd to include all or part of the contents of an fd in the output file. Will be useful for re-sparsing files where fd will point to the input sparse file. Change-Id: I5d4ab07fb37231e8e9c1912f62a2968c8b0a00ef
Diffstat (limited to 'libsparse')
-rw-r--r--libsparse/backed_block.c37
-rw-r--r--libsparse/backed_block.h4
-rw-r--r--libsparse/include/sparse/sparse.h26
-rw-r--r--libsparse/output_file.c37
-rw-r--r--libsparse/output_file.h2
-rw-r--r--libsparse/sparse.c10
6 files changed, 99 insertions, 17 deletions
diff --git a/libsparse/backed_block.c b/libsparse/backed_block.c
index b25919008..8c3fab04a 100644
--- a/libsparse/backed_block.c
+++ b/libsparse/backed_block.c
@@ -35,6 +35,10 @@ struct backed_block {
35 int64_t offset; 35 int64_t offset;
36 } file; 36 } file;
37 struct { 37 struct {
38 int fd;
39 int64_t offset;
40 } fd;
41 struct {
38 uint32_t val; 42 uint32_t val;
39 } fill; 43 } fill;
40 }; 44 };
@@ -78,10 +82,20 @@ const char *backed_block_filename(struct backed_block *bb)
78 return bb->file.filename; 82 return bb->file.filename;
79} 83}
80 84
85int backed_block_fd(struct backed_block *bb)
86{
87 assert(bb->type == BACKED_BLOCK_FD);
88 return bb->fd.fd;
89}
90
81int64_t backed_block_file_offset(struct backed_block *bb) 91int64_t backed_block_file_offset(struct backed_block *bb)
82{ 92{
83 assert(bb->type == BACKED_BLOCK_FILE); 93 assert(bb->type == BACKED_BLOCK_FILE || bb->type == BACKED_BLOCK_FD);
84 return bb->file.offset; 94 if (bb->type == BACKED_BLOCK_FILE) {
95 return bb->file.offset;
96 } else { /* bb->type == BACKED_BLOCK_FD */
97 return bb->fd.offset;
98 }
85} 99}
86 100
87uint32_t backed_block_fill_val(struct backed_block *bb) 101uint32_t backed_block_fill_val(struct backed_block *bb)
@@ -211,3 +225,22 @@ int backed_block_add_file(struct backed_block_list *bbl, const char *filename,
211 225
212 return queue_bb(bbl, bb); 226 return queue_bb(bbl, bb);
213} 227}
228
229/* Queues a chunk of a fd to be written to the specified data blocks */
230int backed_block_add_fd(struct backed_block_list *bbl, int fd, int64_t offset,
231 unsigned int len, unsigned int block)
232{
233 struct backed_block *bb = calloc(1, sizeof(struct backed_block));
234 if (bb == NULL) {
235 return -ENOMEM;
236 }
237
238 bb->block = block;
239 bb->len = len;
240 bb->type = BACKED_BLOCK_FD;
241 bb->fd.fd = fd;
242 bb->fd.offset = offset;
243 bb->next = NULL;
244
245 return queue_bb(bbl, bb);
246}
diff --git a/libsparse/backed_block.h b/libsparse/backed_block.h
index 316650505..ca2ad1d9b 100644
--- a/libsparse/backed_block.h
+++ b/libsparse/backed_block.h
@@ -25,6 +25,7 @@ struct backed_block;
25enum backed_block_type { 25enum backed_block_type {
26 BACKED_BLOCK_DATA, 26 BACKED_BLOCK_DATA,
27 BACKED_BLOCK_FILE, 27 BACKED_BLOCK_FILE,
28 BACKED_BLOCK_FD,
28 BACKED_BLOCK_FILL, 29 BACKED_BLOCK_FILL,
29}; 30};
30 31
@@ -34,6 +35,8 @@ int backed_block_add_fill(struct backed_block_list *bbl, unsigned int fill_val,
34 unsigned int len, unsigned int block); 35 unsigned int len, unsigned int block);
35int backed_block_add_file(struct backed_block_list *bbl, const char *filename, 36int backed_block_add_file(struct backed_block_list *bbl, const char *filename,
36 int64_t offset, unsigned int len, unsigned int block); 37 int64_t offset, unsigned int len, unsigned int block);
38int backed_block_add_fd(struct backed_block_list *bbl, int fd,
39 int64_t offset, unsigned int len, unsigned int block);
37 40
38struct backed_block *backed_block_iter_new(struct backed_block_list *bbl); 41struct backed_block *backed_block_iter_new(struct backed_block_list *bbl);
39struct backed_block *backed_block_iter_next(struct backed_block *bb); 42struct backed_block *backed_block_iter_next(struct backed_block *bb);
@@ -41,6 +44,7 @@ unsigned int backed_block_len(struct backed_block *bb);
41unsigned int backed_block_block(struct backed_block *bb); 44unsigned int backed_block_block(struct backed_block *bb);
42void *backed_block_data(struct backed_block *bb); 45void *backed_block_data(struct backed_block *bb);
43const char *backed_block_filename(struct backed_block *bb); 46const char *backed_block_filename(struct backed_block *bb);
47int backed_block_fd(struct backed_block *bb);
44int64_t backed_block_file_offset(struct backed_block *bb); 48int64_t backed_block_file_offset(struct backed_block *bb);
45uint32_t backed_block_fill_val(struct backed_block *bb); 49uint32_t backed_block_fill_val(struct backed_block *bb);
46enum backed_block_type backed_block_type(struct backed_block *bb); 50enum backed_block_type backed_block_type(struct backed_block *bb);
diff --git a/libsparse/include/sparse/sparse.h b/libsparse/include/sparse/sparse.h
index db0688471..6484333ef 100644
--- a/libsparse/include/sparse/sparse.h
+++ b/libsparse/include/sparse/sparse.h
@@ -111,6 +111,32 @@ int sparse_file_add_file(struct sparse_file *s,
111 unsigned int block); 111 unsigned int block);
112 112
113/** 113/**
114 * sparse_file_add_file - associate a chunk of a file with a sparse file
115 *
116 * @s - sparse file cookie
117 * @filename - filename of the file to be copied
118 * @file_offset - offset into the copied file
119 * @len - length of the copied block
120 * @block - offset in blocks into the sparse file to place the file chunk
121 *
122 * Associates a chunk of an existing fd with a sparse file cookie.
123 * The region [block * block_size : block * block_size + len) must not already
124 * be used in the sparse file. If len is not a multiple of the block size the
125 * data will be padded with zeros.
126 *
127 * Allows adding large amounts of data to a sparse file without needing to keep
128 * it all mapped. File size is limited by available virtual address space,
129 * exceptionally large files may need to be added in multiple chunks.
130 *
131 * The fd must remain open until the sparse file is closed or the fd block is
132 * removed from the sparse file.
133 *
134 * Returns 0 on success, negative errno on error.
135 */
136int sparse_file_add_fd(struct sparse_file *s,
137 int fd, int64_t file_offset, unsigned int len, unsigned int block);
138
139/**
114 * sparse_file_write - write a sparse file to a file 140 * sparse_file_write - write a sparse file to a file
115 * 141 *
116 * @s - sparse file cookie 142 * @s - sparse file cookie
diff --git a/libsparse/output_file.c b/libsparse/output_file.c
index f911f8cc5..4193fd17d 100644
--- a/libsparse/output_file.c
+++ b/libsparse/output_file.c
@@ -511,38 +511,28 @@ int write_fill_chunk(struct output_file *out, unsigned int len,
511 return out->sparse_ops->write_fill_chunk(out, len, fill_val); 511 return out->sparse_ops->write_fill_chunk(out, len, fill_val);
512} 512}
513 513
514/* Write a contiguous region of data blocks from a file */ 514int write_fd_chunk(struct output_file *out, unsigned int len,
515int write_file_chunk(struct output_file *out, unsigned int len, 515 int fd, int64_t offset)
516 const char *file, int64_t offset)
517{ 516{
518 int ret; 517 int ret;
519 int64_t aligned_offset; 518 int64_t aligned_offset;
520 int aligned_diff; 519 int aligned_diff;
521 int buffer_size; 520 int buffer_size;
522 521
523 int file_fd = open(file, O_RDONLY | O_BINARY);
524 if (file_fd < 0) {
525 return -errno;
526 }
527
528 aligned_offset = offset & ~(4096 - 1); 522 aligned_offset = offset & ~(4096 - 1);
529 aligned_diff = offset - aligned_offset; 523 aligned_diff = offset - aligned_offset;
530 buffer_size = len + aligned_diff; 524 buffer_size = len + aligned_diff;
531 525
532#ifndef USE_MINGW 526#ifndef USE_MINGW
533 char *data = mmap64(NULL, buffer_size, PROT_READ, MAP_SHARED, file_fd, 527 char *data = mmap64(NULL, buffer_size, PROT_READ, MAP_SHARED, fd,
534 aligned_offset); 528 aligned_offset);
535 if (data == MAP_FAILED) { 529 if (data == MAP_FAILED) {
536 ret = -errno; 530 return -errno;
537 close(file_fd);
538 return ret;
539 } 531 }
540#else 532#else
541 char *data = malloc(buffer_size); 533 char *data = malloc(buffer_size);
542 if (!data) { 534 if (!data) {
543 ret = -errno; 535 return -errno;
544 close(file_fd);
545 return ret;
546 } 536 }
547 memset(data, 0, buffer_size); 537 memset(data, 0, buffer_size);
548#endif 538#endif
@@ -554,6 +544,23 @@ int write_file_chunk(struct output_file *out, unsigned int len,
554#else 544#else
555 free(data); 545 free(data);
556#endif 546#endif
547
548 return ret;
549}
550
551/* Write a contiguous region of data blocks from a file */
552int write_file_chunk(struct output_file *out, unsigned int len,
553 const char *file, int64_t offset)
554{
555 int ret;
556
557 int file_fd = open(file, O_RDONLY | O_BINARY);
558 if (file_fd < 0) {
559 return -errno;
560 }
561
562 ret = write_fd_chunk(out, len, file_fd, offset);
563
557 close(file_fd); 564 close(file_fd);
558 565
559 return ret; 566 return ret;
diff --git a/libsparse/output_file.h b/libsparse/output_file.h
index cb2feb7fb..d23abf381 100644
--- a/libsparse/output_file.h
+++ b/libsparse/output_file.h
@@ -31,6 +31,8 @@ int write_fill_chunk(struct output_file *out, unsigned int len,
31 uint32_t fill_val); 31 uint32_t fill_val);
32int write_file_chunk(struct output_file *out, unsigned int len, 32int write_file_chunk(struct output_file *out, unsigned int len,
33 const char *file, int64_t offset); 33 const char *file, int64_t offset);
34int write_fd_chunk(struct output_file *out, unsigned int len,
35 int fd, int64_t offset);
34int write_skip_chunk(struct output_file *out, int64_t len); 36int write_skip_chunk(struct output_file *out, int64_t len);
35void close_output_file(struct output_file *out); 37void close_output_file(struct output_file *out);
36 38
diff --git a/libsparse/sparse.c b/libsparse/sparse.c
index fce9dbbb6..4ebcf0f8d 100644
--- a/libsparse/sparse.c
+++ b/libsparse/sparse.c
@@ -70,6 +70,12 @@ int sparse_file_add_file(struct sparse_file *s,
70 len, block); 70 len, block);
71} 71}
72 72
73int sparse_file_add_fd(struct sparse_file *s,
74 int fd, int64_t file_offset, unsigned int len, unsigned int block)
75{
76 return backed_block_add_fd(s->backed_block_list, fd, file_offset,
77 len, block);
78}
73unsigned int sparse_count_chunks(struct sparse_file *s) 79unsigned int sparse_count_chunks(struct sparse_file *s)
74{ 80{
75 struct backed_block *bb; 81 struct backed_block *bb;
@@ -122,6 +128,10 @@ int sparse_file_write(struct sparse_file *s, int fd, bool gz, bool sparse,
122 write_file_chunk(out, backed_block_len(bb), 128 write_file_chunk(out, backed_block_len(bb),
123 backed_block_filename(bb), backed_block_file_offset(bb)); 129 backed_block_filename(bb), backed_block_file_offset(bb));
124 break; 130 break;
131 case BACKED_BLOCK_FD:
132 write_fd_chunk(out, backed_block_len(bb),
133 backed_block_fd(bb), backed_block_file_offset(bb));
134 break;
125 case BACKED_BLOCK_FILL: 135 case BACKED_BLOCK_FILL:
126 write_fill_chunk(out, backed_block_len(bb), 136 write_fill_chunk(out, backed_block_len(bb),
127 backed_block_fill_val(bb)); 137 backed_block_fill_val(bb));