summaryrefslogtreecommitdiffstats
path: root/libsparse/simg2img.c
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2012-04-25 19:02:58 -0700
committerColin Cross <ccross@android.com>2012-07-09 22:09:37 -0700
commit0c4c47f88dfc15cada154a1cf9b4db88b49890f0 (patch)
tree36b4a1635c149cbdb26347387185a5c824cd203a /libsparse/simg2img.c
parent13a560659381b34ce3edbfa8dbe6c0aa6c076f20 (diff)
downloadsystem_core-0c4c47f88dfc15cada154a1cf9b4db88b49890f0.zip
system_core-0c4c47f88dfc15cada154a1cf9b4db88b49890f0.tar.gz
system_core-0c4c47f88dfc15cada154a1cf9b4db88b49890f0.tar.bz2
libsparse: add sparse_file read and convert tools to use it
Abstract the logic from simg2img into libsparse, and add logic for reading a regular image into libsparse. simg2img then becomes a simple wrapper around libsparse. img2simg was not actually making the file sparse, it was using sparse files to create multiple files that could be pieced back together. Replace it with a simple wrapper around libsparse. Its functionality will be replaced by an simg2simg that can resparse a file into smaller chunks. Change-Id: I266f70e1c750454183ce46c71a7bb66bbb033a26
Diffstat (limited to 'libsparse/simg2img.c')
-rw-r--r--libsparse/simg2img.c258
1 files changed, 7 insertions, 251 deletions
diff --git a/libsparse/simg2img.c b/libsparse/simg2img.c
index 486b805..ab35583 100644
--- a/libsparse/simg2img.c
+++ b/libsparse/simg2img.c
@@ -14,194 +14,36 @@
* limitations under the License.
*/
-#define _FILE_OFFSET_BITS 64
-#define _LARGEFILE64_SOURCE 1
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "sparse_defs.h"
-#include "sparse_format.h"
-#include "sparse_crc32.h"
+#include <sparse/sparse.h>
#include <fcntl.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <sys/mman.h>
#include <unistd.h>
-#define COPY_BUF_SIZE (1024*1024)
-u8 *copybuf;
-
-/* This will be malloc'ed with the size of blk_sz from the sparse file header */
-u8* zerobuf;
-
-#define SPARSE_HEADER_MAJOR_VER 1
-#define SPARSE_HEADER_LEN (sizeof(sparse_header_t))
-#define CHUNK_HEADER_LEN (sizeof(chunk_header_t))
-
void usage()
{
fprintf(stderr, "Usage: simg2img <sparse_image_file> <raw_image_file>\n");
}
-static int read_all(int fd, void *buf, size_t len)
-{
- size_t total = 0;
- int ret;
- char *ptr = buf;
-
- while (total < len) {
- ret = read(fd, ptr, len - total);
-
- if (ret < 0)
- return ret;
-
- if (ret == 0)
- return total;
-
- ptr += ret;
- total += ret;
- }
-
- return total;
-}
-
-static int write_all(int fd, void *buf, size_t len)
-{
- size_t total = 0;
- int ret;
- char *ptr = buf;
-
- while (total < len) {
- ret = write(fd, ptr, len - total);
-
- if (ret < 0)
- return ret;
-
- if (ret == 0)
- return total;
-
- ptr += ret;
- total += ret;
- }
-
- return total;
-}
-
-int process_raw_chunk(int in, int out, u32 blocks, u32 blk_sz, u32 *crc32)
-{
- u64 len = (u64)blocks * blk_sz;
- int ret;
- int chunk;
-
- while (len) {
- chunk = (len > COPY_BUF_SIZE) ? COPY_BUF_SIZE : len;
- ret = read_all(in, copybuf, chunk);
- if (ret != chunk) {
- fprintf(stderr, "read returned an error copying a raw chunk: %d %d\n",
- ret, chunk);
- exit(-1);
- }
- *crc32 = sparse_crc32(*crc32, copybuf, chunk);
- ret = write_all(out, copybuf, chunk);
- if (ret != chunk) {
- fprintf(stderr, "write returned an error copying a raw chunk\n");
- exit(-1);
- }
- len -= chunk;
- }
-
- return blocks;
-}
-
-
-int process_fill_chunk(int in, int out, u32 blocks, u32 blk_sz, u32 *crc32)
-{
- u64 len = (u64)blocks * blk_sz;
- int ret;
- int chunk;
- u32 fill_val;
- u32 *fillbuf;
- unsigned int i;
-
- /* Fill copy_buf with the fill value */
- ret = read_all(in, &fill_val, sizeof(fill_val));
- fillbuf = (u32 *)copybuf;
- for (i = 0; i < (COPY_BUF_SIZE / sizeof(fill_val)); i++) {
- fillbuf[i] = fill_val;
- }
-
- while (len) {
- chunk = (len > COPY_BUF_SIZE) ? COPY_BUF_SIZE : len;
- *crc32 = sparse_crc32(*crc32, copybuf, chunk);
- ret = write_all(out, copybuf, chunk);
- if (ret != chunk) {
- fprintf(stderr, "write returned an error copying a raw chunk\n");
- exit(-1);
- }
- len -= chunk;
- }
-
- return blocks;
-}
-
-int process_skip_chunk(int out, u32 blocks, u32 blk_sz, u32 *crc32)
-{
- /* len needs to be 64 bits, as the sparse file specifies the skip amount
- * as a 32 bit value of blocks.
- */
- u64 len = (u64)blocks * blk_sz;
-
- lseek64(out, len, SEEK_CUR);
-
- return blocks;
-}
-
-int process_crc32_chunk(int in, u32 crc32)
-{
- u32 file_crc32;
- int ret;
-
- ret = read_all(in, &file_crc32, 4);
- if (ret != 4) {
- fprintf(stderr, "read returned an error copying a crc32 chunk\n");
- exit(-1);
- }
-
- if (file_crc32 != crc32) {
- fprintf(stderr, "computed crc32 of 0x%8.8x, expected 0x%8.8x\n",
- crc32, file_crc32);
- exit(-1);
- }
-
- return 0;
-}
-
int main(int argc, char *argv[])
{
int in;
int out;
unsigned int i;
- sparse_header_t sparse_header;
- chunk_header_t chunk_header;
- u32 crc32 = 0;
- u32 total_blocks = 0;
int ret;
+ struct sparse_file *s;
if (argc != 3) {
usage();
exit(-1);
}
- if ( (copybuf = malloc(COPY_BUF_SIZE)) == 0) {
- fprintf(stderr, "Cannot malloc copy buf\n");
- exit(-1);
- }
-
if (strcmp(argv[1], "-") == 0) {
in = STDIN_FILENO;
} else {
@@ -220,102 +62,16 @@ int main(int argc, char *argv[])
}
}
- ret = read_all(in, &sparse_header, sizeof(sparse_header));
- if (ret != sizeof(sparse_header)) {
- fprintf(stderr, "Error reading sparse file header\n");
- exit(-1);
- }
-
- if (sparse_header.magic != SPARSE_HEADER_MAGIC) {
- fprintf(stderr, "Bad magic\n");
- exit(-1);
- }
-
- if (sparse_header.major_version != SPARSE_HEADER_MAJOR_VER) {
- fprintf(stderr, "Unknown major version number\n");
- exit(-1);
- }
-
- if (sparse_header.file_hdr_sz > SPARSE_HEADER_LEN) {
- /* Skip the remaining bytes in a header that is longer than
- * we expected.
- */
- lseek64(in, sparse_header.file_hdr_sz - SPARSE_HEADER_LEN, SEEK_CUR);
- }
-
- if ( (zerobuf = malloc(sparse_header.blk_sz)) == 0) {
- fprintf(stderr, "Cannot malloc zero buf\n");
- exit(-1);
- }
-
- for (i=0; i<sparse_header.total_chunks; i++) {
- ret = read_all(in, &chunk_header, sizeof(chunk_header));
- if (ret != sizeof(chunk_header)) {
- fprintf(stderr, "Error reading chunk header\n");
- exit(-1);
- }
-
- if (sparse_header.chunk_hdr_sz > CHUNK_HEADER_LEN) {
- /* Skip the remaining bytes in a header that is longer than
- * we expected.
- */
- lseek64(in, sparse_header.chunk_hdr_sz - CHUNK_HEADER_LEN, SEEK_CUR);
- }
-
- switch (chunk_header.chunk_type) {
- case CHUNK_TYPE_RAW:
- if (chunk_header.total_sz != (sparse_header.chunk_hdr_sz +
- (chunk_header.chunk_sz * sparse_header.blk_sz)) ) {
- fprintf(stderr, "Bogus chunk size for chunk %d, type Raw\n", i);
- exit(-1);
- }
- total_blocks += process_raw_chunk(in, out,
- chunk_header.chunk_sz, sparse_header.blk_sz, &crc32);
- break;
- case CHUNK_TYPE_FILL:
- if (chunk_header.total_sz != (sparse_header.chunk_hdr_sz + sizeof(u32)) ) {
- fprintf(stderr, "Bogus chunk size for chunk %d, type Fill\n", i);
- exit(-1);
- }
- total_blocks += process_fill_chunk(in, out,
- chunk_header.chunk_sz, sparse_header.blk_sz, &crc32);
- break;
- case CHUNK_TYPE_DONT_CARE:
- if (chunk_header.total_sz != sparse_header.chunk_hdr_sz) {
- fprintf(stderr, "Bogus chunk size for chunk %d, type Dont Care\n", i);
- exit(-1);
- }
- total_blocks += process_skip_chunk(out,
- chunk_header.chunk_sz, sparse_header.blk_sz, &crc32);
- break;
- case CHUNK_TYPE_CRC32:
- process_crc32_chunk(in, crc32);
- break;
- default:
- fprintf(stderr, "Unknown chunk type 0x%4.4x\n", chunk_header.chunk_type);
- }
-
- }
-
- /* If the last chunk was a skip, then the code just did a seek, but
- * no write, and the file won't actually be the correct size. This
- * will make the file the correct size. Make sure the offset is
- * computed in 64 bits, and the function called can handle 64 bits.
- */
- if (ftruncate64(out, (u64)total_blocks * sparse_header.blk_sz)) {
- fprintf(stderr, "Error calling ftruncate() to set the image size\n");
+ s = sparse_file_import(in, true, false);
+ if (!s) {
+ fprintf(stderr, "Failed to read sparse file\n");
exit(-1);
}
+ ret = sparse_file_write(s, out, false, false, false);
close(in);
close(out);
- if (sparse_header.total_blks != total_blocks) {
- fprintf(stderr, "Wrote %d blocks, expected to write %d blocks\n",
- total_blocks, sparse_header.total_blks);
- exit(-1);
- }
-
exit(0);
}